xref: /aosp_15_r20/external/skia/src/gpu/graphite/vk/VulkanGraphicsPipeline.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2023 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanGraphicsPipeline.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ShaderErrorHandler.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/TextureInfo.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkSLTypeShared.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTraceEvent.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/SkSLToBackend.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Attribute.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ContextUtils.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/GraphicsPipelineDesc.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Log.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RenderPassDesc.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RendererProvider.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ResourceTypes.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RuntimeEffectDictionary.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ShaderInfo.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanCaps.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanGraphicsPipeline.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanRenderPass.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanResourceProvider.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanSharedContext.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/vk/VulkanUtilsPriv.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLProgramKind.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLProgramSettings.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLProgram.h"
33*c8dee2aaSAndroid Build Coastguard Worker 
34*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite {
35*c8dee2aaSAndroid Build Coastguard Worker 
attrib_type_to_vkformat(VertexAttribType type)36*c8dee2aaSAndroid Build Coastguard Worker static inline VkFormat attrib_type_to_vkformat(VertexAttribType type) {
37*c8dee2aaSAndroid Build Coastguard Worker     switch (type) {
38*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kFloat:
39*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R32_SFLOAT;
40*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kFloat2:
41*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R32G32_SFLOAT;
42*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kFloat3:
43*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R32G32B32_SFLOAT;
44*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kFloat4:
45*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R32G32B32A32_SFLOAT;
46*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kHalf:
47*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R16_SFLOAT;
48*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kHalf2:
49*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R16G16_SFLOAT;
50*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kHalf4:
51*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R16G16B16A16_SFLOAT;
52*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kInt2:
53*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R32G32_SINT;
54*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kInt3:
55*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R32G32B32_SINT;
56*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kInt4:
57*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R32G32B32A32_SINT;
58*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUInt2:
59*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R32G32_UINT;
60*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kByte:
61*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R8_SINT;
62*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kByte2:
63*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R8G8_SINT;
64*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kByte4:
65*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R8G8B8A8_SINT;
66*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUByte:
67*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R8_UINT;
68*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUByte2:
69*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R8G8_UINT;
70*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUByte4:
71*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R8G8B8A8_UINT;
72*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUByte_norm:
73*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R8_UNORM;
74*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUByte4_norm:
75*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R8G8B8A8_UNORM;
76*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kShort2:
77*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R16G16_SINT;
78*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kShort4:
79*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R16G16B16A16_SINT;
80*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUShort2:
81*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R16G16_UINT;
82*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUShort2_norm:
83*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R16G16_UNORM;
84*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kInt:
85*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R32_SINT;
86*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUInt:
87*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R32_UINT;
88*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUShort_norm:
89*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R16_UNORM;
90*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUShort4_norm:
91*c8dee2aaSAndroid Build Coastguard Worker             return VK_FORMAT_R16G16B16A16_UNORM;
92*c8dee2aaSAndroid Build Coastguard Worker     }
93*c8dee2aaSAndroid Build Coastguard Worker     SK_ABORT("Unknown vertex attrib type");
94*c8dee2aaSAndroid Build Coastguard Worker }
95*c8dee2aaSAndroid Build Coastguard Worker 
setup_vertex_input_state(const SkSpan<const Attribute> & vertexAttrs,const SkSpan<const Attribute> & instanceAttrs,VkPipelineVertexInputStateCreateInfo * vertexInputInfo,skia_private::STArray<2,VkVertexInputBindingDescription,true> * bindingDescs,skia_private::STArray<16,VkVertexInputAttributeDescription> * attributeDescs)96*c8dee2aaSAndroid Build Coastguard Worker static void setup_vertex_input_state(
97*c8dee2aaSAndroid Build Coastguard Worker         const SkSpan<const Attribute>& vertexAttrs,
98*c8dee2aaSAndroid Build Coastguard Worker         const SkSpan<const Attribute>& instanceAttrs,
99*c8dee2aaSAndroid Build Coastguard Worker         VkPipelineVertexInputStateCreateInfo* vertexInputInfo,
100*c8dee2aaSAndroid Build Coastguard Worker         skia_private::STArray<2, VkVertexInputBindingDescription, true>* bindingDescs,
101*c8dee2aaSAndroid Build Coastguard Worker         skia_private::STArray<16, VkVertexInputAttributeDescription>* attributeDescs) {
102*c8dee2aaSAndroid Build Coastguard Worker     // Setup attribute & binding descriptions
103*c8dee2aaSAndroid Build Coastguard Worker     int attribIndex = 0;
104*c8dee2aaSAndroid Build Coastguard Worker     size_t vertexAttributeOffset = 0;
105*c8dee2aaSAndroid Build Coastguard Worker     for (auto attrib : vertexAttrs) {
106*c8dee2aaSAndroid Build Coastguard Worker         VkVertexInputAttributeDescription vkAttrib;
107*c8dee2aaSAndroid Build Coastguard Worker         vkAttrib.location = attribIndex++;
108*c8dee2aaSAndroid Build Coastguard Worker         vkAttrib.binding = VulkanGraphicsPipeline::kVertexBufferIndex;
109*c8dee2aaSAndroid Build Coastguard Worker         vkAttrib.format = attrib_type_to_vkformat(attrib.cpuType());
110*c8dee2aaSAndroid Build Coastguard Worker         vkAttrib.offset = vertexAttributeOffset;
111*c8dee2aaSAndroid Build Coastguard Worker         vertexAttributeOffset += attrib.sizeAlign4();
112*c8dee2aaSAndroid Build Coastguard Worker         attributeDescs->push_back(vkAttrib);
113*c8dee2aaSAndroid Build Coastguard Worker     }
114*c8dee2aaSAndroid Build Coastguard Worker 
115*c8dee2aaSAndroid Build Coastguard Worker     size_t instanceAttributeOffset = 0;
116*c8dee2aaSAndroid Build Coastguard Worker     for (auto attrib : instanceAttrs) {
117*c8dee2aaSAndroid Build Coastguard Worker         VkVertexInputAttributeDescription vkAttrib;
118*c8dee2aaSAndroid Build Coastguard Worker         vkAttrib.location = attribIndex++;
119*c8dee2aaSAndroid Build Coastguard Worker         vkAttrib.binding = VulkanGraphicsPipeline::kInstanceBufferIndex;
120*c8dee2aaSAndroid Build Coastguard Worker         vkAttrib.format = attrib_type_to_vkformat(attrib.cpuType());
121*c8dee2aaSAndroid Build Coastguard Worker         vkAttrib.offset = instanceAttributeOffset;
122*c8dee2aaSAndroid Build Coastguard Worker         instanceAttributeOffset += attrib.sizeAlign4();
123*c8dee2aaSAndroid Build Coastguard Worker         attributeDescs->push_back(vkAttrib);
124*c8dee2aaSAndroid Build Coastguard Worker     }
125*c8dee2aaSAndroid Build Coastguard Worker 
126*c8dee2aaSAndroid Build Coastguard Worker     if (bindingDescs && !vertexAttrs.empty()) {
127*c8dee2aaSAndroid Build Coastguard Worker         bindingDescs->push_back() = {
128*c8dee2aaSAndroid Build Coastguard Worker                 VulkanGraphicsPipeline::kVertexBufferIndex,
129*c8dee2aaSAndroid Build Coastguard Worker                 (uint32_t) vertexAttributeOffset,
130*c8dee2aaSAndroid Build Coastguard Worker                 VK_VERTEX_INPUT_RATE_VERTEX
131*c8dee2aaSAndroid Build Coastguard Worker         };
132*c8dee2aaSAndroid Build Coastguard Worker     }
133*c8dee2aaSAndroid Build Coastguard Worker     if (bindingDescs && !instanceAttrs.empty()) {
134*c8dee2aaSAndroid Build Coastguard Worker         bindingDescs->push_back() = {
135*c8dee2aaSAndroid Build Coastguard Worker                 VulkanGraphicsPipeline::kInstanceBufferIndex,
136*c8dee2aaSAndroid Build Coastguard Worker                 (uint32_t) instanceAttributeOffset,
137*c8dee2aaSAndroid Build Coastguard Worker                 VK_VERTEX_INPUT_RATE_INSTANCE
138*c8dee2aaSAndroid Build Coastguard Worker         };
139*c8dee2aaSAndroid Build Coastguard Worker     }
140*c8dee2aaSAndroid Build Coastguard Worker 
141*c8dee2aaSAndroid Build Coastguard Worker     memset(vertexInputInfo, 0, sizeof(VkPipelineVertexInputStateCreateInfo));
142*c8dee2aaSAndroid Build Coastguard Worker     vertexInputInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
143*c8dee2aaSAndroid Build Coastguard Worker     vertexInputInfo->pNext = nullptr;
144*c8dee2aaSAndroid Build Coastguard Worker     vertexInputInfo->flags = 0;
145*c8dee2aaSAndroid Build Coastguard Worker     vertexInputInfo->vertexBindingDescriptionCount = bindingDescs ? bindingDescs->size() : 0;
146*c8dee2aaSAndroid Build Coastguard Worker     vertexInputInfo->pVertexBindingDescriptions =
147*c8dee2aaSAndroid Build Coastguard Worker             bindingDescs && !bindingDescs->empty() ? bindingDescs->begin() : VK_NULL_HANDLE;
148*c8dee2aaSAndroid Build Coastguard Worker     vertexInputInfo->vertexAttributeDescriptionCount = attributeDescs ? attributeDescs->size() : 0;
149*c8dee2aaSAndroid Build Coastguard Worker     vertexInputInfo->pVertexAttributeDescriptions =
150*c8dee2aaSAndroid Build Coastguard Worker             attributeDescs && !attributeDescs->empty() ? attributeDescs->begin() : VK_NULL_HANDLE;
151*c8dee2aaSAndroid Build Coastguard Worker }
152*c8dee2aaSAndroid Build Coastguard Worker 
primitive_type_to_vk_topology(PrimitiveType primitiveType)153*c8dee2aaSAndroid Build Coastguard Worker static VkPrimitiveTopology primitive_type_to_vk_topology(PrimitiveType primitiveType) {
154*c8dee2aaSAndroid Build Coastguard Worker     switch (primitiveType) {
155*c8dee2aaSAndroid Build Coastguard Worker         case PrimitiveType::kTriangles:
156*c8dee2aaSAndroid Build Coastguard Worker             return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
157*c8dee2aaSAndroid Build Coastguard Worker         case PrimitiveType::kTriangleStrip:
158*c8dee2aaSAndroid Build Coastguard Worker             return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
159*c8dee2aaSAndroid Build Coastguard Worker         case PrimitiveType::kPoints:
160*c8dee2aaSAndroid Build Coastguard Worker             return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
161*c8dee2aaSAndroid Build Coastguard Worker     }
162*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
163*c8dee2aaSAndroid Build Coastguard Worker }
164*c8dee2aaSAndroid Build Coastguard Worker 
setup_input_assembly_state(PrimitiveType primitiveType,VkPipelineInputAssemblyStateCreateInfo * inputAssemblyInfo)165*c8dee2aaSAndroid Build Coastguard Worker static void setup_input_assembly_state(PrimitiveType primitiveType,
166*c8dee2aaSAndroid Build Coastguard Worker                                        VkPipelineInputAssemblyStateCreateInfo* inputAssemblyInfo) {
167*c8dee2aaSAndroid Build Coastguard Worker     memset(inputAssemblyInfo, 0, sizeof(VkPipelineInputAssemblyStateCreateInfo));
168*c8dee2aaSAndroid Build Coastguard Worker     inputAssemblyInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
169*c8dee2aaSAndroid Build Coastguard Worker     inputAssemblyInfo->pNext = nullptr;
170*c8dee2aaSAndroid Build Coastguard Worker     inputAssemblyInfo->flags = 0;
171*c8dee2aaSAndroid Build Coastguard Worker     inputAssemblyInfo->primitiveRestartEnable = false;
172*c8dee2aaSAndroid Build Coastguard Worker     inputAssemblyInfo->topology = primitive_type_to_vk_topology(primitiveType);
173*c8dee2aaSAndroid Build Coastguard Worker }
174*c8dee2aaSAndroid Build Coastguard Worker 
stencil_op_to_vk_stencil_op(StencilOp op)175*c8dee2aaSAndroid Build Coastguard Worker static VkStencilOp stencil_op_to_vk_stencil_op(StencilOp op) {
176*c8dee2aaSAndroid Build Coastguard Worker     static const VkStencilOp gTable[] = {
177*c8dee2aaSAndroid Build Coastguard Worker         VK_STENCIL_OP_KEEP,                 // kKeep
178*c8dee2aaSAndroid Build Coastguard Worker         VK_STENCIL_OP_ZERO,                 // kZero
179*c8dee2aaSAndroid Build Coastguard Worker         VK_STENCIL_OP_REPLACE,              // kReplace
180*c8dee2aaSAndroid Build Coastguard Worker         VK_STENCIL_OP_INVERT,               // kInvert
181*c8dee2aaSAndroid Build Coastguard Worker         VK_STENCIL_OP_INCREMENT_AND_WRAP,   // kIncWrap
182*c8dee2aaSAndroid Build Coastguard Worker         VK_STENCIL_OP_DECREMENT_AND_WRAP,   // kDecWrap
183*c8dee2aaSAndroid Build Coastguard Worker         VK_STENCIL_OP_INCREMENT_AND_CLAMP,  // kIncClamp
184*c8dee2aaSAndroid Build Coastguard Worker         VK_STENCIL_OP_DECREMENT_AND_CLAMP,  // kDecClamp
185*c8dee2aaSAndroid Build Coastguard Worker     };
186*c8dee2aaSAndroid Build Coastguard Worker     static_assert(std::size(gTable) == kStencilOpCount);
187*c8dee2aaSAndroid Build Coastguard Worker     static_assert(0 == (int)StencilOp::kKeep);
188*c8dee2aaSAndroid Build Coastguard Worker     static_assert(1 == (int)StencilOp::kZero);
189*c8dee2aaSAndroid Build Coastguard Worker     static_assert(2 == (int)StencilOp::kReplace);
190*c8dee2aaSAndroid Build Coastguard Worker     static_assert(3 == (int)StencilOp::kInvert);
191*c8dee2aaSAndroid Build Coastguard Worker     static_assert(4 == (int)StencilOp::kIncWrap);
192*c8dee2aaSAndroid Build Coastguard Worker     static_assert(5 == (int)StencilOp::kDecWrap);
193*c8dee2aaSAndroid Build Coastguard Worker     static_assert(6 == (int)StencilOp::kIncClamp);
194*c8dee2aaSAndroid Build Coastguard Worker     static_assert(7 == (int)StencilOp::kDecClamp);
195*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(op < (StencilOp)kStencilOpCount);
196*c8dee2aaSAndroid Build Coastguard Worker     return gTable[(int)op];
197*c8dee2aaSAndroid Build Coastguard Worker }
198*c8dee2aaSAndroid Build Coastguard Worker 
compare_op_to_vk_compare_op(CompareOp op)199*c8dee2aaSAndroid Build Coastguard Worker static VkCompareOp compare_op_to_vk_compare_op(CompareOp op) {
200*c8dee2aaSAndroid Build Coastguard Worker     static const VkCompareOp gTable[] = {
201*c8dee2aaSAndroid Build Coastguard Worker         VK_COMPARE_OP_ALWAYS,              // kAlways
202*c8dee2aaSAndroid Build Coastguard Worker         VK_COMPARE_OP_NEVER,               // kNever
203*c8dee2aaSAndroid Build Coastguard Worker         VK_COMPARE_OP_GREATER,             // kGreater
204*c8dee2aaSAndroid Build Coastguard Worker         VK_COMPARE_OP_GREATER_OR_EQUAL,    // kGEqual
205*c8dee2aaSAndroid Build Coastguard Worker         VK_COMPARE_OP_LESS,                // kLess
206*c8dee2aaSAndroid Build Coastguard Worker         VK_COMPARE_OP_LESS_OR_EQUAL,       // kLEqual
207*c8dee2aaSAndroid Build Coastguard Worker         VK_COMPARE_OP_EQUAL,               // kEqual
208*c8dee2aaSAndroid Build Coastguard Worker         VK_COMPARE_OP_NOT_EQUAL,           // kNotEqual
209*c8dee2aaSAndroid Build Coastguard Worker     };
210*c8dee2aaSAndroid Build Coastguard Worker     static_assert(std::size(gTable) == kCompareOpCount);
211*c8dee2aaSAndroid Build Coastguard Worker     static_assert(0 == (int)CompareOp::kAlways);
212*c8dee2aaSAndroid Build Coastguard Worker     static_assert(1 == (int)CompareOp::kNever);
213*c8dee2aaSAndroid Build Coastguard Worker     static_assert(2 == (int)CompareOp::kGreater);
214*c8dee2aaSAndroid Build Coastguard Worker     static_assert(3 == (int)CompareOp::kGEqual);
215*c8dee2aaSAndroid Build Coastguard Worker     static_assert(4 == (int)CompareOp::kLess);
216*c8dee2aaSAndroid Build Coastguard Worker     static_assert(5 == (int)CompareOp::kLEqual);
217*c8dee2aaSAndroid Build Coastguard Worker     static_assert(6 == (int)CompareOp::kEqual);
218*c8dee2aaSAndroid Build Coastguard Worker     static_assert(7 == (int)CompareOp::kNotEqual);
219*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(op < (CompareOp)kCompareOpCount);
220*c8dee2aaSAndroid Build Coastguard Worker 
221*c8dee2aaSAndroid Build Coastguard Worker     return gTable[(int)op];
222*c8dee2aaSAndroid Build Coastguard Worker }
223*c8dee2aaSAndroid Build Coastguard Worker 
setup_stencil_op_state(VkStencilOpState * opState,const DepthStencilSettings::Face & face,uint32_t referenceValue)224*c8dee2aaSAndroid Build Coastguard Worker static void setup_stencil_op_state(VkStencilOpState* opState,
225*c8dee2aaSAndroid Build Coastguard Worker                                    const DepthStencilSettings::Face& face,
226*c8dee2aaSAndroid Build Coastguard Worker                                    uint32_t referenceValue) {
227*c8dee2aaSAndroid Build Coastguard Worker     opState->failOp = stencil_op_to_vk_stencil_op(face.fStencilFailOp);
228*c8dee2aaSAndroid Build Coastguard Worker     opState->passOp = stencil_op_to_vk_stencil_op(face.fDepthStencilPassOp);
229*c8dee2aaSAndroid Build Coastguard Worker     opState->depthFailOp = stencil_op_to_vk_stencil_op(face.fDepthFailOp);
230*c8dee2aaSAndroid Build Coastguard Worker     opState->compareOp = compare_op_to_vk_compare_op(face.fCompareOp);
231*c8dee2aaSAndroid Build Coastguard Worker     opState->compareMask = face.fReadMask; // TODO - check this.
232*c8dee2aaSAndroid Build Coastguard Worker     opState->writeMask = face.fWriteMask;
233*c8dee2aaSAndroid Build Coastguard Worker     opState->reference = referenceValue;
234*c8dee2aaSAndroid Build Coastguard Worker }
235*c8dee2aaSAndroid Build Coastguard Worker 
setup_depth_stencil_state(const DepthStencilSettings & stencilSettings,VkPipelineDepthStencilStateCreateInfo * stencilInfo)236*c8dee2aaSAndroid Build Coastguard Worker static void setup_depth_stencil_state(const DepthStencilSettings& stencilSettings,
237*c8dee2aaSAndroid Build Coastguard Worker                                       VkPipelineDepthStencilStateCreateInfo* stencilInfo) {
238*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(stencilSettings.fDepthTestEnabled ||
239*c8dee2aaSAndroid Build Coastguard Worker              stencilSettings.fDepthCompareOp == CompareOp::kAlways);
240*c8dee2aaSAndroid Build Coastguard Worker 
241*c8dee2aaSAndroid Build Coastguard Worker     memset(stencilInfo, 0, sizeof(VkPipelineDepthStencilStateCreateInfo));
242*c8dee2aaSAndroid Build Coastguard Worker     stencilInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
243*c8dee2aaSAndroid Build Coastguard Worker     stencilInfo->pNext = nullptr;
244*c8dee2aaSAndroid Build Coastguard Worker     stencilInfo->flags = 0;
245*c8dee2aaSAndroid Build Coastguard Worker     stencilInfo->depthTestEnable = stencilSettings.fDepthTestEnabled;
246*c8dee2aaSAndroid Build Coastguard Worker     stencilInfo->depthWriteEnable = stencilSettings.fDepthWriteEnabled;
247*c8dee2aaSAndroid Build Coastguard Worker     stencilInfo->depthCompareOp = compare_op_to_vk_compare_op(stencilSettings.fDepthCompareOp);
248*c8dee2aaSAndroid Build Coastguard Worker     stencilInfo->depthBoundsTestEnable = VK_FALSE; // Default value TODO - Confirm
249*c8dee2aaSAndroid Build Coastguard Worker     stencilInfo->stencilTestEnable = stencilSettings.fStencilTestEnabled;
250*c8dee2aaSAndroid Build Coastguard Worker     if (stencilSettings.fStencilTestEnabled) {
251*c8dee2aaSAndroid Build Coastguard Worker         setup_stencil_op_state(&stencilInfo->front,
252*c8dee2aaSAndroid Build Coastguard Worker                                stencilSettings.fFrontStencil,
253*c8dee2aaSAndroid Build Coastguard Worker                                stencilSettings.fStencilReferenceValue);
254*c8dee2aaSAndroid Build Coastguard Worker         setup_stencil_op_state(&stencilInfo->back,
255*c8dee2aaSAndroid Build Coastguard Worker                                stencilSettings.fBackStencil,
256*c8dee2aaSAndroid Build Coastguard Worker                                stencilSettings.fStencilReferenceValue);
257*c8dee2aaSAndroid Build Coastguard Worker     }
258*c8dee2aaSAndroid Build Coastguard Worker     stencilInfo->minDepthBounds = 0.0f;
259*c8dee2aaSAndroid Build Coastguard Worker     stencilInfo->maxDepthBounds = 1.0f;
260*c8dee2aaSAndroid Build Coastguard Worker }
261*c8dee2aaSAndroid Build Coastguard Worker 
setup_viewport_scissor_state(VkPipelineViewportStateCreateInfo * viewportInfo)262*c8dee2aaSAndroid Build Coastguard Worker static void setup_viewport_scissor_state(VkPipelineViewportStateCreateInfo* viewportInfo) {
263*c8dee2aaSAndroid Build Coastguard Worker     memset(viewportInfo, 0, sizeof(VkPipelineViewportStateCreateInfo));
264*c8dee2aaSAndroid Build Coastguard Worker     viewportInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
265*c8dee2aaSAndroid Build Coastguard Worker     viewportInfo->pNext = nullptr;
266*c8dee2aaSAndroid Build Coastguard Worker     viewportInfo->flags = 0;
267*c8dee2aaSAndroid Build Coastguard Worker 
268*c8dee2aaSAndroid Build Coastguard Worker     viewportInfo->viewportCount = 1;
269*c8dee2aaSAndroid Build Coastguard Worker     viewportInfo->pViewports = nullptr; // This is set dynamically with a draw pass command
270*c8dee2aaSAndroid Build Coastguard Worker 
271*c8dee2aaSAndroid Build Coastguard Worker     viewportInfo->scissorCount = 1;
272*c8dee2aaSAndroid Build Coastguard Worker     viewportInfo->pScissors = nullptr; // This is set dynamically with a draw pass command
273*c8dee2aaSAndroid Build Coastguard Worker 
274*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(viewportInfo->viewportCount == viewportInfo->scissorCount);
275*c8dee2aaSAndroid Build Coastguard Worker }
276*c8dee2aaSAndroid Build Coastguard Worker 
setup_multisample_state(int numSamples,VkPipelineMultisampleStateCreateInfo * multisampleInfo)277*c8dee2aaSAndroid Build Coastguard Worker static void setup_multisample_state(int numSamples,
278*c8dee2aaSAndroid Build Coastguard Worker                                     VkPipelineMultisampleStateCreateInfo* multisampleInfo) {
279*c8dee2aaSAndroid Build Coastguard Worker     memset(multisampleInfo, 0, sizeof(VkPipelineMultisampleStateCreateInfo));
280*c8dee2aaSAndroid Build Coastguard Worker     multisampleInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
281*c8dee2aaSAndroid Build Coastguard Worker     multisampleInfo->pNext = nullptr;
282*c8dee2aaSAndroid Build Coastguard Worker     multisampleInfo->flags = 0;
283*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(skgpu::SampleCountToVkSampleCount(numSamples,
284*c8dee2aaSAndroid Build Coastguard Worker                                                      &multisampleInfo->rasterizationSamples));
285*c8dee2aaSAndroid Build Coastguard Worker     multisampleInfo->sampleShadingEnable = VK_FALSE;
286*c8dee2aaSAndroid Build Coastguard Worker     multisampleInfo->minSampleShading = 0.0f;
287*c8dee2aaSAndroid Build Coastguard Worker     multisampleInfo->pSampleMask = nullptr;
288*c8dee2aaSAndroid Build Coastguard Worker     multisampleInfo->alphaToCoverageEnable = VK_FALSE;
289*c8dee2aaSAndroid Build Coastguard Worker     multisampleInfo->alphaToOneEnable = VK_FALSE;
290*c8dee2aaSAndroid Build Coastguard Worker }
291*c8dee2aaSAndroid Build Coastguard Worker 
blend_coeff_to_vk_blend(skgpu::BlendCoeff coeff)292*c8dee2aaSAndroid Build Coastguard Worker static VkBlendFactor blend_coeff_to_vk_blend(skgpu::BlendCoeff coeff) {
293*c8dee2aaSAndroid Build Coastguard Worker     switch (coeff) {
294*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kZero:
295*c8dee2aaSAndroid Build Coastguard Worker             return VK_BLEND_FACTOR_ZERO;
296*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kOne:
297*c8dee2aaSAndroid Build Coastguard Worker             return VK_BLEND_FACTOR_ONE;
298*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kSC:
299*c8dee2aaSAndroid Build Coastguard Worker             return VK_BLEND_FACTOR_SRC_COLOR;
300*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kISC:
301*c8dee2aaSAndroid Build Coastguard Worker             return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
302*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kDC:
303*c8dee2aaSAndroid Build Coastguard Worker             return VK_BLEND_FACTOR_DST_COLOR;
304*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kIDC:
305*c8dee2aaSAndroid Build Coastguard Worker             return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
306*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kSA:
307*c8dee2aaSAndroid Build Coastguard Worker             return VK_BLEND_FACTOR_SRC_ALPHA;
308*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kISA:
309*c8dee2aaSAndroid Build Coastguard Worker             return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
310*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kDA:
311*c8dee2aaSAndroid Build Coastguard Worker             return VK_BLEND_FACTOR_DST_ALPHA;
312*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kIDA:
313*c8dee2aaSAndroid Build Coastguard Worker             return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
314*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kConstC:
315*c8dee2aaSAndroid Build Coastguard Worker             return VK_BLEND_FACTOR_CONSTANT_COLOR;
316*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kIConstC:
317*c8dee2aaSAndroid Build Coastguard Worker             return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
318*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kS2C:
319*c8dee2aaSAndroid Build Coastguard Worker             return VK_BLEND_FACTOR_SRC1_COLOR;
320*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kIS2C:
321*c8dee2aaSAndroid Build Coastguard Worker             return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
322*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kS2A:
323*c8dee2aaSAndroid Build Coastguard Worker             return VK_BLEND_FACTOR_SRC1_ALPHA;
324*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kIS2A:
325*c8dee2aaSAndroid Build Coastguard Worker             return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
326*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kIllegal:
327*c8dee2aaSAndroid Build Coastguard Worker             return VK_BLEND_FACTOR_ZERO;
328*c8dee2aaSAndroid Build Coastguard Worker     }
329*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
330*c8dee2aaSAndroid Build Coastguard Worker }
331*c8dee2aaSAndroid Build Coastguard Worker 
blend_equation_to_vk_blend_op(skgpu::BlendEquation equation)332*c8dee2aaSAndroid Build Coastguard Worker static VkBlendOp blend_equation_to_vk_blend_op(skgpu::BlendEquation equation) {
333*c8dee2aaSAndroid Build Coastguard Worker     static const VkBlendOp gTable[] = {
334*c8dee2aaSAndroid Build Coastguard Worker         // Basic blend ops
335*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_ADD,
336*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_SUBTRACT,
337*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_REVERSE_SUBTRACT,
338*c8dee2aaSAndroid Build Coastguard Worker 
339*c8dee2aaSAndroid Build Coastguard Worker         // Advanced blend ops
340*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_SCREEN_EXT,
341*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_OVERLAY_EXT,
342*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_DARKEN_EXT,
343*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_LIGHTEN_EXT,
344*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_COLORDODGE_EXT,
345*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_COLORBURN_EXT,
346*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_HARDLIGHT_EXT,
347*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_SOFTLIGHT_EXT,
348*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_DIFFERENCE_EXT,
349*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_EXCLUSION_EXT,
350*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_MULTIPLY_EXT,
351*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_HSL_HUE_EXT,
352*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_HSL_SATURATION_EXT,
353*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_HSL_COLOR_EXT,
354*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_HSL_LUMINOSITY_EXT,
355*c8dee2aaSAndroid Build Coastguard Worker 
356*c8dee2aaSAndroid Build Coastguard Worker         // Illegal.
357*c8dee2aaSAndroid Build Coastguard Worker         VK_BLEND_OP_ADD,
358*c8dee2aaSAndroid Build Coastguard Worker     };
359*c8dee2aaSAndroid Build Coastguard Worker     static_assert(0 == (int)skgpu::BlendEquation::kAdd);
360*c8dee2aaSAndroid Build Coastguard Worker     static_assert(1 == (int)skgpu::BlendEquation::kSubtract);
361*c8dee2aaSAndroid Build Coastguard Worker     static_assert(2 == (int)skgpu::BlendEquation::kReverseSubtract);
362*c8dee2aaSAndroid Build Coastguard Worker     static_assert(3 == (int)skgpu::BlendEquation::kScreen);
363*c8dee2aaSAndroid Build Coastguard Worker     static_assert(4 == (int)skgpu::BlendEquation::kOverlay);
364*c8dee2aaSAndroid Build Coastguard Worker     static_assert(5 == (int)skgpu::BlendEquation::kDarken);
365*c8dee2aaSAndroid Build Coastguard Worker     static_assert(6 == (int)skgpu::BlendEquation::kLighten);
366*c8dee2aaSAndroid Build Coastguard Worker     static_assert(7 == (int)skgpu::BlendEquation::kColorDodge);
367*c8dee2aaSAndroid Build Coastguard Worker     static_assert(8 == (int)skgpu::BlendEquation::kColorBurn);
368*c8dee2aaSAndroid Build Coastguard Worker     static_assert(9 == (int)skgpu::BlendEquation::kHardLight);
369*c8dee2aaSAndroid Build Coastguard Worker     static_assert(10 == (int)skgpu::BlendEquation::kSoftLight);
370*c8dee2aaSAndroid Build Coastguard Worker     static_assert(11 == (int)skgpu::BlendEquation::kDifference);
371*c8dee2aaSAndroid Build Coastguard Worker     static_assert(12 == (int)skgpu::BlendEquation::kExclusion);
372*c8dee2aaSAndroid Build Coastguard Worker     static_assert(13 == (int)skgpu::BlendEquation::kMultiply);
373*c8dee2aaSAndroid Build Coastguard Worker     static_assert(14 == (int)skgpu::BlendEquation::kHSLHue);
374*c8dee2aaSAndroid Build Coastguard Worker     static_assert(15 == (int)skgpu::BlendEquation::kHSLSaturation);
375*c8dee2aaSAndroid Build Coastguard Worker     static_assert(16 == (int)skgpu::BlendEquation::kHSLColor);
376*c8dee2aaSAndroid Build Coastguard Worker     static_assert(17 == (int)skgpu::BlendEquation::kHSLLuminosity);
377*c8dee2aaSAndroid Build Coastguard Worker     static_assert(std::size(gTable) == skgpu::kBlendEquationCnt);
378*c8dee2aaSAndroid Build Coastguard Worker 
379*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT((unsigned)equation < skgpu::kBlendEquationCnt);
380*c8dee2aaSAndroid Build Coastguard Worker     return gTable[(int)equation];
381*c8dee2aaSAndroid Build Coastguard Worker }
382*c8dee2aaSAndroid Build Coastguard Worker 
setup_color_blend_state(const skgpu::BlendInfo & blendInfo,VkPipelineColorBlendStateCreateInfo * colorBlendInfo,VkPipelineColorBlendAttachmentState * attachmentState)383*c8dee2aaSAndroid Build Coastguard Worker static void setup_color_blend_state(const skgpu::BlendInfo& blendInfo,
384*c8dee2aaSAndroid Build Coastguard Worker                                     VkPipelineColorBlendStateCreateInfo* colorBlendInfo,
385*c8dee2aaSAndroid Build Coastguard Worker                                     VkPipelineColorBlendAttachmentState* attachmentState) {
386*c8dee2aaSAndroid Build Coastguard Worker     skgpu::BlendEquation equation = blendInfo.fEquation;
387*c8dee2aaSAndroid Build Coastguard Worker     skgpu::BlendCoeff srcCoeff = blendInfo.fSrcBlend;
388*c8dee2aaSAndroid Build Coastguard Worker     skgpu::BlendCoeff dstCoeff = blendInfo.fDstBlend;
389*c8dee2aaSAndroid Build Coastguard Worker     bool blendOff = skgpu::BlendShouldDisable(equation, srcCoeff, dstCoeff);
390*c8dee2aaSAndroid Build Coastguard Worker 
391*c8dee2aaSAndroid Build Coastguard Worker     memset(attachmentState, 0, sizeof(VkPipelineColorBlendAttachmentState));
392*c8dee2aaSAndroid Build Coastguard Worker     attachmentState->blendEnable = !blendOff;
393*c8dee2aaSAndroid Build Coastguard Worker     if (!blendOff) {
394*c8dee2aaSAndroid Build Coastguard Worker         attachmentState->srcColorBlendFactor = blend_coeff_to_vk_blend(srcCoeff);
395*c8dee2aaSAndroid Build Coastguard Worker         attachmentState->dstColorBlendFactor = blend_coeff_to_vk_blend(dstCoeff);
396*c8dee2aaSAndroid Build Coastguard Worker         attachmentState->colorBlendOp = blend_equation_to_vk_blend_op(equation);
397*c8dee2aaSAndroid Build Coastguard Worker         attachmentState->srcAlphaBlendFactor = blend_coeff_to_vk_blend(srcCoeff);
398*c8dee2aaSAndroid Build Coastguard Worker         attachmentState->dstAlphaBlendFactor = blend_coeff_to_vk_blend(dstCoeff);
399*c8dee2aaSAndroid Build Coastguard Worker         attachmentState->alphaBlendOp = blend_equation_to_vk_blend_op(equation);
400*c8dee2aaSAndroid Build Coastguard Worker     }
401*c8dee2aaSAndroid Build Coastguard Worker 
402*c8dee2aaSAndroid Build Coastguard Worker     if (!blendInfo.fWritesColor) {
403*c8dee2aaSAndroid Build Coastguard Worker         attachmentState->colorWriteMask = 0;
404*c8dee2aaSAndroid Build Coastguard Worker     } else {
405*c8dee2aaSAndroid Build Coastguard Worker         attachmentState->colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
406*c8dee2aaSAndroid Build Coastguard Worker                                           VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
407*c8dee2aaSAndroid Build Coastguard Worker     }
408*c8dee2aaSAndroid Build Coastguard Worker 
409*c8dee2aaSAndroid Build Coastguard Worker     memset(colorBlendInfo, 0, sizeof(VkPipelineColorBlendStateCreateInfo));
410*c8dee2aaSAndroid Build Coastguard Worker     colorBlendInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
411*c8dee2aaSAndroid Build Coastguard Worker     colorBlendInfo->pNext = nullptr;
412*c8dee2aaSAndroid Build Coastguard Worker     colorBlendInfo->flags = 0;
413*c8dee2aaSAndroid Build Coastguard Worker     colorBlendInfo->logicOpEnable = VK_FALSE;
414*c8dee2aaSAndroid Build Coastguard Worker     colorBlendInfo->attachmentCount = 1;
415*c8dee2aaSAndroid Build Coastguard Worker     colorBlendInfo->pAttachments = attachmentState;
416*c8dee2aaSAndroid Build Coastguard Worker     // colorBlendInfo->blendConstants is set dynamically
417*c8dee2aaSAndroid Build Coastguard Worker }
418*c8dee2aaSAndroid Build Coastguard Worker 
setup_raster_state(bool isWireframe,VkPipelineRasterizationStateCreateInfo * rasterInfo)419*c8dee2aaSAndroid Build Coastguard Worker static void setup_raster_state(bool isWireframe,
420*c8dee2aaSAndroid Build Coastguard Worker                                VkPipelineRasterizationStateCreateInfo* rasterInfo) {
421*c8dee2aaSAndroid Build Coastguard Worker     memset(rasterInfo, 0, sizeof(VkPipelineRasterizationStateCreateInfo));
422*c8dee2aaSAndroid Build Coastguard Worker     rasterInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
423*c8dee2aaSAndroid Build Coastguard Worker     rasterInfo->pNext = nullptr;
424*c8dee2aaSAndroid Build Coastguard Worker     rasterInfo->flags = 0;
425*c8dee2aaSAndroid Build Coastguard Worker     rasterInfo->depthClampEnable = VK_FALSE;
426*c8dee2aaSAndroid Build Coastguard Worker     rasterInfo->rasterizerDiscardEnable = VK_FALSE;
427*c8dee2aaSAndroid Build Coastguard Worker     rasterInfo->polygonMode = isWireframe ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL;
428*c8dee2aaSAndroid Build Coastguard Worker     rasterInfo->cullMode = VK_CULL_MODE_NONE;
429*c8dee2aaSAndroid Build Coastguard Worker     rasterInfo->frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
430*c8dee2aaSAndroid Build Coastguard Worker     rasterInfo->depthBiasEnable = VK_FALSE;
431*c8dee2aaSAndroid Build Coastguard Worker     rasterInfo->depthBiasConstantFactor = 0.0f;
432*c8dee2aaSAndroid Build Coastguard Worker     rasterInfo->depthBiasClamp = 0.0f;
433*c8dee2aaSAndroid Build Coastguard Worker     rasterInfo->depthBiasSlopeFactor = 0.0f;
434*c8dee2aaSAndroid Build Coastguard Worker     rasterInfo->lineWidth = 1.0f;
435*c8dee2aaSAndroid Build Coastguard Worker }
436*c8dee2aaSAndroid Build Coastguard Worker 
setup_shader_stage_info(VkShaderStageFlagBits stage,VkShaderModule shaderModule,VkPipelineShaderStageCreateInfo * shaderStageInfo)437*c8dee2aaSAndroid Build Coastguard Worker static void setup_shader_stage_info(VkShaderStageFlagBits stage,
438*c8dee2aaSAndroid Build Coastguard Worker                                     VkShaderModule shaderModule,
439*c8dee2aaSAndroid Build Coastguard Worker                                     VkPipelineShaderStageCreateInfo* shaderStageInfo) {
440*c8dee2aaSAndroid Build Coastguard Worker     memset(shaderStageInfo, 0, sizeof(VkPipelineShaderStageCreateInfo));
441*c8dee2aaSAndroid Build Coastguard Worker     shaderStageInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
442*c8dee2aaSAndroid Build Coastguard Worker     shaderStageInfo->pNext = nullptr;
443*c8dee2aaSAndroid Build Coastguard Worker     shaderStageInfo->flags = 0;
444*c8dee2aaSAndroid Build Coastguard Worker     shaderStageInfo->stage = stage;
445*c8dee2aaSAndroid Build Coastguard Worker     shaderStageInfo->module = shaderModule;
446*c8dee2aaSAndroid Build Coastguard Worker     shaderStageInfo->pName = "main";
447*c8dee2aaSAndroid Build Coastguard Worker     shaderStageInfo->pSpecializationInfo = nullptr;
448*c8dee2aaSAndroid Build Coastguard Worker }
449*c8dee2aaSAndroid Build Coastguard Worker 
450*c8dee2aaSAndroid Build Coastguard Worker 
descriptor_data_to_layout(const VulkanSharedContext * sharedContext,const SkSpan<DescriptorData> & descriptorData)451*c8dee2aaSAndroid Build Coastguard Worker static VkDescriptorSetLayout descriptor_data_to_layout(const VulkanSharedContext* sharedContext,
452*c8dee2aaSAndroid Build Coastguard Worker         const SkSpan<DescriptorData>& descriptorData) {
453*c8dee2aaSAndroid Build Coastguard Worker     if (descriptorData.empty()) { return VK_NULL_HANDLE; }
454*c8dee2aaSAndroid Build Coastguard Worker 
455*c8dee2aaSAndroid Build Coastguard Worker     VkDescriptorSetLayout setLayout;
456*c8dee2aaSAndroid Build Coastguard Worker     DescriptorDataToVkDescSetLayout(sharedContext, descriptorData, &setLayout);
457*c8dee2aaSAndroid Build Coastguard Worker     if (setLayout == VK_NULL_HANDLE) {
458*c8dee2aaSAndroid Build Coastguard Worker         SKGPU_LOG_E("Failed to create descriptor set layout; pipeline creation will fail.\n");
459*c8dee2aaSAndroid Build Coastguard Worker         return VK_NULL_HANDLE;
460*c8dee2aaSAndroid Build Coastguard Worker     }
461*c8dee2aaSAndroid Build Coastguard Worker     return setLayout;
462*c8dee2aaSAndroid Build Coastguard Worker }
463*c8dee2aaSAndroid Build Coastguard Worker 
destroy_desc_set_layouts(const VulkanSharedContext * sharedContext,skia_private::TArray<VkDescriptorSetLayout> & setLayouts)464*c8dee2aaSAndroid Build Coastguard Worker static void destroy_desc_set_layouts(const VulkanSharedContext* sharedContext,
465*c8dee2aaSAndroid Build Coastguard Worker                                      skia_private::TArray<VkDescriptorSetLayout>& setLayouts) {
466*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < setLayouts.size(); i++) {
467*c8dee2aaSAndroid Build Coastguard Worker         if (setLayouts[i] != VK_NULL_HANDLE) {
468*c8dee2aaSAndroid Build Coastguard Worker             VULKAN_CALL(sharedContext->interface(),
469*c8dee2aaSAndroid Build Coastguard Worker             DestroyDescriptorSetLayout(sharedContext->device(),
470*c8dee2aaSAndroid Build Coastguard Worker                                        setLayouts[i],
471*c8dee2aaSAndroid Build Coastguard Worker                                        nullptr));
472*c8dee2aaSAndroid Build Coastguard Worker         }
473*c8dee2aaSAndroid Build Coastguard Worker     }
474*c8dee2aaSAndroid Build Coastguard Worker }
475*c8dee2aaSAndroid Build Coastguard Worker 
setup_pipeline_layout(const VulkanSharedContext * sharedContext,bool usesIntrinsicConstantUbo,bool useMSAALoadPushConstant,bool hasStepUniforms,bool hasPaintUniforms,bool hasGradientBuffer,int numTextureSamplers,int numInputAttachments,SkSpan<sk_sp<VulkanSampler>> immutableSamplers)476*c8dee2aaSAndroid Build Coastguard Worker static VkPipelineLayout setup_pipeline_layout(const VulkanSharedContext* sharedContext,
477*c8dee2aaSAndroid Build Coastguard Worker                                               bool usesIntrinsicConstantUbo,
478*c8dee2aaSAndroid Build Coastguard Worker                                               bool useMSAALoadPushConstant,
479*c8dee2aaSAndroid Build Coastguard Worker                                               bool hasStepUniforms,
480*c8dee2aaSAndroid Build Coastguard Worker                                               bool hasPaintUniforms,
481*c8dee2aaSAndroid Build Coastguard Worker                                               bool hasGradientBuffer,
482*c8dee2aaSAndroid Build Coastguard Worker                                               int numTextureSamplers,
483*c8dee2aaSAndroid Build Coastguard Worker                                               int numInputAttachments,
484*c8dee2aaSAndroid Build Coastguard Worker                                               SkSpan<sk_sp<VulkanSampler>> immutableSamplers) {
485*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!useMSAALoadPushConstant ||
486*c8dee2aaSAndroid Build Coastguard Worker              (!usesIntrinsicConstantUbo && !hasStepUniforms && !hasPaintUniforms));
487*c8dee2aaSAndroid Build Coastguard Worker     // Determine descriptor set layouts for this pipeline based upon render pass information.
488*c8dee2aaSAndroid Build Coastguard Worker     skia_private::STArray<3, VkDescriptorSetLayout> setLayouts;
489*c8dee2aaSAndroid Build Coastguard Worker 
490*c8dee2aaSAndroid Build Coastguard Worker     // Determine uniform descriptor set layout
491*c8dee2aaSAndroid Build Coastguard Worker     skia_private::STArray<VulkanGraphicsPipeline::kNumUniformBuffers, DescriptorData>
492*c8dee2aaSAndroid Build Coastguard Worker             uniformDescriptors;
493*c8dee2aaSAndroid Build Coastguard Worker     if (usesIntrinsicConstantUbo) {
494*c8dee2aaSAndroid Build Coastguard Worker         uniformDescriptors.push_back(VulkanGraphicsPipeline::kIntrinsicUniformBufferDescriptor);
495*c8dee2aaSAndroid Build Coastguard Worker     }
496*c8dee2aaSAndroid Build Coastguard Worker 
497*c8dee2aaSAndroid Build Coastguard Worker     DescriptorType uniformBufferType = sharedContext->caps()->storageBufferSupport()
498*c8dee2aaSAndroid Build Coastguard Worker                                             ? DescriptorType::kStorageBuffer
499*c8dee2aaSAndroid Build Coastguard Worker                                             : DescriptorType::kUniformBuffer;
500*c8dee2aaSAndroid Build Coastguard Worker     if (hasStepUniforms) {
501*c8dee2aaSAndroid Build Coastguard Worker         uniformDescriptors.push_back({
502*c8dee2aaSAndroid Build Coastguard Worker             uniformBufferType,
503*c8dee2aaSAndroid Build Coastguard Worker             /*count=*/1,
504*c8dee2aaSAndroid Build Coastguard Worker             VulkanGraphicsPipeline::kRenderStepUniformBufferIndex,
505*c8dee2aaSAndroid Build Coastguard Worker             PipelineStageFlags::kVertexShader | PipelineStageFlags::kFragmentShader});
506*c8dee2aaSAndroid Build Coastguard Worker     }
507*c8dee2aaSAndroid Build Coastguard Worker     if (hasPaintUniforms) {
508*c8dee2aaSAndroid Build Coastguard Worker         uniformDescriptors.push_back({
509*c8dee2aaSAndroid Build Coastguard Worker             uniformBufferType,
510*c8dee2aaSAndroid Build Coastguard Worker             /*count=*/1,
511*c8dee2aaSAndroid Build Coastguard Worker             VulkanGraphicsPipeline::kPaintUniformBufferIndex,
512*c8dee2aaSAndroid Build Coastguard Worker             PipelineStageFlags::kFragmentShader});
513*c8dee2aaSAndroid Build Coastguard Worker     }
514*c8dee2aaSAndroid Build Coastguard Worker     if (hasGradientBuffer) {
515*c8dee2aaSAndroid Build Coastguard Worker         uniformDescriptors.push_back({
516*c8dee2aaSAndroid Build Coastguard Worker             DescriptorType::kStorageBuffer,
517*c8dee2aaSAndroid Build Coastguard Worker             /*count=*/1,
518*c8dee2aaSAndroid Build Coastguard Worker             VulkanGraphicsPipeline::kGradientBufferIndex,
519*c8dee2aaSAndroid Build Coastguard Worker             PipelineStageFlags::kFragmentShader});
520*c8dee2aaSAndroid Build Coastguard Worker     }
521*c8dee2aaSAndroid Build Coastguard Worker 
522*c8dee2aaSAndroid Build Coastguard Worker     if (!uniformDescriptors.empty()) {
523*c8dee2aaSAndroid Build Coastguard Worker         VkDescriptorSetLayout uniformSetLayout =
524*c8dee2aaSAndroid Build Coastguard Worker                 descriptor_data_to_layout(sharedContext, {uniformDescriptors});
525*c8dee2aaSAndroid Build Coastguard Worker         if (uniformSetLayout == VK_NULL_HANDLE) { return VK_NULL_HANDLE; }
526*c8dee2aaSAndroid Build Coastguard Worker         setLayouts.push_back(uniformSetLayout);
527*c8dee2aaSAndroid Build Coastguard Worker     }
528*c8dee2aaSAndroid Build Coastguard Worker 
529*c8dee2aaSAndroid Build Coastguard Worker     // Determine input attachment descriptor set layout
530*c8dee2aaSAndroid Build Coastguard Worker     if (numInputAttachments > 0) {
531*c8dee2aaSAndroid Build Coastguard Worker         // For now, we only expect to have up to 1 input attachment. We also share that descriptor
532*c8dee2aaSAndroid Build Coastguard Worker         // set number with uniform descriptors for normal graphics pipeline usages, so verify that
533*c8dee2aaSAndroid Build Coastguard Worker         // we are not using any uniform descriptors to avoid conflicts.
534*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(numInputAttachments == 1 && uniformDescriptors.empty());
535*c8dee2aaSAndroid Build Coastguard Worker         skia_private::TArray<DescriptorData> inputAttachmentDescriptors(numInputAttachments);
536*c8dee2aaSAndroid Build Coastguard Worker         inputAttachmentDescriptors.push_back(VulkanGraphicsPipeline::kInputAttachmentDescriptor);
537*c8dee2aaSAndroid Build Coastguard Worker 
538*c8dee2aaSAndroid Build Coastguard Worker         VkDescriptorSetLayout inputAttachmentDescSetLayout =
539*c8dee2aaSAndroid Build Coastguard Worker                 descriptor_data_to_layout(sharedContext, {inputAttachmentDescriptors});
540*c8dee2aaSAndroid Build Coastguard Worker 
541*c8dee2aaSAndroid Build Coastguard Worker         if (inputAttachmentDescSetLayout == VK_NULL_HANDLE) {
542*c8dee2aaSAndroid Build Coastguard Worker             destroy_desc_set_layouts(sharedContext, setLayouts);
543*c8dee2aaSAndroid Build Coastguard Worker             return VK_NULL_HANDLE;
544*c8dee2aaSAndroid Build Coastguard Worker         }
545*c8dee2aaSAndroid Build Coastguard Worker         setLayouts.push_back(inputAttachmentDescSetLayout);
546*c8dee2aaSAndroid Build Coastguard Worker     }
547*c8dee2aaSAndroid Build Coastguard Worker 
548*c8dee2aaSAndroid Build Coastguard Worker     // Determine texture/sampler descriptor set layout
549*c8dee2aaSAndroid Build Coastguard Worker     if (numTextureSamplers > 0) {
550*c8dee2aaSAndroid Build Coastguard Worker         skia_private::TArray<DescriptorData> textureSamplerDescs(numTextureSamplers);
551*c8dee2aaSAndroid Build Coastguard Worker         // The immutable sampler span size must be = the total number of texture/samplers such that
552*c8dee2aaSAndroid Build Coastguard Worker         // we can use the index of a sampler as its binding index (or we just have none, which
553*c8dee2aaSAndroid Build Coastguard Worker         // enables us to skip some of this logic entirely).
554*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(immutableSamplers.empty() ||
555*c8dee2aaSAndroid Build Coastguard Worker                  SkTo<int>(immutableSamplers.size()) == numTextureSamplers);
556*c8dee2aaSAndroid Build Coastguard Worker 
557*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < numTextureSamplers; i++) {
558*c8dee2aaSAndroid Build Coastguard Worker             Sampler* immutableSampler = nullptr;
559*c8dee2aaSAndroid Build Coastguard Worker             if (!immutableSamplers.empty() && immutableSamplers[i]) {
560*c8dee2aaSAndroid Build Coastguard Worker                 immutableSampler = immutableSamplers[i].get();
561*c8dee2aaSAndroid Build Coastguard Worker             }
562*c8dee2aaSAndroid Build Coastguard Worker             textureSamplerDescs.push_back({DescriptorType::kCombinedTextureSampler,
563*c8dee2aaSAndroid Build Coastguard Worker                                            /*count=*/1,
564*c8dee2aaSAndroid Build Coastguard Worker                                            /*bindingIdx=*/i,
565*c8dee2aaSAndroid Build Coastguard Worker                                            PipelineStageFlags::kFragmentShader,
566*c8dee2aaSAndroid Build Coastguard Worker                                            immutableSampler});
567*c8dee2aaSAndroid Build Coastguard Worker         }
568*c8dee2aaSAndroid Build Coastguard Worker 
569*c8dee2aaSAndroid Build Coastguard Worker         VkDescriptorSetLayout textureSamplerDescSetLayout =
570*c8dee2aaSAndroid Build Coastguard Worker                 descriptor_data_to_layout(sharedContext, {textureSamplerDescs});
571*c8dee2aaSAndroid Build Coastguard Worker 
572*c8dee2aaSAndroid Build Coastguard Worker         if (textureSamplerDescSetLayout == VK_NULL_HANDLE) {
573*c8dee2aaSAndroid Build Coastguard Worker             destroy_desc_set_layouts(sharedContext, setLayouts);
574*c8dee2aaSAndroid Build Coastguard Worker             return VK_NULL_HANDLE;
575*c8dee2aaSAndroid Build Coastguard Worker         }
576*c8dee2aaSAndroid Build Coastguard Worker         setLayouts.push_back(textureSamplerDescSetLayout);
577*c8dee2aaSAndroid Build Coastguard Worker     }
578*c8dee2aaSAndroid Build Coastguard Worker 
579*c8dee2aaSAndroid Build Coastguard Worker     VkPushConstantRange pushConstantRange;
580*c8dee2aaSAndroid Build Coastguard Worker     if (useMSAALoadPushConstant) {
581*c8dee2aaSAndroid Build Coastguard Worker         pushConstantRange.offset = 0;
582*c8dee2aaSAndroid Build Coastguard Worker         pushConstantRange.size = 32;
583*c8dee2aaSAndroid Build Coastguard Worker         pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
584*c8dee2aaSAndroid Build Coastguard Worker     }
585*c8dee2aaSAndroid Build Coastguard Worker 
586*c8dee2aaSAndroid Build Coastguard Worker     // Generate a pipeline layout using the now-populated descriptor set layout array
587*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineLayoutCreateInfo layoutCreateInfo;
588*c8dee2aaSAndroid Build Coastguard Worker     memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
589*c8dee2aaSAndroid Build Coastguard Worker     layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
590*c8dee2aaSAndroid Build Coastguard Worker     layoutCreateInfo.pNext = nullptr;
591*c8dee2aaSAndroid Build Coastguard Worker     layoutCreateInfo.flags = 0;
592*c8dee2aaSAndroid Build Coastguard Worker     layoutCreateInfo.setLayoutCount = setLayouts.size();
593*c8dee2aaSAndroid Build Coastguard Worker     layoutCreateInfo.pSetLayouts = setLayouts.begin();
594*c8dee2aaSAndroid Build Coastguard Worker     // TODO: Add support for push constants.
595*c8dee2aaSAndroid Build Coastguard Worker     layoutCreateInfo.pushConstantRangeCount = useMSAALoadPushConstant ? 1 : 0;
596*c8dee2aaSAndroid Build Coastguard Worker     layoutCreateInfo.pPushConstantRanges = useMSAALoadPushConstant ? &pushConstantRange : nullptr;
597*c8dee2aaSAndroid Build Coastguard Worker 
598*c8dee2aaSAndroid Build Coastguard Worker     VkResult result;
599*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineLayout layout;
600*c8dee2aaSAndroid Build Coastguard Worker     VULKAN_CALL_RESULT(sharedContext,
601*c8dee2aaSAndroid Build Coastguard Worker                        result,
602*c8dee2aaSAndroid Build Coastguard Worker                        CreatePipelineLayout(sharedContext->device(),
603*c8dee2aaSAndroid Build Coastguard Worker                                             &layoutCreateInfo,
604*c8dee2aaSAndroid Build Coastguard Worker                                             /*const VkAllocationCallbacks*=*/nullptr,
605*c8dee2aaSAndroid Build Coastguard Worker                                             &layout));
606*c8dee2aaSAndroid Build Coastguard Worker 
607*c8dee2aaSAndroid Build Coastguard Worker     // DescriptorSetLayouts can be deleted after the pipeline layout is created.
608*c8dee2aaSAndroid Build Coastguard Worker     destroy_desc_set_layouts(sharedContext, setLayouts);
609*c8dee2aaSAndroid Build Coastguard Worker 
610*c8dee2aaSAndroid Build Coastguard Worker     return result == VK_SUCCESS ? layout : VK_NULL_HANDLE;
611*c8dee2aaSAndroid Build Coastguard Worker }
612*c8dee2aaSAndroid Build Coastguard Worker 
destroy_shader_modules(const VulkanSharedContext * sharedContext,VkShaderModule vsModule,VkShaderModule fsModule)613*c8dee2aaSAndroid Build Coastguard Worker static void destroy_shader_modules(const VulkanSharedContext* sharedContext,
614*c8dee2aaSAndroid Build Coastguard Worker                                    VkShaderModule vsModule,
615*c8dee2aaSAndroid Build Coastguard Worker                                    VkShaderModule fsModule) {
616*c8dee2aaSAndroid Build Coastguard Worker     if (vsModule != VK_NULL_HANDLE) {
617*c8dee2aaSAndroid Build Coastguard Worker         VULKAN_CALL(sharedContext->interface(),
618*c8dee2aaSAndroid Build Coastguard Worker                     DestroyShaderModule(sharedContext->device(), vsModule, nullptr));
619*c8dee2aaSAndroid Build Coastguard Worker     }
620*c8dee2aaSAndroid Build Coastguard Worker     if (fsModule != VK_NULL_HANDLE) {
621*c8dee2aaSAndroid Build Coastguard Worker         VULKAN_CALL(sharedContext->interface(),
622*c8dee2aaSAndroid Build Coastguard Worker                     DestroyShaderModule(sharedContext->device(), fsModule, nullptr));
623*c8dee2aaSAndroid Build Coastguard Worker     }
624*c8dee2aaSAndroid Build Coastguard Worker }
625*c8dee2aaSAndroid Build Coastguard Worker 
setup_dynamic_state(VkPipelineDynamicStateCreateInfo * dynamicInfo,VkDynamicState * dynamicStates)626*c8dee2aaSAndroid Build Coastguard Worker static void setup_dynamic_state(VkPipelineDynamicStateCreateInfo* dynamicInfo,
627*c8dee2aaSAndroid Build Coastguard Worker                                 VkDynamicState* dynamicStates) {
628*c8dee2aaSAndroid Build Coastguard Worker     memset(dynamicInfo, 0, sizeof(VkPipelineDynamicStateCreateInfo));
629*c8dee2aaSAndroid Build Coastguard Worker     dynamicInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
630*c8dee2aaSAndroid Build Coastguard Worker     dynamicInfo->pNext = VK_NULL_HANDLE;
631*c8dee2aaSAndroid Build Coastguard Worker     dynamicInfo->flags = 0;
632*c8dee2aaSAndroid Build Coastguard Worker     dynamicStates[0] = VK_DYNAMIC_STATE_VIEWPORT;
633*c8dee2aaSAndroid Build Coastguard Worker     dynamicStates[1] = VK_DYNAMIC_STATE_SCISSOR;
634*c8dee2aaSAndroid Build Coastguard Worker     dynamicStates[2] = VK_DYNAMIC_STATE_BLEND_CONSTANTS;
635*c8dee2aaSAndroid Build Coastguard Worker     dynamicInfo->dynamicStateCount = 3;
636*c8dee2aaSAndroid Build Coastguard Worker     dynamicInfo->pDynamicStates = dynamicStates;
637*c8dee2aaSAndroid Build Coastguard Worker }
638*c8dee2aaSAndroid Build Coastguard Worker 
Make(VulkanResourceProvider * rsrcProvider,const RuntimeEffectDictionary * runtimeDict,const GraphicsPipelineDesc & pipelineDesc,const RenderPassDesc & renderPassDesc,SkEnumBitMask<PipelineCreationFlags> pipelineCreationFlags)639*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanGraphicsPipeline> VulkanGraphicsPipeline::Make(
640*c8dee2aaSAndroid Build Coastguard Worker         VulkanResourceProvider* rsrcProvider,
641*c8dee2aaSAndroid Build Coastguard Worker         const RuntimeEffectDictionary* runtimeDict,
642*c8dee2aaSAndroid Build Coastguard Worker         const GraphicsPipelineDesc& pipelineDesc,
643*c8dee2aaSAndroid Build Coastguard Worker         const RenderPassDesc& renderPassDesc,
644*c8dee2aaSAndroid Build Coastguard Worker         SkEnumBitMask<PipelineCreationFlags> pipelineCreationFlags) {
645*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(rsrcProvider);
646*c8dee2aaSAndroid Build Coastguard Worker     SkSL::Program::Interface vsInterface, fsInterface;
647*c8dee2aaSAndroid Build Coastguard Worker 
648*c8dee2aaSAndroid Build Coastguard Worker     SkSL::ProgramSettings settings;
649*c8dee2aaSAndroid Build Coastguard Worker     settings.fSharpenTextures = true;
650*c8dee2aaSAndroid Build Coastguard Worker     settings.fForceNoRTFlip = true; // TODO: Confirm
651*c8dee2aaSAndroid Build Coastguard Worker 
652*c8dee2aaSAndroid Build Coastguard Worker     const VulkanSharedContext* sharedContext = rsrcProvider->vulkanSharedContext();
653*c8dee2aaSAndroid Build Coastguard Worker     ShaderErrorHandler* errorHandler = sharedContext->caps()->shaderErrorHandler();
654*c8dee2aaSAndroid Build Coastguard Worker 
655*c8dee2aaSAndroid Build Coastguard Worker     const RenderStep* step = sharedContext->rendererProvider()->lookup(pipelineDesc.renderStepID());
656*c8dee2aaSAndroid Build Coastguard Worker     const bool useStorageBuffers = sharedContext->caps()->storageBufferSupport();
657*c8dee2aaSAndroid Build Coastguard Worker 
658*c8dee2aaSAndroid Build Coastguard Worker     if (step->vertexAttributes().size() + step->instanceAttributes().size() >
659*c8dee2aaSAndroid Build Coastguard Worker         sharedContext->vulkanCaps().maxVertexAttributes()) {
660*c8dee2aaSAndroid Build Coastguard Worker         SKGPU_LOG_W("Requested more than the supported number of vertex attributes");
661*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
662*c8dee2aaSAndroid Build Coastguard Worker     }
663*c8dee2aaSAndroid Build Coastguard Worker 
664*c8dee2aaSAndroid Build Coastguard Worker     skia_private::TArray<SamplerDesc> descContainer {};
665*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<ShaderInfo> shaderInfo = ShaderInfo::Make(sharedContext->caps(),
666*c8dee2aaSAndroid Build Coastguard Worker                                                               sharedContext->shaderCodeDictionary(),
667*c8dee2aaSAndroid Build Coastguard Worker                                                               runtimeDict,
668*c8dee2aaSAndroid Build Coastguard Worker                                                               step,
669*c8dee2aaSAndroid Build Coastguard Worker                                                               pipelineDesc.paintParamsID(),
670*c8dee2aaSAndroid Build Coastguard Worker                                                               useStorageBuffers,
671*c8dee2aaSAndroid Build Coastguard Worker                                                               renderPassDesc.fWriteSwizzle,
672*c8dee2aaSAndroid Build Coastguard Worker                                                               &descContainer);
673*c8dee2aaSAndroid Build Coastguard Worker 
674*c8dee2aaSAndroid Build Coastguard Worker     // Populate an array of sampler ptrs where a sampler's index within the array indicates their
675*c8dee2aaSAndroid Build Coastguard Worker     // binding index within the descriptor set. Initialize all values to nullptr, which represents a
676*c8dee2aaSAndroid Build Coastguard Worker     // "regular", dynamic sampler at that index.
677*c8dee2aaSAndroid Build Coastguard Worker     skia_private::TArray<sk_sp<VulkanSampler>> immutableSamplers;
678*c8dee2aaSAndroid Build Coastguard Worker     immutableSamplers.push_back_n(shaderInfo->numFragmentTexturesAndSamplers());
679*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(rsrcProvider);
680*c8dee2aaSAndroid Build Coastguard Worker     // This logic relies upon Vulkan using combined texture/sampler bindings, which is necessary for
681*c8dee2aaSAndroid Build Coastguard Worker     // ycbcr samplers per the Vulkan spec.
682*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!sharedContext->caps()->resourceBindingRequirements().fSeparateTextureAndSamplerBinding
683*c8dee2aaSAndroid Build Coastguard Worker              && shaderInfo->numFragmentTexturesAndSamplers() == descContainer.size());
684*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < descContainer.size(); i++) {
685*c8dee2aaSAndroid Build Coastguard Worker         // If a SamplerDesc is not equivalent to the default-initialized SamplerDesc, that indicates
686*c8dee2aaSAndroid Build Coastguard Worker         // the usage of an immutable sampler. That sampler desc should then be used to obtain an
687*c8dee2aaSAndroid Build Coastguard Worker         // actual immutable sampler from the resource provider and added at the proper index within
688*c8dee2aaSAndroid Build Coastguard Worker         // immutableSamplers for inclusion in the pipeline layout.
689*c8dee2aaSAndroid Build Coastguard Worker         if (descContainer.at(i) != SamplerDesc()) {
690*c8dee2aaSAndroid Build Coastguard Worker             sk_sp<Sampler> immutableSampler =
691*c8dee2aaSAndroid Build Coastguard Worker                     rsrcProvider->findOrCreateCompatibleSampler(descContainer.at(i));
692*c8dee2aaSAndroid Build Coastguard Worker             sk_sp<VulkanSampler> vulkanSampler =
693*c8dee2aaSAndroid Build Coastguard Worker                     sk_ref_sp<VulkanSampler>(static_cast<VulkanSampler*>(immutableSampler.get()));
694*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(vulkanSampler);
695*c8dee2aaSAndroid Build Coastguard Worker             immutableSamplers[i] = std::move(vulkanSampler);
696*c8dee2aaSAndroid Build Coastguard Worker         }
697*c8dee2aaSAndroid Build Coastguard Worker     }
698*c8dee2aaSAndroid Build Coastguard Worker 
699*c8dee2aaSAndroid Build Coastguard Worker     const std::string& fsSkSL = shaderInfo->fragmentSkSL();
700*c8dee2aaSAndroid Build Coastguard Worker 
701*c8dee2aaSAndroid Build Coastguard Worker     const bool hasFragmentSkSL = !fsSkSL.empty();
702*c8dee2aaSAndroid Build Coastguard Worker     std::string vsSPIRV, fsSPIRV;
703*c8dee2aaSAndroid Build Coastguard Worker     VkShaderModule fsModule = VK_NULL_HANDLE, vsModule = VK_NULL_HANDLE;
704*c8dee2aaSAndroid Build Coastguard Worker 
705*c8dee2aaSAndroid Build Coastguard Worker     if (hasFragmentSkSL) {
706*c8dee2aaSAndroid Build Coastguard Worker         if (!skgpu::SkSLToSPIRV(sharedContext->caps()->shaderCaps(),
707*c8dee2aaSAndroid Build Coastguard Worker                                 fsSkSL,
708*c8dee2aaSAndroid Build Coastguard Worker                                 SkSL::ProgramKind::kGraphiteFragment,
709*c8dee2aaSAndroid Build Coastguard Worker                                 settings,
710*c8dee2aaSAndroid Build Coastguard Worker                                 &fsSPIRV,
711*c8dee2aaSAndroid Build Coastguard Worker                                 &fsInterface,
712*c8dee2aaSAndroid Build Coastguard Worker                                 errorHandler)) {
713*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
714*c8dee2aaSAndroid Build Coastguard Worker         }
715*c8dee2aaSAndroid Build Coastguard Worker 
716*c8dee2aaSAndroid Build Coastguard Worker         fsModule = createVulkanShaderModule(sharedContext, fsSPIRV, VK_SHADER_STAGE_FRAGMENT_BIT);
717*c8dee2aaSAndroid Build Coastguard Worker         if (!fsModule) {
718*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
719*c8dee2aaSAndroid Build Coastguard Worker         }
720*c8dee2aaSAndroid Build Coastguard Worker     }
721*c8dee2aaSAndroid Build Coastguard Worker 
722*c8dee2aaSAndroid Build Coastguard Worker     const std::string& vsSkSL = shaderInfo->vertexSkSL();
723*c8dee2aaSAndroid Build Coastguard Worker     if (!skgpu::SkSLToSPIRV(sharedContext->caps()->shaderCaps(),
724*c8dee2aaSAndroid Build Coastguard Worker                             vsSkSL,
725*c8dee2aaSAndroid Build Coastguard Worker                             SkSL::ProgramKind::kGraphiteVertex,
726*c8dee2aaSAndroid Build Coastguard Worker                             settings,
727*c8dee2aaSAndroid Build Coastguard Worker                             &vsSPIRV,
728*c8dee2aaSAndroid Build Coastguard Worker                             &vsInterface,
729*c8dee2aaSAndroid Build Coastguard Worker                             errorHandler)) {
730*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
731*c8dee2aaSAndroid Build Coastguard Worker     }
732*c8dee2aaSAndroid Build Coastguard Worker 
733*c8dee2aaSAndroid Build Coastguard Worker     vsModule = createVulkanShaderModule(sharedContext, vsSPIRV, VK_SHADER_STAGE_VERTEX_BIT);
734*c8dee2aaSAndroid Build Coastguard Worker     if (!vsModule) {
735*c8dee2aaSAndroid Build Coastguard Worker         // Clean up the other shader module before returning.
736*c8dee2aaSAndroid Build Coastguard Worker         destroy_shader_modules(sharedContext, VK_NULL_HANDLE, fsModule);
737*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
738*c8dee2aaSAndroid Build Coastguard Worker     }
739*c8dee2aaSAndroid Build Coastguard Worker 
740*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineVertexInputStateCreateInfo vertexInputInfo;
741*c8dee2aaSAndroid Build Coastguard Worker     skia_private::STArray<2, VkVertexInputBindingDescription, true> bindingDescs;
742*c8dee2aaSAndroid Build Coastguard Worker     skia_private::STArray<16, VkVertexInputAttributeDescription> attributeDescs;
743*c8dee2aaSAndroid Build Coastguard Worker     setup_vertex_input_state(step->vertexAttributes(),
744*c8dee2aaSAndroid Build Coastguard Worker                              step->instanceAttributes(),
745*c8dee2aaSAndroid Build Coastguard Worker                              &vertexInputInfo,
746*c8dee2aaSAndroid Build Coastguard Worker                              &bindingDescs,
747*c8dee2aaSAndroid Build Coastguard Worker                              &attributeDescs);
748*c8dee2aaSAndroid Build Coastguard Worker 
749*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo;
750*c8dee2aaSAndroid Build Coastguard Worker     setup_input_assembly_state(step->primitiveType(), &inputAssemblyInfo);
751*c8dee2aaSAndroid Build Coastguard Worker 
752*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineDepthStencilStateCreateInfo depthStencilInfo;
753*c8dee2aaSAndroid Build Coastguard Worker     setup_depth_stencil_state(step->depthStencilSettings(), &depthStencilInfo);
754*c8dee2aaSAndroid Build Coastguard Worker 
755*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineViewportStateCreateInfo viewportInfo;
756*c8dee2aaSAndroid Build Coastguard Worker     setup_viewport_scissor_state(&viewportInfo);
757*c8dee2aaSAndroid Build Coastguard Worker 
758*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineMultisampleStateCreateInfo multisampleInfo;
759*c8dee2aaSAndroid Build Coastguard Worker     setup_multisample_state(renderPassDesc.fColorAttachment.fTextureInfo.numSamples(),
760*c8dee2aaSAndroid Build Coastguard Worker                             &multisampleInfo);
761*c8dee2aaSAndroid Build Coastguard Worker 
762*c8dee2aaSAndroid Build Coastguard Worker     // We will only have one color blend attachment per pipeline.
763*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineColorBlendAttachmentState attachmentStates[1];
764*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineColorBlendStateCreateInfo colorBlendInfo;
765*c8dee2aaSAndroid Build Coastguard Worker     setup_color_blend_state(shaderInfo->blendInfo(), &colorBlendInfo, attachmentStates);
766*c8dee2aaSAndroid Build Coastguard Worker 
767*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineRasterizationStateCreateInfo rasterInfo;
768*c8dee2aaSAndroid Build Coastguard Worker     // TODO: Check for wire frame mode once that is an available context option within graphite.
769*c8dee2aaSAndroid Build Coastguard Worker     setup_raster_state(/*isWireframe=*/false, &rasterInfo);
770*c8dee2aaSAndroid Build Coastguard Worker 
771*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineShaderStageCreateInfo pipelineShaderStages[2];
772*c8dee2aaSAndroid Build Coastguard Worker     setup_shader_stage_info(VK_SHADER_STAGE_VERTEX_BIT,
773*c8dee2aaSAndroid Build Coastguard Worker                             vsModule,
774*c8dee2aaSAndroid Build Coastguard Worker                             &pipelineShaderStages[0]);
775*c8dee2aaSAndroid Build Coastguard Worker     if (hasFragmentSkSL) {
776*c8dee2aaSAndroid Build Coastguard Worker         setup_shader_stage_info(VK_SHADER_STAGE_FRAGMENT_BIT,
777*c8dee2aaSAndroid Build Coastguard Worker                                 fsModule,
778*c8dee2aaSAndroid Build Coastguard Worker                                 &pipelineShaderStages[1]);
779*c8dee2aaSAndroid Build Coastguard Worker     }
780*c8dee2aaSAndroid Build Coastguard Worker 
781*c8dee2aaSAndroid Build Coastguard Worker     // TODO: Query RenderPassDesc for input attachment information. For now, we only use one for
782*c8dee2aaSAndroid Build Coastguard Worker     // loading MSAA from resolve so we can simply pass in 0 when not doing that.
783*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineLayout pipelineLayout =
784*c8dee2aaSAndroid Build Coastguard Worker             setup_pipeline_layout(sharedContext,
785*c8dee2aaSAndroid Build Coastguard Worker                                   /*usesIntrinsicConstantUbo=*/true,
786*c8dee2aaSAndroid Build Coastguard Worker                                   /*useMSAALoadPushConstant=*/false,
787*c8dee2aaSAndroid Build Coastguard Worker                                   !step->uniforms().empty(),
788*c8dee2aaSAndroid Build Coastguard Worker                                   shaderInfo->hasPaintUniforms(),
789*c8dee2aaSAndroid Build Coastguard Worker                                   shaderInfo->hasGradientBuffer(),
790*c8dee2aaSAndroid Build Coastguard Worker                                   shaderInfo->numFragmentTexturesAndSamplers(),
791*c8dee2aaSAndroid Build Coastguard Worker                                   /*numInputAttachments=*/0,
792*c8dee2aaSAndroid Build Coastguard Worker                                   SkSpan<sk_sp<VulkanSampler>>(immutableSamplers));
793*c8dee2aaSAndroid Build Coastguard Worker 
794*c8dee2aaSAndroid Build Coastguard Worker     if (pipelineLayout == VK_NULL_HANDLE) {
795*c8dee2aaSAndroid Build Coastguard Worker         destroy_shader_modules(sharedContext, vsModule, fsModule);
796*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
797*c8dee2aaSAndroid Build Coastguard Worker     }
798*c8dee2aaSAndroid Build Coastguard Worker 
799*c8dee2aaSAndroid Build Coastguard Worker     VkDynamicState dynamicStates[3];
800*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineDynamicStateCreateInfo dynamicInfo;
801*c8dee2aaSAndroid Build Coastguard Worker     setup_dynamic_state(&dynamicInfo, dynamicStates);
802*c8dee2aaSAndroid Build Coastguard Worker 
803*c8dee2aaSAndroid Build Coastguard Worker     bool loadMsaaFromResolve = renderPassDesc.fColorResolveAttachment.fTextureInfo.isValid() &&
804*c8dee2aaSAndroid Build Coastguard Worker                                renderPassDesc.fColorResolveAttachment.fLoadOp == LoadOp::kLoad;
805*c8dee2aaSAndroid Build Coastguard Worker 
806*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<VulkanRenderPass> compatibleRenderPass =
807*c8dee2aaSAndroid Build Coastguard Worker             rsrcProvider->findOrCreateRenderPass(renderPassDesc, /*compatibleOnly=*/true);
808*c8dee2aaSAndroid Build Coastguard Worker 
809*c8dee2aaSAndroid Build Coastguard Worker     VkGraphicsPipelineCreateInfo pipelineCreateInfo;
810*c8dee2aaSAndroid Build Coastguard Worker     memset(&pipelineCreateInfo, 0, sizeof(VkGraphicsPipelineCreateInfo));
811*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
812*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pNext = nullptr;
813*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.flags = 0;
814*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.stageCount = hasFragmentSkSL ? 2 : 1;
815*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pStages = &pipelineShaderStages[0];
816*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pVertexInputState = &vertexInputInfo;
817*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pInputAssemblyState = &inputAssemblyInfo;
818*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pTessellationState = nullptr;
819*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pViewportState = &viewportInfo;
820*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pRasterizationState = &rasterInfo;
821*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pMultisampleState = &multisampleInfo;
822*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pDepthStencilState = &depthStencilInfo;
823*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pColorBlendState = &colorBlendInfo;
824*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pDynamicState = &dynamicInfo;
825*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.layout = pipelineLayout;
826*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.renderPass = compatibleRenderPass->renderPass();
827*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.subpass = loadMsaaFromResolve ? 1 : 0;
828*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
829*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.basePipelineIndex = -1;
830*c8dee2aaSAndroid Build Coastguard Worker 
831*c8dee2aaSAndroid Build Coastguard Worker     VkPipeline vkPipeline;
832*c8dee2aaSAndroid Build Coastguard Worker     VkResult result;
833*c8dee2aaSAndroid Build Coastguard Worker     {
834*c8dee2aaSAndroid Build Coastguard Worker         TRACE_EVENT0_ALWAYS("skia.shaders", "VkCreateGraphicsPipeline");
835*c8dee2aaSAndroid Build Coastguard Worker         VULKAN_CALL_RESULT(sharedContext,
836*c8dee2aaSAndroid Build Coastguard Worker                            result,
837*c8dee2aaSAndroid Build Coastguard Worker                            CreateGraphicsPipelines(sharedContext->device(),
838*c8dee2aaSAndroid Build Coastguard Worker                                                    rsrcProvider->pipelineCache(),
839*c8dee2aaSAndroid Build Coastguard Worker                                                    /*createInfoCount=*/1,
840*c8dee2aaSAndroid Build Coastguard Worker                                                    &pipelineCreateInfo,
841*c8dee2aaSAndroid Build Coastguard Worker                                                    /*pAllocator=*/nullptr,
842*c8dee2aaSAndroid Build Coastguard Worker                                                    &vkPipeline));
843*c8dee2aaSAndroid Build Coastguard Worker     }
844*c8dee2aaSAndroid Build Coastguard Worker     if (result != VK_SUCCESS) {
845*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Failed to create pipeline. Error: %d\n", result);
846*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
847*c8dee2aaSAndroid Build Coastguard Worker     }
848*c8dee2aaSAndroid Build Coastguard Worker 
849*c8dee2aaSAndroid Build Coastguard Worker     // After creating the pipeline object, we can clean up the VkShaderModule(s).
850*c8dee2aaSAndroid Build Coastguard Worker     destroy_shader_modules(sharedContext, vsModule, fsModule);
851*c8dee2aaSAndroid Build Coastguard Worker 
852*c8dee2aaSAndroid Build Coastguard Worker     PipelineInfo pipelineInfo{*shaderInfo, pipelineCreationFlags};
853*c8dee2aaSAndroid Build Coastguard Worker #if defined(GPU_TEST_UTILS)
854*c8dee2aaSAndroid Build Coastguard Worker     pipelineInfo.fNativeVertexShader   = "SPIR-V disassembly not available";
855*c8dee2aaSAndroid Build Coastguard Worker     pipelineInfo.fNativeFragmentShader = "SPIR-V disassmebly not available";
856*c8dee2aaSAndroid Build Coastguard Worker #endif
857*c8dee2aaSAndroid Build Coastguard Worker 
858*c8dee2aaSAndroid Build Coastguard Worker     return sk_sp<VulkanGraphicsPipeline>(
859*c8dee2aaSAndroid Build Coastguard Worker             new VulkanGraphicsPipeline(sharedContext,
860*c8dee2aaSAndroid Build Coastguard Worker                                        pipelineInfo,
861*c8dee2aaSAndroid Build Coastguard Worker                                        pipelineLayout,
862*c8dee2aaSAndroid Build Coastguard Worker                                        vkPipeline,
863*c8dee2aaSAndroid Build Coastguard Worker                                        /*ownsPipelineLayout=*/true,
864*c8dee2aaSAndroid Build Coastguard Worker                                        std::move(immutableSamplers)));
865*c8dee2aaSAndroid Build Coastguard Worker }
866*c8dee2aaSAndroid Build Coastguard Worker 
InitializeMSAALoadPipelineStructs(const VulkanSharedContext * sharedContext,VkShaderModule * outVertexShaderModule,VkShaderModule * outFragShaderModule,VkPipelineShaderStageCreateInfo * outShaderStageInfo,VkPipelineLayout * outPipelineLayout)867*c8dee2aaSAndroid Build Coastguard Worker bool VulkanGraphicsPipeline::InitializeMSAALoadPipelineStructs(
868*c8dee2aaSAndroid Build Coastguard Worker         const VulkanSharedContext* sharedContext,
869*c8dee2aaSAndroid Build Coastguard Worker         VkShaderModule* outVertexShaderModule,
870*c8dee2aaSAndroid Build Coastguard Worker         VkShaderModule* outFragShaderModule,
871*c8dee2aaSAndroid Build Coastguard Worker         VkPipelineShaderStageCreateInfo* outShaderStageInfo,
872*c8dee2aaSAndroid Build Coastguard Worker         VkPipelineLayout* outPipelineLayout) {
873*c8dee2aaSAndroid Build Coastguard Worker     SkSL::Program::Interface vsInterface, fsInterface;
874*c8dee2aaSAndroid Build Coastguard Worker     SkSL::ProgramSettings settings;
875*c8dee2aaSAndroid Build Coastguard Worker     settings.fForceNoRTFlip = true;
876*c8dee2aaSAndroid Build Coastguard Worker     std::string vsSPIRV, fsSPIRV;
877*c8dee2aaSAndroid Build Coastguard Worker     ShaderErrorHandler* errorHandler = sharedContext->caps()->shaderErrorHandler();
878*c8dee2aaSAndroid Build Coastguard Worker 
879*c8dee2aaSAndroid Build Coastguard Worker     std::string vertShaderText;
880*c8dee2aaSAndroid Build Coastguard Worker     vertShaderText.append(
881*c8dee2aaSAndroid Build Coastguard Worker             "layout(vulkan,  push_constant) uniform vertexUniformBuffer {"
882*c8dee2aaSAndroid Build Coastguard Worker             "half4 uPosXform;"
883*c8dee2aaSAndroid Build Coastguard Worker             "};"
884*c8dee2aaSAndroid Build Coastguard Worker 
885*c8dee2aaSAndroid Build Coastguard Worker             "// MSAA Load Program VS\n"
886*c8dee2aaSAndroid Build Coastguard Worker             "void main() {"
887*c8dee2aaSAndroid Build Coastguard Worker             "float2 position = float2(sk_VertexID >> 1, sk_VertexID & 1);"
888*c8dee2aaSAndroid Build Coastguard Worker             "sk_Position.xy = position * uPosXform.xy + uPosXform.zw;"
889*c8dee2aaSAndroid Build Coastguard Worker             "sk_Position.zw = half2(0, 1);"
890*c8dee2aaSAndroid Build Coastguard Worker             "}");
891*c8dee2aaSAndroid Build Coastguard Worker 
892*c8dee2aaSAndroid Build Coastguard Worker     std::string fragShaderText;
893*c8dee2aaSAndroid Build Coastguard Worker     fragShaderText.append(
894*c8dee2aaSAndroid Build Coastguard Worker             "layout(vulkan, input_attachment_index=0, set=0, binding=0) subpassInput uInput;"
895*c8dee2aaSAndroid Build Coastguard Worker 
896*c8dee2aaSAndroid Build Coastguard Worker             "// MSAA Load Program FS\n"
897*c8dee2aaSAndroid Build Coastguard Worker             "void main() {"
898*c8dee2aaSAndroid Build Coastguard Worker             "sk_FragColor = subpassLoad(uInput);"
899*c8dee2aaSAndroid Build Coastguard Worker             "}");
900*c8dee2aaSAndroid Build Coastguard Worker 
901*c8dee2aaSAndroid Build Coastguard Worker     if (!skgpu::SkSLToSPIRV(sharedContext->caps()->shaderCaps(),
902*c8dee2aaSAndroid Build Coastguard Worker                             vertShaderText,
903*c8dee2aaSAndroid Build Coastguard Worker                             SkSL::ProgramKind::kGraphiteVertex,
904*c8dee2aaSAndroid Build Coastguard Worker                             settings,
905*c8dee2aaSAndroid Build Coastguard Worker                             &vsSPIRV,
906*c8dee2aaSAndroid Build Coastguard Worker                             &vsInterface,
907*c8dee2aaSAndroid Build Coastguard Worker                             errorHandler)) {
908*c8dee2aaSAndroid Build Coastguard Worker         return false;
909*c8dee2aaSAndroid Build Coastguard Worker     }
910*c8dee2aaSAndroid Build Coastguard Worker     if (!skgpu::SkSLToSPIRV(sharedContext->caps()->shaderCaps(),
911*c8dee2aaSAndroid Build Coastguard Worker                             fragShaderText,
912*c8dee2aaSAndroid Build Coastguard Worker                             SkSL::ProgramKind::kGraphiteFragment,
913*c8dee2aaSAndroid Build Coastguard Worker                             settings,
914*c8dee2aaSAndroid Build Coastguard Worker                             &fsSPIRV,
915*c8dee2aaSAndroid Build Coastguard Worker                             &fsInterface,
916*c8dee2aaSAndroid Build Coastguard Worker                             errorHandler)) {
917*c8dee2aaSAndroid Build Coastguard Worker         return false;
918*c8dee2aaSAndroid Build Coastguard Worker     }
919*c8dee2aaSAndroid Build Coastguard Worker     *outFragShaderModule =
920*c8dee2aaSAndroid Build Coastguard Worker             createVulkanShaderModule(sharedContext, fsSPIRV, VK_SHADER_STAGE_FRAGMENT_BIT);
921*c8dee2aaSAndroid Build Coastguard Worker     if (*outFragShaderModule == VK_NULL_HANDLE) {
922*c8dee2aaSAndroid Build Coastguard Worker         return false;
923*c8dee2aaSAndroid Build Coastguard Worker     }
924*c8dee2aaSAndroid Build Coastguard Worker 
925*c8dee2aaSAndroid Build Coastguard Worker     *outVertexShaderModule =
926*c8dee2aaSAndroid Build Coastguard Worker             createVulkanShaderModule(sharedContext, vsSPIRV, VK_SHADER_STAGE_VERTEX_BIT);
927*c8dee2aaSAndroid Build Coastguard Worker     if (*outVertexShaderModule == VK_NULL_HANDLE) {
928*c8dee2aaSAndroid Build Coastguard Worker         destroy_shader_modules(sharedContext, VK_NULL_HANDLE, *outFragShaderModule);
929*c8dee2aaSAndroid Build Coastguard Worker         return false;
930*c8dee2aaSAndroid Build Coastguard Worker     }
931*c8dee2aaSAndroid Build Coastguard Worker 
932*c8dee2aaSAndroid Build Coastguard Worker     setup_shader_stage_info(VK_SHADER_STAGE_VERTEX_BIT,
933*c8dee2aaSAndroid Build Coastguard Worker                             *outVertexShaderModule,
934*c8dee2aaSAndroid Build Coastguard Worker                             &outShaderStageInfo[0]);
935*c8dee2aaSAndroid Build Coastguard Worker 
936*c8dee2aaSAndroid Build Coastguard Worker     setup_shader_stage_info(VK_SHADER_STAGE_FRAGMENT_BIT,
937*c8dee2aaSAndroid Build Coastguard Worker                             *outFragShaderModule,
938*c8dee2aaSAndroid Build Coastguard Worker                             &outShaderStageInfo[1]);
939*c8dee2aaSAndroid Build Coastguard Worker 
940*c8dee2aaSAndroid Build Coastguard Worker     // The load msaa pipeline takes no step or paint uniforms and no instance attributes. It only
941*c8dee2aaSAndroid Build Coastguard Worker     // references one input attachment texture (which does not require a sampler) and one vertex
942*c8dee2aaSAndroid Build Coastguard Worker     // attribute (NDC position)
943*c8dee2aaSAndroid Build Coastguard Worker     skia_private::TArray<DescriptorData> inputAttachmentDescriptors(1);
944*c8dee2aaSAndroid Build Coastguard Worker     inputAttachmentDescriptors.push_back(VulkanGraphicsPipeline::kInputAttachmentDescriptor);
945*c8dee2aaSAndroid Build Coastguard Worker     // TODO: Do we need to consider the potential usage of immutable YCbCr samplers here?
946*c8dee2aaSAndroid Build Coastguard Worker     *outPipelineLayout = setup_pipeline_layout(sharedContext,
947*c8dee2aaSAndroid Build Coastguard Worker                                                /*usesIntrinsicConstantUbo=*/false,
948*c8dee2aaSAndroid Build Coastguard Worker                                                /*useMSAALoadPushConstant=*/true,
949*c8dee2aaSAndroid Build Coastguard Worker                                                /*hasStepUniforms=*/false,
950*c8dee2aaSAndroid Build Coastguard Worker                                                /*hasPaintUniforms=*/false,
951*c8dee2aaSAndroid Build Coastguard Worker                                                /*hasGradientBuffer=*/false,
952*c8dee2aaSAndroid Build Coastguard Worker                                                /*numTextureSamplers=*/0,
953*c8dee2aaSAndroid Build Coastguard Worker                                                /*numInputAttachments=*/1,
954*c8dee2aaSAndroid Build Coastguard Worker                                                /*immutableSamplers=*/{});
955*c8dee2aaSAndroid Build Coastguard Worker 
956*c8dee2aaSAndroid Build Coastguard Worker     if (*outPipelineLayout == VK_NULL_HANDLE) {
957*c8dee2aaSAndroid Build Coastguard Worker         destroy_shader_modules(sharedContext, *outVertexShaderModule, *outFragShaderModule);
958*c8dee2aaSAndroid Build Coastguard Worker         return false;
959*c8dee2aaSAndroid Build Coastguard Worker     }
960*c8dee2aaSAndroid Build Coastguard Worker     return true;
961*c8dee2aaSAndroid Build Coastguard Worker }
962*c8dee2aaSAndroid Build Coastguard Worker 
MakeLoadMSAAPipeline(const VulkanSharedContext * sharedContext,VkShaderModule vsModule,VkShaderModule fsModule,VkPipelineShaderStageCreateInfo * pipelineShaderStages,VkPipelineLayout pipelineLayout,sk_sp<VulkanRenderPass> compatibleRenderPass,VkPipelineCache pipelineCache,const TextureInfo & dstColorAttachmentTexInfo)963*c8dee2aaSAndroid Build Coastguard Worker sk_sp<VulkanGraphicsPipeline> VulkanGraphicsPipeline::MakeLoadMSAAPipeline(
964*c8dee2aaSAndroid Build Coastguard Worker         const VulkanSharedContext* sharedContext,
965*c8dee2aaSAndroid Build Coastguard Worker         VkShaderModule vsModule,
966*c8dee2aaSAndroid Build Coastguard Worker         VkShaderModule fsModule,
967*c8dee2aaSAndroid Build Coastguard Worker         VkPipelineShaderStageCreateInfo* pipelineShaderStages,
968*c8dee2aaSAndroid Build Coastguard Worker         VkPipelineLayout pipelineLayout,
969*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<VulkanRenderPass> compatibleRenderPass,
970*c8dee2aaSAndroid Build Coastguard Worker         VkPipelineCache pipelineCache,
971*c8dee2aaSAndroid Build Coastguard Worker         const TextureInfo& dstColorAttachmentTexInfo) {
972*c8dee2aaSAndroid Build Coastguard Worker 
973*c8dee2aaSAndroid Build Coastguard Worker     int numSamples = dstColorAttachmentTexInfo.numSamples();
974*c8dee2aaSAndroid Build Coastguard Worker 
975*c8dee2aaSAndroid Build Coastguard Worker     // Create vertex attribute list
976*c8dee2aaSAndroid Build Coastguard Worker     SkSpan<const Attribute> loadMSAAVertexAttribs = {};
977*c8dee2aaSAndroid Build Coastguard Worker 
978*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineVertexInputStateCreateInfo vertexInputInfo;
979*c8dee2aaSAndroid Build Coastguard Worker     skia_private::STArray<2, VkVertexInputBindingDescription, true> bindingDescs;
980*c8dee2aaSAndroid Build Coastguard Worker     skia_private::STArray<16, VkVertexInputAttributeDescription> attributeDescs;
981*c8dee2aaSAndroid Build Coastguard Worker     setup_vertex_input_state(loadMSAAVertexAttribs,
982*c8dee2aaSAndroid Build Coastguard Worker                              /*instanceAttrs=*/{}, // Load msaa pipeline takes no instance attribs
983*c8dee2aaSAndroid Build Coastguard Worker                              &vertexInputInfo,
984*c8dee2aaSAndroid Build Coastguard Worker                              &bindingDescs,
985*c8dee2aaSAndroid Build Coastguard Worker                              &attributeDescs);
986*c8dee2aaSAndroid Build Coastguard Worker 
987*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo;
988*c8dee2aaSAndroid Build Coastguard Worker     setup_input_assembly_state(PrimitiveType::kTriangleStrip, &inputAssemblyInfo);
989*c8dee2aaSAndroid Build Coastguard Worker 
990*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineDepthStencilStateCreateInfo depthStencilInfo;
991*c8dee2aaSAndroid Build Coastguard Worker     setup_depth_stencil_state(/*stencilSettings=*/{}, &depthStencilInfo);
992*c8dee2aaSAndroid Build Coastguard Worker 
993*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineViewportStateCreateInfo viewportInfo;
994*c8dee2aaSAndroid Build Coastguard Worker     setup_viewport_scissor_state(&viewportInfo);
995*c8dee2aaSAndroid Build Coastguard Worker 
996*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineMultisampleStateCreateInfo multisampleInfo;
997*c8dee2aaSAndroid Build Coastguard Worker     setup_multisample_state(numSamples, &multisampleInfo);
998*c8dee2aaSAndroid Build Coastguard Worker 
999*c8dee2aaSAndroid Build Coastguard Worker     // We will only have one color blend attachment per pipeline.
1000*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineColorBlendAttachmentState attachmentStates[1];
1001*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineColorBlendStateCreateInfo colorBlendInfo;
1002*c8dee2aaSAndroid Build Coastguard Worker     setup_color_blend_state({}, &colorBlendInfo, attachmentStates);
1003*c8dee2aaSAndroid Build Coastguard Worker 
1004*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineRasterizationStateCreateInfo rasterInfo;
1005*c8dee2aaSAndroid Build Coastguard Worker     // TODO: Check for wire frame mode once that is an available context option within graphite.
1006*c8dee2aaSAndroid Build Coastguard Worker     setup_raster_state(/*isWireframe=*/false, &rasterInfo);
1007*c8dee2aaSAndroid Build Coastguard Worker 
1008*c8dee2aaSAndroid Build Coastguard Worker     VkDynamicState dynamicStates[3];
1009*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineDynamicStateCreateInfo dynamicInfo;
1010*c8dee2aaSAndroid Build Coastguard Worker     setup_dynamic_state(&dynamicInfo, dynamicStates);
1011*c8dee2aaSAndroid Build Coastguard Worker 
1012*c8dee2aaSAndroid Build Coastguard Worker     VkGraphicsPipelineCreateInfo pipelineCreateInfo;
1013*c8dee2aaSAndroid Build Coastguard Worker     memset(&pipelineCreateInfo, 0, sizeof(VkGraphicsPipelineCreateInfo));
1014*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
1015*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pNext = nullptr;
1016*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.flags = 0;
1017*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.stageCount = 2;
1018*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pStages = pipelineShaderStages;
1019*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pVertexInputState = &vertexInputInfo;
1020*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pInputAssemblyState = &inputAssemblyInfo;
1021*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pTessellationState = nullptr;
1022*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pViewportState = &viewportInfo;
1023*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pRasterizationState = &rasterInfo;
1024*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pMultisampleState = &multisampleInfo;
1025*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pDepthStencilState = &depthStencilInfo;
1026*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pColorBlendState = &colorBlendInfo;
1027*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.pDynamicState = &dynamicInfo;
1028*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.layout = pipelineLayout;
1029*c8dee2aaSAndroid Build Coastguard Worker     pipelineCreateInfo.renderPass = compatibleRenderPass->renderPass();
1030*c8dee2aaSAndroid Build Coastguard Worker 
1031*c8dee2aaSAndroid Build Coastguard Worker     VkPipeline vkPipeline;
1032*c8dee2aaSAndroid Build Coastguard Worker     VkResult result;
1033*c8dee2aaSAndroid Build Coastguard Worker     {
1034*c8dee2aaSAndroid Build Coastguard Worker         TRACE_EVENT0_ALWAYS("skia.shaders", "CreateGraphicsPipeline");
1035*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(pipelineCache != VK_NULL_HANDLE);
1036*c8dee2aaSAndroid Build Coastguard Worker         VULKAN_CALL_RESULT(sharedContext,
1037*c8dee2aaSAndroid Build Coastguard Worker                            result,
1038*c8dee2aaSAndroid Build Coastguard Worker                            CreateGraphicsPipelines(sharedContext->device(),
1039*c8dee2aaSAndroid Build Coastguard Worker                                                    pipelineCache,
1040*c8dee2aaSAndroid Build Coastguard Worker                                                    /*createInfoCount=*/1,
1041*c8dee2aaSAndroid Build Coastguard Worker                                                    &pipelineCreateInfo,
1042*c8dee2aaSAndroid Build Coastguard Worker                                                    /*pAllocator=*/nullptr,
1043*c8dee2aaSAndroid Build Coastguard Worker                                                    &vkPipeline));
1044*c8dee2aaSAndroid Build Coastguard Worker     }
1045*c8dee2aaSAndroid Build Coastguard Worker     if (result != VK_SUCCESS) {
1046*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Failed to create pipeline. Error: %d\n", result);
1047*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1048*c8dee2aaSAndroid Build Coastguard Worker     }
1049*c8dee2aaSAndroid Build Coastguard Worker 
1050*c8dee2aaSAndroid Build Coastguard Worker     // This is an internal shader, so don't bother filling in the shader code metadata
1051*c8dee2aaSAndroid Build Coastguard Worker     PipelineInfo pipelineInfo{};
1052*c8dee2aaSAndroid Build Coastguard Worker     return sk_sp<VulkanGraphicsPipeline>(
1053*c8dee2aaSAndroid Build Coastguard Worker             new VulkanGraphicsPipeline(sharedContext,
1054*c8dee2aaSAndroid Build Coastguard Worker                                        pipelineInfo,
1055*c8dee2aaSAndroid Build Coastguard Worker                                        pipelineLayout,
1056*c8dee2aaSAndroid Build Coastguard Worker                                        vkPipeline,
1057*c8dee2aaSAndroid Build Coastguard Worker                                        /*ownsPipelineLayout=*/false,
1058*c8dee2aaSAndroid Build Coastguard Worker                                        /*immutableSamplers=*/{}));
1059*c8dee2aaSAndroid Build Coastguard Worker }
1060*c8dee2aaSAndroid Build Coastguard Worker 
VulkanGraphicsPipeline(const VulkanSharedContext * sharedContext,const PipelineInfo & pipelineInfo,VkPipelineLayout pipelineLayout,VkPipeline pipeline,bool ownsPipelineLayout,skia_private::TArray<sk_sp<VulkanSampler>> immutableSamplers)1061*c8dee2aaSAndroid Build Coastguard Worker VulkanGraphicsPipeline::VulkanGraphicsPipeline(
1062*c8dee2aaSAndroid Build Coastguard Worker         const VulkanSharedContext* sharedContext,
1063*c8dee2aaSAndroid Build Coastguard Worker         const PipelineInfo& pipelineInfo,
1064*c8dee2aaSAndroid Build Coastguard Worker         VkPipelineLayout pipelineLayout,
1065*c8dee2aaSAndroid Build Coastguard Worker         VkPipeline pipeline,
1066*c8dee2aaSAndroid Build Coastguard Worker         bool ownsPipelineLayout,
1067*c8dee2aaSAndroid Build Coastguard Worker         skia_private::TArray<sk_sp<VulkanSampler>> immutableSamplers)
1068*c8dee2aaSAndroid Build Coastguard Worker     : GraphicsPipeline(sharedContext, pipelineInfo)
1069*c8dee2aaSAndroid Build Coastguard Worker     , fPipelineLayout(pipelineLayout)
1070*c8dee2aaSAndroid Build Coastguard Worker     , fPipeline(pipeline)
1071*c8dee2aaSAndroid Build Coastguard Worker     , fOwnsPipelineLayout(ownsPipelineLayout)
1072*c8dee2aaSAndroid Build Coastguard Worker     , fImmutableSamplers(std::move(immutableSamplers)) {}
1073*c8dee2aaSAndroid Build Coastguard Worker 
freeGpuData()1074*c8dee2aaSAndroid Build Coastguard Worker void VulkanGraphicsPipeline::freeGpuData() {
1075*c8dee2aaSAndroid Build Coastguard Worker     auto sharedCtxt = static_cast<const VulkanSharedContext*>(this->sharedContext());
1076*c8dee2aaSAndroid Build Coastguard Worker     if (fPipeline != VK_NULL_HANDLE) {
1077*c8dee2aaSAndroid Build Coastguard Worker         VULKAN_CALL(sharedCtxt->interface(),
1078*c8dee2aaSAndroid Build Coastguard Worker             DestroyPipeline(sharedCtxt->device(), fPipeline, nullptr));
1079*c8dee2aaSAndroid Build Coastguard Worker     }
1080*c8dee2aaSAndroid Build Coastguard Worker     if (fOwnsPipelineLayout && fPipelineLayout != VK_NULL_HANDLE) {
1081*c8dee2aaSAndroid Build Coastguard Worker         VULKAN_CALL(sharedCtxt->interface(),
1082*c8dee2aaSAndroid Build Coastguard Worker                     DestroyPipelineLayout(sharedCtxt->device(), fPipelineLayout, nullptr));
1083*c8dee2aaSAndroid Build Coastguard Worker     }
1084*c8dee2aaSAndroid Build Coastguard Worker }
1085*c8dee2aaSAndroid Build Coastguard Worker 
1086*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite
1087