]> git.tdb.fi Git - libs/gl.git/commitdiff
Apply only changed parts of VulkanPipelineState
authorMikko Rasa <tdb@tdb.fi>
Sat, 15 Jan 2022 09:06:08 +0000 (11:06 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sat, 15 Jan 2022 09:06:08 +0000 (11:06 +0200)
source/backends/vulkan/commands_backend.cpp
source/backends/vulkan/commands_backend.h
source/backends/vulkan/pipelinestate_backend.cpp
source/backends/vulkan/pipelinestate_backend.h

index d655134d032fdf95cf05fe6a5d7941868cd2c341..8f32e0b024bd9c0264e8376331eceffca1105eff 100644 (file)
@@ -78,6 +78,7 @@ void VulkanCommands::begin_buffer(VkRenderPass render_pass)
        }
 
        vk.BeginCommandBuffer(buffer, begin_info);
+       last_pipeline = 0;
 }
 
 void VulkanCommands::begin_render_pass(bool clear, const ClearValue *clear_values)
@@ -255,7 +256,8 @@ void VulkanCommands::draw_instanced(const Batch &batch, unsigned count)
                 begin_render_pass(false, 0);
 
        pipeline_state->refresh();
-       pipeline_state->apply(pass_buffer, frame_index, fb_is_swapchain);
+       pipeline_state->apply(pass_buffer, last_pipeline, frame_index, fb_is_swapchain);
+       last_pipeline = pipeline_state;
        unsigned first_index = batch.get_offset()/batch.get_index_size();
        vk.CmdDrawIndexed(pass_buffer, batch.size(), count, first_index, 0, 0);
 }
index 00e492f2542c2fa9fada9c0929480503cb842f25..7e1554413bb10acebd50e840a540ed2c7dbd2777 100644 (file)
@@ -47,6 +47,7 @@ protected:
        VkCommandBuffer primary_buffer = 0;
        VkCommandBuffer pass_buffer = 0;
        const PipelineState *pipeline_state = 0;
+       const PipelineState *last_pipeline = 0;
        const Framebuffer *framebuffer = 0;
        Rect viewport = Rect::max();
        bool fb_is_swapchain = false;
index 1d381022ace90136fc193681d97361a3b5f3d063..4f50c77e11b62ed78b736a58fe35ad35dceeee98 100644 (file)
@@ -35,13 +35,18 @@ void VulkanPipelineState::update() const
 {
        const PipelineState &self = *static_cast<const PipelineState *>(this);
 
+       unapplied |= changes&(PipelineState::VIEWPORT|PipelineState::SCISSOR|PipelineState::VERTEX_SETUP);
+
        if(changes&PipelineState::VERTEX_SETUP)
                self.vertex_setup->refresh();
 
        constexpr unsigned pipeline_mask = PipelineState::SHPROG|PipelineState::VERTEX_SETUP|PipelineState::FACE_CULL|
                PipelineState::DEPTH_TEST|PipelineState::STENCIL_TEST|PipelineState::BLEND|PipelineState::PRIMITIVE_TYPE;
        if(changes&pipeline_mask)
+       {
                handle = device.get_pipeline_cache().get_pipeline(self);
+               unapplied |= PipelineState::SHPROG;
+       }
 
        if(changes&(PipelineState::SHPROG|PipelineState::UNIFORMS|PipelineState::TEXTURES))
        {
@@ -74,6 +79,7 @@ void VulkanPipelineState::update() const
                        for(unsigned i=0; i<descriptor_set_handles.size(); ++i)
                                if(changed_sets&(1<<i))
                                        descriptor_set_handles[i] = device.get_pipeline_cache().get_descriptor_set(self, i);
+                       unapplied |= PipelineState::UNIFORMS;
                }
        }
 
@@ -346,19 +352,43 @@ unsigned VulkanPipelineState::fill_descriptor_writes(unsigned index, vector<char
        return n_writes;
 }
 
-void VulkanPipelineState::apply(VkCommandBuffer command_buffer, unsigned frame, bool negative_viewport) const
+void VulkanPipelineState::apply(VkCommandBuffer command_buffer, const VulkanPipelineState *last, unsigned frame, bool negative_viewport) const
 {
        const PipelineState &self = *static_cast<const PipelineState *>(this);
        const VulkanFunctions &vk = device.get_functions();
 
-       vk.CmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, handle);
-       if(const VertexSetup *vs = self.vertex_setup)
+       if(!last)
+               unapplied = ~0U;
+       else if(last!=this)
        {
-               vk.CmdBindVertexBuffers(command_buffer, 0, vs->n_bindings, vs->buffers, vs->offsets);
-               VkIndexType index_type = static_cast<VkIndexType>(get_vulkan_index_type(vs->get_index_type()));
-               vk.CmdBindIndexBuffer(command_buffer, vs->get_index_buffer()->handle, 0, index_type);
+               const PipelineState &last_ps = *static_cast<const PipelineState *>(last);
+               if(handle!=last->handle)
+                       unapplied |= PipelineState::SHPROG;
+               if(self.vertex_setup!=last_ps.vertex_setup)
+                       unapplied |= PipelineState::VERTEX_SETUP;
+               for(unsigned i=0; (i<descriptor_set_handles.size() && i<last->descriptor_set_handles.size()); ++i)
+                       if(descriptor_set_handles[i]!=last->descriptor_set_handles[i])
+                       {
+                               unapplied |= PipelineState::UNIFORMS;
+                               break;
+                       }
+               if(self.viewport!=last_ps.viewport)
+                       unapplied |= PipelineState::VIEWPORT;
+               if(self.scissor!=last_ps.scissor)
+                       unapplied |= PipelineState::SCISSOR;
        }
 
+       if(unapplied&PipelineState::SHPROG)
+               vk.CmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, handle);
+
+       if(unapplied&PipelineState::VERTEX_SETUP)
+               if(const VertexSetup *vs = self.vertex_setup)
+               {
+                       vk.CmdBindVertexBuffers(command_buffer, 0, vs->n_bindings, vs->buffers, vs->offsets);
+                       VkIndexType index_type = static_cast<VkIndexType>(get_vulkan_index_type(vs->get_index_type()));
+                       vk.CmdBindIndexBuffer(command_buffer, vs->get_index_buffer()->handle, 0, index_type);
+               }
+
        if(!self.uniform_blocks.empty())
        {
                const PipelineState::BoundUniformBlock &first_block = self.uniform_blocks.front();
@@ -370,7 +400,7 @@ void VulkanPipelineState::apply(VkCommandBuffer command_buffer, unsigned frame,
                }
        }
 
-       if(!descriptor_set_handles.empty())
+       if((unapplied&PipelineState::UNIFORMS) && !descriptor_set_handles.empty())
        {
                vector<uint32_t> dynamic_offsets;
                dynamic_offsets.reserve(self.uniform_blocks.size());
@@ -387,30 +417,41 @@ void VulkanPipelineState::apply(VkCommandBuffer command_buffer, unsigned frame,
                        0, descriptor_set_handles.size(), descriptor_set_handles.data(), dynamic_offsets.size(), dynamic_offsets.data());
        }
 
-       Rect fb_rect = self.framebuffer->get_rect();
-
-       Rect viewport_rect = fb_rect.intersect(self.viewport);
-       VkViewport viewport = { };
-       viewport.x = viewport_rect.left;
-       viewport.y = viewport_rect.bottom;
-       viewport.width = viewport_rect.width;
-       viewport.height = viewport_rect.height;
-       if(negative_viewport)
+       if(unapplied&(PipelineState::VIEWPORT|PipelineState::SCISSOR))
        {
-               viewport.y += viewport.height;
-               viewport.height = -viewport.height;
+               Rect fb_rect = self.framebuffer->get_rect();
+
+               if(unapplied&PipelineState::VIEWPORT)
+               {
+                       Rect viewport_rect = fb_rect.intersect(self.viewport);
+                       VkViewport viewport = { };
+                       viewport.x = viewport_rect.left;
+                       viewport.y = viewport_rect.bottom;
+                       viewport.width = viewport_rect.width;
+                       viewport.height = viewport_rect.height;
+                       if(negative_viewport)
+                       {
+                               viewport.y += viewport.height;
+                               viewport.height = -viewport.height;
+                       }
+                       viewport.minDepth = 0.0f;
+                       viewport.maxDepth = 1.0f;
+                       vk.CmdSetViewport(command_buffer, 0, 1, &viewport);
+               }
+
+               if(unapplied&PipelineState::SCISSOR)
+               {
+                       Rect scissor_rect = fb_rect.intersect(self.scissor);
+                       VkRect2D scissor = { };
+                       scissor.offset.x = scissor_rect.left;
+                       scissor.offset.y = scissor_rect.bottom;
+                       scissor.extent.width = scissor_rect.width;
+                       scissor.extent.height = scissor_rect.height;
+                       vk.CmdSetScissor(command_buffer, 0, 1, &scissor);
+               }
        }
-       viewport.minDepth = 0.0f;
-       viewport.maxDepth = 1.0f;
-       vk.CmdSetViewport(command_buffer, 0, 1, &viewport);
-
-       Rect scissor_rect = fb_rect.intersect(self.scissor);
-       VkRect2D scissor = { };
-       scissor.offset.x = scissor_rect.left;
-       scissor.offset.y = scissor_rect.bottom;
-       scissor.extent.width = scissor_rect.width;
-       scissor.extent.height = scissor_rect.height;
-       vk.CmdSetScissor(command_buffer, 0, 1, &scissor);
+
+       unapplied = 0;
 }
 
 } // namespace GL
index 82f664c1c9b881ae7ffafd083111317cde9f6e29..d482081bb400d4bc987c71048366eee26585536d 100644 (file)
@@ -17,6 +17,7 @@ class VulkanPipelineState: public NonCopyable
 protected:
        Device &device;
        mutable unsigned changes = 0;
+       mutable unsigned unapplied = 0;
        mutable VkPipeline handle;
        mutable std::vector<VkDescriptorSet> descriptor_set_handles;
 
@@ -33,7 +34,7 @@ protected:
        VkDescriptorSetLayout get_descriptor_set_layout(unsigned) const;
        unsigned fill_descriptor_writes(unsigned, std::vector<char> &) const;
 
-       void apply(VkCommandBuffer, unsigned, bool) const;
+       void apply(VkCommandBuffer, const VulkanPipelineState *, unsigned, bool) const;
 };
 
 using PipelineStateBackend = VulkanPipelineState;