blob: 22777df94ab5957383bc630e1cb3e2e795940f7f [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:
20 return VK_FORMAT_R32_SFLOAT;
21 case kVec2f_GrVertexAttribType:
22 return VK_FORMAT_R32G32_SFLOAT;
23 case kVec3f_GrVertexAttribType:
24 return VK_FORMAT_R32G32B32_SFLOAT;
25 case kVec4f_GrVertexAttribType:
26 return VK_FORMAT_R32G32B32A32_SFLOAT;
27 case kVec2i_GrVertexAttribType:
28 return VK_FORMAT_R32G32_SINT;
29 case kVec3i_GrVertexAttribType:
30 return VK_FORMAT_R32G32B32_SINT;
31 case kVec4i_GrVertexAttribType:
32 return VK_FORMAT_R32G32B32A32_SINT;
33 case kUByte_GrVertexAttribType:
34 return VK_FORMAT_R8_UNORM;
35 case kVec4ub_GrVertexAttribType:
36 return VK_FORMAT_R8G8B8A8_UNORM;
Robert Phillipse84c0872017-08-24 11:32:33 -040037 case kVec2us_norm_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050038 return VK_FORMAT_R16G16_UNORM;
Robert Phillipse84c0872017-08-24 11:32:33 -040039 case kVec2us_uint_GrVertexAttribType:
40 return VK_FORMAT_R16G16_UINT;
csmartdaltonb37cb232017-02-08 14:56:27 -050041 case kInt_GrVertexAttribType:
42 return VK_FORMAT_R32_SINT;
43 case kUint_GrVertexAttribType:
44 return VK_FORMAT_R32_UINT;
45 }
Ben Wagnerb4aab9a2017-08-16 10:53:04 -040046 SK_ABORT("Unknown vertex attrib type");
csmartdaltonb37cb232017-02-08 14:56:27 -050047 return VK_FORMAT_UNDEFINED;
Greg Daniel164a9f02016-02-22 09:56:40 -050048}
49
50static void setup_vertex_input_state(const GrPrimitiveProcessor& primProc,
Chris Dalton1d616352017-05-31 12:51:23 -060051 VkPipelineVertexInputStateCreateInfo* vertexInputInfo,
52 SkSTArray<2, VkVertexInputBindingDescription, true>* bindingDescs,
53 VkVertexInputAttributeDescription* attributeDesc) {
54 uint32_t vertexBinding, instanceBinding;
55
56 if (primProc.hasVertexAttribs()) {
57 vertexBinding = bindingDescs->count();
58 bindingDescs->push_back() = {
59 vertexBinding,
60 (uint32_t) primProc.getVertexStride(),
61 VK_VERTEX_INPUT_RATE_VERTEX
62 };
63 }
64
65 if (primProc.hasInstanceAttribs()) {
66 instanceBinding = bindingDescs->count();
67 bindingDescs->push_back() = {
68 instanceBinding,
69 (uint32_t) primProc.getInstanceStride(),
70 VK_VERTEX_INPUT_RATE_INSTANCE
71 };
72 }
Greg Daniel164a9f02016-02-22 09:56:40 -050073
74 // setup attribute descriptions
75 int vaCount = primProc.numAttribs();
Greg Daniel164a9f02016-02-22 09:56:40 -050076 if (vaCount > 0) {
Greg Daniel164a9f02016-02-22 09:56:40 -050077 for (int attribIndex = 0; attribIndex < vaCount; attribIndex++) {
Chris Dalton1d616352017-05-31 12:51:23 -060078 using InputRate = GrPrimitiveProcessor::Attribute::InputRate;
Greg Daniel164a9f02016-02-22 09:56:40 -050079 const GrGeometryProcessor::Attribute& attrib = primProc.getAttrib(attribIndex);
Greg Daniel164a9f02016-02-22 09:56:40 -050080 VkVertexInputAttributeDescription& vkAttrib = attributeDesc[attribIndex];
81 vkAttrib.location = attribIndex; // for now assume location = attribIndex
Chris Dalton1d616352017-05-31 12:51:23 -060082 vkAttrib.binding = InputRate::kPerInstance == attrib.fInputRate ? instanceBinding
83 : vertexBinding;
84 vkAttrib.format = attrib_type_to_vkformat(attrib.fType);
85 vkAttrib.offset = attrib.fOffsetInRecord;
Greg Daniel164a9f02016-02-22 09:56:40 -050086 }
87 }
88
89 memset(vertexInputInfo, 0, sizeof(VkPipelineVertexInputStateCreateInfo));
90 vertexInputInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
91 vertexInputInfo->pNext = nullptr;
92 vertexInputInfo->flags = 0;
Chris Dalton1d616352017-05-31 12:51:23 -060093 vertexInputInfo->vertexBindingDescriptionCount = bindingDescs->count();
94 vertexInputInfo->pVertexBindingDescriptions = bindingDescs->begin();
Greg Daniel164a9f02016-02-22 09:56:40 -050095 vertexInputInfo->vertexAttributeDescriptionCount = vaCount;
96 vertexInputInfo->pVertexAttributeDescriptions = attributeDesc;
97}
98
Chris Dalton3809bab2017-06-13 10:55:06 -060099static VkPrimitiveTopology gr_primitive_type_to_vk_topology(GrPrimitiveType primitiveType) {
100 switch (primitiveType) {
101 case GrPrimitiveType::kTriangles:
102 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
103 case GrPrimitiveType::kTriangleStrip:
104 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
105 case GrPrimitiveType::kTriangleFan:
106 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
107 case GrPrimitiveType::kPoints:
108 return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
109 case GrPrimitiveType::kLines:
110 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
111 case GrPrimitiveType::kLineStrip:
112 return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
113 case GrPrimitiveType::kLinesAdjacency:
114 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY;
115 }
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400116 SK_ABORT("invalid GrPrimitiveType");
Chris Dalton3809bab2017-06-13 10:55:06 -0600117 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
118}
Greg Daniel164a9f02016-02-22 09:56:40 -0500119
120static void setup_input_assembly_state(GrPrimitiveType primitiveType,
121 VkPipelineInputAssemblyStateCreateInfo* inputAssemblyInfo) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500122 memset(inputAssemblyInfo, 0, sizeof(VkPipelineInputAssemblyStateCreateInfo));
123 inputAssemblyInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
124 inputAssemblyInfo->pNext = nullptr;
125 inputAssemblyInfo->flags = 0;
126 inputAssemblyInfo->primitiveRestartEnable = false;
Chris Dalton3809bab2017-06-13 10:55:06 -0600127 inputAssemblyInfo->topology = gr_primitive_type_to_vk_topology(primitiveType);
Greg Daniel164a9f02016-02-22 09:56:40 -0500128}
129
130
egdanielec440992016-09-13 09:54:11 -0700131static VkStencilOp stencil_op_to_vk_stencil_op(GrStencilOp op) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500132 static const VkStencilOp gTable[] = {
cdalton93a379b2016-05-11 13:58:08 -0700133 VK_STENCIL_OP_KEEP, // kKeep
134 VK_STENCIL_OP_ZERO, // kZero
135 VK_STENCIL_OP_REPLACE, // kReplace
136 VK_STENCIL_OP_INVERT, // kInvert
137 VK_STENCIL_OP_INCREMENT_AND_WRAP, // kIncWrap
138 VK_STENCIL_OP_DECREMENT_AND_WRAP, // kDecWrap
139 VK_STENCIL_OP_INCREMENT_AND_CLAMP, // kIncClamp
140 VK_STENCIL_OP_DECREMENT_AND_CLAMP, // kDecClamp
Greg Daniel164a9f02016-02-22 09:56:40 -0500141 };
cdalton93a379b2016-05-11 13:58:08 -0700142 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kGrStencilOpCount);
143 GR_STATIC_ASSERT(0 == (int)GrStencilOp::kKeep);
144 GR_STATIC_ASSERT(1 == (int)GrStencilOp::kZero);
145 GR_STATIC_ASSERT(2 == (int)GrStencilOp::kReplace);
146 GR_STATIC_ASSERT(3 == (int)GrStencilOp::kInvert);
147 GR_STATIC_ASSERT(4 == (int)GrStencilOp::kIncWrap);
148 GR_STATIC_ASSERT(5 == (int)GrStencilOp::kDecWrap);
149 GR_STATIC_ASSERT(6 == (int)GrStencilOp::kIncClamp);
150 GR_STATIC_ASSERT(7 == (int)GrStencilOp::kDecClamp);
151 SkASSERT(op < (GrStencilOp)kGrStencilOpCount);
152 return gTable[(int)op];
Greg Daniel164a9f02016-02-22 09:56:40 -0500153}
154
egdanielec440992016-09-13 09:54:11 -0700155static VkCompareOp stencil_func_to_vk_compare_op(GrStencilTest test) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500156 static const VkCompareOp gTable[] = {
cdalton93a379b2016-05-11 13:58:08 -0700157 VK_COMPARE_OP_ALWAYS, // kAlways
158 VK_COMPARE_OP_NEVER, // kNever
159 VK_COMPARE_OP_GREATER, // kGreater
160 VK_COMPARE_OP_GREATER_OR_EQUAL, // kGEqual
161 VK_COMPARE_OP_LESS, // kLess
162 VK_COMPARE_OP_LESS_OR_EQUAL, // kLEqual
163 VK_COMPARE_OP_EQUAL, // kEqual
164 VK_COMPARE_OP_NOT_EQUAL, // kNotEqual
Greg Daniel164a9f02016-02-22 09:56:40 -0500165 };
cdalton93a379b2016-05-11 13:58:08 -0700166 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kGrStencilTestCount);
167 GR_STATIC_ASSERT(0 == (int)GrStencilTest::kAlways);
168 GR_STATIC_ASSERT(1 == (int)GrStencilTest::kNever);
169 GR_STATIC_ASSERT(2 == (int)GrStencilTest::kGreater);
170 GR_STATIC_ASSERT(3 == (int)GrStencilTest::kGEqual);
171 GR_STATIC_ASSERT(4 == (int)GrStencilTest::kLess);
172 GR_STATIC_ASSERT(5 == (int)GrStencilTest::kLEqual);
173 GR_STATIC_ASSERT(6 == (int)GrStencilTest::kEqual);
174 GR_STATIC_ASSERT(7 == (int)GrStencilTest::kNotEqual);
175 SkASSERT(test < (GrStencilTest)kGrStencilTestCount);
Greg Daniel164a9f02016-02-22 09:56:40 -0500176
cdalton93a379b2016-05-11 13:58:08 -0700177 return gTable[(int)test];
Greg Daniel164a9f02016-02-22 09:56:40 -0500178}
179
egdanielec440992016-09-13 09:54:11 -0700180static void setup_depth_stencil_state(const GrStencilSettings& stencilSettings,
181 VkPipelineDepthStencilStateCreateInfo* stencilInfo) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500182 memset(stencilInfo, 0, sizeof(VkPipelineDepthStencilStateCreateInfo));
183 stencilInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
184 stencilInfo->pNext = nullptr;
185 stencilInfo->flags = 0;
186 // set depth testing defaults
187 stencilInfo->depthTestEnable = VK_FALSE;
188 stencilInfo->depthWriteEnable = VK_FALSE;
189 stencilInfo->depthCompareOp = VK_COMPARE_OP_ALWAYS;
190 stencilInfo->depthBoundsTestEnable = VK_FALSE;
191 stencilInfo->stencilTestEnable = !stencilSettings.isDisabled();
192 if (!stencilSettings.isDisabled()) {
193 // Set front face
cdalton93a379b2016-05-11 13:58:08 -0700194 const GrStencilSettings::Face& front = stencilSettings.front();
195 stencilInfo->front.failOp = stencil_op_to_vk_stencil_op(front.fFailOp);
196 stencilInfo->front.passOp = stencil_op_to_vk_stencil_op(front.fPassOp);
Greg Daniel164a9f02016-02-22 09:56:40 -0500197 stencilInfo->front.depthFailOp = stencilInfo->front.failOp;
cdalton93a379b2016-05-11 13:58:08 -0700198 stencilInfo->front.compareOp = stencil_func_to_vk_compare_op(front.fTest);
199 stencilInfo->front.compareMask = front.fTestMask;
200 stencilInfo->front.writeMask = front.fWriteMask;
201 stencilInfo->front.reference = front.fRef;
Greg Daniel164a9f02016-02-22 09:56:40 -0500202
203 // Set back face
cdalton93a379b2016-05-11 13:58:08 -0700204 if (!stencilSettings.isTwoSided()) {
205 stencilInfo->back = stencilInfo->front;
206 } else {
207 const GrStencilSettings::Face& back = stencilSettings.back();
208 stencilInfo->back.failOp = stencil_op_to_vk_stencil_op(back.fFailOp);
209 stencilInfo->back.passOp = stencil_op_to_vk_stencil_op(back.fPassOp);
210 stencilInfo->back.depthFailOp = stencilInfo->front.failOp;
211 stencilInfo->back.compareOp = stencil_func_to_vk_compare_op(back.fTest);
212 stencilInfo->back.compareMask = back.fTestMask;
213 stencilInfo->back.writeMask = back.fWriteMask;
214 stencilInfo->back.reference = back.fRef;
215 }
Greg Daniel164a9f02016-02-22 09:56:40 -0500216 }
217 stencilInfo->minDepthBounds = 0.0f;
218 stencilInfo->maxDepthBounds = 1.0f;
219}
220
egdanielec440992016-09-13 09:54:11 -0700221static void setup_viewport_scissor_state(VkPipelineViewportStateCreateInfo* viewportInfo) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500222 memset(viewportInfo, 0, sizeof(VkPipelineViewportStateCreateInfo));
223 viewportInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
224 viewportInfo->pNext = nullptr;
225 viewportInfo->flags = 0;
226
Greg Daniel164a9f02016-02-22 09:56:40 -0500227 viewportInfo->viewportCount = 1;
egdaniel470d77a2016-03-18 12:50:27 -0700228 viewportInfo->pViewports = nullptr; // This is set dynamically
Greg Daniel164a9f02016-02-22 09:56:40 -0500229
egdaniel470d77a2016-03-18 12:50:27 -0700230 viewportInfo->scissorCount = 1;
231 viewportInfo->pScissors = nullptr; // This is set dynamically
Greg Daniel164a9f02016-02-22 09:56:40 -0500232
Greg Daniel164a9f02016-02-22 09:56:40 -0500233 SkASSERT(viewportInfo->viewportCount == viewportInfo->scissorCount);
234}
235
egdanielec440992016-09-13 09:54:11 -0700236static void setup_multisample_state(const GrPipeline& pipeline,
237 const GrPrimitiveProcessor& primProc,
238 const GrCaps* caps,
239 VkPipelineMultisampleStateCreateInfo* multisampleInfo) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500240 memset(multisampleInfo, 0, sizeof(VkPipelineMultisampleStateCreateInfo));
241 multisampleInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
242 multisampleInfo->pNext = nullptr;
243 multisampleInfo->flags = 0;
Robert Phillips2890fbf2017-07-26 15:48:41 -0400244 int numSamples = pipeline.proxy()->numColorSamples();
Greg Daniel164a9f02016-02-22 09:56:40 -0500245 SkAssertResult(GrSampleCountToVkSampleCount(numSamples,
246 &multisampleInfo->rasterizationSamples));
ethannicholas28ef4452016-03-25 09:26:03 -0700247 float sampleShading = primProc.getSampleShading();
248 SkASSERT(sampleShading == 0.0f || caps->sampleShadingSupport());
249 multisampleInfo->sampleShadingEnable = sampleShading > 0.0f;
250 multisampleInfo->minSampleShading = sampleShading;
Greg Daniel164a9f02016-02-22 09:56:40 -0500251 multisampleInfo->pSampleMask = nullptr;
252 multisampleInfo->alphaToCoverageEnable = VK_FALSE;
253 multisampleInfo->alphaToOneEnable = VK_FALSE;
254}
255
256static VkBlendFactor blend_coeff_to_vk_blend(GrBlendCoeff coeff) {
257 static const VkBlendFactor gTable[] = {
258 VK_BLEND_FACTOR_ZERO, // kZero_GrBlendCoeff
259 VK_BLEND_FACTOR_ONE, // kOne_GrBlendCoeff
260 VK_BLEND_FACTOR_SRC_COLOR, // kSC_GrBlendCoeff
261 VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, // kISC_GrBlendCoeff
262 VK_BLEND_FACTOR_DST_COLOR, // kDC_GrBlendCoeff
263 VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, // kIDC_GrBlendCoeff
264 VK_BLEND_FACTOR_SRC_ALPHA, // kSA_GrBlendCoeff
265 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // kISA_GrBlendCoeff
266 VK_BLEND_FACTOR_DST_ALPHA, // kDA_GrBlendCoeff
267 VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, // kIDA_GrBlendCoeff
268 VK_BLEND_FACTOR_CONSTANT_COLOR, // kConstC_GrBlendCoeff
269 VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, // kIConstC_GrBlendCoeff
270 VK_BLEND_FACTOR_CONSTANT_ALPHA, // kConstA_GrBlendCoeff
271 VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA, // kIConstA_GrBlendCoeff
272 VK_BLEND_FACTOR_SRC1_COLOR, // kS2C_GrBlendCoeff
273 VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR, // kIS2C_GrBlendCoeff
274 VK_BLEND_FACTOR_SRC1_ALPHA, // kS2A_GrBlendCoeff
275 VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, // kIS2A_GrBlendCoeff
276
277 };
278 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kGrBlendCoeffCnt);
279 GR_STATIC_ASSERT(0 == kZero_GrBlendCoeff);
280 GR_STATIC_ASSERT(1 == kOne_GrBlendCoeff);
281 GR_STATIC_ASSERT(2 == kSC_GrBlendCoeff);
282 GR_STATIC_ASSERT(3 == kISC_GrBlendCoeff);
283 GR_STATIC_ASSERT(4 == kDC_GrBlendCoeff);
284 GR_STATIC_ASSERT(5 == kIDC_GrBlendCoeff);
285 GR_STATIC_ASSERT(6 == kSA_GrBlendCoeff);
286 GR_STATIC_ASSERT(7 == kISA_GrBlendCoeff);
287 GR_STATIC_ASSERT(8 == kDA_GrBlendCoeff);
288 GR_STATIC_ASSERT(9 == kIDA_GrBlendCoeff);
289 GR_STATIC_ASSERT(10 == kConstC_GrBlendCoeff);
290 GR_STATIC_ASSERT(11 == kIConstC_GrBlendCoeff);
291 GR_STATIC_ASSERT(12 == kConstA_GrBlendCoeff);
292 GR_STATIC_ASSERT(13 == kIConstA_GrBlendCoeff);
293 GR_STATIC_ASSERT(14 == kS2C_GrBlendCoeff);
294 GR_STATIC_ASSERT(15 == kIS2C_GrBlendCoeff);
295 GR_STATIC_ASSERT(16 == kS2A_GrBlendCoeff);
296 GR_STATIC_ASSERT(17 == kIS2A_GrBlendCoeff);
297
298 SkASSERT((unsigned)coeff < kGrBlendCoeffCnt);
299 return gTable[coeff];
300}
301
302
303static VkBlendOp blend_equation_to_vk_blend_op(GrBlendEquation equation) {
304 static const VkBlendOp gTable[] = {
305 VK_BLEND_OP_ADD, // kAdd_GrBlendEquation
306 VK_BLEND_OP_SUBTRACT, // kSubtract_GrBlendEquation
307 VK_BLEND_OP_REVERSE_SUBTRACT, // kReverseSubtract_GrBlendEquation
308 };
309 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kFirstAdvancedGrBlendEquation);
310 GR_STATIC_ASSERT(0 == kAdd_GrBlendEquation);
311 GR_STATIC_ASSERT(1 == kSubtract_GrBlendEquation);
312 GR_STATIC_ASSERT(2 == kReverseSubtract_GrBlendEquation);
313
314 SkASSERT((unsigned)equation < kGrBlendCoeffCnt);
315 return gTable[equation];
316}
317
egdanielec440992016-09-13 09:54:11 -0700318static bool blend_coeff_refs_constant(GrBlendCoeff coeff) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500319 static const bool gCoeffReferencesBlendConst[] = {
320 false,
321 false,
322 false,
323 false,
324 false,
325 false,
326 false,
327 false,
328 false,
329 false,
330 true,
331 true,
332 true,
333 true,
334
335 // extended blend coeffs
336 false,
337 false,
338 false,
339 false,
340 };
341 return gCoeffReferencesBlendConst[coeff];
342 GR_STATIC_ASSERT(kGrBlendCoeffCnt == SK_ARRAY_COUNT(gCoeffReferencesBlendConst));
343 // Individual enum asserts already made in blend_coeff_to_vk_blend
344}
345
egdanielec440992016-09-13 09:54:11 -0700346static void setup_color_blend_state(const GrPipeline& pipeline,
347 VkPipelineColorBlendStateCreateInfo* colorBlendInfo,
348 VkPipelineColorBlendAttachmentState* attachmentState) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500349 GrXferProcessor::BlendInfo blendInfo;
350 pipeline.getXferProcessor().getBlendInfo(&blendInfo);
351
352 GrBlendEquation equation = blendInfo.fEquation;
353 GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
354 GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
355 bool blendOff = (kAdd_GrBlendEquation == equation || kSubtract_GrBlendEquation == equation) &&
356 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff;
357
358 memset(attachmentState, 0, sizeof(VkPipelineColorBlendAttachmentState));
359 attachmentState->blendEnable = !blendOff;
360 if (!blendOff) {
361 attachmentState->srcColorBlendFactor = blend_coeff_to_vk_blend(srcCoeff);
362 attachmentState->dstColorBlendFactor = blend_coeff_to_vk_blend(dstCoeff);
363 attachmentState->colorBlendOp = blend_equation_to_vk_blend_op(equation);
364 attachmentState->srcAlphaBlendFactor = blend_coeff_to_vk_blend(srcCoeff);
365 attachmentState->dstAlphaBlendFactor = blend_coeff_to_vk_blend(dstCoeff);
366 attachmentState->alphaBlendOp = blend_equation_to_vk_blend_op(equation);
367 }
egdaniel3d5d9ac2016-03-01 12:56:15 -0800368
369 if (!blendInfo.fWriteColor) {
370 attachmentState->colorWriteMask = 0;
371 } else {
372 attachmentState->colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
373 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
374 }
Greg Daniel164a9f02016-02-22 09:56:40 -0500375
376 memset(colorBlendInfo, 0, sizeof(VkPipelineColorBlendStateCreateInfo));
377 colorBlendInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
378 colorBlendInfo->pNext = nullptr;
379 colorBlendInfo->flags = 0;
380 colorBlendInfo->logicOpEnable = VK_FALSE;
381 colorBlendInfo->attachmentCount = 1;
382 colorBlendInfo->pAttachments = attachmentState;
egdaniel470d77a2016-03-18 12:50:27 -0700383 // colorBlendInfo->blendConstants is set dynamically
Greg Daniel164a9f02016-02-22 09:56:40 -0500384}
385
egdanielec440992016-09-13 09:54:11 -0700386static void setup_raster_state(const GrPipeline& pipeline,
Jim Van Verthfbdc0802017-05-02 16:15:53 -0400387 const GrCaps* caps,
egdanielec440992016-09-13 09:54:11 -0700388 VkPipelineRasterizationStateCreateInfo* rasterInfo) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500389 memset(rasterInfo, 0, sizeof(VkPipelineRasterizationStateCreateInfo));
390 rasterInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
391 rasterInfo->pNext = nullptr;
392 rasterInfo->flags = 0;
393 rasterInfo->depthClampEnable = VK_FALSE;
394 rasterInfo->rasterizerDiscardEnable = VK_FALSE;
Jim Van Verthfbdc0802017-05-02 16:15:53 -0400395 rasterInfo->polygonMode = caps->wireframeMode() ? VK_POLYGON_MODE_LINE
396 : VK_POLYGON_MODE_FILL;
Brian Salomonf0861672017-05-08 11:10:10 -0400397 rasterInfo->cullMode = VK_CULL_MODE_NONE;
Greg Daniel164a9f02016-02-22 09:56:40 -0500398 rasterInfo->frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
399 rasterInfo->depthBiasEnable = VK_FALSE;
400 rasterInfo->depthBiasConstantFactor = 0.0f;
401 rasterInfo->depthBiasClamp = 0.0f;
402 rasterInfo->depthBiasSlopeFactor = 0.0f;
403 rasterInfo->lineWidth = 1.0f;
404}
405
egdanielec440992016-09-13 09:54:11 -0700406static void setup_dynamic_state(VkPipelineDynamicStateCreateInfo* dynamicInfo,
407 VkDynamicState* dynamicStates) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500408 memset(dynamicInfo, 0, sizeof(VkPipelineDynamicStateCreateInfo));
409 dynamicInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
egdaniel470d77a2016-03-18 12:50:27 -0700410 dynamicInfo->pNext = VK_NULL_HANDLE;
411 dynamicInfo->flags = 0;
412 dynamicStates[0] = VK_DYNAMIC_STATE_VIEWPORT;
413 dynamicStates[1] = VK_DYNAMIC_STATE_SCISSOR;
414 dynamicStates[2] = VK_DYNAMIC_STATE_BLEND_CONSTANTS;
415 dynamicInfo->dynamicStateCount = 3;
416 dynamicInfo->pDynamicStates = dynamicStates;
Greg Daniel164a9f02016-02-22 09:56:40 -0500417}
418
419GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, const GrPipeline& pipeline,
csmartdaltonc633abb2016-11-01 08:55:55 -0700420 const GrStencilSettings& stencil,
Greg Daniel164a9f02016-02-22 09:56:40 -0500421 const GrPrimitiveProcessor& primProc,
422 VkPipelineShaderStageCreateInfo* shaderStageInfo,
423 int shaderStageCount,
424 GrPrimitiveType primitiveType,
425 const GrVkRenderPass& renderPass,
jvanverth03509ea2016-03-02 13:19:47 -0800426 VkPipelineLayout layout,
427 VkPipelineCache cache) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500428 VkPipelineVertexInputStateCreateInfo vertexInputInfo;
Chris Dalton1d616352017-05-31 12:51:23 -0600429 SkSTArray<2, VkVertexInputBindingDescription, true> bindingDescs;
egdanielb05df0f2016-06-27 07:15:20 -0700430 SkSTArray<16, VkVertexInputAttributeDescription> attributeDesc;
431 SkASSERT(primProc.numAttribs() <= gpu->vkCaps().maxVertexAttributes());
432 VkVertexInputAttributeDescription* pAttribs = attributeDesc.push_back_n(primProc.numAttribs());
Chris Dalton1d616352017-05-31 12:51:23 -0600433 setup_vertex_input_state(primProc, &vertexInputInfo, &bindingDescs, pAttribs);
Greg Daniel164a9f02016-02-22 09:56:40 -0500434
435 VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo;
436 setup_input_assembly_state(primitiveType, &inputAssemblyInfo);
437
438 VkPipelineDepthStencilStateCreateInfo depthStencilInfo;
csmartdaltonc633abb2016-11-01 08:55:55 -0700439 setup_depth_stencil_state(stencil, &depthStencilInfo);
Greg Daniel164a9f02016-02-22 09:56:40 -0500440
Greg Daniel164a9f02016-02-22 09:56:40 -0500441 VkPipelineViewportStateCreateInfo viewportInfo;
egdanielec440992016-09-13 09:54:11 -0700442 setup_viewport_scissor_state(&viewportInfo);
Greg Daniel164a9f02016-02-22 09:56:40 -0500443
444 VkPipelineMultisampleStateCreateInfo multisampleInfo;
ethannicholas28ef4452016-03-25 09:26:03 -0700445 setup_multisample_state(pipeline, primProc, gpu->caps(), &multisampleInfo);
Greg Daniel164a9f02016-02-22 09:56:40 -0500446
447 // We will only have one color attachment per pipeline.
448 VkPipelineColorBlendAttachmentState attachmentStates[1];
449 VkPipelineColorBlendStateCreateInfo colorBlendInfo;
egdanielec440992016-09-13 09:54:11 -0700450 setup_color_blend_state(pipeline, &colorBlendInfo, attachmentStates);
Greg Daniel164a9f02016-02-22 09:56:40 -0500451
452 VkPipelineRasterizationStateCreateInfo rasterInfo;
Jim Van Verthfbdc0802017-05-02 16:15:53 -0400453 setup_raster_state(pipeline, gpu->caps(), &rasterInfo);
Greg Daniel164a9f02016-02-22 09:56:40 -0500454
egdaniel470d77a2016-03-18 12:50:27 -0700455 VkDynamicState dynamicStates[3];
Greg Daniel164a9f02016-02-22 09:56:40 -0500456 VkPipelineDynamicStateCreateInfo dynamicInfo;
egdanielec440992016-09-13 09:54:11 -0700457 setup_dynamic_state(&dynamicInfo, dynamicStates);
Greg Daniel164a9f02016-02-22 09:56:40 -0500458
459 VkGraphicsPipelineCreateInfo pipelineCreateInfo;
460 memset(&pipelineCreateInfo, 0, sizeof(VkGraphicsPipelineCreateInfo));
461 pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
462 pipelineCreateInfo.pNext = nullptr;
463 pipelineCreateInfo.flags = 0;
464 pipelineCreateInfo.stageCount = shaderStageCount;
465 pipelineCreateInfo.pStages = shaderStageInfo;
466 pipelineCreateInfo.pVertexInputState = &vertexInputInfo;
467 pipelineCreateInfo.pInputAssemblyState = &inputAssemblyInfo;
468 pipelineCreateInfo.pTessellationState = nullptr;
469 pipelineCreateInfo.pViewportState = &viewportInfo;
470 pipelineCreateInfo.pRasterizationState = &rasterInfo;
471 pipelineCreateInfo.pMultisampleState = &multisampleInfo;
472 pipelineCreateInfo.pDepthStencilState = &depthStencilInfo;
473 pipelineCreateInfo.pColorBlendState = &colorBlendInfo;
474 pipelineCreateInfo.pDynamicState = &dynamicInfo;
475 pipelineCreateInfo.layout = layout;
476 pipelineCreateInfo.renderPass = renderPass.vkRenderPass();
477 pipelineCreateInfo.subpass = 0;
478 pipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
479 pipelineCreateInfo.basePipelineIndex = -1;
480
481 VkPipeline vkPipeline;
482 VkResult err = GR_VK_CALL(gpu->vkInterface(), CreateGraphicsPipelines(gpu->device(),
halcanary9d524f22016-03-29 09:03:52 -0700483 cache, 1,
484 &pipelineCreateInfo,
Greg Daniel164a9f02016-02-22 09:56:40 -0500485 nullptr, &vkPipeline));
486 if (err) {
487 return nullptr;
488 }
489
490 return new GrVkPipeline(vkPipeline);
491}
492
493void GrVkPipeline::freeGPUData(const GrVkGpu* gpu) const {
494 GR_VK_CALL(gpu->vkInterface(), DestroyPipeline(gpu->device(), fPipeline, nullptr));
495}
496
Chris Dalton46983b72017-06-06 12:27:16 -0600497void GrVkPipeline::SetDynamicScissorRectState(GrVkGpu* gpu,
498 GrVkCommandBuffer* cmdBuffer,
499 const GrRenderTarget* renderTarget,
500 SkIRect scissorRect) {
501 if (!scissorRect.intersect(SkIRect::MakeWH(renderTarget->width(), renderTarget->height()))) {
502 scissorRect.setEmpty();
egdaniel470d77a2016-03-18 12:50:27 -0700503 }
Chris Dalton46983b72017-06-06 12:27:16 -0600504
505 VkRect2D scissor;
506 scissor.offset.x = scissorRect.fLeft;
507 scissor.extent.width = scissorRect.width();
Robert Phillips7294b852017-08-01 13:51:44 +0000508 if (kTopLeft_GrSurfaceOrigin == renderTarget->origin()) {
Chris Dalton46983b72017-06-06 12:27:16 -0600509 scissor.offset.y = scissorRect.fTop;
510 } else {
Robert Phillips7294b852017-08-01 13:51:44 +0000511 SkASSERT(kBottomLeft_GrSurfaceOrigin == renderTarget->origin());
Chris Dalton46983b72017-06-06 12:27:16 -0600512 scissor.offset.y = renderTarget->height() - scissorRect.fBottom;
513 }
514 scissor.extent.height = scissorRect.height();
515
516 SkASSERT(scissor.offset.x >= 0);
517 SkASSERT(scissor.offset.y >= 0);
egdaniel470d77a2016-03-18 12:50:27 -0700518 cmdBuffer->setScissor(gpu, 0, 1, &scissor);
519}
520
Chris Dalton46983b72017-06-06 12:27:16 -0600521void GrVkPipeline::SetDynamicViewportState(GrVkGpu* gpu,
522 GrVkCommandBuffer* cmdBuffer,
523 const GrRenderTarget* renderTarget) {
egdaniel470d77a2016-03-18 12:50:27 -0700524 // We always use one viewport the size of the RT
525 VkViewport viewport;
526 viewport.x = 0.0f;
527 viewport.y = 0.0f;
Chris Dalton46983b72017-06-06 12:27:16 -0600528 viewport.width = SkIntToScalar(renderTarget->width());
529 viewport.height = SkIntToScalar(renderTarget->height());
egdaniel470d77a2016-03-18 12:50:27 -0700530 viewport.minDepth = 0.0f;
531 viewport.maxDepth = 1.0f;
532 cmdBuffer->setViewport(gpu, 0, 1, &viewport);
533}
534
Chris Dalton46983b72017-06-06 12:27:16 -0600535void GrVkPipeline::SetDynamicBlendConstantState(GrVkGpu* gpu,
536 GrVkCommandBuffer* cmdBuffer,
537 GrPixelConfig pixelConfig,
538 const GrXferProcessor& xferProcessor) {
egdaniel470d77a2016-03-18 12:50:27 -0700539 GrXferProcessor::BlendInfo blendInfo;
Chris Dalton46983b72017-06-06 12:27:16 -0600540 xferProcessor.getBlendInfo(&blendInfo);
egdaniel470d77a2016-03-18 12:50:27 -0700541 GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
542 GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
543 float floatColors[4];
544 if (blend_coeff_refs_constant(srcCoeff) || blend_coeff_refs_constant(dstCoeff)) {
Greg Daniel6c9f1012017-05-11 09:20:59 -0400545 // Swizzle the blend to match what the shader will output.
Chris Dalton46983b72017-06-06 12:27:16 -0600546 const GrSwizzle& swizzle = gpu->caps()->shaderCaps()->configOutputSwizzle(pixelConfig);
Greg Daniel6c9f1012017-05-11 09:20:59 -0400547 GrColor blendConst = swizzle.applyTo(blendInfo.fBlendConstant);
548 GrColorToRGBAFloat(blendConst, floatColors);
egdaniel470d77a2016-03-18 12:50:27 -0700549 } else {
550 memset(floatColors, 0, 4 * sizeof(float));
551 }
552 cmdBuffer->setBlendConstants(gpu, floatColors);
553}