From 5cd49386989d8b01e7c2033e19221b384e1564e7 Mon Sep 17 00:00:00 2001 From: Krzysztof Jakubowski Date: Wed, 8 Jan 2025 20:34:06 +0100 Subject: [PATCH] Canvas2D: added scissor rect support --- include/fwk/gfx/canvas_2d.h | 10 ++++++++-- include/fwk/gfx/drawing.h | 4 ++-- src/gfx/canvas_2d.cpp | 21 ++++++++++++++++++++- src/gfx/drawing.cpp | 12 +++++++++++- 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/include/fwk/gfx/canvas_2d.h b/include/fwk/gfx/canvas_2d.h index 2b686baf..3a3abdce 100644 --- a/include/fwk/gfx/canvas_2d.h +++ b/include/fwk/gfx/canvas_2d.h @@ -39,6 +39,9 @@ class Canvas2D { void setMaterial(const SimpleMaterial &); SimpleMaterial getMaterial() const; + void setScissorRect(Maybe); + Maybe getScissorRect() const; + void pushViewMatrix(); void popViewMatrix(); void mulViewMatrix(const Matrix4 &); @@ -79,12 +82,14 @@ class Canvas2D { private: struct Group { - Group(int first_index, int pipeline_index) - : first_index(first_index), num_indices(0), pipeline_index(pipeline_index) {} + Group(int first_index, int pipeline_index, int scissor_rect_index) + : first_index(first_index), num_indices(0), pipeline_index(pipeline_index), + scissor_rect_index(scissor_rect_index) {} PVImageView texture; int first_index, num_indices; int pipeline_index; + int scissor_rect_index; }; int getPipeline(const SimplePipelineSetup &); @@ -99,6 +104,7 @@ class Canvas2D { vector m_pipelines; vector m_group_matrices; vector m_groups; + vector m_scissor_rects; PodVector m_positions; PodVector m_tex_coords; diff --git a/include/fwk/gfx/drawing.h b/include/fwk/gfx/drawing.h index 578d3bef..7c7fc762 100644 --- a/include/fwk/gfx/drawing.h +++ b/include/fwk/gfx/drawing.h @@ -61,20 +61,20 @@ struct SimpleDrawCall { // Vertex data: // indices, tex_coords, normals & colors are optional - VBufferSpan indices; VBufferSpan vertices; VBufferSpan tex_coords; VBufferSpan colors; // Instance data: - struct Instance { PVImageView texture; int pipeline_index; int first_index, num_vertices; + int scissor_rect_index; }; VBufferSpan instance_matrices; + vector scissor_rects; vector instances; vector pipelines; }; diff --git a/src/gfx/canvas_2d.cpp b/src/gfx/canvas_2d.cpp index d2455014..b95b33f1 100644 --- a/src/gfx/canvas_2d.cpp +++ b/src/gfx/canvas_2d.cpp @@ -27,7 +27,7 @@ namespace fwk { Canvas2D::Canvas2D(const IRect &viewport, Orient2D orient) : m_matrix_stack(projectionMatrix2D(viewport, orient), viewMatrix2D(viewport, float2(0, 0))), m_viewport(viewport) { - m_groups.emplace_back(0, getPipeline({})); + m_groups.emplace_back(0, getPipeline({}), -1); m_group_matrices.emplace_back(m_matrix_stack.fullMatrix()); } @@ -81,10 +81,12 @@ Ex Canvas2D::genDrawCall(ShaderCompiler &compiler, VulkanDevice instance.pipeline_index = group.pipeline_index + (skip_first_pipeline ? -1 : 0); instance.num_vertices = group.num_indices; instance.first_index = group.first_index; + instance.scissor_rect_index = group.scissor_rect_index; } auto setups = subSpan(m_pipelines, skip_first_pipeline ? 1 : 0); dc.pipelines = EX_PASS(SimpleDrawCall::makePipelines(compiler, device, render_pass, setups)); + dc.scissor_rects = m_scissor_rects; return dc; } @@ -160,6 +162,23 @@ SimpleMaterial Canvas2D::getMaterial() const { return SimpleMaterial{group.texture, IColor(m_cur_color), pipe.flags, pipe.blending_mode}; } +void Canvas2D::setScissorRect(Maybe rect) { + if(getScissorRect() == rect) + return; + splitGroup(); + int scissor_index = -1; + if(rect) { + scissor_index = m_scissor_rects.size(); + m_scissor_rects.emplace_back(*rect); + } + m_groups.back().scissor_rect_index = scissor_index; +} + +Maybe Canvas2D::getScissorRect() const { + int index = m_groups.back().scissor_rect_index; + return index == -1 ? Maybe() : m_scissor_rects[index]; +} + void Canvas2D::pushViewMatrix() { m_matrix_stack.pushViewMatrix(); if(!splitGroup()) diff --git a/src/gfx/drawing.cpp b/src/gfx/drawing.cpp index 4ceac2c6..f47dcba6 100644 --- a/src/gfx/drawing.cpp +++ b/src/gfx/drawing.cpp @@ -127,7 +127,9 @@ void SimpleDrawCall::render(VulkanDevice &device) { cmds.bindIndices(indices); uint instance_id = 0; - for(auto &instance : instances) { + for(int i = 0; i < instances.size(); i++) { + auto &instance = instances[i]; + if(instance.pipeline_index != prev_pipeline_idx) { cmds.bind(pipelines[instance.pipeline_index]); prev_pipeline_idx = instance.pipeline_index; @@ -137,12 +139,20 @@ void SimpleDrawCall::render(VulkanDevice &device) { cmds.bindDS(1).set(0, {{sampler, instance.texture}}); prev_tex = instance.texture; } + if(i == 0 || instance.scissor_rect_index != instances[i - 1].scissor_rect_index) { + Maybe scissor_rect; + if(instance.scissor_rect_index != -1) + scissor_rect = scissor_rects[instance.scissor_rect_index]; + cmds.setScissor(scissor_rect); + } if(indices) cmds.drawIndexed(instance.num_vertices, 1, instance.first_index, instance_id++); else cmds.draw(instance.num_vertices, 1, instance.first_index, instance_id++); } + + cmds.setScissor(none); } /*