]> git.tdb.fi Git - libs/gl.git/blobdiff - source/backends/vulkan/pipelinestate_backend.cpp
Store simpler states by value in PipelineState
[libs/gl.git] / source / backends / vulkan / pipelinestate_backend.cpp
index a1a03d3d8fcb31d2646027036bb4936a237d4194..efa08a8634ecf15b755b459121f629a2682da529 100644 (file)
@@ -49,7 +49,8 @@ void VulkanPipelineState::update() const
                for(const PipelineState::BoundUniformBlock &u: self.uniform_blocks)
                        if(u.changed || changed_sets==~0U)
                        {
-                               u.used = self.shprog->uses_uniform_block_binding(u.binding);
+                               if(u.block)
+                                       u.used = self.shprog->uses_uniform_block_binding(u.binding);
                                if(u.binding>=0)
                                        changed_sets |= 1<<(u.binding>>20);
                                u.changed = false;
@@ -57,7 +58,8 @@ void VulkanPipelineState::update() const
                for(const PipelineState::BoundTexture &t: self.textures)
                        if(t.changed || changed_sets==~0U)
                        {
-                               t.used = self.shprog->uses_texture_binding(t.binding);
+                               if(t.texture && t.sampler)
+                                       t.used = self.shprog->uses_texture_binding(t.binding);
                                changed_sets |= 1<<(t.binding>>20);
                                if(t.texture && t.level>=0)
                                        t.texture->refresh_mip_views();
@@ -92,31 +94,28 @@ uint64_t VulkanPipelineState::compute_hash() const
 
        result = hash_round<64>(result, format.get_samples());
 
-       if(const DepthTest *depth_test = self.depth_test)
-               if(depth_test->enabled)
-               {
-                       result = hash_round<64>(result, depth_test->compare);
-                       result = hash_update<64>(result, depth_test->write);
-               }
+       if(self.depth_test.enabled)
+       {
+               result = hash_round<64>(result, self.depth_test.compare);
+               result = hash_update<64>(result, self.depth_test.write);
+       }
 
-       if(const StencilTest *stencil_test = self.stencil_test)
-               if(stencil_test->enabled)
-               {
-                       result = hash_round<64>(result, stencil_test->compare);
-                       result = hash_round<64>(result, stencil_test->stencil_fail_op);
-                       result = hash_round<64>(result, stencil_test->depth_fail_op);
-                       result = hash_round<64>(result, stencil_test->depth_pass_op);
-                       result = hash_update<64>(result, stencil_test->reference);
-               }
+       if(self.stencil_test.enabled)
+       {
+               result = hash_round<64>(result, self.stencil_test.compare);
+               result = hash_round<64>(result, self.stencil_test.stencil_fail_op);
+               result = hash_round<64>(result, self.stencil_test.depth_fail_op);
+               result = hash_round<64>(result, self.stencil_test.depth_pass_op);
+               result = hash_update<64>(result, self.stencil_test.reference);
+       }
 
-       if(const Blend *blend = self.blend)
-               if(blend->enabled)
-               {
-                       result = hash_round<64>(result, blend->equation);
-                       result = hash_round<64>(result, blend->src_factor);
-                       result = hash_round<64>(result, blend->dst_factor);
-                       result = hash_round<64>(result, blend->write_mask);
-               }
+       if(self.blend.enabled)
+       {
+               result = hash_round<64>(result, self.blend.equation);
+               result = hash_round<64>(result, self.blend.src_factor);
+               result = hash_round<64>(result, self.blend.dst_factor);
+               result = hash_round<64>(result, self.blend.write_mask);
+       }
 
        for(FrameAttachment a: format)
                result = hash_update<64>(result, a);
@@ -190,44 +189,31 @@ void VulkanPipelineState::fill_creation_info(vector<char> &buffer) const
        multisample_info->alphaToOneEnable = VK_FALSE;
 
        depth_stencil_info->sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
-       if(const DepthTest *depth_test = self.depth_test)
+       depth_stencil_info->depthTestEnable = self.depth_test.enabled;
+       depth_stencil_info->depthWriteEnable = self.depth_test.write;
+       depth_stencil_info->depthCompareOp = static_cast<VkCompareOp>(get_vulkan_predicate(self.depth_test.compare));
+       depth_stencil_info->depthBoundsTestEnable = VK_FALSE;
+
+       depth_stencil_info->stencilTestEnable = self.stencil_test.enabled;
+       depth_stencil_info->front.failOp = static_cast<VkStencilOp>(get_vulkan_stencil_op(self.stencil_test.stencil_fail_op));
+       depth_stencil_info->front.passOp = static_cast<VkStencilOp>(get_vulkan_stencil_op(self.stencil_test.depth_pass_op));
+       depth_stencil_info->front.depthFailOp = static_cast<VkStencilOp>(get_vulkan_stencil_op(self.stencil_test.depth_fail_op));
+       depth_stencil_info->front.compareOp = static_cast<VkCompareOp>(get_vulkan_predicate(self.stencil_test.compare));
+       depth_stencil_info->front.compareMask = 0xFFFFFFFFU;
+       depth_stencil_info->front.writeMask = 0xFFFFFFFFU;
+       depth_stencil_info->front.reference = self.stencil_test.reference;
+       depth_stencil_info->back = depth_stencil_info->front;
+
+       for(unsigned i=0; i<n_color_attachments; ++i)
        {
-               depth_stencil_info->depthTestEnable = depth_test->enabled;
-               depth_stencil_info->depthWriteEnable = depth_test->write;
-               depth_stencil_info->depthCompareOp = static_cast<VkCompareOp>(get_vulkan_predicate(depth_test->compare));
-               depth_stencil_info->depthBoundsTestEnable = VK_FALSE;
-       }
-       if(const StencilTest *stencil_test = self.stencil_test)
-       {
-               depth_stencil_info->stencilTestEnable = stencil_test->enabled;
-               depth_stencil_info->front.failOp = static_cast<VkStencilOp>(get_vulkan_stencil_op(stencil_test->stencil_fail_op));
-               depth_stencil_info->front.passOp = static_cast<VkStencilOp>(get_vulkan_stencil_op(stencil_test->depth_pass_op));
-               depth_stencil_info->front.depthFailOp = static_cast<VkStencilOp>(get_vulkan_stencil_op(stencil_test->depth_fail_op));
-               depth_stencil_info->front.compareOp = static_cast<VkCompareOp>(get_vulkan_predicate(stencil_test->compare));
-               depth_stencil_info->front.compareMask = 0xFFFFFFFFU;
-               depth_stencil_info->front.writeMask = 0xFFFFFFFFU;
-               depth_stencil_info->front.reference = stencil_test->reference;
-               depth_stencil_info->back = depth_stencil_info->front;
-       }
-
-       if(const Blend *blend = self.blend)
-       {
-               for(unsigned i=0; i<n_color_attachments; ++i)
-               {
-                       blend_attachments[i].blendEnable = blend->enabled;
-                       blend_attachments[i].srcColorBlendFactor = static_cast<VkBlendFactor>(get_vulkan_blend_factor(blend->src_factor));
-                       blend_attachments[i].dstColorBlendFactor = static_cast<VkBlendFactor>(get_vulkan_blend_factor(blend->dst_factor));
-                       blend_attachments[i].colorBlendOp = static_cast<VkBlendOp>(get_vulkan_blend_equation(blend->equation));
-                       blend_attachments[i].srcAlphaBlendFactor = blend_attachments[i].srcColorBlendFactor;
-                       blend_attachments[i].dstAlphaBlendFactor = blend_attachments[i].dstColorBlendFactor;
-                       blend_attachments[i].alphaBlendOp = blend_attachments[i].colorBlendOp;
-                       blend_attachments[i].colorWriteMask = get_vulkan_color_mask(blend->write_mask);
-               }
-       }
-       else
-       {
-               for(unsigned i=0; i<n_color_attachments; ++i)
-                       blend_attachments[i].colorWriteMask = VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT;
+               blend_attachments[i].blendEnable = self.blend.enabled;
+               blend_attachments[i].srcColorBlendFactor = static_cast<VkBlendFactor>(get_vulkan_blend_factor(self.blend.src_factor));
+               blend_attachments[i].dstColorBlendFactor = static_cast<VkBlendFactor>(get_vulkan_blend_factor(self.blend.dst_factor));
+               blend_attachments[i].colorBlendOp = static_cast<VkBlendOp>(get_vulkan_blend_equation(self.blend.equation));
+               blend_attachments[i].srcAlphaBlendFactor = blend_attachments[i].srcColorBlendFactor;
+               blend_attachments[i].dstAlphaBlendFactor = blend_attachments[i].dstColorBlendFactor;
+               blend_attachments[i].alphaBlendOp = blend_attachments[i].colorBlendOp;
+               blend_attachments[i].colorWriteMask = get_vulkan_color_mask(self.blend.write_mask);
        }
 
        blend_info->sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
@@ -275,13 +261,14 @@ uint64_t VulkanPipelineState::compute_descriptor_set_hash(unsigned index) const
                {
                        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));
                }
        for(const PipelineState::BoundTexture &t: self.textures)
                if(t.used && (t.binding>>20)==index)
                {
                        result = hash_update<64>(result, t.binding);
-                       result = hash_update<64>(result, reinterpret_cast<uintptr_t>(t.texture));
-                       result = hash_update<64>(result, reinterpret_cast<uintptr_t>(t.sampler));
+                       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);
                }
 
@@ -319,14 +306,14 @@ unsigned VulkanPipelineState::fill_descriptor_writes(unsigned index, vector<char
        for(const PipelineState::BoundUniformBlock &u: self.uniform_blocks)
                if(u.used && u.binding>=0 && static_cast<unsigned>(u.binding>>20)==index)
                {
-                       buffer_ptr->buffer = handle_cast<::VkBuffer>(u.block->get_buffer()->handle);
+                       buffer_ptr->buffer = handle_cast<::VkBuffer>(u.buffer->handle);
                        buffer_ptr->offset = u.block->get_offset();
                        buffer_ptr->range = u.block->get_data_size();
 
                        write_ptr->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
                        write_ptr->dstBinding = u.binding&0xFFFFF;
                        write_ptr->descriptorCount = 1;
-                       write_ptr->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+                       write_ptr->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
                        write_ptr->pBufferInfo = buffer_ptr;
 
                        ++buffer_ptr;
@@ -356,7 +343,7 @@ unsigned VulkanPipelineState::fill_descriptor_writes(unsigned index, vector<char
        return n_writes;
 }
 
-void VulkanPipelineState::apply(VkCommandBuffer command_buffer, bool negative_viewport) const
+void VulkanPipelineState::apply(VkCommandBuffer command_buffer, unsigned frame, bool negative_viewport) const
 {
        const PipelineState &self = *static_cast<const PipelineState *>(this);
        const VulkanFunctions &vk = device.get_functions();
@@ -381,23 +368,30 @@ void VulkanPipelineState::apply(VkCommandBuffer command_buffer, bool negative_vi
        }
 
        if(!descriptor_set_handles.empty())
-               vk.CmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, self.shprog->layout_handle, 0, descriptor_set_handles.size(), descriptor_set_handles.data(), 0, 0);
-
-       VkViewport viewport = { };
-       if(self.viewport)
-       {
-               viewport.x = self.viewport->left;
-               viewport.y = self.viewport->bottom;
-               viewport.width = self.viewport->width;
-               viewport.height = self.viewport->height;
-       }
-       else
        {
-               viewport.x = 0;
-               viewport.y = 0;
-               viewport.width = self.framebuffer->get_width();
-               viewport.height = self.framebuffer->get_height();
+               vector<uint32_t> dynamic_offsets;
+               dynamic_offsets.reserve(self.uniform_blocks.size());
+               for(const PipelineState::BoundUniformBlock &u: self.uniform_blocks)
+                       if(u.used && u.binding>=0)
+                       {
+                               if(u.buffer->get_usage()==STREAMING)
+                                       dynamic_offsets.push_back(frame*u.buffer->get_size());
+                               else
+                                       dynamic_offsets.push_back(0);
+                       }
+
+               vk.CmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, self.shprog->layout_handle,
+                       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)
        {
                viewport.y += viewport.height;
@@ -407,21 +401,12 @@ void VulkanPipelineState::apply(VkCommandBuffer command_buffer, bool negative_vi
        viewport.maxDepth = 1.0f;
        vk.CmdSetViewport(command_buffer, 0, 1, &viewport);
 
+       Rect scissor_rect = fb_rect.intersect(self.scissor);
        VkRect2D scissor = { };
-       if(self.scissor)
-       {
-               scissor.offset.x = self.scissor->left;
-               scissor.offset.y = self.scissor->bottom;
-               scissor.extent.width = self.scissor->width;
-               scissor.extent.height = self.scissor->height;
-       }
-       else
-       {
-               scissor.offset.x = 0;
-               scissor.offset.y = 0;
-               scissor.extent.width = self.framebuffer->get_width();
-               scissor.extent.height = self.framebuffer->get_height();
-       }
+       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);
 }