@@ -35,6 +35,7 @@ namespace gpuav {
3535DescriptorSetSubState::DescriptorSetSubState (const vvl::DescriptorSet& set, Validator& state_data)
3636 : vvl::DescriptorSetSubState(set), descriptor_encodings_(state_data) {
3737 BuildBindingLayouts ();
38+ CreateDescriptorEncodingBuffer ();
3839}
3940
4041DescriptorSetSubState::~DescriptorSetSubState () { descriptor_encodings_.Destroy (); }
@@ -55,6 +56,21 @@ void DescriptorSetSubState::BuildBindingLayouts() {
5556 }
5657}
5758
59+ void DescriptorSetSubState::CreateDescriptorEncodingBuffer () {
60+ VkBufferCreateInfo buffer_info = vku::InitStruct<VkBufferCreateInfo>();
61+ buffer_info.size = base.GetNonInlineDescriptorCount () * sizeof (glsl::DescriptorEncoding);
62+ buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
63+
64+ // The descriptor state buffer can be very large (4mb+ in some games). Allocating it as HOST_CACHED
65+ // and manually flushing it at the end of the state updates is faster than using HOST_COHERENT.
66+ VmaAllocationCreateInfo alloc_info{};
67+ alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
68+ const VkResult result = descriptor_encodings_.Create (&buffer_info, &alloc_info);
69+ if (result != VK_SUCCESS) {
70+ return ;
71+ }
72+ }
73+
5874template <typename StateObject>
5975DescriptorId GetId (const StateObject* obj, bool allow_null = true ) {
6076 if (!obj) {
@@ -175,34 +191,16 @@ VkDeviceAddress DescriptorSetSubState::GetDescriptorEncodingsAddress(Validator&
175191 std::lock_guard guard (state_lock_);
176192 const uint32_t current_version = current_version_.load ();
177193
178- // Will be empty on first time getting the state
179- if (descriptor_encodings_.Address () != 0 ) {
180- if (last_used_version_ == current_version) {
181- return descriptor_encodings_.Address (); // nothing has changed
182- } else {
183- // will replace (descriptor array size might have change, so need to resize buffer)
184- descriptor_encodings_.Destroy ();
185- }
186- }
194+ assert (descriptor_encodings_.Address () != 0 );
187195
188- last_used_version_ = current_version;
189-
190- if (base.GetNonInlineDescriptorCount () == 0 ) {
191- // no descriptors case, return a dummy state object
196+ if (last_used_version_ == current_version) {
197+ // nothing has changed
192198 return descriptor_encodings_.Address ();
193199 }
194200
195- VkBufferCreateInfo buffer_info = vku::InitStruct<VkBufferCreateInfo>();
196- buffer_info.size = base.GetNonInlineDescriptorCount () * sizeof (glsl::DescriptorEncoding);
197- buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
198-
199- // The descriptor state buffer can be very large (4mb+ in some games). Allocating it as HOST_CACHED
200- // and manually flushing it at the end of the state updates is faster than using HOST_COHERENT.
201- VmaAllocationCreateInfo alloc_info{};
202- alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
203- const VkResult result = descriptor_encodings_.Create (&buffer_info, &alloc_info);
204- if (result != VK_SUCCESS) {
205- return 0 ;
201+ if (base.GetNonInlineDescriptorCount () == 0 ) {
202+ // no descriptors, return a dummy state object
203+ return descriptor_encodings_.Address ();
206204 }
207205
208206 auto descriptor_encodings = (glsl::DescriptorEncoding*)descriptor_encodings_.GetMappedPtr ();
@@ -245,6 +243,8 @@ VkDeviceAddress DescriptorSetSubState::GetDescriptorEncodingsAddress(Validator&
245243 // Flush the descriptor encodings before unmapping so that they are visible to the GPU
246244 descriptor_encodings_.FlushAllocation ();
247245
246+ last_used_version_ = current_version;
247+
248248 return descriptor_encodings_.Address ();
249249}
250250
0 commit comments