| /* | |
| * Copyright 2022 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "src/gpu/graphite/render/CoverBoundsRenderStep.h" | |
| #include "src/base/SkVx.h" | |
| #include "src/gpu/graphite/DrawParams.h" | |
| #include "src/gpu/graphite/DrawWriter.h" | |
| #include "src/gpu/graphite/render/CommonDepthStencilSettings.h" | |
| namespace skgpu::graphite { | |
| CoverBoundsRenderStep::CoverBoundsRenderStep(bool inverseFill) | |
| : RenderStep("CoverBoundsRenderStep", | |
| inverseFill ? "inverse" : "regular", | |
| Flags::kPerformsShading, | |
| /*uniforms=*/{}, | |
| PrimitiveType::kTriangleStrip, | |
| inverseFill ? kInverseCoverPass : kRegularCoverPass, | |
| /*vertexAttrs=*/{{"position", | |
| VertexAttribType::kFloat4, | |
| SkSLType::kFloat4}}, | |
| /*instanceAttrs=*/{{"bounds", VertexAttribType::kFloat4, SkSLType::kFloat4}, | |
| {"depth", VertexAttribType::kFloat, SkSLType::kFloat}, | |
| {"ssboIndex", VertexAttribType::kInt, SkSLType::kInt}, | |
| {"mat0", VertexAttribType::kFloat3, SkSLType::kFloat3}, | |
| {"mat1", VertexAttribType::kFloat3, SkSLType::kFloat3}, | |
| {"mat2", VertexAttribType::kFloat3, SkSLType::kFloat3}}) | |
| , fInverseFill(inverseFill) {} | |
| CoverBoundsRenderStep::~CoverBoundsRenderStep() {} | |
| std::string CoverBoundsRenderStep::vertexSkSL() const { | |
| // Returns the body of a vertex function, which must define a float4 devPosition variable and | |
| // must write to an already-defined float2 stepLocalCoords variable. | |
| return "float4 devPosition = cover_bounds_vertex_fn(" | |
| "float2(sk_VertexID / 2, sk_VertexID % 2), " | |
| "bounds, depth, float3x3(mat0, mat1, mat2), " | |
| "stepLocalCoords);\n"; | |
| } | |
| void CoverBoundsRenderStep::writeVertices(DrawWriter* writer, | |
| const DrawParams& params, | |
| int ssboIndex) const { | |
| // Each instance is 4 vertices, forming 2 triangles from a single triangle strip, so no indices | |
| // are needed. sk_VertexID is used to place vertex positions, so no vertex buffer is needed. | |
| DrawWriter::Instances instances{*writer, {}, {}, 4}; | |
| skvx::float4 bounds; | |
| const SkM44* m; | |
| if (fInverseFill) { | |
| // Normally all bounding boxes are sorted such that l<r and t<b. We upload an inverted | |
| // rectangle [r,b,l,t] when it's an inverse fill to encode that the bounds are already in | |
| // device space and then use the inverse of the transform to compute local coordinates. | |
| bounds = skvx::shuffle</*R*/2, /*B*/3, /*L*/0, /*T*/1>( | |
| skvx::cast<float>(skvx::int4::Load(¶ms.clip().scissor()))); | |
| m = ¶ms.transform().inverse(); | |
| } else { | |
| bounds = params.geometry().bounds().ltrb(); | |
| m = ¶ms.transform().matrix(); | |
| } | |
| // Since the local coords always have Z=0, we can discard the 3rd row and column of the matrix. | |
| instances.append(1) << bounds << params.order().depthAsFloat() << ssboIndex | |
| << m->rc(0,0) << m->rc(1,0) << m->rc(3,0) | |
| << m->rc(0,1) << m->rc(1,1) << m->rc(3,1) | |
| << m->rc(0,3) << m->rc(1,3) << m->rc(3,3); | |
| } | |
| void CoverBoundsRenderStep::writeUniformsAndTextures(const DrawParams&, | |
| PipelineDataGatherer*) const { | |
| // All data is uploaded as instance attributes, so no uniforms are needed. | |
| } | |
| } // namespace skgpu::graphite |