xref: /aosp_15_r20/external/skia/src/gpu/ganesh/vk/GrVkPipeline.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7 
8 #include "src/gpu/ganesh/vk/GrVkPipeline.h"
9 
10 #include "include/core/SkRect.h"
11 #include "include/core/SkScalar.h"
12 #include "include/core/SkSize.h"
13 #include "include/gpu/ganesh/GrTypes.h"
14 #include "include/private/SkColorData.h"
15 #include "include/private/base/SkTArray.h"
16 #include "include/private/gpu/ganesh/GrTypesPriv.h"
17 #include "src/core/SkTraceEvent.h"
18 #include "src/gpu/Blend.h"
19 #include "src/gpu/Swizzle.h"
20 #include "src/gpu/ganesh/GrCaps.h"
21 #include "src/gpu/ganesh/GrGeometryProcessor.h"
22 #include "src/gpu/ganesh/GrPipeline.h"
23 #include "src/gpu/ganesh/GrProgramInfo.h"
24 #include "src/gpu/ganesh/GrStencilSettings.h"
25 #include "src/gpu/ganesh/GrXferProcessor.h"
26 #include "src/gpu/ganesh/vk/GrVkCaps.h"
27 #include "src/gpu/ganesh/vk/GrVkCommandBuffer.h"
28 #include "src/gpu/ganesh/vk/GrVkGpu.h"
29 #include "src/gpu/ganesh/vk/GrVkUtil.h"
30 #include "src/gpu/vk/VulkanUtilsPriv.h"
31 
32 #include <string.h>
33 #include <array>
34 #include <optional>
35 
36 using namespace skia_private;
37 
38 #if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
39 #include <sanitizer/lsan_interface.h>
40 #endif
41 
attrib_type_to_vkformat(GrVertexAttribType type)42 static inline VkFormat attrib_type_to_vkformat(GrVertexAttribType type) {
43     switch (type) {
44         case kFloat_GrVertexAttribType:
45             return VK_FORMAT_R32_SFLOAT;
46         case kFloat2_GrVertexAttribType:
47             return VK_FORMAT_R32G32_SFLOAT;
48         case kFloat3_GrVertexAttribType:
49             return VK_FORMAT_R32G32B32_SFLOAT;
50         case kFloat4_GrVertexAttribType:
51             return VK_FORMAT_R32G32B32A32_SFLOAT;
52         case kHalf_GrVertexAttribType:
53             return VK_FORMAT_R16_SFLOAT;
54         case kHalf2_GrVertexAttribType:
55             return VK_FORMAT_R16G16_SFLOAT;
56         case kHalf4_GrVertexAttribType:
57             return VK_FORMAT_R16G16B16A16_SFLOAT;
58         case kInt2_GrVertexAttribType:
59             return VK_FORMAT_R32G32_SINT;
60         case kInt3_GrVertexAttribType:
61             return VK_FORMAT_R32G32B32_SINT;
62         case kInt4_GrVertexAttribType:
63             return VK_FORMAT_R32G32B32A32_SINT;
64         case kByte_GrVertexAttribType:
65             return VK_FORMAT_R8_SINT;
66         case kByte2_GrVertexAttribType:
67             return VK_FORMAT_R8G8_SINT;
68         case kByte4_GrVertexAttribType:
69             return VK_FORMAT_R8G8B8A8_SINT;
70         case kUByte_GrVertexAttribType:
71             return VK_FORMAT_R8_UINT;
72         case kUByte2_GrVertexAttribType:
73             return VK_FORMAT_R8G8_UINT;
74         case kUByte4_GrVertexAttribType:
75             return VK_FORMAT_R8G8B8A8_UINT;
76         case kUByte_norm_GrVertexAttribType:
77             return VK_FORMAT_R8_UNORM;
78         case kUByte4_norm_GrVertexAttribType:
79             return VK_FORMAT_R8G8B8A8_UNORM;
80         case kShort2_GrVertexAttribType:
81             return VK_FORMAT_R16G16_SINT;
82         case kShort4_GrVertexAttribType:
83             return VK_FORMAT_R16G16B16A16_SINT;
84         case kUShort2_GrVertexAttribType:
85             return VK_FORMAT_R16G16_UINT;
86         case kUShort2_norm_GrVertexAttribType:
87             return VK_FORMAT_R16G16_UNORM;
88         case kInt_GrVertexAttribType:
89             return VK_FORMAT_R32_SINT;
90         case kUInt_GrVertexAttribType:
91             return VK_FORMAT_R32_UINT;
92         case kUShort_norm_GrVertexAttribType:
93             return VK_FORMAT_R16_UNORM;
94         case kUShort4_norm_GrVertexAttribType:
95             return VK_FORMAT_R16G16B16A16_UNORM;
96     }
97     SK_ABORT("Unknown vertex attrib type");
98 }
99 
setup_vertex_input_state(const GrGeometryProcessor::AttributeSet & vertexAttribs,const GrGeometryProcessor::AttributeSet & instanceAttribs,VkPipelineVertexInputStateCreateInfo * vertexInputInfo,STArray<2,VkVertexInputBindingDescription,true> * bindingDescs,VkVertexInputAttributeDescription * attributeDesc)100 static void setup_vertex_input_state(
101         const GrGeometryProcessor::AttributeSet& vertexAttribs,
102         const GrGeometryProcessor::AttributeSet& instanceAttribs,
103         VkPipelineVertexInputStateCreateInfo* vertexInputInfo,
104         STArray<2, VkVertexInputBindingDescription, true>* bindingDescs,
105         VkVertexInputAttributeDescription* attributeDesc) {
106     int vaCount = vertexAttribs.count();
107     int iaCount = instanceAttribs.count();
108 
109     uint32_t vertexBinding = 0, instanceBinding = 0;
110 
111     int nextBinding = bindingDescs->size();
112     if (vaCount) {
113         vertexBinding = nextBinding++;
114     }
115 
116     if (iaCount) {
117         instanceBinding = nextBinding;
118     }
119 
120     // setup attribute descriptions
121     int attribIndex = 0;
122     for (auto attrib : vertexAttribs) {
123         VkVertexInputAttributeDescription& vkAttrib = attributeDesc[attribIndex];
124         vkAttrib.location = attribIndex++;  // for now assume location = attribIndex
125         vkAttrib.binding = vertexBinding;
126         vkAttrib.format = attrib_type_to_vkformat(attrib.cpuType());
127         vkAttrib.offset = *attrib.offset();
128     }
129 
130     for (auto attrib : instanceAttribs) {
131         VkVertexInputAttributeDescription& vkAttrib = attributeDesc[attribIndex];
132         vkAttrib.location = attribIndex++;  // for now assume location = attribIndex
133         vkAttrib.binding = instanceBinding;
134         vkAttrib.format = attrib_type_to_vkformat(attrib.cpuType());
135         vkAttrib.offset = *attrib.offset();
136     }
137 
138     if (vaCount) {
139         bindingDescs->push_back() = {
140                 vertexBinding,
141                 (uint32_t) vertexAttribs.stride(),
142                 VK_VERTEX_INPUT_RATE_VERTEX
143         };
144     }
145     if (iaCount) {
146         bindingDescs->push_back() = {
147                 instanceBinding,
148                 (uint32_t) instanceAttribs.stride(),
149                 VK_VERTEX_INPUT_RATE_INSTANCE
150         };
151     }
152 
153     memset(vertexInputInfo, 0, sizeof(VkPipelineVertexInputStateCreateInfo));
154     vertexInputInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
155     vertexInputInfo->pNext = nullptr;
156     vertexInputInfo->flags = 0;
157     vertexInputInfo->vertexBindingDescriptionCount = bindingDescs->size();
158     vertexInputInfo->pVertexBindingDescriptions = bindingDescs->begin();
159     vertexInputInfo->vertexAttributeDescriptionCount = vaCount + iaCount;
160     vertexInputInfo->pVertexAttributeDescriptions = attributeDesc;
161 }
162 
gr_primitive_type_to_vk_topology(GrPrimitiveType primitiveType)163 static VkPrimitiveTopology gr_primitive_type_to_vk_topology(GrPrimitiveType primitiveType) {
164     switch (primitiveType) {
165         case GrPrimitiveType::kTriangles:
166             return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
167         case GrPrimitiveType::kTriangleStrip:
168             return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
169         case GrPrimitiveType::kPoints:
170             return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
171         case GrPrimitiveType::kLines:
172             return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
173         case GrPrimitiveType::kLineStrip:
174             return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
175     }
176     SkUNREACHABLE;
177 }
178 
setup_input_assembly_state(GrPrimitiveType primitiveType,VkPipelineInputAssemblyStateCreateInfo * inputAssemblyInfo)179 static void setup_input_assembly_state(GrPrimitiveType primitiveType,
180                                        VkPipelineInputAssemblyStateCreateInfo* inputAssemblyInfo) {
181     memset(inputAssemblyInfo, 0, sizeof(VkPipelineInputAssemblyStateCreateInfo));
182     inputAssemblyInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
183     inputAssemblyInfo->pNext = nullptr;
184     inputAssemblyInfo->flags = 0;
185     inputAssemblyInfo->primitiveRestartEnable = false;
186     inputAssemblyInfo->topology = gr_primitive_type_to_vk_topology(primitiveType);
187 }
188 
stencil_op_to_vk_stencil_op(GrStencilOp op)189 static VkStencilOp stencil_op_to_vk_stencil_op(GrStencilOp op) {
190     static const VkStencilOp gTable[] = {
191         VK_STENCIL_OP_KEEP,                 // kKeep
192         VK_STENCIL_OP_ZERO,                 // kZero
193         VK_STENCIL_OP_REPLACE,              // kReplace
194         VK_STENCIL_OP_INVERT,               // kInvert
195         VK_STENCIL_OP_INCREMENT_AND_WRAP,   // kIncWrap
196         VK_STENCIL_OP_DECREMENT_AND_WRAP,   // kDecWrap
197         VK_STENCIL_OP_INCREMENT_AND_CLAMP,  // kIncClamp
198         VK_STENCIL_OP_DECREMENT_AND_CLAMP,  // kDecClamp
199     };
200     static_assert(std::size(gTable) == kGrStencilOpCount);
201     static_assert(0 == (int)GrStencilOp::kKeep);
202     static_assert(1 == (int)GrStencilOp::kZero);
203     static_assert(2 == (int)GrStencilOp::kReplace);
204     static_assert(3 == (int)GrStencilOp::kInvert);
205     static_assert(4 == (int)GrStencilOp::kIncWrap);
206     static_assert(5 == (int)GrStencilOp::kDecWrap);
207     static_assert(6 == (int)GrStencilOp::kIncClamp);
208     static_assert(7 == (int)GrStencilOp::kDecClamp);
209     SkASSERT(op < (GrStencilOp)kGrStencilOpCount);
210     return gTable[(int)op];
211 }
212 
stencil_func_to_vk_compare_op(GrStencilTest test)213 static VkCompareOp stencil_func_to_vk_compare_op(GrStencilTest test) {
214     static const VkCompareOp gTable[] = {
215         VK_COMPARE_OP_ALWAYS,              // kAlways
216         VK_COMPARE_OP_NEVER,               // kNever
217         VK_COMPARE_OP_GREATER,             // kGreater
218         VK_COMPARE_OP_GREATER_OR_EQUAL,    // kGEqual
219         VK_COMPARE_OP_LESS,                // kLess
220         VK_COMPARE_OP_LESS_OR_EQUAL,       // kLEqual
221         VK_COMPARE_OP_EQUAL,               // kEqual
222         VK_COMPARE_OP_NOT_EQUAL,           // kNotEqual
223     };
224     static_assert(std::size(gTable) == kGrStencilTestCount);
225     static_assert(0 == (int)GrStencilTest::kAlways);
226     static_assert(1 == (int)GrStencilTest::kNever);
227     static_assert(2 == (int)GrStencilTest::kGreater);
228     static_assert(3 == (int)GrStencilTest::kGEqual);
229     static_assert(4 == (int)GrStencilTest::kLess);
230     static_assert(5 == (int)GrStencilTest::kLEqual);
231     static_assert(6 == (int)GrStencilTest::kEqual);
232     static_assert(7 == (int)GrStencilTest::kNotEqual);
233     SkASSERT(test < (GrStencilTest)kGrStencilTestCount);
234 
235     return gTable[(int)test];
236 }
237 
setup_stencil_op_state(VkStencilOpState * opState,const GrStencilSettings::Face & stencilFace)238 static void setup_stencil_op_state(
239         VkStencilOpState* opState, const GrStencilSettings::Face& stencilFace) {
240     opState->failOp = stencil_op_to_vk_stencil_op(stencilFace.fFailOp);
241     opState->passOp = stencil_op_to_vk_stencil_op(stencilFace.fPassOp);
242     opState->depthFailOp = opState->failOp;
243     opState->compareOp = stencil_func_to_vk_compare_op(stencilFace.fTest);
244     opState->compareMask = stencilFace.fTestMask;
245     opState->writeMask = stencilFace.fWriteMask;
246     opState->reference = stencilFace.fRef;
247 }
248 
setup_depth_stencil_state(const GrStencilSettings & stencilSettings,GrSurfaceOrigin origin,VkPipelineDepthStencilStateCreateInfo * stencilInfo)249 static void setup_depth_stencil_state(
250         const GrStencilSettings& stencilSettings,
251         GrSurfaceOrigin origin,
252         VkPipelineDepthStencilStateCreateInfo* stencilInfo) {
253 
254     memset(stencilInfo, 0, sizeof(VkPipelineDepthStencilStateCreateInfo));
255     stencilInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
256     stencilInfo->pNext = nullptr;
257     stencilInfo->flags = 0;
258     // set depth testing defaults
259     stencilInfo->depthTestEnable = VK_FALSE;
260     stencilInfo->depthWriteEnable = VK_FALSE;
261     stencilInfo->depthCompareOp = VK_COMPARE_OP_ALWAYS;
262     stencilInfo->depthBoundsTestEnable = VK_FALSE;
263     stencilInfo->stencilTestEnable = !stencilSettings.isDisabled();
264     if (!stencilSettings.isDisabled()) {
265         if (!stencilSettings.isTwoSided()) {
266             setup_stencil_op_state(&stencilInfo->front, stencilSettings.singleSidedFace());
267             stencilInfo->back = stencilInfo->front;
268         } else {
269             setup_stencil_op_state(&stencilInfo->front, stencilSettings.postOriginCCWFace(origin));
270             setup_stencil_op_state(&stencilInfo->back, stencilSettings.postOriginCWFace(origin));
271         }
272     }
273     stencilInfo->minDepthBounds = 0.0f;
274     stencilInfo->maxDepthBounds = 1.0f;
275 }
276 
setup_viewport_scissor_state(VkPipelineViewportStateCreateInfo * viewportInfo)277 static void setup_viewport_scissor_state(VkPipelineViewportStateCreateInfo* viewportInfo) {
278     memset(viewportInfo, 0, sizeof(VkPipelineViewportStateCreateInfo));
279     viewportInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
280     viewportInfo->pNext = nullptr;
281     viewportInfo->flags = 0;
282 
283     viewportInfo->viewportCount = 1;
284     viewportInfo->pViewports = nullptr; // This is set dynamically
285 
286     viewportInfo->scissorCount = 1;
287     viewportInfo->pScissors = nullptr; // This is set dynamically
288 
289     SkASSERT(viewportInfo->viewportCount == viewportInfo->scissorCount);
290 }
291 
setup_multisample_state(int numSamples,const GrCaps * caps,VkPipelineMultisampleStateCreateInfo * multisampleInfo)292 static void setup_multisample_state(int numSamples,
293                                     const GrCaps* caps,
294                                     VkPipelineMultisampleStateCreateInfo* multisampleInfo) {
295     memset(multisampleInfo, 0, sizeof(VkPipelineMultisampleStateCreateInfo));
296     multisampleInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
297     multisampleInfo->pNext = nullptr;
298     multisampleInfo->flags = 0;
299     SkAssertResult(skgpu::SampleCountToVkSampleCount(numSamples,
300                                                      &multisampleInfo->rasterizationSamples));
301     multisampleInfo->sampleShadingEnable = VK_FALSE;
302     multisampleInfo->minSampleShading = 0.0f;
303     multisampleInfo->pSampleMask = nullptr;
304     multisampleInfo->alphaToCoverageEnable = VK_FALSE;
305     multisampleInfo->alphaToOneEnable = VK_FALSE;
306 }
307 
blend_coeff_to_vk_blend(skgpu::BlendCoeff coeff)308 static VkBlendFactor blend_coeff_to_vk_blend(skgpu::BlendCoeff coeff) {
309     switch (coeff) {
310         case skgpu::BlendCoeff::kZero:
311             return VK_BLEND_FACTOR_ZERO;
312         case skgpu::BlendCoeff::kOne:
313             return VK_BLEND_FACTOR_ONE;
314         case skgpu::BlendCoeff::kSC:
315             return VK_BLEND_FACTOR_SRC_COLOR;
316         case skgpu::BlendCoeff::kISC:
317             return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
318         case skgpu::BlendCoeff::kDC:
319             return VK_BLEND_FACTOR_DST_COLOR;
320         case skgpu::BlendCoeff::kIDC:
321             return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
322         case skgpu::BlendCoeff::kSA:
323             return VK_BLEND_FACTOR_SRC_ALPHA;
324         case skgpu::BlendCoeff::kISA:
325             return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
326         case skgpu::BlendCoeff::kDA:
327             return VK_BLEND_FACTOR_DST_ALPHA;
328         case skgpu::BlendCoeff::kIDA:
329             return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
330         case skgpu::BlendCoeff::kConstC:
331             return VK_BLEND_FACTOR_CONSTANT_COLOR;
332         case skgpu::BlendCoeff::kIConstC:
333             return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
334         case skgpu::BlendCoeff::kS2C:
335             return VK_BLEND_FACTOR_SRC1_COLOR;
336         case skgpu::BlendCoeff::kIS2C:
337             return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
338         case skgpu::BlendCoeff::kS2A:
339             return VK_BLEND_FACTOR_SRC1_ALPHA;
340         case skgpu::BlendCoeff::kIS2A:
341             return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
342         case skgpu::BlendCoeff::kIllegal:
343             return VK_BLEND_FACTOR_ZERO;
344     }
345     SkUNREACHABLE;
346 }
347 
blend_equation_to_vk_blend_op(skgpu::BlendEquation equation)348 static VkBlendOp blend_equation_to_vk_blend_op(skgpu::BlendEquation equation) {
349     static const VkBlendOp gTable[] = {
350         // Basic blend ops
351         VK_BLEND_OP_ADD,
352         VK_BLEND_OP_SUBTRACT,
353         VK_BLEND_OP_REVERSE_SUBTRACT,
354 
355         // Advanced blend ops
356         VK_BLEND_OP_SCREEN_EXT,
357         VK_BLEND_OP_OVERLAY_EXT,
358         VK_BLEND_OP_DARKEN_EXT,
359         VK_BLEND_OP_LIGHTEN_EXT,
360         VK_BLEND_OP_COLORDODGE_EXT,
361         VK_BLEND_OP_COLORBURN_EXT,
362         VK_BLEND_OP_HARDLIGHT_EXT,
363         VK_BLEND_OP_SOFTLIGHT_EXT,
364         VK_BLEND_OP_DIFFERENCE_EXT,
365         VK_BLEND_OP_EXCLUSION_EXT,
366         VK_BLEND_OP_MULTIPLY_EXT,
367         VK_BLEND_OP_HSL_HUE_EXT,
368         VK_BLEND_OP_HSL_SATURATION_EXT,
369         VK_BLEND_OP_HSL_COLOR_EXT,
370         VK_BLEND_OP_HSL_LUMINOSITY_EXT,
371 
372         // Illegal.
373         VK_BLEND_OP_ADD,
374     };
375     static_assert(0 == (int)skgpu::BlendEquation::kAdd);
376     static_assert(1 == (int)skgpu::BlendEquation::kSubtract);
377     static_assert(2 == (int)skgpu::BlendEquation::kReverseSubtract);
378     static_assert(3 == (int)skgpu::BlendEquation::kScreen);
379     static_assert(4 == (int)skgpu::BlendEquation::kOverlay);
380     static_assert(5 == (int)skgpu::BlendEquation::kDarken);
381     static_assert(6 == (int)skgpu::BlendEquation::kLighten);
382     static_assert(7 == (int)skgpu::BlendEquation::kColorDodge);
383     static_assert(8 == (int)skgpu::BlendEquation::kColorBurn);
384     static_assert(9 == (int)skgpu::BlendEquation::kHardLight);
385     static_assert(10 == (int)skgpu::BlendEquation::kSoftLight);
386     static_assert(11 == (int)skgpu::BlendEquation::kDifference);
387     static_assert(12 == (int)skgpu::BlendEquation::kExclusion);
388     static_assert(13 == (int)skgpu::BlendEquation::kMultiply);
389     static_assert(14 == (int)skgpu::BlendEquation::kHSLHue);
390     static_assert(15 == (int)skgpu::BlendEquation::kHSLSaturation);
391     static_assert(16 == (int)skgpu::BlendEquation::kHSLColor);
392     static_assert(17 == (int)skgpu::BlendEquation::kHSLLuminosity);
393     static_assert(std::size(gTable) == skgpu::kBlendEquationCnt);
394 
395     SkASSERT((unsigned)equation < skgpu::kBlendEquationCnt);
396     return gTable[(int)equation];
397 }
398 
setup_color_blend_state(const skgpu::BlendInfo & blendInfo,VkPipelineColorBlendStateCreateInfo * colorBlendInfo,VkPipelineColorBlendAttachmentState * attachmentState)399 static void setup_color_blend_state(const skgpu::BlendInfo& blendInfo,
400                                     VkPipelineColorBlendStateCreateInfo* colorBlendInfo,
401                                     VkPipelineColorBlendAttachmentState* attachmentState) {
402     skgpu::BlendEquation equation = blendInfo.fEquation;
403     skgpu::BlendCoeff srcCoeff = blendInfo.fSrcBlend;
404     skgpu::BlendCoeff dstCoeff = blendInfo.fDstBlend;
405     bool blendOff = skgpu::BlendShouldDisable(equation, srcCoeff, dstCoeff);
406 
407     memset(attachmentState, 0, sizeof(VkPipelineColorBlendAttachmentState));
408     attachmentState->blendEnable = !blendOff;
409     if (!blendOff) {
410         attachmentState->srcColorBlendFactor = blend_coeff_to_vk_blend(srcCoeff);
411         attachmentState->dstColorBlendFactor = blend_coeff_to_vk_blend(dstCoeff);
412         attachmentState->colorBlendOp = blend_equation_to_vk_blend_op(equation);
413         attachmentState->srcAlphaBlendFactor = blend_coeff_to_vk_blend(srcCoeff);
414         attachmentState->dstAlphaBlendFactor = blend_coeff_to_vk_blend(dstCoeff);
415         attachmentState->alphaBlendOp = blend_equation_to_vk_blend_op(equation);
416     }
417 
418     if (!blendInfo.fWritesColor) {
419         attachmentState->colorWriteMask = 0;
420     } else {
421         attachmentState->colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
422                                           VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
423     }
424 
425     memset(colorBlendInfo, 0, sizeof(VkPipelineColorBlendStateCreateInfo));
426     colorBlendInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
427     colorBlendInfo->pNext = nullptr;
428     colorBlendInfo->flags = 0;
429     colorBlendInfo->logicOpEnable = VK_FALSE;
430     colorBlendInfo->attachmentCount = 1;
431     colorBlendInfo->pAttachments = attachmentState;
432     // colorBlendInfo->blendConstants is set dynamically
433 }
434 
setup_raster_state(bool isWireframe,const GrCaps * caps,VkPipelineRasterizationStateCreateInfo * rasterInfo)435 static void setup_raster_state(bool isWireframe,
436                                const GrCaps* caps,
437                                VkPipelineRasterizationStateCreateInfo* rasterInfo) {
438     memset(rasterInfo, 0, sizeof(VkPipelineRasterizationStateCreateInfo));
439     rasterInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
440     rasterInfo->pNext = nullptr;
441     rasterInfo->flags = 0;
442     rasterInfo->depthClampEnable = VK_FALSE;
443     rasterInfo->rasterizerDiscardEnable = VK_FALSE;
444     rasterInfo->polygonMode = (caps->wireframeMode() || isWireframe) ?
445             VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL;
446     rasterInfo->cullMode = VK_CULL_MODE_NONE;
447     rasterInfo->frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
448     rasterInfo->depthBiasEnable = VK_FALSE;
449     rasterInfo->depthBiasConstantFactor = 0.0f;
450     rasterInfo->depthBiasClamp = 0.0f;
451     rasterInfo->depthBiasSlopeFactor = 0.0f;
452     rasterInfo->lineWidth = 1.0f;
453 }
454 
setup_conservative_raster_info(VkPipelineRasterizationConservativeStateCreateInfoEXT * conservativeRasterInfo)455 static void setup_conservative_raster_info(
456         VkPipelineRasterizationConservativeStateCreateInfoEXT* conservativeRasterInfo) {
457     memset(conservativeRasterInfo, 0,
458            sizeof(VkPipelineRasterizationConservativeStateCreateInfoEXT));
459     conservativeRasterInfo->sType =
460             VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT;
461     conservativeRasterInfo->pNext = nullptr;
462     conservativeRasterInfo->flags = 0;
463     conservativeRasterInfo->conservativeRasterizationMode =
464             VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
465     conservativeRasterInfo->extraPrimitiveOverestimationSize = 0;
466 }
467 
setup_dynamic_state(VkPipelineDynamicStateCreateInfo * dynamicInfo,VkDynamicState * dynamicStates)468 static void setup_dynamic_state(VkPipelineDynamicStateCreateInfo* dynamicInfo,
469                                 VkDynamicState* dynamicStates) {
470     memset(dynamicInfo, 0, sizeof(VkPipelineDynamicStateCreateInfo));
471     dynamicInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
472     dynamicInfo->pNext = VK_NULL_HANDLE;
473     dynamicInfo->flags = 0;
474     dynamicStates[0] = VK_DYNAMIC_STATE_VIEWPORT;
475     dynamicStates[1] = VK_DYNAMIC_STATE_SCISSOR;
476     dynamicStates[2] = VK_DYNAMIC_STATE_BLEND_CONSTANTS;
477     dynamicInfo->dynamicStateCount = 3;
478     dynamicInfo->pDynamicStates = dynamicStates;
479 }
480 
Make(GrVkGpu * gpu,const GrGeometryProcessor::AttributeSet & vertexAttribs,const GrGeometryProcessor::AttributeSet & instanceAttribs,GrPrimitiveType primitiveType,GrSurfaceOrigin origin,const GrStencilSettings & stencilSettings,int numSamples,bool isHWAntialiasState,const skgpu::BlendInfo & blendInfo,bool isWireframe,bool useConservativeRaster,uint32_t subpass,VkPipelineShaderStageCreateInfo * shaderStageInfo,int shaderStageCount,VkRenderPass compatibleRenderPass,VkPipelineLayout layout,bool ownsLayout,VkPipelineCache cache)481 sk_sp<GrVkPipeline> GrVkPipeline::Make(GrVkGpu* gpu,
482                                    const GrGeometryProcessor::AttributeSet& vertexAttribs,
483                                    const GrGeometryProcessor::AttributeSet& instanceAttribs,
484                                    GrPrimitiveType primitiveType,
485                                    GrSurfaceOrigin origin,
486                                    const GrStencilSettings& stencilSettings,
487                                    int numSamples,
488                                    bool isHWAntialiasState,
489                                    const skgpu::BlendInfo& blendInfo,
490                                    bool isWireframe,
491                                    bool useConservativeRaster,
492                                    uint32_t subpass,
493                                    VkPipelineShaderStageCreateInfo* shaderStageInfo,
494                                    int shaderStageCount,
495                                    VkRenderPass compatibleRenderPass,
496                                    VkPipelineLayout layout,
497                                    bool ownsLayout,
498                                    VkPipelineCache cache) {
499     VkPipelineVertexInputStateCreateInfo vertexInputInfo;
500     STArray<2, VkVertexInputBindingDescription, true> bindingDescs;
501     STArray<16, VkVertexInputAttributeDescription> attributeDesc;
502     int totalAttributeCnt = vertexAttribs.count() + instanceAttribs.count();
503     SkASSERT(totalAttributeCnt <= gpu->vkCaps().maxVertexAttributes());
504     VkVertexInputAttributeDescription* pAttribs = attributeDesc.push_back_n(totalAttributeCnt);
505     setup_vertex_input_state(vertexAttribs, instanceAttribs, &vertexInputInfo, &bindingDescs,
506                              pAttribs);
507 
508     VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo;
509     setup_input_assembly_state(primitiveType, &inputAssemblyInfo);
510 
511     VkPipelineDepthStencilStateCreateInfo depthStencilInfo;
512     setup_depth_stencil_state(stencilSettings, origin, &depthStencilInfo);
513 
514     VkPipelineViewportStateCreateInfo viewportInfo;
515     setup_viewport_scissor_state(&viewportInfo);
516 
517     VkPipelineMultisampleStateCreateInfo multisampleInfo;
518     setup_multisample_state(numSamples, gpu->caps(), &multisampleInfo);
519 
520     // We will only have one color attachment per pipeline.
521     VkPipelineColorBlendAttachmentState attachmentStates[1];
522     VkPipelineColorBlendStateCreateInfo colorBlendInfo;
523     setup_color_blend_state(blendInfo, &colorBlendInfo, attachmentStates);
524 
525     VkPipelineRasterizationStateCreateInfo rasterInfo;
526     setup_raster_state(isWireframe, gpu->caps(), &rasterInfo);
527 
528     VkPipelineRasterizationConservativeStateCreateInfoEXT conservativeRasterInfo;
529     if (useConservativeRaster) {
530         SkASSERT(gpu->caps()->conservativeRasterSupport());
531         setup_conservative_raster_info(&conservativeRasterInfo);
532         conservativeRasterInfo.pNext = rasterInfo.pNext;
533         rasterInfo.pNext = &conservativeRasterInfo;
534     }
535 
536     VkDynamicState dynamicStates[3];
537     VkPipelineDynamicStateCreateInfo dynamicInfo;
538     setup_dynamic_state(&dynamicInfo, dynamicStates);
539 
540     VkGraphicsPipelineCreateInfo pipelineCreateInfo;
541     memset(&pipelineCreateInfo, 0, sizeof(VkGraphicsPipelineCreateInfo));
542     pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
543     pipelineCreateInfo.pNext = nullptr;
544     pipelineCreateInfo.flags = 0;
545     pipelineCreateInfo.stageCount = shaderStageCount;
546     pipelineCreateInfo.pStages = shaderStageInfo;
547     pipelineCreateInfo.pVertexInputState = &vertexInputInfo;
548     pipelineCreateInfo.pInputAssemblyState = &inputAssemblyInfo;
549     pipelineCreateInfo.pTessellationState = nullptr;
550     pipelineCreateInfo.pViewportState = &viewportInfo;
551     pipelineCreateInfo.pRasterizationState = &rasterInfo;
552     pipelineCreateInfo.pMultisampleState = &multisampleInfo;
553     pipelineCreateInfo.pDepthStencilState = &depthStencilInfo;
554     pipelineCreateInfo.pColorBlendState = &colorBlendInfo;
555     pipelineCreateInfo.pDynamicState = &dynamicInfo;
556     pipelineCreateInfo.layout = layout;
557     pipelineCreateInfo.renderPass = compatibleRenderPass;
558     pipelineCreateInfo.subpass = subpass;
559     pipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
560     pipelineCreateInfo.basePipelineIndex = -1;
561 
562     VkPipeline vkPipeline;
563     VkResult err;
564     {
565         TRACE_EVENT0_ALWAYS("skia.shaders", "CreateGraphicsPipeline");
566 #if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
567         // skia:8712
568         __lsan::ScopedDisabler lsanDisabler;
569 #endif
570         GR_VK_CALL_RESULT(gpu, err, CreateGraphicsPipelines(gpu->device(), cache, 1,
571                                                             &pipelineCreateInfo, nullptr,
572                                                             &vkPipeline));
573     }
574     if (err) {
575         SkDebugf("Failed to create pipeline. Error: %d\n", err);
576         return nullptr;
577     }
578 
579     if (!ownsLayout) {
580         layout = VK_NULL_HANDLE;
581     }
582     return sk_sp<GrVkPipeline>(new GrVkPipeline(gpu, vkPipeline, layout));
583 }
584 
Make(GrVkGpu * gpu,const GrProgramInfo & programInfo,VkPipelineShaderStageCreateInfo * shaderStageInfo,int shaderStageCount,VkRenderPass compatibleRenderPass,VkPipelineLayout layout,VkPipelineCache cache,uint32_t subpass)585 sk_sp<GrVkPipeline> GrVkPipeline::Make(GrVkGpu* gpu,
586                                        const GrProgramInfo& programInfo,
587                                        VkPipelineShaderStageCreateInfo* shaderStageInfo,
588                                        int shaderStageCount,
589                                        VkRenderPass compatibleRenderPass,
590                                        VkPipelineLayout layout,
591                                        VkPipelineCache cache,
592                                        uint32_t subpass) {
593     const GrGeometryProcessor& geomProc = programInfo.geomProc();
594     const GrPipeline& pipeline = programInfo.pipeline();
595 
596     return Make(gpu,
597                 geomProc.vertexAttributes(),
598                 geomProc.instanceAttributes(),
599                 programInfo.primitiveType(),
600                 programInfo.origin(),
601                 programInfo.nonGLStencilSettings(),
602                 programInfo.numSamples(),
603                 programInfo.numSamples() > 1,
604                 pipeline.getXferProcessor().getBlendInfo(),
605                 pipeline.isWireframe(),
606                 pipeline.usesConservativeRaster(),
607                 subpass,
608                 shaderStageInfo,
609                 shaderStageCount,
610                 compatibleRenderPass,
611                 layout,
612                 /*ownsLayout=*/true,
613                 cache);
614 }
615 
freeGPUData() const616 void GrVkPipeline::freeGPUData() const {
617     GR_VK_CALL(fGpu->vkInterface(), DestroyPipeline(fGpu->device(), fPipeline, nullptr));
618     if (fPipelineLayout != VK_NULL_HANDLE) {
619         GR_VK_CALL(fGpu->vkInterface(),
620                    DestroyPipelineLayout(fGpu->device(), fPipelineLayout, nullptr));
621     }
622 }
623 
SetDynamicScissorRectState(GrVkGpu * gpu,GrVkCommandBuffer * cmdBuffer,SkISize colorAttachmentDimensions,GrSurfaceOrigin rtOrigin,const SkIRect & scissorRect)624 void GrVkPipeline::SetDynamicScissorRectState(GrVkGpu* gpu,
625                                               GrVkCommandBuffer* cmdBuffer,
626                                               SkISize colorAttachmentDimensions,
627                                               GrSurfaceOrigin rtOrigin,
628                                               const SkIRect& scissorRect) {
629     SkASSERT(scissorRect.isEmpty() ||
630              SkIRect::MakeSize(colorAttachmentDimensions).contains(scissorRect));
631 
632     VkRect2D scissor;
633     scissor.offset.x = scissorRect.fLeft;
634     scissor.extent.width = scissorRect.width();
635     if (kTopLeft_GrSurfaceOrigin == rtOrigin) {
636         scissor.offset.y = scissorRect.fTop;
637     } else {
638         SkASSERT(kBottomLeft_GrSurfaceOrigin == rtOrigin);
639         scissor.offset.y = colorAttachmentDimensions.height() - scissorRect.fBottom;
640     }
641     scissor.extent.height = scissorRect.height();
642 
643     SkASSERT(scissor.offset.x >= 0);
644     SkASSERT(scissor.offset.y >= 0);
645     cmdBuffer->setScissor(gpu, 0, 1, &scissor);
646 }
647 
SetDynamicViewportState(GrVkGpu * gpu,GrVkCommandBuffer * cmdBuffer,SkISize colorAttachmentDimensions)648 void GrVkPipeline::SetDynamicViewportState(GrVkGpu* gpu,
649                                            GrVkCommandBuffer* cmdBuffer,
650                                            SkISize colorAttachmentDimensions) {
651     // We always use one viewport the size of the RT
652     VkViewport viewport;
653     viewport.x = 0.0f;
654     viewport.y = 0.0f;
655     viewport.width = SkIntToScalar(colorAttachmentDimensions.width());
656     viewport.height = SkIntToScalar(colorAttachmentDimensions.height());
657     viewport.minDepth = 0.0f;
658     viewport.maxDepth = 1.0f;
659     cmdBuffer->setViewport(gpu, 0, 1, &viewport);
660 }
661 
SetDynamicBlendConstantState(GrVkGpu * gpu,GrVkCommandBuffer * cmdBuffer,const skgpu::Swizzle & swizzle,const GrXferProcessor & xferProcessor)662 void GrVkPipeline::SetDynamicBlendConstantState(GrVkGpu* gpu,
663                                                 GrVkCommandBuffer* cmdBuffer,
664                                                 const skgpu::Swizzle& swizzle,
665                                                 const GrXferProcessor& xferProcessor) {
666     const skgpu::BlendInfo& blendInfo = xferProcessor.getBlendInfo();
667     skgpu::BlendCoeff srcCoeff = blendInfo.fSrcBlend;
668     skgpu::BlendCoeff dstCoeff = blendInfo.fDstBlend;
669     float floatColors[4];
670     if (skgpu::BlendCoeffRefsConstant(srcCoeff) || skgpu::BlendCoeffRefsConstant(dstCoeff)) {
671         // Swizzle the blend to match what the shader will output.
672         SkPMColor4f blendConst = swizzle.applyTo(blendInfo.fBlendConstant);
673         floatColors[0] = blendConst.fR;
674         floatColors[1] = blendConst.fG;
675         floatColors[2] = blendConst.fB;
676         floatColors[3] = blendConst.fA;
677         cmdBuffer->setBlendConstants(gpu, floatColors);
678     }
679 }
680