renderer_vulkan: Add scissor and viewport to dynamic pipeline state (#7114)
Adds the current viewport and scissor to the dynamic pipeline state to reduce redundant viewport/scissor assignments in the command buffer. This greatly reduces the amount of API calls to `vkCmdSetViewport` and `vkCmdSetScissor` by only emitting the API call when the state actually changes.
This commit is contained in:
		@@ -89,6 +89,9 @@ struct DynamicState {
 | 
			
		||||
    u8 stencil_compare_mask;
 | 
			
		||||
    u8 stencil_write_mask;
 | 
			
		||||
 | 
			
		||||
    Common::Rectangle<u32> scissor;
 | 
			
		||||
    Common::Rectangle<s32> viewport;
 | 
			
		||||
 | 
			
		||||
    bool operator==(const DynamicState& other) const noexcept {
 | 
			
		||||
        return std::memcmp(this, &other, sizeof(DynamicState)) == 0;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -206,6 +206,32 @@ bool PipelineCache::BindPipeline(const PipelineInfo& info, bool wait_built) {
 | 
			
		||||
                      current_depth_stencil = current_info.depth_stencil,
 | 
			
		||||
                      rasterization = info.rasterization,
 | 
			
		||||
                      depth_stencil = info.depth_stencil](vk::CommandBuffer cmdbuf) {
 | 
			
		||||
        if (dynamic.viewport != current_dynamic.viewport || is_dirty) {
 | 
			
		||||
            const vk::Viewport vk_viewport = {
 | 
			
		||||
                .x = static_cast<f32>(dynamic.viewport.left),
 | 
			
		||||
                .y = static_cast<f32>(dynamic.viewport.top),
 | 
			
		||||
                .width = static_cast<f32>(dynamic.viewport.GetWidth()),
 | 
			
		||||
                .height = static_cast<f32>(dynamic.viewport.GetHeight()),
 | 
			
		||||
                .minDepth = 0.f,
 | 
			
		||||
                .maxDepth = 1.f,
 | 
			
		||||
            };
 | 
			
		||||
            cmdbuf.setViewport(0, vk_viewport);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (dynamic.scissor != current_dynamic.scissor || is_dirty) {
 | 
			
		||||
            const vk::Rect2D scissor = {
 | 
			
		||||
                .offset{
 | 
			
		||||
                    .x = static_cast<s32>(dynamic.scissor.left),
 | 
			
		||||
                    .y = static_cast<s32>(dynamic.scissor.bottom),
 | 
			
		||||
                },
 | 
			
		||||
                .extent{
 | 
			
		||||
                    .width = dynamic.scissor.GetWidth(),
 | 
			
		||||
                    .height = dynamic.scissor.GetHeight(),
 | 
			
		||||
                },
 | 
			
		||||
            };
 | 
			
		||||
            cmdbuf.setScissor(0, scissor);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (dynamic.stencil_compare_mask != current_dynamic.stencil_compare_mask || is_dirty) {
 | 
			
		||||
            cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eFrontAndBack,
 | 
			
		||||
                                         dynamic.stencil_compare_mask);
 | 
			
		||||
 
 | 
			
		||||
@@ -512,30 +512,13 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
 | 
			
		||||
 | 
			
		||||
    // Configure viewport and scissor
 | 
			
		||||
    const auto viewport = fb_helper.Viewport();
 | 
			
		||||
    scheduler.Record([viewport, draw_rect](vk::CommandBuffer cmdbuf) {
 | 
			
		||||
        const vk::Viewport vk_viewport = {
 | 
			
		||||
            .x = static_cast<f32>(viewport.x),
 | 
			
		||||
            .y = static_cast<f32>(viewport.y),
 | 
			
		||||
            .width = static_cast<f32>(viewport.width),
 | 
			
		||||
            .height = static_cast<f32>(viewport.height),
 | 
			
		||||
            .minDepth = 0.f,
 | 
			
		||||
            .maxDepth = 1.f,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        const vk::Rect2D scissor = {
 | 
			
		||||
            .offset{
 | 
			
		||||
                .x = static_cast<s32>(draw_rect.left),
 | 
			
		||||
                .y = static_cast<s32>(draw_rect.bottom),
 | 
			
		||||
            },
 | 
			
		||||
            .extent{
 | 
			
		||||
                .width = draw_rect.GetWidth(),
 | 
			
		||||
                .height = draw_rect.GetHeight(),
 | 
			
		||||
            },
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        cmdbuf.setViewport(0, vk_viewport);
 | 
			
		||||
        cmdbuf.setScissor(0, scissor);
 | 
			
		||||
    });
 | 
			
		||||
    pipeline_info.dynamic.viewport = Common::Rectangle<s32>{
 | 
			
		||||
        viewport.x,
 | 
			
		||||
        viewport.y,
 | 
			
		||||
        viewport.x + viewport.width,
 | 
			
		||||
        viewport.y + viewport.height,
 | 
			
		||||
    };
 | 
			
		||||
    pipeline_info.dynamic.scissor = draw_rect;
 | 
			
		||||
 | 
			
		||||
    // Draw the vertex batch
 | 
			
		||||
    bool succeeded = true;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user