]> git.tdb.fi Git - libs/gl.git/blobdiff - source/backends/vulkan/pipelinestate_backend.cpp
Fix handling of descriptor set bindings when shader stages change
[libs/gl.git] / source / backends / vulkan / pipelinestate_backend.cpp
index 02e7993c665fb52dd95e9ff3f92020cfb2584a68..4eba2895e4925cd9282672a22d207f248ca4d2a4 100644 (file)
@@ -77,9 +77,14 @@ void VulkanPipelineState::update() const
                if(changed_sets)
                {
                        descriptor_set_slots.resize(self.shprog->get_n_descriptor_sets());
+                       first_changed_desc_set = descriptor_set_slots.size();
                        for(unsigned i=0; i<descriptor_set_slots.size(); ++i)
                                if(changed_sets&(1<<i))
+                               {
                                        descriptor_set_slots[i] = device.get_descriptor_pool().get_descriptor_set_slot(self, i);
+                                       first_changed_desc_set = min(first_changed_desc_set, i);
+                               }
+
                        unapplied |= PipelineState::UNIFORMS;
                }
        }
@@ -261,6 +266,7 @@ 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);
+       bool empty = true;
 
        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)
@@ -269,6 +275,7 @@ uint64_t VulkanPipelineState::compute_descriptor_set_hash(unsigned index) const
                        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));
+                       empty = false;
                }
 
        auto j = lower_bound_member(self.textures, index<<20, &PipelineState::BoundTexture::binding);
@@ -279,8 +286,12 @@ uint64_t VulkanPipelineState::compute_descriptor_set_hash(unsigned index) const
                        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);
+                       empty = false;
                }
 
+       if(!empty)
+               result = hash_update<64>(result, self.shprog->stage_flags);
+
        return result;
 }
 
@@ -374,21 +385,30 @@ void VulkanPipelineState::apply(VkCommandBuffer command_buffer, const VulkanPipe
        const PipelineState &self = *static_cast<const PipelineState *>(this);
        const VulkanFunctions &vk = device.get_functions();
 
-       unsigned first_changed_desc_set = 0;
        if(!last)
+       {
                unapplied = ~0U;
+               first_changed_desc_set = 0;
+       }
        else if(last!=this)
        {
                const PipelineState &last_ps = *static_cast<const PipelineState *>(last);
                if(handle!=last->handle)
+               {
                        unapplied |= PipelineState::SHPROG;
+                       if(self.shprog->stage_flags!=last_ps.shprog->stage_flags)
+                       {
+                               unapplied |= PipelineState::UNIFORMS;
+                               first_changed_desc_set = 0;
+                       }
+               }
                if(self.vertex_setup!=last_ps.vertex_setup)
                        unapplied |= PipelineState::VERTEX_SETUP;
-               for(unsigned i=0; (i<descriptor_set_slots.size() && i<last->descriptor_set_slots.size()); ++i)
-                       if(descriptor_set_slots[i]!=last->descriptor_set_slots[i])
+               for(unsigned i=0; i<descriptor_set_slots.size(); ++i)
+                       if(i>=last->descriptor_set_slots.size() || descriptor_set_slots[i]!=last->descriptor_set_slots[i])
                        {
                                unapplied |= PipelineState::UNIFORMS;
-                               first_changed_desc_set = i;
+                               first_changed_desc_set = min(first_changed_desc_set, i);
                                break;
                        }
                if(self.viewport!=last_ps.viewport)
@@ -466,6 +486,7 @@ void VulkanPipelineState::apply(VkCommandBuffer command_buffer, const VulkanPipe
        }
 
        unapplied = 0;
+       first_changed_desc_set = descriptor_set_slots.size();
 }
 
 } // namespace GL