Avi Drissman | 05dfbc82 | 2022-09-13 21:25:34 | [diff] [blame] | 1 | // Copyright 2017 The Chromium Authors |
Eric Karl | 16711ec | 2017-11-18 00:58:11 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "gpu/command_buffer/client/client_transfer_cache.h" |
| 6 | |
| 7 | namespace gpu { |
| 8 | |
Jonathan Backer | f949391 | 2018-02-12 23:00:09 | [diff] [blame] | 9 | ClientTransferCache::ClientTransferCache(Client* client) : client_(client) {} |
| 10 | |
Eric Karl | 16711ec | 2017-11-18 00:58:11 | [diff] [blame] | 11 | ClientTransferCache::~ClientTransferCache() = default; |
| 12 | |
Jonathan Backer | f949391 | 2018-02-12 23:00:09 | [diff] [blame] | 13 | void* ClientTransferCache::MapEntry(MappedMemoryManager* mapped_memory, |
Antoine Labour | a204d55 | 2019-01-08 21:26:52 | [diff] [blame] | 14 | uint32_t size) { |
Antoine Labour | 16d0691 | 2018-01-22 23:53:42 | [diff] [blame] | 15 | DCHECK(!mapped_ptr_); |
Adrienne Walker | 458236c | 2018-10-12 22:09:46 | [diff] [blame] | 16 | DCHECK(!transfer_buffer_ptr_); |
Jonathan Backer | f949391 | 2018-02-12 23:00:09 | [diff] [blame] | 17 | mapped_ptr_.emplace(size, client_->cmd_buffer_helper(), mapped_memory); |
Antoine Labour | 16d0691 | 2018-01-22 23:53:42 | [diff] [blame] | 18 | if (!mapped_ptr_->valid()) { |
Anton Bikineev | aabbd608 | 2021-05-15 17:57:20 | [diff] [blame] | 19 | mapped_ptr_ = absl::nullopt; |
Antoine Labour | 16d0691 | 2018-01-22 23:53:42 | [diff] [blame] | 20 | return nullptr; |
Antoine Labour | 16d0691 | 2018-01-22 23:53:42 | [diff] [blame] | 21 | } |
Adrienne Walker | 458236c | 2018-10-12 22:09:46 | [diff] [blame] | 22 | return mapped_ptr_->address(); |
| 23 | } |
| 24 | |
| 25 | void* ClientTransferCache::MapTransferBufferEntry( |
| 26 | TransferBufferInterface* transfer_buffer, |
Antoine Labour | a204d55 | 2019-01-08 21:26:52 | [diff] [blame] | 27 | uint32_t size) { |
Adrienne Walker | 458236c | 2018-10-12 22:09:46 | [diff] [blame] | 28 | DCHECK(!mapped_ptr_); |
| 29 | DCHECK(!transfer_buffer_ptr_); |
| 30 | transfer_buffer_ptr_.emplace(size, client_->cmd_buffer_helper(), |
| 31 | transfer_buffer); |
| 32 | if (!transfer_buffer_ptr_->valid()) { |
Anton Bikineev | aabbd608 | 2021-05-15 17:57:20 | [diff] [blame] | 33 | transfer_buffer_ptr_ = absl::nullopt; |
Adrienne Walker | 458236c | 2018-10-12 22:09:46 | [diff] [blame] | 34 | return nullptr; |
| 35 | } |
| 36 | return transfer_buffer_ptr_->address(); |
Eric Karl | 16711ec | 2017-11-18 00:58:11 | [diff] [blame] | 37 | } |
| 38 | |
Jonathan Backer | f949391 | 2018-02-12 23:00:09 | [diff] [blame] | 39 | void ClientTransferCache::UnmapAndCreateEntry(uint32_t type, uint32_t id) { |
Antoine Labour | 16d0691 | 2018-01-22 23:53:42 | [diff] [blame] | 40 | EntryKey key(type, id); |
| 41 | |
Eric Karl | 5a20a59 | 2017-12-13 02:53:16 | [diff] [blame] | 42 | base::AutoLock hold(lock_); |
Khushal | 7c03b1e | 2018-10-25 06:57:24 | [diff] [blame] | 43 | auto handle = CreateDiscardableHandle(key); |
Eric Karl | 0e15698 | 2019-04-16 00:31:18 | [diff] [blame] | 44 | if (!handle.IsValid()) { |
| 45 | // Release any data pointers. Keeping these alive longer can lead to issues |
| 46 | // with transfer buffer reallocation. |
Anton Bikineev | aabbd608 | 2021-05-15 17:57:20 | [diff] [blame] | 47 | mapped_ptr_ = absl::nullopt; |
| 48 | transfer_buffer_ptr_ = absl::nullopt; |
Khushal | 2ae1a08f | 2018-07-23 21:25:36 | [diff] [blame] | 49 | return; |
Eric Karl | 0e15698 | 2019-04-16 00:31:18 | [diff] [blame] | 50 | } |
Khushal | 2ae1a08f | 2018-07-23 21:25:36 | [diff] [blame] | 51 | |
Adrienne Walker | 458236c | 2018-10-12 22:09:46 | [diff] [blame] | 52 | if (mapped_ptr_) { |
| 53 | DCHECK(!transfer_buffer_ptr_); |
| 54 | client_->IssueCreateTransferCacheEntry( |
| 55 | type, id, handle.shm_id(), handle.byte_offset(), mapped_ptr_->shm_id(), |
| 56 | mapped_ptr_->offset(), mapped_ptr_->size()); |
Anton Bikineev | aabbd608 | 2021-05-15 17:57:20 | [diff] [blame] | 57 | mapped_ptr_ = absl::nullopt; |
Adrienne Walker | 458236c | 2018-10-12 22:09:46 | [diff] [blame] | 58 | } else { |
| 59 | DCHECK(!mapped_ptr_); |
| 60 | client_->IssueCreateTransferCacheEntry( |
| 61 | type, id, handle.shm_id(), handle.byte_offset(), |
| 62 | transfer_buffer_ptr_->shm_id(), transfer_buffer_ptr_->offset(), |
| 63 | transfer_buffer_ptr_->size()); |
Anton Bikineev | aabbd608 | 2021-05-15 17:57:20 | [diff] [blame] | 64 | transfer_buffer_ptr_ = absl::nullopt; |
Adrienne Walker | 458236c | 2018-10-12 22:09:46 | [diff] [blame] | 65 | } |
Antoine Labour | 16d0691 | 2018-01-22 23:53:42 | [diff] [blame] | 66 | } |
| 67 | |
Khushal | 7c03b1e | 2018-10-25 06:57:24 | [diff] [blame] | 68 | void ClientTransferCache::AddTransferCacheEntry(uint32_t type, |
| 69 | uint32_t id, |
| 70 | uint32_t shm_id, |
| 71 | uint32_t shm_offset, |
Antoine Labour | a204d55 | 2019-01-08 21:26:52 | [diff] [blame] | 72 | uint32_t size) { |
Khushal | 7c03b1e | 2018-10-25 06:57:24 | [diff] [blame] | 73 | DCHECK(!mapped_ptr_); |
| 74 | EntryKey key(type, id); |
| 75 | |
| 76 | base::AutoLock hold(lock_); |
| 77 | auto handle = CreateDiscardableHandle(key); |
| 78 | if (!handle.IsValid()) |
| 79 | return; |
| 80 | |
| 81 | client_->IssueCreateTransferCacheEntry(type, id, handle.shm_id(), |
| 82 | handle.byte_offset(), shm_id, |
| 83 | shm_offset, size); |
| 84 | } |
| 85 | |
Andres Calderon Jaramillo | 1e14110 | 2018-11-13 02:07:18 | [diff] [blame] | 86 | void ClientTransferCache::StartTransferCacheEntry( |
| 87 | uint32_t type, |
| 88 | uint32_t id, |
| 89 | base::OnceCallback<void(ClientDiscardableHandle)> create_entry_cb) { |
| 90 | DCHECK(!mapped_ptr_); |
| 91 | EntryKey key(type, id); |
| 92 | |
| 93 | base::AutoLock hold(lock_); |
Andres Calderon Jaramillo | 8235453 | 2018-11-27 20:53:06 | [diff] [blame] | 94 | auto handle = CreateDiscardableHandle(key); |
| 95 | if (!handle.IsValid()) |
| 96 | return; |
Andres Calderon Jaramillo | 1e14110 | 2018-11-13 02:07:18 | [diff] [blame] | 97 | |
| 98 | // Call |create_entry_cb| while |lock_| is held so that in case another thread |
| 99 | // tries to lock the cache entry later, it can assume that the creation of the |
| 100 | // service-side cache entry has been triggered. |
Andres Calderon Jaramillo | 8235453 | 2018-11-27 20:53:06 | [diff] [blame] | 101 | std::move(create_entry_cb).Run(handle); |
Andres Calderon Jaramillo | 1e14110 | 2018-11-13 02:07:18 | [diff] [blame] | 102 | } |
| 103 | |
Khushal | 7c03b1e | 2018-10-25 06:57:24 | [diff] [blame] | 104 | ClientDiscardableHandle ClientTransferCache::CreateDiscardableHandle( |
| 105 | const EntryKey& key) { |
Khushal | 7c03b1e | 2018-10-25 06:57:24 | [diff] [blame] | 106 | ClientDiscardableHandle::Id discardable_handle_id = |
| 107 | discardable_manager_.CreateHandle(client_->command_buffer()); |
| 108 | if (discardable_handle_id.is_null()) |
| 109 | return ClientDiscardableHandle(); |
| 110 | |
| 111 | // We must have a valid handle here, since the id was generated above and |
| 112 | // should be in locked state. |
| 113 | ClientDiscardableHandle handle = |
| 114 | discardable_manager_.GetHandle(discardable_handle_id); |
| 115 | |
| 116 | // Store the mapping from the given namespace/discardable_handle_id to the |
| 117 | // transfer cache discardable_handle_id. |
| 118 | DCHECK(FindDiscardableHandleId(key).is_null()); |
| 119 | discardable_handle_id_map_.emplace(key, discardable_handle_id); |
| 120 | return handle; |
| 121 | } |
| 122 | |
Antoine Labour | 16d0691 | 2018-01-22 23:53:42 | [diff] [blame] | 123 | bool ClientTransferCache::LockEntry(uint32_t type, uint32_t id) { |
| 124 | EntryKey key(type, id); |
| 125 | |
| 126 | base::AutoLock hold(lock_); |
| 127 | auto discardable_handle_id = FindDiscardableHandleId(key); |
Vladimir Levin | 5d3f4ab | 2017-12-12 19:43:38 | [diff] [blame] | 128 | if (discardable_handle_id.is_null()) |
| 129 | return false; |
| 130 | |
| 131 | if (discardable_manager_.LockHandle(discardable_handle_id)) |
Eric Karl | 16711ec | 2017-11-18 00:58:11 | [diff] [blame] | 132 | return true; |
| 133 | |
Eric Karl | 4eb20dc | 2017-12-08 22:04:46 | [diff] [blame] | 134 | // Could not lock. Entry is already deleted service side. |
Antoine Labour | 16d0691 | 2018-01-22 23:53:42 | [diff] [blame] | 135 | discardable_handle_id_map_.erase(key); |
Eric Karl | 16711ec | 2017-11-18 00:58:11 | [diff] [blame] | 136 | return false; |
| 137 | } |
| 138 | |
Antoine Labour | 16d0691 | 2018-01-22 23:53:42 | [diff] [blame] | 139 | void ClientTransferCache::UnlockEntries( |
Antoine Labour | 16d0691 | 2018-01-22 23:53:42 | [diff] [blame] | 140 | const std::vector<std::pair<uint32_t, uint32_t>>& entries) { |
Eric Karl | 5a20a59 | 2017-12-13 02:53:16 | [diff] [blame] | 141 | base::AutoLock hold(lock_); |
Vladimir Levin | 1a23a18 | 2017-12-15 02:29:05 | [diff] [blame] | 142 | for (const auto& entry : entries) { |
Antoine Labour | 16d0691 | 2018-01-22 23:53:42 | [diff] [blame] | 143 | DCHECK(!FindDiscardableHandleId(entry).is_null()); |
Jonathan Backer | f949391 | 2018-02-12 23:00:09 | [diff] [blame] | 144 | client_->IssueUnlockTransferCacheEntry(entry.first, entry.second); |
Vladimir Levin | 1a23a18 | 2017-12-15 02:29:05 | [diff] [blame] | 145 | } |
Eric Karl | 16711ec | 2017-11-18 00:58:11 | [diff] [blame] | 146 | } |
| 147 | |
Jonathan Backer | f949391 | 2018-02-12 23:00:09 | [diff] [blame] | 148 | void ClientTransferCache::DeleteEntry(uint32_t type, uint32_t id) { |
Antoine Labour | 16d0691 | 2018-01-22 23:53:42 | [diff] [blame] | 149 | EntryKey key(type, id); |
Eric Karl | 5a20a59 | 2017-12-13 02:53:16 | [diff] [blame] | 150 | base::AutoLock hold(lock_); |
Antoine Labour | 16d0691 | 2018-01-22 23:53:42 | [diff] [blame] | 151 | auto discardable_handle_id = FindDiscardableHandleId(key); |
Vladimir Levin | 5d3f4ab | 2017-12-12 19:43:38 | [diff] [blame] | 152 | if (discardable_handle_id.is_null()) |
| 153 | return; |
| 154 | |
| 155 | discardable_manager_.FreeHandle(discardable_handle_id); |
Jonathan Backer | f949391 | 2018-02-12 23:00:09 | [diff] [blame] | 156 | client_->IssueDeleteTransferCacheEntry(type, id); |
Antoine Labour | 16d0691 | 2018-01-22 23:53:42 | [diff] [blame] | 157 | discardable_handle_id_map_.erase(key); |
Vladimir Levin | 5d3f4ab | 2017-12-12 19:43:38 | [diff] [blame] | 158 | } |
| 159 | |
| 160 | ClientDiscardableHandle::Id ClientTransferCache::FindDiscardableHandleId( |
Antoine Labour | 16d0691 | 2018-01-22 23:53:42 | [diff] [blame] | 161 | const EntryKey& key) { |
Antoine Labour | 16d0691 | 2018-01-22 23:53:42 | [diff] [blame] | 162 | auto id_map_it = discardable_handle_id_map_.find(key); |
| 163 | if (id_map_it == discardable_handle_id_map_.end()) |
Vladimir Levin | 5d3f4ab | 2017-12-12 19:43:38 | [diff] [blame] | 164 | return ClientDiscardableHandle::Id(); |
| 165 | return id_map_it->second; |
| 166 | } |
| 167 | |
Eric Karl | 16711ec | 2017-11-18 00:58:11 | [diff] [blame] | 168 | } // namespace gpu |