blob: b72b05b850717564e4b73661401a98355982aa20 [file] [log] [blame]
Greg Daniel164a9f02016-02-22 09:56:40 -05001/*
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 "GrVkPipeline.h"
9
10#include "GrGeometryProcessor.h"
11#include "GrPipeline.h"
egdaniel470d77a2016-03-18 12:50:27 -070012#include "GrVkCommandBuffer.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050013#include "GrVkGpu.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050014#include "GrVkRenderTarget.h"
15#include "GrVkUtil.h"
16
csmartdaltonb37cb232017-02-08 14:56:27 -050017static inline VkFormat attrib_type_to_vkformat(GrVertexAttribType type) {
18 switch (type) {
19 case kFloat_GrVertexAttribType:
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040020 case kHalf_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050021 return VK_FORMAT_R32_SFLOAT;
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040022 case kFloat2_GrVertexAttribType:
23 case kHalf2_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050024 return VK_FORMAT_R32G32_SFLOAT;
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040025 case kFloat3_GrVertexAttribType:
26 case kHalf3_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050027 return VK_FORMAT_R32G32B32_SFLOAT;
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040028 case kFloat4_GrVertexAttribType:
29 case kHalf4_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050030 return VK_FORMAT_R32G32B32A32_SFLOAT;
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040031 case kInt2_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050032 return VK_FORMAT_R32G32_SINT;
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040033 case kInt3_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050034 return VK_FORMAT_R32G32B32_SINT;
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040035 case kInt4_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050036 return VK_FORMAT_R32G32B32A32_SINT;
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040037 case kUByte_norm_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050038 return VK_FORMAT_R8_UNORM;
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040039 case kUByte4_norm_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050040 return VK_FORMAT_R8G8B8A8_UNORM;
Chris Daltona045eea2017-10-24 13:22:10 -060041 case kShort2_GrVertexAttribType:
42 return VK_FORMAT_R16G16_SINT;
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040043 case kUShort2_GrVertexAttribType:
Robert Phillips8296e752017-08-25 08:45:21 -040044 return VK_FORMAT_R16G16_UINT;
Chris Daltona045eea2017-10-24 13:22:10 -060045 case kUShort2_norm_GrVertexAttribType:
46 return VK_FORMAT_R16G16_UNORM;
csmartdaltonb37cb232017-02-08 14:56:27 -050047 case kInt_GrVertexAttribType:
48 return VK_FORMAT_R32_SINT;
49 case kUint_GrVertexAttribType:
50 return VK_FORMAT_R32_UINT;
51 }
Ben Wagnerb4aab9a2017-08-16 10:53:04 -040052 SK_ABORT("Unknown vertex attrib type");
csmartdaltonb37cb232017-02-08 14:56:27 -050053 return VK_FORMAT_UNDEFINED;
Greg Daniel164a9f02016-02-22 09:56:40 -050054}
55
56static void setup_vertex_input_state(const GrPrimitiveProcessor& primProc,
Chris Dalton1d616352017-05-31 12:51:23 -060057 VkPipelineVertexInputStateCreateInfo* vertexInputInfo,
58 SkSTArray<2, VkVertexInputBindingDescription, true>* bindingDescs,
59 VkVertexInputAttributeDescription* attributeDesc) {
Kevin Lubick42846132018-01-05 10:11:11 -050060 uint32_t vertexBinding = 0, instanceBinding = 0;
Chris Dalton1d616352017-05-31 12:51:23 -060061
62 if (primProc.hasVertexAttribs()) {
63 vertexBinding = bindingDescs->count();
64 bindingDescs->push_back() = {
65 vertexBinding,
66 (uint32_t) primProc.getVertexStride(),
67 VK_VERTEX_INPUT_RATE_VERTEX
68 };
69 }
70
71 if (primProc.hasInstanceAttribs()) {
72 instanceBinding = bindingDescs->count();
73 bindingDescs->push_back() = {
74 instanceBinding,
75 (uint32_t) primProc.getInstanceStride(),
76 VK_VERTEX_INPUT_RATE_INSTANCE
77 };
78 }
Greg Daniel164a9f02016-02-22 09:56:40 -050079
80 // setup attribute descriptions
81 int vaCount = primProc.numAttribs();
Greg Daniel164a9f02016-02-22 09:56:40 -050082 if (vaCount > 0) {
Greg Daniel164a9f02016-02-22 09:56:40 -050083 for (int attribIndex = 0; attribIndex < vaCount; attribIndex++) {
Chris Dalton1d616352017-05-31 12:51:23 -060084 using InputRate = GrPrimitiveProcessor::Attribute::InputRate;
Greg Daniel164a9f02016-02-22 09:56:40 -050085 const GrGeometryProcessor::Attribute& attrib = primProc.getAttrib(attribIndex);
Greg Daniel164a9f02016-02-22 09:56:40 -050086 VkVertexInputAttributeDescription& vkAttrib = attributeDesc[attribIndex];
87 vkAttrib.location = attribIndex; // for now assume location = attribIndex
Brian Salomon70132d02018-05-29 15:33:06 -040088 vkAttrib.binding =
89 InputRate::kPerInstance == attrib.inputRate() ? instanceBinding : vertexBinding;
90 vkAttrib.format = attrib_type_to_vkformat(attrib.type());
91 vkAttrib.offset = attrib.offsetInRecord();
Greg Daniel164a9f02016-02-22 09:56:40 -050092 }
93 }
94
95 memset(vertexInputInfo, 0, sizeof(VkPipelineVertexInputStateCreateInfo));
96 vertexInputInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
97 vertexInputInfo->pNext = nullptr;
98 vertexInputInfo->flags = 0;
Chris Dalton1d616352017-05-31 12:51:23 -060099 vertexInputInfo->vertexBindingDescriptionCount = bindingDescs->count();
100 vertexInputInfo->pVertexBindingDescriptions = bindingDescs->begin();
Greg Daniel164a9f02016-02-22 09:56:40 -0500101 vertexInputInfo->vertexAttributeDescriptionCount = vaCount;
102 vertexInputInfo->pVertexAttributeDescriptions = attributeDesc;
103}
104
Chris Dalton3809bab2017-06-13 10:55:06 -0600105static VkPrimitiveTopology gr_primitive_type_to_vk_topology(GrPrimitiveType primitiveType) {
106 switch (primitiveType) {
107 case GrPrimitiveType::kTriangles:
108 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
109 case GrPrimitiveType::kTriangleStrip:
110 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
Chris Dalton3809bab2017-06-13 10:55:06 -0600111 case GrPrimitiveType::kPoints:
112 return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
113 case GrPrimitiveType::kLines:
114 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
115 case GrPrimitiveType::kLineStrip:
116 return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
117 case GrPrimitiveType::kLinesAdjacency:
118 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY;
119 }
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400120 SK_ABORT("invalid GrPrimitiveType");
Chris Dalton3809bab2017-06-13 10:55:06 -0600121 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
122}
Greg Daniel164a9f02016-02-22 09:56:40 -0500123
124static void setup_input_assembly_state(GrPrimitiveType primitiveType,
125 VkPipelineInputAssemblyStateCreateInfo* inputAssemblyInfo) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500126 memset(inputAssemblyInfo, 0, sizeof(VkPipelineInputAssemblyStateCreateInfo));
127 inputAssemblyInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
128 inputAssemblyInfo->pNext = nullptr;
129 inputAssemblyInfo->flags = 0;
130 inputAssemblyInfo->primitiveRestartEnable = false;
Chris Dalton3809bab2017-06-13 10:55:06 -0600131 inputAssemblyInfo->topology = gr_primitive_type_to_vk_topology(primitiveType);
Greg Daniel164a9f02016-02-22 09:56:40 -0500132}
133
134
egdanielec440992016-09-13 09:54:11 -0700135static VkStencilOp stencil_op_to_vk_stencil_op(GrStencilOp op) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500136 static const VkStencilOp gTable[] = {
cdalton93a379b2016-05-11 13:58:08 -0700137 VK_STENCIL_OP_KEEP, // kKeep
138 VK_STENCIL_OP_ZERO, // kZero
139 VK_STENCIL_OP_REPLACE, // kReplace
140 VK_STENCIL_OP_INVERT, // kInvert
141 VK_STENCIL_OP_INCREMENT_AND_WRAP, // kIncWrap
142 VK_STENCIL_OP_DECREMENT_AND_WRAP, // kDecWrap
143 VK_STENCIL_OP_INCREMENT_AND_CLAMP, // kIncClamp
144 VK_STENCIL_OP_DECREMENT_AND_CLAMP, // kDecClamp
Greg Daniel164a9f02016-02-22 09:56:40 -0500145 };
cdalton93a379b2016-05-11 13:58:08 -0700146 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kGrStencilOpCount);
147 GR_STATIC_ASSERT(0 == (int)GrStencilOp::kKeep);
148 GR_STATIC_ASSERT(1 == (int)GrStencilOp::kZero);
149 GR_STATIC_ASSERT(2 == (int)GrStencilOp::kReplace);
150 GR_STATIC_ASSERT(3 == (int)GrStencilOp::kInvert);
151 GR_STATIC_ASSERT(4 == (int)GrStencilOp::kIncWrap);
152 GR_STATIC_ASSERT(5 == (int)GrStencilOp::kDecWrap);
153 GR_STATIC_ASSERT(6 == (int)GrStencilOp::kIncClamp);
154 GR_STATIC_ASSERT(7 == (int)GrStencilOp::kDecClamp);
155 SkASSERT(op < (GrStencilOp)kGrStencilOpCount);
156 return gTable[(int)op];
Greg Daniel164a9f02016-02-22 09:56:40 -0500157}
158
egdanielec440992016-09-13 09:54:11 -0700159static VkCompareOp stencil_func_to_vk_compare_op(GrStencilTest test) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500160 static const VkCompareOp gTable[] = {
cdalton93a379b2016-05-11 13:58:08 -0700161 VK_COMPARE_OP_ALWAYS, // kAlways
162 VK_COMPARE_OP_NEVER, // kNever
163 VK_COMPARE_OP_GREATER, // kGreater
164 VK_COMPARE_OP_GREATER_OR_EQUAL, // kGEqual
165 VK_COMPARE_OP_LESS, // kLess
166 VK_COMPARE_OP_LESS_OR_EQUAL, // kLEqual
167 VK_COMPARE_OP_EQUAL, // kEqual
168 VK_COMPARE_OP_NOT_EQUAL, // kNotEqual
Greg Daniel164a9f02016-02-22 09:56:40 -0500169 };
cdalton93a379b2016-05-11 13:58:08 -0700170 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kGrStencilTestCount);
171 GR_STATIC_ASSERT(0 == (int)GrStencilTest::kAlways);
172 GR_STATIC_ASSERT(1 == (int)GrStencilTest::kNever);
173 GR_STATIC_ASSERT(2 == (int)GrStencilTest::kGreater);
174 GR_STATIC_ASSERT(3 == (int)GrStencilTest::kGEqual);
175 GR_STATIC_ASSERT(4 == (int)GrStencilTest::kLess);
176 GR_STATIC_ASSERT(5 == (int)GrStencilTest::kLEqual);
177 GR_STATIC_ASSERT(6 == (int)GrStencilTest::kEqual);
178 GR_STATIC_ASSERT(7 == (int)GrStencilTest::kNotEqual);
179 SkASSERT(test < (GrStencilTest)kGrStencilTestCount);
Greg Daniel164a9f02016-02-22 09:56:40 -0500180
cdalton93a379b2016-05-11 13:58:08 -0700181 return gTable[(int)test];
Greg Daniel164a9f02016-02-22 09:56:40 -0500182}
183
egdanielec440992016-09-13 09:54:11 -0700184static void setup_depth_stencil_state(const GrStencilSettings& stencilSettings,
185 VkPipelineDepthStencilStateCreateInfo* stencilInfo) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500186 memset(stencilInfo, 0, sizeof(VkPipelineDepthStencilStateCreateInfo));
187 stencilInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
188 stencilInfo->pNext = nullptr;
189 stencilInfo->flags = 0;
190 // set depth testing defaults
191 stencilInfo->depthTestEnable = VK_FALSE;
192 stencilInfo->depthWriteEnable = VK_FALSE;
193 stencilInfo->depthCompareOp = VK_COMPARE_OP_ALWAYS;
194 stencilInfo->depthBoundsTestEnable = VK_FALSE;
195 stencilInfo->stencilTestEnable = !stencilSettings.isDisabled();
196 if (!stencilSettings.isDisabled()) {
197 // Set front face
cdalton93a379b2016-05-11 13:58:08 -0700198 const GrStencilSettings::Face& front = stencilSettings.front();
199 stencilInfo->front.failOp = stencil_op_to_vk_stencil_op(front.fFailOp);
200 stencilInfo->front.passOp = stencil_op_to_vk_stencil_op(front.fPassOp);
Greg Daniel164a9f02016-02-22 09:56:40 -0500201 stencilInfo->front.depthFailOp = stencilInfo->front.failOp;
cdalton93a379b2016-05-11 13:58:08 -0700202 stencilInfo->front.compareOp = stencil_func_to_vk_compare_op(front.fTest);
203 stencilInfo->front.compareMask = front.fTestMask;
204 stencilInfo->front.writeMask = front.fWriteMask;
205 stencilInfo->front.reference = front.fRef;
Greg Daniel164a9f02016-02-22 09:56:40 -0500206
207 // Set back face
cdalton93a379b2016-05-11 13:58:08 -0700208 if (!stencilSettings.isTwoSided()) {
209 stencilInfo->back = stencilInfo->front;
210 } else {
211 const GrStencilSettings::Face& back = stencilSettings.back();
212 stencilInfo->back.failOp = stencil_op_to_vk_stencil_op(back.fFailOp);
213 stencilInfo->back.passOp = stencil_op_to_vk_stencil_op(back.fPassOp);
214 stencilInfo->back.depthFailOp = stencilInfo->front.failOp;
215 stencilInfo->back.compareOp = stencil_func_to_vk_compare_op(back.fTest);
216 stencilInfo->back.compareMask = back.fTestMask;
217 stencilInfo->back.writeMask = back.fWriteMask;
218 stencilInfo->back.reference = back.fRef;
219 }
Greg Daniel164a9f02016-02-22 09:56:40 -0500220 }
221 stencilInfo->minDepthBounds = 0.0f;
222 stencilInfo->maxDepthBounds = 1.0f;
223}
224
egdanielec440992016-09-13 09:54:11 -0700225static void setup_viewport_scissor_state(VkPipelineViewportStateCreateInfo* viewportInfo) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500226 memset(viewportInfo, 0, sizeof(VkPipelineViewportStateCreateInfo));
227 viewportInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
228 viewportInfo->pNext = nullptr;
229 viewportInfo->flags = 0;
230
Greg Daniel164a9f02016-02-22 09:56:40 -0500231 viewportInfo->viewportCount = 1;
egdaniel470d77a2016-03-18 12:50:27 -0700232 viewportInfo->pViewports = nullptr; // This is set dynamically
Greg Daniel164a9f02016-02-22 09:56:40 -0500233
egdaniel470d77a2016-03-18 12:50:27 -0700234 viewportInfo->scissorCount = 1;
235 viewportInfo->pScissors = nullptr; // This is set dynamically
Greg Daniel164a9f02016-02-22 09:56:40 -0500236
Greg Daniel164a9f02016-02-22 09:56:40 -0500237 SkASSERT(viewportInfo->viewportCount == viewportInfo->scissorCount);
238}
239
egdanielec440992016-09-13 09:54:11 -0700240static void setup_multisample_state(const GrPipeline& pipeline,
241 const GrPrimitiveProcessor& primProc,
242 const GrCaps* caps,
243 VkPipelineMultisampleStateCreateInfo* multisampleInfo) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500244 memset(multisampleInfo, 0, sizeof(VkPipelineMultisampleStateCreateInfo));
245 multisampleInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
246 multisampleInfo->pNext = nullptr;
247 multisampleInfo->flags = 0;
Robert Phillips2890fbf2017-07-26 15:48:41 -0400248 int numSamples = pipeline.proxy()->numColorSamples();
Greg Daniel164a9f02016-02-22 09:56:40 -0500249 SkAssertResult(GrSampleCountToVkSampleCount(numSamples,
250 &multisampleInfo->rasterizationSamples));
ethannicholas28ef4452016-03-25 09:26:03 -0700251 float sampleShading = primProc.getSampleShading();
252 SkASSERT(sampleShading == 0.0f || caps->sampleShadingSupport());
253 multisampleInfo->sampleShadingEnable = sampleShading > 0.0f;
254 multisampleInfo->minSampleShading = sampleShading;
Greg Daniel164a9f02016-02-22 09:56:40 -0500255 multisampleInfo->pSampleMask = nullptr;
256 multisampleInfo->alphaToCoverageEnable = VK_FALSE;
257 multisampleInfo->alphaToOneEnable = VK_FALSE;
258}
259
260static VkBlendFactor blend_coeff_to_vk_blend(GrBlendCoeff coeff) {
261 static const VkBlendFactor gTable[] = {
262 VK_BLEND_FACTOR_ZERO, // kZero_GrBlendCoeff
263 VK_BLEND_FACTOR_ONE, // kOne_GrBlendCoeff
264 VK_BLEND_FACTOR_SRC_COLOR, // kSC_GrBlendCoeff
265 VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, // kISC_GrBlendCoeff
266 VK_BLEND_FACTOR_DST_COLOR, // kDC_GrBlendCoeff
267 VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, // kIDC_GrBlendCoeff
268 VK_BLEND_FACTOR_SRC_ALPHA, // kSA_GrBlendCoeff
269 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // kISA_GrBlendCoeff
270 VK_BLEND_FACTOR_DST_ALPHA, // kDA_GrBlendCoeff
271 VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, // kIDA_GrBlendCoeff
272 VK_BLEND_FACTOR_CONSTANT_COLOR, // kConstC_GrBlendCoeff
273 VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, // kIConstC_GrBlendCoeff
274 VK_BLEND_FACTOR_CONSTANT_ALPHA, // kConstA_GrBlendCoeff
275 VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA, // kIConstA_GrBlendCoeff
276 VK_BLEND_FACTOR_SRC1_COLOR, // kS2C_GrBlendCoeff
277 VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR, // kIS2C_GrBlendCoeff
278 VK_BLEND_FACTOR_SRC1_ALPHA, // kS2A_GrBlendCoeff
279 VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, // kIS2A_GrBlendCoeff
280
281 };
282 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kGrBlendCoeffCnt);
283 GR_STATIC_ASSERT(0 == kZero_GrBlendCoeff);
284 GR_STATIC_ASSERT(1 == kOne_GrBlendCoeff);
285 GR_STATIC_ASSERT(2 == kSC_GrBlendCoeff);
286 GR_STATIC_ASSERT(3 == kISC_GrBlendCoeff);
287 GR_STATIC_ASSERT(4 == kDC_GrBlendCoeff);
288 GR_STATIC_ASSERT(5 == kIDC_GrBlendCoeff);
289 GR_STATIC_ASSERT(6 == kSA_GrBlendCoeff);
290 GR_STATIC_ASSERT(7 == kISA_GrBlendCoeff);
291 GR_STATIC_ASSERT(8 == kDA_GrBlendCoeff);
292 GR_STATIC_ASSERT(9 == kIDA_GrBlendCoeff);
293 GR_STATIC_ASSERT(10 == kConstC_GrBlendCoeff);
294 GR_STATIC_ASSERT(11 == kIConstC_GrBlendCoeff);
295 GR_STATIC_ASSERT(12 == kConstA_GrBlendCoeff);
296 GR_STATIC_ASSERT(13 == kIConstA_GrBlendCoeff);
297 GR_STATIC_ASSERT(14 == kS2C_GrBlendCoeff);
298 GR_STATIC_ASSERT(15 == kIS2C_GrBlendCoeff);
299 GR_STATIC_ASSERT(16 == kS2A_GrBlendCoeff);
300 GR_STATIC_ASSERT(17 == kIS2A_GrBlendCoeff);
301
302 SkASSERT((unsigned)coeff < kGrBlendCoeffCnt);
303 return gTable[coeff];
304}
305
306
307static VkBlendOp blend_equation_to_vk_blend_op(GrBlendEquation equation) {
308 static const VkBlendOp gTable[] = {
309 VK_BLEND_OP_ADD, // kAdd_GrBlendEquation
310 VK_BLEND_OP_SUBTRACT, // kSubtract_GrBlendEquation
311 VK_BLEND_OP_REVERSE_SUBTRACT, // kReverseSubtract_GrBlendEquation
312 };
313 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kFirstAdvancedGrBlendEquation);
314 GR_STATIC_ASSERT(0 == kAdd_GrBlendEquation);
315 GR_STATIC_ASSERT(1 == kSubtract_GrBlendEquation);
316 GR_STATIC_ASSERT(2 == kReverseSubtract_GrBlendEquation);
317
318 SkASSERT((unsigned)equation < kGrBlendCoeffCnt);
319 return gTable[equation];
320}
321
egdanielec440992016-09-13 09:54:11 -0700322static bool blend_coeff_refs_constant(GrBlendCoeff coeff) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500323 static const bool gCoeffReferencesBlendConst[] = {
324 false,
325 false,
326 false,
327 false,
328 false,
329 false,
330 false,
331 false,
332 false,
333 false,
334 true,
335 true,
336 true,
337 true,
338
339 // extended blend coeffs
340 false,
341 false,
342 false,
343 false,
344 };
345 return gCoeffReferencesBlendConst[coeff];
346 GR_STATIC_ASSERT(kGrBlendCoeffCnt == SK_ARRAY_COUNT(gCoeffReferencesBlendConst));
347 // Individual enum asserts already made in blend_coeff_to_vk_blend
348}
349
egdanielec440992016-09-13 09:54:11 -0700350static void setup_color_blend_state(const GrPipeline& pipeline,
351 VkPipelineColorBlendStateCreateInfo* colorBlendInfo,
352 VkPipelineColorBlendAttachmentState* attachmentState) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500353 GrXferProcessor::BlendInfo blendInfo;
354 pipeline.getXferProcessor().getBlendInfo(&blendInfo);
355
356 GrBlendEquation equation = blendInfo.fEquation;
357 GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
358 GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
359 bool blendOff = (kAdd_GrBlendEquation == equation || kSubtract_GrBlendEquation == equation) &&
360 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff;
361
362 memset(attachmentState, 0, sizeof(VkPipelineColorBlendAttachmentState));
363 attachmentState->blendEnable = !blendOff;
364 if (!blendOff) {
365 attachmentState->srcColorBlendFactor = blend_coeff_to_vk_blend(srcCoeff);
366 attachmentState->dstColorBlendFactor = blend_coeff_to_vk_blend(dstCoeff);
367 attachmentState->colorBlendOp = blend_equation_to_vk_blend_op(equation);
368 attachmentState->srcAlphaBlendFactor = blend_coeff_to_vk_blend(srcCoeff);
369 attachmentState->dstAlphaBlendFactor = blend_coeff_to_vk_blend(dstCoeff);
370 attachmentState->alphaBlendOp = blend_equation_to_vk_blend_op(equation);
371 }
egdaniel3d5d9ac2016-03-01 12:56:15 -0800372
373 if (!blendInfo.fWriteColor) {
374 attachmentState->colorWriteMask = 0;
375 } else {
376 attachmentState->colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
377 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
378 }
Greg Daniel164a9f02016-02-22 09:56:40 -0500379
380 memset(colorBlendInfo, 0, sizeof(VkPipelineColorBlendStateCreateInfo));
381 colorBlendInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
382 colorBlendInfo->pNext = nullptr;
383 colorBlendInfo->flags = 0;
384 colorBlendInfo->logicOpEnable = VK_FALSE;
385 colorBlendInfo->attachmentCount = 1;
386 colorBlendInfo->pAttachments = attachmentState;
egdaniel470d77a2016-03-18 12:50:27 -0700387 // colorBlendInfo->blendConstants is set dynamically
Greg Daniel164a9f02016-02-22 09:56:40 -0500388}
389
egdanielec440992016-09-13 09:54:11 -0700390static void setup_raster_state(const GrPipeline& pipeline,
Jim Van Verthfbdc0802017-05-02 16:15:53 -0400391 const GrCaps* caps,
egdanielec440992016-09-13 09:54:11 -0700392 VkPipelineRasterizationStateCreateInfo* rasterInfo) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500393 memset(rasterInfo, 0, sizeof(VkPipelineRasterizationStateCreateInfo));
394 rasterInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
395 rasterInfo->pNext = nullptr;
396 rasterInfo->flags = 0;
397 rasterInfo->depthClampEnable = VK_FALSE;
398 rasterInfo->rasterizerDiscardEnable = VK_FALSE;
Jim Van Verthfbdc0802017-05-02 16:15:53 -0400399 rasterInfo->polygonMode = caps->wireframeMode() ? VK_POLYGON_MODE_LINE
400 : VK_POLYGON_MODE_FILL;
Brian Salomonf0861672017-05-08 11:10:10 -0400401 rasterInfo->cullMode = VK_CULL_MODE_NONE;
Greg Daniel164a9f02016-02-22 09:56:40 -0500402 rasterInfo->frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
403 rasterInfo->depthBiasEnable = VK_FALSE;
404 rasterInfo->depthBiasConstantFactor = 0.0f;
405 rasterInfo->depthBiasClamp = 0.0f;
406 rasterInfo->depthBiasSlopeFactor = 0.0f;
407 rasterInfo->lineWidth = 1.0f;
408}
409
Jim Van Verth6a40abc2017-11-02 16:56:09 +0000410static void setup_dynamic_state(VkPipelineDynamicStateCreateInfo* dynamicInfo,
411 VkDynamicState* dynamicStates) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500412 memset(dynamicInfo, 0, sizeof(VkPipelineDynamicStateCreateInfo));
413 dynamicInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
egdaniel470d77a2016-03-18 12:50:27 -0700414 dynamicInfo->pNext = VK_NULL_HANDLE;
415 dynamicInfo->flags = 0;
Jim Van Verth6a40abc2017-11-02 16:56:09 +0000416 dynamicStates[0] = VK_DYNAMIC_STATE_VIEWPORT;
417 dynamicStates[1] = VK_DYNAMIC_STATE_SCISSOR;
418 dynamicStates[2] = VK_DYNAMIC_STATE_BLEND_CONSTANTS;
419 dynamicInfo->dynamicStateCount = 3;
420 dynamicInfo->pDynamicStates = dynamicStates;
Greg Daniel164a9f02016-02-22 09:56:40 -0500421}
422
423GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, const GrPipeline& pipeline,
csmartdaltonc633abb2016-11-01 08:55:55 -0700424 const GrStencilSettings& stencil,
Greg Daniel164a9f02016-02-22 09:56:40 -0500425 const GrPrimitiveProcessor& primProc,
426 VkPipelineShaderStageCreateInfo* shaderStageInfo,
427 int shaderStageCount,
428 GrPrimitiveType primitiveType,
429 const GrVkRenderPass& renderPass,
jvanverth03509ea2016-03-02 13:19:47 -0800430 VkPipelineLayout layout,
431 VkPipelineCache cache) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500432 VkPipelineVertexInputStateCreateInfo vertexInputInfo;
Chris Dalton1d616352017-05-31 12:51:23 -0600433 SkSTArray<2, VkVertexInputBindingDescription, true> bindingDescs;
egdanielb05df0f2016-06-27 07:15:20 -0700434 SkSTArray<16, VkVertexInputAttributeDescription> attributeDesc;
435 SkASSERT(primProc.numAttribs() <= gpu->vkCaps().maxVertexAttributes());
436 VkVertexInputAttributeDescription* pAttribs = attributeDesc.push_back_n(primProc.numAttribs());
Chris Dalton1d616352017-05-31 12:51:23 -0600437 setup_vertex_input_state(primProc, &vertexInputInfo, &bindingDescs, pAttribs);
Greg Daniel164a9f02016-02-22 09:56:40 -0500438
439 VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo;
440 setup_input_assembly_state(primitiveType, &inputAssemblyInfo);
441
442 VkPipelineDepthStencilStateCreateInfo depthStencilInfo;
csmartdaltonc633abb2016-11-01 08:55:55 -0700443 setup_depth_stencil_state(stencil, &depthStencilInfo);
Greg Daniel164a9f02016-02-22 09:56:40 -0500444
Greg Daniel164a9f02016-02-22 09:56:40 -0500445 VkPipelineViewportStateCreateInfo viewportInfo;
egdanielec440992016-09-13 09:54:11 -0700446 setup_viewport_scissor_state(&viewportInfo);
Greg Daniel164a9f02016-02-22 09:56:40 -0500447
448 VkPipelineMultisampleStateCreateInfo multisampleInfo;
ethannicholas28ef4452016-03-25 09:26:03 -0700449 setup_multisample_state(pipeline, primProc, gpu->caps(), &multisampleInfo);
Greg Daniel164a9f02016-02-22 09:56:40 -0500450
451 // We will only have one color attachment per pipeline.
452 VkPipelineColorBlendAttachmentState attachmentStates[1];
453 VkPipelineColorBlendStateCreateInfo colorBlendInfo;
egdanielec440992016-09-13 09:54:11 -0700454 setup_color_blend_state(pipeline, &colorBlendInfo, attachmentStates);
Greg Daniel164a9f02016-02-22 09:56:40 -0500455
456 VkPipelineRasterizationStateCreateInfo rasterInfo;
Jim Van Verthfbdc0802017-05-02 16:15:53 -0400457 setup_raster_state(pipeline, gpu->caps(), &rasterInfo);
Greg Daniel164a9f02016-02-22 09:56:40 -0500458
Jim Van Verth6a40abc2017-11-02 16:56:09 +0000459 VkDynamicState dynamicStates[3];
Greg Daniel164a9f02016-02-22 09:56:40 -0500460 VkPipelineDynamicStateCreateInfo dynamicInfo;
Jim Van Verth6a40abc2017-11-02 16:56:09 +0000461 setup_dynamic_state(&dynamicInfo, dynamicStates);
Greg Daniel164a9f02016-02-22 09:56:40 -0500462
463 VkGraphicsPipelineCreateInfo pipelineCreateInfo;
464 memset(&pipelineCreateInfo, 0, sizeof(VkGraphicsPipelineCreateInfo));
465 pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
466 pipelineCreateInfo.pNext = nullptr;
467 pipelineCreateInfo.flags = 0;
468 pipelineCreateInfo.stageCount = shaderStageCount;
469 pipelineCreateInfo.pStages = shaderStageInfo;
470 pipelineCreateInfo.pVertexInputState = &vertexInputInfo;
471 pipelineCreateInfo.pInputAssemblyState = &inputAssemblyInfo;
472 pipelineCreateInfo.pTessellationState = nullptr;
473 pipelineCreateInfo.pViewportState = &viewportInfo;
474 pipelineCreateInfo.pRasterizationState = &rasterInfo;
475 pipelineCreateInfo.pMultisampleState = &multisampleInfo;
476 pipelineCreateInfo.pDepthStencilState = &depthStencilInfo;
477 pipelineCreateInfo.pColorBlendState = &colorBlendInfo;
478 pipelineCreateInfo.pDynamicState = &dynamicInfo;
479 pipelineCreateInfo.layout = layout;
480 pipelineCreateInfo.renderPass = renderPass.vkRenderPass();
481 pipelineCreateInfo.subpass = 0;
482 pipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
483 pipelineCreateInfo.basePipelineIndex = -1;
484
485 VkPipeline vkPipeline;
486 VkResult err = GR_VK_CALL(gpu->vkInterface(), CreateGraphicsPipelines(gpu->device(),
halcanary9d524f22016-03-29 09:03:52 -0700487 cache, 1,
488 &pipelineCreateInfo,
Greg Daniel164a9f02016-02-22 09:56:40 -0500489 nullptr, &vkPipeline));
490 if (err) {
Greg Daniel5ba448c2018-02-26 13:30:47 -0500491 SkDebugf("Failed to create pipeline. Error: %d\n", err);
Greg Daniel164a9f02016-02-22 09:56:40 -0500492 return nullptr;
493 }
494
495 return new GrVkPipeline(vkPipeline);
496}
497
498void GrVkPipeline::freeGPUData(const GrVkGpu* gpu) const {
499 GR_VK_CALL(gpu->vkInterface(), DestroyPipeline(gpu->device(), fPipeline, nullptr));
500}
501
Jim Van Verth6a40abc2017-11-02 16:56:09 +0000502void GrVkPipeline::SetDynamicScissorRectState(GrVkGpu* gpu,
503 GrVkCommandBuffer* cmdBuffer,
504 const GrRenderTarget* renderTarget,
505 GrSurfaceOrigin rtOrigin,
506 SkIRect scissorRect) {
507 if (!scissorRect.intersect(SkIRect::MakeWH(renderTarget->width(), renderTarget->height()))) {
508 scissorRect.setEmpty();
509 }
510
511 VkRect2D scissor;
512 scissor.offset.x = scissorRect.fLeft;
513 scissor.extent.width = scissorRect.width();
514 if (kTopLeft_GrSurfaceOrigin == rtOrigin) {
515 scissor.offset.y = scissorRect.fTop;
516 } else {
517 SkASSERT(kBottomLeft_GrSurfaceOrigin == rtOrigin);
518 scissor.offset.y = renderTarget->height() - scissorRect.fBottom;
519 }
520 scissor.extent.height = scissorRect.height();
521
522 SkASSERT(scissor.offset.x >= 0);
523 SkASSERT(scissor.offset.y >= 0);
524 cmdBuffer->setScissor(gpu, 0, 1, &scissor);
525}
526
Chris Dalton46983b72017-06-06 12:27:16 -0600527void GrVkPipeline::SetDynamicViewportState(GrVkGpu* gpu,
528 GrVkCommandBuffer* cmdBuffer,
529 const GrRenderTarget* renderTarget) {
egdaniel470d77a2016-03-18 12:50:27 -0700530 // We always use one viewport the size of the RT
531 VkViewport viewport;
532 viewport.x = 0.0f;
533 viewport.y = 0.0f;
Chris Dalton46983b72017-06-06 12:27:16 -0600534 viewport.width = SkIntToScalar(renderTarget->width());
535 viewport.height = SkIntToScalar(renderTarget->height());
egdaniel470d77a2016-03-18 12:50:27 -0700536 viewport.minDepth = 0.0f;
537 viewport.maxDepth = 1.0f;
538 cmdBuffer->setViewport(gpu, 0, 1, &viewport);
539}
540
Chris Dalton46983b72017-06-06 12:27:16 -0600541void GrVkPipeline::SetDynamicBlendConstantState(GrVkGpu* gpu,
542 GrVkCommandBuffer* cmdBuffer,
543 GrPixelConfig pixelConfig,
544 const GrXferProcessor& xferProcessor) {
egdaniel470d77a2016-03-18 12:50:27 -0700545 GrXferProcessor::BlendInfo blendInfo;
Chris Dalton46983b72017-06-06 12:27:16 -0600546 xferProcessor.getBlendInfo(&blendInfo);
egdaniel470d77a2016-03-18 12:50:27 -0700547 GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
548 GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
549 float floatColors[4];
550 if (blend_coeff_refs_constant(srcCoeff) || blend_coeff_refs_constant(dstCoeff)) {
Greg Daniel6c9f1012017-05-11 09:20:59 -0400551 // Swizzle the blend to match what the shader will output.
Chris Dalton46983b72017-06-06 12:27:16 -0600552 const GrSwizzle& swizzle = gpu->caps()->shaderCaps()->configOutputSwizzle(pixelConfig);
Greg Daniel6c9f1012017-05-11 09:20:59 -0400553 GrColor blendConst = swizzle.applyTo(blendInfo.fBlendConstant);
554 GrColorToRGBAFloat(blendConst, floatColors);
egdaniel470d77a2016-03-18 12:50:27 -0700555 } else {
556 memset(floatColors, 0, 4 * sizeof(float));
557 }
558 cmdBuffer->setBlendConstants(gpu, floatColors);
559}