From 1ed4d66194a8a86413701a4c4e4178c2fb0a4ded Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 15 Mar 2022 21:25:18 +0200 Subject: [PATCH] Make use of the sorted nature of PipelineState resource arrays Since descriptor set is in the high bits, lower_bound can be used to find its first resource and then go through elements until the next set is reached. --- .../backends/vulkan/pipelinestate_backend.cpp | 64 +++++++++++-------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/source/backends/vulkan/pipelinestate_backend.cpp b/source/backends/vulkan/pipelinestate_backend.cpp index e4321509..31488bad 100644 --- a/source/backends/vulkan/pipelinestate_backend.cpp +++ b/source/backends/vulkan/pipelinestate_backend.cpp @@ -1,3 +1,4 @@ +#include #include #include "batch.h" #include "blend.h" @@ -260,20 +261,24 @@ uint64_t VulkanPipelineState::compute_descriptor_set_hash(unsigned index) const const PipelineState &self = *static_cast(this); uint64_t result = hash<64>(0, 0); - for(const PipelineState::BoundUniformBlock &b: self.uniform_blocks) - if(b.used && b.binding>=0 && static_cast(b.binding>>20)==index) + + auto i = lower_bound_member(self.uniform_blocks, static_cast(index)<<20, &PipelineState::BoundUniformBlock::binding); + for(; (i!=self.uniform_blocks.end() && static_cast(i->binding)>>20==index); ++i) + if(i->used) { - result = hash_update<64>(result, b.binding); - result = hash_update<64>(result, reinterpret_cast(b.block)); - result = hash_update<64>(result, reinterpret_cast(b.buffer->handle)); + result = hash_update<64>(result, i->binding); + result = hash_update<64>(result, reinterpret_cast(i->block)); + result = hash_update<64>(result, reinterpret_cast(i->buffer->handle)); } - for(const PipelineState::BoundTexture &t: self.textures) - if(t.used && (t.binding>>20)==index) + + auto j = lower_bound_member(self.textures, index<<20, &PipelineState::BoundTexture::binding); + for(; (j!=self.textures.end() && j->binding>>20==index); ++j) + if(j->used) { - result = hash_update<64>(result, t.binding); - result = hash_update<64>(result, reinterpret_cast(t.texture->handle)); - result = hash_update<64>(result, reinterpret_cast(t.sampler->handle)); - result = hash_update<64>(result, t.level); + result = hash_update<64>(result, j->binding); + result = hash_update<64>(result, reinterpret_cast(j->texture->handle)); + result = hash_update<64>(result, reinterpret_cast(j->sampler->handle)); + result = hash_update<64>(result, j->level); } return result; @@ -288,13 +293,16 @@ unsigned VulkanPipelineState::fill_descriptor_writes(unsigned index, vector(this); + auto u_begin = lower_bound_member(self.uniform_blocks, static_cast(index)<<20, &PipelineState::BoundUniformBlock::binding); + auto t_begin = lower_bound_member(self.textures, index<<20, &PipelineState::BoundTexture::binding); + unsigned n_buffers = 0; - for(const PipelineState::BoundUniformBlock &u: self.uniform_blocks) - if(u.used && u.binding>=0 && static_cast(u.binding>>20)==index) + for(auto i=u_begin; (i!=self.uniform_blocks.end() && static_cast(i->binding)>>20==index); ++i) + if(i->used) ++n_buffers; unsigned n_images = 0; - for(const PipelineState::BoundTexture &t: self.textures) - if(t.used && (t.binding>>20)==index) + for(auto i=t_begin; (i!=self.textures.end() && i->binding>>20==index); ++i) + if(i->used) ++n_images; unsigned n_writes = n_buffers+n_images; @@ -307,15 +315,15 @@ unsigned VulkanPipelineState::fill_descriptor_writes(unsigned index, vector=0 && static_cast(u.binding>>20)==index) + for(auto i=u_begin; (i!=self.uniform_blocks.end() && static_cast(i->binding)>>20==index); ++i) + if(i->used) { - buffer_ptr->buffer = handle_cast<::VkBuffer>(u.buffer->handle); - buffer_ptr->offset = u.block->get_offset(); - buffer_ptr->range = u.block->get_data_size(); + buffer_ptr->buffer = handle_cast<::VkBuffer>(i->buffer->handle); + buffer_ptr->offset = i->block->get_offset(); + buffer_ptr->range = i->block->get_data_size(); write_ptr->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write_ptr->dstBinding = u.binding&0xFFFFF; + write_ptr->dstBinding = i->binding&0xFFFFF; write_ptr->descriptorCount = 1; write_ptr->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; write_ptr->pBufferInfo = buffer_ptr; @@ -324,18 +332,18 @@ unsigned VulkanPipelineState::fill_descriptor_writes(unsigned index, vector>20)==index) + for(auto i=t_begin; (i!=self.textures.end() && i->binding>>20==index); ++i) + if(i->used) { - image_ptr->sampler = handle_cast<::VkSampler>(t.sampler->handle); - if(t.level<0) - image_ptr->imageView = handle_cast<::VkImageView>(t.texture->view_handle); + image_ptr->sampler = handle_cast<::VkSampler>(i->sampler->handle); + if(i->level<0) + image_ptr->imageView = handle_cast<::VkImageView>(i->texture->view_handle); else - image_ptr->imageView = handle_cast<::VkImageView>(t.texture->mip_view_handles[t.level]); + image_ptr->imageView = handle_cast<::VkImageView>(i->texture->mip_view_handles[i->level]); image_ptr->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; write_ptr->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write_ptr->dstBinding = t.binding&0xFFFFF; + write_ptr->dstBinding = i->binding&0xFFFFF; write_ptr->descriptorCount = 1; write_ptr->descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; write_ptr->pImageInfo = image_ptr; -- 2.43.0