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:
parent
1cf64ffaef
commit
3218af38d0
3 changed files with 36 additions and 24 deletions
|
@ -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,
|
||||
pipeline_info.dynamic.viewport = Common::Rectangle<s32>{
|
||||
viewport.x,
|
||||
viewport.y,
|
||||
viewport.x + viewport.width,
|
||||
viewport.y + viewport.height,
|
||||
};
|
||||
|
||||
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.scissor = draw_rect;
|
||||
|
||||
// Draw the vertex batch
|
||||
bool succeeded = true;
|
||||
|
|
Loading…
Reference in a new issue