/* * 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 "include/core/SkM44.h" #include "src/base/SkEnumBitMask.h" #include "src/base/SkVx.h" #include "src/core/SkSLTypeShared.h" #include "src/gpu/BufferWriter.h" #include "src/gpu/graphite/Attribute.h" #include "src/gpu/graphite/DrawOrder.h" #include "src/gpu/graphite/DrawParams.h" #include "src/gpu/graphite/DrawTypes.h" #include "src/gpu/graphite/DrawWriter.h" #include "src/gpu/graphite/geom/Geometry.h" #include "src/gpu/graphite/geom/Rect.h" #include "src/gpu/graphite/geom/Shape.h" #include "src/gpu/graphite/geom/Transform_graphite.h" #include namespace skgpu::graphite { CoverBoundsRenderStep::CoverBoundsRenderStep(const char* tag, DepthStencilSettings dsSettings) : RenderStep("CoverBoundsRenderStep", tag, Flags::kPerformsShading, /*uniforms=*/{}, PrimitiveType::kTriangleStrip, dsSettings, /*vertexAttrs=*/ {}, /*instanceAttrs=*/{{"bounds", VertexAttribType::kFloat4, SkSLType::kFloat4}, {"depth", VertexAttribType::kFloat, SkSLType::kFloat}, {"ssboIndices", VertexAttribType::kUInt2, SkSLType::kUInt2}, {"mat0", VertexAttribType::kFloat3, SkSLType::kFloat3}, {"mat1", VertexAttribType::kFloat3, SkSLType::kFloat3}, {"mat2", VertexAttribType::kFloat3, SkSLType::kFloat3}}) {} 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, skvx::uint2 ssboIndices) 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; if (params.geometry().isShape() && params.geometry().shape().inverted()) { // Normally all bounding boxes are sorted such that l( skvx::cast(skvx::int4::Load(¶ms.clip().scissor()))); } else { bounds = params.geometry().bounds().ltrb(); } // Since the local coords always have Z=0, we can discard the 3rd row and column of the matrix. const SkM44& m = params.transform().matrix(); instances.append(1) << bounds << params.order().depthAsFloat() << ssboIndices << 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