]> git.tdb.fi Git - libs/gl.git/commitdiff
Make use of the sorted nature of PipelineState resource arrays
authorMikko Rasa <tdb@tdb.fi>
Tue, 15 Mar 2022 19:25:18 +0000 (21:25 +0200)
committerMikko Rasa <tdb@tdb.fi>
Tue, 15 Mar 2022 19:25:18 +0000 (21:25 +0200)
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.

source/backends/vulkan/pipelinestate_backend.cpp

index e43215091300a25bf4c1f01d5ce8260c0b8df099..31488bad1ef92d49b534306ab61721b43fae77ce 100644 (file)
@@ -1,3 +1,4 @@
+#include <msp/core/algorithm.h>
 #include <msp/core/hash.h>
 #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<const PipelineState *>(this);
 
        uint64_t result = hash<64>(0, 0);
-       for(const PipelineState::BoundUniformBlock &b: self.uniform_blocks)
-               if(b.used && b.binding>=0 && static_cast<unsigned>(b.binding>>20)==index)
+
+       auto i = lower_bound_member(self.uniform_blocks, static_cast<int>(index)<<20, &PipelineState::BoundUniformBlock::binding);
+       for(; (i!=self.uniform_blocks.end() && static_cast<unsigned>(i->binding)>>20==index); ++i)
+               if(i->used)
                {
-                       result = hash_update<64>(result, b.binding);
-                       result = hash_update<64>(result, reinterpret_cast<uintptr_t>(b.block));
-                       result = hash_update<64>(result, reinterpret_cast<uintptr_t>(b.buffer->handle));
+                       result = hash_update<64>(result, i->binding);
+                       result = hash_update<64>(result, reinterpret_cast<uintptr_t>(i->block));
+                       result = hash_update<64>(result, reinterpret_cast<uintptr_t>(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<uintptr_t>(t.texture->handle));
-                       result = hash_update<64>(result, reinterpret_cast<uintptr_t>(t.sampler->handle));
-                       result = hash_update<64>(result, t.level);
+                       result = hash_update<64>(result, j->binding);
+                       result = hash_update<64>(result, reinterpret_cast<uintptr_t>(j->texture->handle));
+                       result = hash_update<64>(result, reinterpret_cast<uintptr_t>(j->sampler->handle));
+                       result = hash_update<64>(result, j->level);
                }
 
        return result;
@@ -288,13 +293,16 @@ unsigned VulkanPipelineState::fill_descriptor_writes(unsigned index, vector<char
 {
        const PipelineState &self = *static_cast<const PipelineState *>(this);
 
+       auto u_begin = lower_bound_member(self.uniform_blocks, static_cast<int>(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<unsigned>(u.binding>>20)==index)
+       for(auto i=u_begin; (i!=self.uniform_blocks.end() && static_cast<unsigned>(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<char
        VkDescriptorBufferInfo *buffer_ptr = buffers;
        VkDescriptorImageInfo *image_ptr = images;
 
-       for(const PipelineState::BoundUniformBlock &u: self.uniform_blocks)
-               if(u.used && u.binding>=0 && static_cast<unsigned>(u.binding>>20)==index)
+       for(auto i=u_begin; (i!=self.uniform_blocks.end() && static_cast<unsigned>(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<char
                        ++write_ptr;
                }
 
-       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)
                {
-                       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;