@@ -55,6 +55,21 @@ void DescriptorSetSubState::BuildBindingLayouts() {
5555 }
5656}
5757
58+ void DescriptorSetSubState::CreateDescriptorEncodingBuffer () {
59+ VkBufferCreateInfo buffer_info = vku::InitStruct<VkBufferCreateInfo>();
60+ buffer_info.size = base.GetNonInlineDescriptorCount () * sizeof (glsl::DescriptorEncoding);
61+ buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
62+
63+ // The descriptor state buffer can be very large (4mb+ in some games). Allocating it as HOST_CACHED
64+ // and manually flushing it at the end of the state updates is faster than using HOST_COHERENT.
65+ VmaAllocationCreateInfo alloc_info{};
66+ alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
67+ const VkResult result = descriptor_encodings_.Create (&buffer_info, &alloc_info);
68+ if (result != VK_SUCCESS) {
69+ return ;
70+ }
71+ }
72+
5873template <typename StateObject>
5974DescriptorId GetId (const StateObject* obj, bool allow_null = true ) {
6075 if (!obj) {
@@ -175,34 +190,17 @@ VkDeviceAddress DescriptorSetSubState::GetDescriptorEncodingsAddress(Validator&
175190 std::lock_guard guard (state_lock_);
176191 const uint32_t current_version = current_version_.load ();
177192
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- }
187-
188- last_used_version_ = current_version;
189-
190193 if (base.GetNonInlineDescriptorCount () == 0 ) {
191- // no descriptors case, return a dummy state object
192- return descriptor_encodings_. Address () ;
194+ // no descriptors
195+ return 0 ;
193196 }
194197
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 ;
198+ // Create buffer just in time
199+ if (descriptor_encodings_.IsDestroyed ()) {
200+ CreateDescriptorEncodingBuffer ();
201+ } else if (last_used_version_ == current_version) {
202+ // nothing has changed
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