Index: src/gpu/vk/GrVkPipeline.cpp |
diff --git a/src/gpu/vk/GrVkPipeline.cpp b/src/gpu/vk/GrVkPipeline.cpp |
index becebac269f8d2152a2f446a4ac93c8d8807a686..c9e0c8f4c46073b92261d4040a5ec96aabda5c9d 100644 |
--- a/src/gpu/vk/GrVkPipeline.cpp |
+++ b/src/gpu/vk/GrVkPipeline.cpp |
@@ -1,512 +1,513 @@ |
-/* |
-* Copyright 2016 Google Inc. |
-* |
-* Use of this source code is governed by a BSD-style license that can be |
-* found in the LICENSE file. |
-*/ |
- |
-#include "GrVkPipeline.h" |
- |
-#include "GrGeometryProcessor.h" |
-#include "GrPipeline.h" |
- |
-#include "GrVkGpu.h" |
-#include "GrVkProgramDesc.h" |
-#include "GrVkRenderTarget.h" |
-#include "GrVkUtil.h" |
- |
-static inline const VkFormat& attrib_type_to_vkformat(GrVertexAttribType type) { |
- SkASSERT(type >= 0 && type < kGrVertexAttribTypeCount); |
- static const VkFormat kFormats[kGrVertexAttribTypeCount] = { |
- VK_FORMAT_R32_SFLOAT, // kFloat_GrVertexAttribType |
- VK_FORMAT_R32G32_SFLOAT, // kVec2f_GrVertexAttribType |
- VK_FORMAT_R32G32B32_SFLOAT, // kVec3f_GrVertexAttribType |
- VK_FORMAT_R32G32B32A32_SFLOAT, // kVec4f_GrVertexAttribType |
- VK_FORMAT_R8_UNORM, // kUByte_GrVertexAttribType |
- VK_FORMAT_R8G8B8A8_UNORM, // kVec4ub_GrVertexAttribType |
- VK_FORMAT_R16G16_UNORM, // kVec2us_GrVertexAttribType |
- }; |
- GR_STATIC_ASSERT(0 == kFloat_GrVertexAttribType); |
- GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType); |
- GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType); |
- GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType); |
- GR_STATIC_ASSERT(4 == kUByte_GrVertexAttribType); |
- GR_STATIC_ASSERT(5 == kVec4ub_GrVertexAttribType); |
- GR_STATIC_ASSERT(6 == kVec2us_GrVertexAttribType); |
- GR_STATIC_ASSERT(SK_ARRAY_COUNT(kFormats) == kGrVertexAttribTypeCount); |
- return kFormats[type]; |
-} |
- |
-static void setup_vertex_input_state(const GrPrimitiveProcessor& primProc, |
- VkPipelineVertexInputStateCreateInfo* vertexInputInfo, |
- VkVertexInputBindingDescription* bindingDesc, |
- int maxBindingDescCount, |
- VkVertexInputAttributeDescription* attributeDesc, |
- int maxAttributeDescCount) { |
- // for now we have only one vertex buffer and one binding |
- memset(bindingDesc, 0, sizeof(VkVertexInputBindingDescription)); |
- bindingDesc->binding = 0; |
- bindingDesc->stride = (uint32_t)primProc.getVertexStride(); |
- bindingDesc->inputRate = VK_VERTEX_INPUT_RATE_VERTEX; |
- |
- // setup attribute descriptions |
- int vaCount = primProc.numAttribs(); |
- SkASSERT(vaCount < maxAttributeDescCount); |
- if (vaCount > 0) { |
- size_t offset = 0; |
- for (int attribIndex = 0; attribIndex < vaCount; attribIndex++) { |
- const GrGeometryProcessor::Attribute& attrib = primProc.getAttrib(attribIndex); |
- GrVertexAttribType attribType = attrib.fType; |
- |
- VkVertexInputAttributeDescription& vkAttrib = attributeDesc[attribIndex]; |
- vkAttrib.location = attribIndex; // for now assume location = attribIndex |
- vkAttrib.binding = 0; // for now only one vertex buffer & binding |
- vkAttrib.format = attrib_type_to_vkformat(attribType); |
- vkAttrib.offset = static_cast<uint32_t>(offset); |
- offset += attrib.fOffset; |
- } |
- } |
- |
- memset(vertexInputInfo, 0, sizeof(VkPipelineVertexInputStateCreateInfo)); |
- vertexInputInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; |
- vertexInputInfo->pNext = nullptr; |
- vertexInputInfo->flags = 0; |
- vertexInputInfo->vertexBindingDescriptionCount = 1; |
- vertexInputInfo->pVertexBindingDescriptions = bindingDesc; |
- vertexInputInfo->vertexAttributeDescriptionCount = vaCount; |
- vertexInputInfo->pVertexAttributeDescriptions = attributeDesc; |
-} |
- |
- |
-static void setup_input_assembly_state(GrPrimitiveType primitiveType, |
- VkPipelineInputAssemblyStateCreateInfo* inputAssemblyInfo) { |
- static const VkPrimitiveTopology gPrimitiveType2VkTopology[] = { |
- VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, |
- VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, |
- VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, |
- VK_PRIMITIVE_TOPOLOGY_POINT_LIST, |
- VK_PRIMITIVE_TOPOLOGY_LINE_LIST, |
- VK_PRIMITIVE_TOPOLOGY_LINE_STRIP |
- }; |
- |
- memset(inputAssemblyInfo, 0, sizeof(VkPipelineInputAssemblyStateCreateInfo)); |
- inputAssemblyInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; |
- inputAssemblyInfo->pNext = nullptr; |
- inputAssemblyInfo->flags = 0; |
- inputAssemblyInfo->primitiveRestartEnable = false; |
- inputAssemblyInfo->topology = gPrimitiveType2VkTopology[primitiveType]; |
-} |
- |
- |
-VkStencilOp stencil_op_to_vk_stencil_op(GrStencilOp op) { |
- static const VkStencilOp gTable[] = { |
- VK_STENCIL_OP_KEEP, // kKeep_StencilOp |
- VK_STENCIL_OP_REPLACE, // kReplace_StencilOp |
- VK_STENCIL_OP_INCREMENT_AND_WRAP, // kIncWrap_StencilOp |
- VK_STENCIL_OP_INCREMENT_AND_CLAMP, // kIncClamp_StencilOp |
- VK_STENCIL_OP_DECREMENT_AND_WRAP, // kDecWrap_StencilOp |
- VK_STENCIL_OP_DECREMENT_AND_CLAMP, // kDecClamp_StencilOp |
- VK_STENCIL_OP_ZERO, // kZero_StencilOp |
- VK_STENCIL_OP_INVERT, // kInvert_StencilOp |
- }; |
- GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kStencilOpCount); |
- GR_STATIC_ASSERT(0 == kKeep_StencilOp); |
- GR_STATIC_ASSERT(1 == kReplace_StencilOp); |
- GR_STATIC_ASSERT(2 == kIncWrap_StencilOp); |
- GR_STATIC_ASSERT(3 == kIncClamp_StencilOp); |
- GR_STATIC_ASSERT(4 == kDecWrap_StencilOp); |
- GR_STATIC_ASSERT(5 == kDecClamp_StencilOp); |
- GR_STATIC_ASSERT(6 == kZero_StencilOp); |
- GR_STATIC_ASSERT(7 == kInvert_StencilOp); |
- SkASSERT((unsigned)op < kStencilOpCount); |
- return gTable[op]; |
-} |
- |
-VkCompareOp stencil_func_to_vk_compare_op(GrStencilFunc basicFunc) { |
- static const VkCompareOp gTable[] = { |
- VK_COMPARE_OP_ALWAYS, // kAlways_StencilFunc |
- VK_COMPARE_OP_NEVER, // kNever_StencilFunc |
- VK_COMPARE_OP_GREATER, // kGreater_StencilFunc |
- VK_COMPARE_OP_GREATER_OR_EQUAL, // kGEqual_StencilFunc |
- VK_COMPARE_OP_LESS, // kLess_StencilFunc |
- VK_COMPARE_OP_LESS_OR_EQUAL, // kLEqual_StencilFunc, |
- VK_COMPARE_OP_EQUAL, // kEqual_StencilFunc, |
- VK_COMPARE_OP_NOT_EQUAL, // kNotEqual_StencilFunc, |
- }; |
- GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kBasicStencilFuncCount); |
- GR_STATIC_ASSERT(0 == kAlways_StencilFunc); |
- GR_STATIC_ASSERT(1 == kNever_StencilFunc); |
- GR_STATIC_ASSERT(2 == kGreater_StencilFunc); |
- GR_STATIC_ASSERT(3 == kGEqual_StencilFunc); |
- GR_STATIC_ASSERT(4 == kLess_StencilFunc); |
- GR_STATIC_ASSERT(5 == kLEqual_StencilFunc); |
- GR_STATIC_ASSERT(6 == kEqual_StencilFunc); |
- GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc); |
- SkASSERT((unsigned)basicFunc < kBasicStencilFuncCount); |
- |
- return gTable[basicFunc]; |
-} |
- |
-void setup_depth_stencil_state(const GrVkGpu* gpu, |
- const GrStencilSettings& stencilSettings, |
- VkPipelineDepthStencilStateCreateInfo* stencilInfo) { |
- memset(stencilInfo, 0, sizeof(VkPipelineDepthStencilStateCreateInfo)); |
- stencilInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; |
- stencilInfo->pNext = nullptr; |
- stencilInfo->flags = 0; |
- // set depth testing defaults |
- stencilInfo->depthTestEnable = VK_FALSE; |
- stencilInfo->depthWriteEnable = VK_FALSE; |
- stencilInfo->depthCompareOp = VK_COMPARE_OP_ALWAYS; |
- stencilInfo->depthBoundsTestEnable = VK_FALSE; |
- stencilInfo->stencilTestEnable = !stencilSettings.isDisabled(); |
- if (!stencilSettings.isDisabled()) { |
- // Set front face |
- GrStencilSettings::Face face = GrStencilSettings::kFront_Face; |
- stencilInfo->front.failOp = stencil_op_to_vk_stencil_op(stencilSettings.failOp(face)); |
- stencilInfo->front.passOp = stencil_op_to_vk_stencil_op(stencilSettings.passOp(face)); |
- stencilInfo->front.depthFailOp = stencilInfo->front.failOp; |
- stencilInfo->front.compareOp = stencil_func_to_vk_compare_op(stencilSettings.func(face)); |
- stencilInfo->front.compareMask = stencilSettings.funcMask(face); |
- stencilInfo->front.writeMask = stencilSettings.writeMask(face); |
- stencilInfo->front.reference = stencilSettings.funcRef(face); |
- |
- // Set back face |
- face = GrStencilSettings::kBack_Face; |
- stencilInfo->back.failOp = stencil_op_to_vk_stencil_op(stencilSettings.failOp(face)); |
- stencilInfo->back.passOp = stencil_op_to_vk_stencil_op(stencilSettings.passOp(face)); |
- stencilInfo->back.depthFailOp = stencilInfo->front.failOp; |
- stencilInfo->back.compareOp = stencil_func_to_vk_compare_op(stencilSettings.func(face)); |
- stencilInfo->back.compareMask = stencilSettings.funcMask(face); |
- stencilInfo->back.writeMask = stencilSettings.writeMask(face); |
- stencilInfo->back.reference = stencilSettings.funcRef(face); |
- } |
- stencilInfo->minDepthBounds = 0.0f; |
- stencilInfo->maxDepthBounds = 1.0f; |
-} |
- |
-void setup_viewport_scissor_state(const GrVkGpu* gpu, |
- const GrPipeline& pipeline, |
- const GrVkRenderTarget* vkRT, |
- VkPipelineViewportStateCreateInfo* viewportInfo, |
- VkViewport* viewport, |
- VkRect2D* scissor) { |
- memset(viewportInfo, 0, sizeof(VkPipelineViewportStateCreateInfo)); |
- viewportInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; |
- viewportInfo->pNext = nullptr; |
- viewportInfo->flags = 0; |
- |
- viewport->x = 0.0f; |
- viewport->y = 0.0f; |
- viewport->width = SkIntToScalar(vkRT->width()); |
- viewport->height = SkIntToScalar(vkRT->height()); |
- viewport->minDepth = 0.0f; |
- viewport->maxDepth = 1.0f; |
- viewportInfo->viewportCount = 1; |
- viewportInfo->pViewports = viewport; |
- |
- const GrScissorState& scissorState = pipeline.getScissorState(); |
- if (scissorState.enabled() && |
- !scissorState.rect().contains(0, 0, vkRT->width(), vkRT->height())) { |
- // This all assumes the scissorState has previously been clipped to the device space render |
- // target. |
- scissor->offset.x = scissorState.rect().fLeft; |
- scissor->extent.width = scissorState.rect().width(); |
- if (kTopLeft_GrSurfaceOrigin == vkRT->origin()) { |
- scissor->offset.y = scissorState.rect().fTop; |
- } else { |
- SkASSERT(kBottomLeft_GrSurfaceOrigin == vkRT->origin()); |
- scissor->offset.y = vkRT->height() - scissorState.rect().fBottom; |
- } |
- scissor->extent.height = scissorState.rect().height(); |
- |
- viewportInfo->scissorCount = 1; |
- viewportInfo->pScissors = scissor; |
- SkASSERT(scissor->offset.x >= 0); |
- SkASSERT(scissor->offset.x + scissor->extent.width <= (uint32_t)vkRT->width()); |
- SkASSERT(scissor->offset.y >= 0); |
- SkASSERT(scissor->offset.y + scissor->extent.height <= (uint32_t)vkRT->height()); |
- } else { |
- scissor->extent.width = vkRT->width(); |
- scissor->extent.height = vkRT->height(); |
- scissor->offset.x = 0; |
- scissor->offset.y = 0; |
- viewportInfo->scissorCount = 1; |
- viewportInfo->pScissors = scissor; |
- } |
- SkASSERT(viewportInfo->viewportCount == viewportInfo->scissorCount); |
-} |
- |
-void setup_multisample_state(const GrPipeline& pipeline, |
- VkPipelineMultisampleStateCreateInfo* multisampleInfo) { |
- memset(multisampleInfo, 0, sizeof(VkPipelineMultisampleStateCreateInfo)); |
- multisampleInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; |
- multisampleInfo->pNext = nullptr; |
- multisampleInfo->flags = 0; |
- int numSamples = pipeline.getRenderTarget()->numColorSamples(); |
- SkAssertResult(GrSampleCountToVkSampleCount(numSamples, |
- &multisampleInfo->rasterizationSamples)); |
- multisampleInfo->sampleShadingEnable = VK_FALSE; |
- multisampleInfo->minSampleShading = 0; |
- multisampleInfo->pSampleMask = nullptr; |
- multisampleInfo->alphaToCoverageEnable = VK_FALSE; |
- multisampleInfo->alphaToOneEnable = VK_FALSE; |
-} |
- |
-static VkBlendFactor blend_coeff_to_vk_blend(GrBlendCoeff coeff) { |
- static const VkBlendFactor gTable[] = { |
- VK_BLEND_FACTOR_ZERO, // kZero_GrBlendCoeff |
- VK_BLEND_FACTOR_ONE, // kOne_GrBlendCoeff |
- VK_BLEND_FACTOR_SRC_COLOR, // kSC_GrBlendCoeff |
- VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, // kISC_GrBlendCoeff |
- VK_BLEND_FACTOR_DST_COLOR, // kDC_GrBlendCoeff |
- VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, // kIDC_GrBlendCoeff |
- VK_BLEND_FACTOR_SRC_ALPHA, // kSA_GrBlendCoeff |
- VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // kISA_GrBlendCoeff |
- VK_BLEND_FACTOR_DST_ALPHA, // kDA_GrBlendCoeff |
- VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, // kIDA_GrBlendCoeff |
- VK_BLEND_FACTOR_CONSTANT_COLOR, // kConstC_GrBlendCoeff |
- VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, // kIConstC_GrBlendCoeff |
- VK_BLEND_FACTOR_CONSTANT_ALPHA, // kConstA_GrBlendCoeff |
- VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA, // kIConstA_GrBlendCoeff |
- VK_BLEND_FACTOR_SRC1_COLOR, // kS2C_GrBlendCoeff |
- VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR, // kIS2C_GrBlendCoeff |
- VK_BLEND_FACTOR_SRC1_ALPHA, // kS2A_GrBlendCoeff |
- VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, // kIS2A_GrBlendCoeff |
- |
- }; |
- GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kGrBlendCoeffCnt); |
- GR_STATIC_ASSERT(0 == kZero_GrBlendCoeff); |
- GR_STATIC_ASSERT(1 == kOne_GrBlendCoeff); |
- GR_STATIC_ASSERT(2 == kSC_GrBlendCoeff); |
- GR_STATIC_ASSERT(3 == kISC_GrBlendCoeff); |
- GR_STATIC_ASSERT(4 == kDC_GrBlendCoeff); |
- GR_STATIC_ASSERT(5 == kIDC_GrBlendCoeff); |
- GR_STATIC_ASSERT(6 == kSA_GrBlendCoeff); |
- GR_STATIC_ASSERT(7 == kISA_GrBlendCoeff); |
- GR_STATIC_ASSERT(8 == kDA_GrBlendCoeff); |
- GR_STATIC_ASSERT(9 == kIDA_GrBlendCoeff); |
- GR_STATIC_ASSERT(10 == kConstC_GrBlendCoeff); |
- GR_STATIC_ASSERT(11 == kIConstC_GrBlendCoeff); |
- GR_STATIC_ASSERT(12 == kConstA_GrBlendCoeff); |
- GR_STATIC_ASSERT(13 == kIConstA_GrBlendCoeff); |
- GR_STATIC_ASSERT(14 == kS2C_GrBlendCoeff); |
- GR_STATIC_ASSERT(15 == kIS2C_GrBlendCoeff); |
- GR_STATIC_ASSERT(16 == kS2A_GrBlendCoeff); |
- GR_STATIC_ASSERT(17 == kIS2A_GrBlendCoeff); |
- |
- SkASSERT((unsigned)coeff < kGrBlendCoeffCnt); |
- return gTable[coeff]; |
-} |
- |
- |
-static VkBlendOp blend_equation_to_vk_blend_op(GrBlendEquation equation) { |
- static const VkBlendOp gTable[] = { |
- VK_BLEND_OP_ADD, // kAdd_GrBlendEquation |
- VK_BLEND_OP_SUBTRACT, // kSubtract_GrBlendEquation |
- VK_BLEND_OP_REVERSE_SUBTRACT, // kReverseSubtract_GrBlendEquation |
- }; |
- GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kFirstAdvancedGrBlendEquation); |
- GR_STATIC_ASSERT(0 == kAdd_GrBlendEquation); |
- GR_STATIC_ASSERT(1 == kSubtract_GrBlendEquation); |
- GR_STATIC_ASSERT(2 == kReverseSubtract_GrBlendEquation); |
- |
- SkASSERT((unsigned)equation < kGrBlendCoeffCnt); |
- return gTable[equation]; |
-} |
- |
-bool blend_coeff_refs_constant(GrBlendCoeff coeff) { |
- static const bool gCoeffReferencesBlendConst[] = { |
- false, |
- false, |
- false, |
- false, |
- false, |
- false, |
- false, |
- false, |
- false, |
- false, |
- true, |
- true, |
- true, |
- true, |
- |
- // extended blend coeffs |
- false, |
- false, |
- false, |
- false, |
- }; |
- return gCoeffReferencesBlendConst[coeff]; |
- GR_STATIC_ASSERT(kGrBlendCoeffCnt == SK_ARRAY_COUNT(gCoeffReferencesBlendConst)); |
- // Individual enum asserts already made in blend_coeff_to_vk_blend |
-} |
- |
-void setup_color_blend_state(const GrVkGpu* gpu, |
- const GrPipeline& pipeline, |
- VkPipelineColorBlendStateCreateInfo* colorBlendInfo, |
- VkPipelineColorBlendAttachmentState* attachmentState) { |
- GrXferProcessor::BlendInfo blendInfo; |
- pipeline.getXferProcessor().getBlendInfo(&blendInfo); |
- |
- GrBlendEquation equation = blendInfo.fEquation; |
- GrBlendCoeff srcCoeff = blendInfo.fSrcBlend; |
- GrBlendCoeff dstCoeff = blendInfo.fDstBlend; |
- bool blendOff = (kAdd_GrBlendEquation == equation || kSubtract_GrBlendEquation == equation) && |
- kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff; |
- |
- memset(attachmentState, 0, sizeof(VkPipelineColorBlendAttachmentState)); |
- attachmentState->blendEnable = !blendOff; |
- if (!blendOff) { |
- attachmentState->srcColorBlendFactor = blend_coeff_to_vk_blend(srcCoeff); |
- attachmentState->dstColorBlendFactor = blend_coeff_to_vk_blend(dstCoeff); |
- attachmentState->colorBlendOp = blend_equation_to_vk_blend_op(equation); |
- attachmentState->srcAlphaBlendFactor = blend_coeff_to_vk_blend(srcCoeff); |
- attachmentState->dstAlphaBlendFactor = blend_coeff_to_vk_blend(dstCoeff); |
- attachmentState->alphaBlendOp = blend_equation_to_vk_blend_op(equation); |
- } |
- |
- if (!blendInfo.fWriteColor) { |
- attachmentState->colorWriteMask = 0; |
- } else { |
- attachmentState->colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | |
- VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; |
- } |
- |
- memset(colorBlendInfo, 0, sizeof(VkPipelineColorBlendStateCreateInfo)); |
- colorBlendInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; |
- colorBlendInfo->pNext = nullptr; |
- colorBlendInfo->flags = 0; |
- colorBlendInfo->logicOpEnable = VK_FALSE; |
- colorBlendInfo->attachmentCount = 1; |
- colorBlendInfo->pAttachments = attachmentState; |
- if (blend_coeff_refs_constant(srcCoeff) || blend_coeff_refs_constant(dstCoeff)) { |
- GrColorToRGBAFloat(blendInfo.fBlendConstant, colorBlendInfo->blendConstants); |
- } |
-} |
- |
-VkCullModeFlags draw_face_to_vk_cull_mode(GrPipelineBuilder::DrawFace drawFace) { |
- // Assumes that we've set the front face to be ccw |
- static const VkCullModeFlags gTable[] = { |
- VK_CULL_MODE_NONE, // kBoth_DrawFace |
- VK_CULL_MODE_BACK_BIT, // kCCW_DrawFace, cull back face |
- VK_CULL_MODE_FRONT_BIT, // kCW_DrawFace, cull front face |
- }; |
- GR_STATIC_ASSERT(0 == GrPipelineBuilder::kBoth_DrawFace); |
- GR_STATIC_ASSERT(1 == GrPipelineBuilder::kCCW_DrawFace); |
- GR_STATIC_ASSERT(2 == GrPipelineBuilder::kCW_DrawFace); |
- SkASSERT((unsigned)drawFace <= 2); |
- |
- return gTable[drawFace]; |
-} |
- |
-void setup_raster_state(const GrVkGpu* gpu, |
- const GrPipeline& pipeline, |
- VkPipelineRasterizationStateCreateInfo* rasterInfo) { |
- memset(rasterInfo, 0, sizeof(VkPipelineRasterizationStateCreateInfo)); |
- rasterInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; |
- rasterInfo->pNext = nullptr; |
- rasterInfo->flags = 0; |
- rasterInfo->depthClampEnable = VK_FALSE; |
- rasterInfo->rasterizerDiscardEnable = VK_FALSE; |
- rasterInfo->polygonMode = VK_POLYGON_MODE_FILL; |
- rasterInfo->cullMode = draw_face_to_vk_cull_mode(pipeline.getDrawFace()); |
- rasterInfo->frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; |
- rasterInfo->depthBiasEnable = VK_FALSE; |
- rasterInfo->depthBiasConstantFactor = 0.0f; |
- rasterInfo->depthBiasClamp = 0.0f; |
- rasterInfo->depthBiasSlopeFactor = 0.0f; |
- rasterInfo->lineWidth = 1.0f; |
-} |
- |
-void setup_dynamic_state(const GrVkGpu* gpu, |
- const GrPipeline& pipeline, |
- VkPipelineDynamicStateCreateInfo* dynamicInfo) { |
- memset(dynamicInfo, 0, sizeof(VkPipelineDynamicStateCreateInfo)); |
- dynamicInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; |
- // TODO: mask out any state we might want to set dynamically |
- dynamicInfo->dynamicStateCount = 0; |
-} |
- |
-GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, const GrPipeline& pipeline, |
- const GrPrimitiveProcessor& primProc, |
- VkPipelineShaderStageCreateInfo* shaderStageInfo, |
- int shaderStageCount, |
- GrPrimitiveType primitiveType, |
- const GrVkRenderPass& renderPass, |
- VkPipelineLayout layout) { |
- VkPipelineVertexInputStateCreateInfo vertexInputInfo; |
- VkVertexInputBindingDescription bindingDesc; |
- // TODO: allocate this based on VkPhysicalDeviceLimits::maxVertexInputAttributes |
- static const int kMaxVertexAttributes = 16; |
- static VkVertexInputAttributeDescription attributeDesc[kMaxVertexAttributes]; |
- setup_vertex_input_state(primProc, &vertexInputInfo, &bindingDesc, 1, |
- attributeDesc, kMaxVertexAttributes); |
- |
- VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo; |
- setup_input_assembly_state(primitiveType, &inputAssemblyInfo); |
- |
- VkPipelineDepthStencilStateCreateInfo depthStencilInfo; |
- setup_depth_stencil_state(gpu, pipeline.getStencil(), &depthStencilInfo); |
- |
- GrRenderTarget* rt = pipeline.getRenderTarget(); |
- GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt); |
- VkPipelineViewportStateCreateInfo viewportInfo; |
- VkViewport viewport; |
- VkRect2D scissor; |
- setup_viewport_scissor_state(gpu, pipeline, vkRT, &viewportInfo, &viewport, &scissor); |
- |
- VkPipelineMultisampleStateCreateInfo multisampleInfo; |
- setup_multisample_state(pipeline, &multisampleInfo); |
- |
- // We will only have one color attachment per pipeline. |
- VkPipelineColorBlendAttachmentState attachmentStates[1]; |
- VkPipelineColorBlendStateCreateInfo colorBlendInfo; |
- setup_color_blend_state(gpu, pipeline, &colorBlendInfo, attachmentStates); |
- |
- VkPipelineRasterizationStateCreateInfo rasterInfo; |
- setup_raster_state(gpu, pipeline, &rasterInfo); |
- |
- VkPipelineDynamicStateCreateInfo dynamicInfo; |
- setup_dynamic_state(gpu, pipeline, &dynamicInfo); |
- |
- VkGraphicsPipelineCreateInfo pipelineCreateInfo; |
- memset(&pipelineCreateInfo, 0, sizeof(VkGraphicsPipelineCreateInfo)); |
- pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; |
- pipelineCreateInfo.pNext = nullptr; |
- pipelineCreateInfo.flags = 0; |
- pipelineCreateInfo.stageCount = shaderStageCount; |
- pipelineCreateInfo.pStages = shaderStageInfo; |
- pipelineCreateInfo.pVertexInputState = &vertexInputInfo; |
- pipelineCreateInfo.pInputAssemblyState = &inputAssemblyInfo; |
- pipelineCreateInfo.pTessellationState = nullptr; |
- pipelineCreateInfo.pViewportState = &viewportInfo; |
- pipelineCreateInfo.pRasterizationState = &rasterInfo; |
- pipelineCreateInfo.pMultisampleState = &multisampleInfo; |
- pipelineCreateInfo.pDepthStencilState = &depthStencilInfo; |
- pipelineCreateInfo.pColorBlendState = &colorBlendInfo; |
- pipelineCreateInfo.pDynamicState = &dynamicInfo; |
- pipelineCreateInfo.layout = layout; |
- pipelineCreateInfo.renderPass = renderPass.vkRenderPass(); |
- pipelineCreateInfo.subpass = 0; |
- pipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE; |
- pipelineCreateInfo.basePipelineIndex = -1; |
- |
- VkPipeline vkPipeline; |
- VkResult err = GR_VK_CALL(gpu->vkInterface(), CreateGraphicsPipelines(gpu->device(), |
- VK_NULL_HANDLE, 1, |
- &pipelineCreateInfo, |
- nullptr, &vkPipeline)); |
- if (err) { |
- return nullptr; |
- } |
- |
- return new GrVkPipeline(vkPipeline); |
-} |
- |
-void GrVkPipeline::freeGPUData(const GrVkGpu* gpu) const { |
- GR_VK_CALL(gpu->vkInterface(), DestroyPipeline(gpu->device(), fPipeline, nullptr)); |
-} |
- |
- |
+/* |
+* Copyright 2016 Google Inc. |
+* |
+* Use of this source code is governed by a BSD-style license that can be |
+* found in the LICENSE file. |
+*/ |
+ |
+#include "GrVkPipeline.h" |
+ |
+#include "GrGeometryProcessor.h" |
+#include "GrPipeline.h" |
+ |
+#include "GrVkGpu.h" |
+#include "GrVkProgramDesc.h" |
+#include "GrVkRenderTarget.h" |
+#include "GrVkUtil.h" |
+ |
+static inline const VkFormat& attrib_type_to_vkformat(GrVertexAttribType type) { |
+ SkASSERT(type >= 0 && type < kGrVertexAttribTypeCount); |
+ static const VkFormat kFormats[kGrVertexAttribTypeCount] = { |
+ VK_FORMAT_R32_SFLOAT, // kFloat_GrVertexAttribType |
+ VK_FORMAT_R32G32_SFLOAT, // kVec2f_GrVertexAttribType |
+ VK_FORMAT_R32G32B32_SFLOAT, // kVec3f_GrVertexAttribType |
+ VK_FORMAT_R32G32B32A32_SFLOAT, // kVec4f_GrVertexAttribType |
+ VK_FORMAT_R8_UNORM, // kUByte_GrVertexAttribType |
+ VK_FORMAT_R8G8B8A8_UNORM, // kVec4ub_GrVertexAttribType |
+ VK_FORMAT_R16G16_UNORM, // kVec2us_GrVertexAttribType |
+ }; |
+ GR_STATIC_ASSERT(0 == kFloat_GrVertexAttribType); |
+ GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType); |
+ GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType); |
+ GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType); |
+ GR_STATIC_ASSERT(4 == kUByte_GrVertexAttribType); |
+ GR_STATIC_ASSERT(5 == kVec4ub_GrVertexAttribType); |
+ GR_STATIC_ASSERT(6 == kVec2us_GrVertexAttribType); |
+ GR_STATIC_ASSERT(SK_ARRAY_COUNT(kFormats) == kGrVertexAttribTypeCount); |
+ return kFormats[type]; |
+} |
+ |
+static void setup_vertex_input_state(const GrPrimitiveProcessor& primProc, |
+ VkPipelineVertexInputStateCreateInfo* vertexInputInfo, |
+ VkVertexInputBindingDescription* bindingDesc, |
+ int maxBindingDescCount, |
+ VkVertexInputAttributeDescription* attributeDesc, |
+ int maxAttributeDescCount) { |
+ // for now we have only one vertex buffer and one binding |
+ memset(bindingDesc, 0, sizeof(VkVertexInputBindingDescription)); |
+ bindingDesc->binding = 0; |
+ bindingDesc->stride = (uint32_t)primProc.getVertexStride(); |
+ bindingDesc->inputRate = VK_VERTEX_INPUT_RATE_VERTEX; |
+ |
+ // setup attribute descriptions |
+ int vaCount = primProc.numAttribs(); |
+ SkASSERT(vaCount < maxAttributeDescCount); |
+ if (vaCount > 0) { |
+ size_t offset = 0; |
+ for (int attribIndex = 0; attribIndex < vaCount; attribIndex++) { |
+ const GrGeometryProcessor::Attribute& attrib = primProc.getAttrib(attribIndex); |
+ GrVertexAttribType attribType = attrib.fType; |
+ |
+ VkVertexInputAttributeDescription& vkAttrib = attributeDesc[attribIndex]; |
+ vkAttrib.location = attribIndex; // for now assume location = attribIndex |
+ vkAttrib.binding = 0; // for now only one vertex buffer & binding |
+ vkAttrib.format = attrib_type_to_vkformat(attribType); |
+ vkAttrib.offset = static_cast<uint32_t>(offset); |
+ offset += attrib.fOffset; |
+ } |
+ } |
+ |
+ memset(vertexInputInfo, 0, sizeof(VkPipelineVertexInputStateCreateInfo)); |
+ vertexInputInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; |
+ vertexInputInfo->pNext = nullptr; |
+ vertexInputInfo->flags = 0; |
+ vertexInputInfo->vertexBindingDescriptionCount = 1; |
+ vertexInputInfo->pVertexBindingDescriptions = bindingDesc; |
+ vertexInputInfo->vertexAttributeDescriptionCount = vaCount; |
+ vertexInputInfo->pVertexAttributeDescriptions = attributeDesc; |
+} |
+ |
+ |
+static void setup_input_assembly_state(GrPrimitiveType primitiveType, |
+ VkPipelineInputAssemblyStateCreateInfo* inputAssemblyInfo) { |
+ static const VkPrimitiveTopology gPrimitiveType2VkTopology[] = { |
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, |
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, |
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, |
+ VK_PRIMITIVE_TOPOLOGY_POINT_LIST, |
+ VK_PRIMITIVE_TOPOLOGY_LINE_LIST, |
+ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP |
+ }; |
+ |
+ memset(inputAssemblyInfo, 0, sizeof(VkPipelineInputAssemblyStateCreateInfo)); |
+ inputAssemblyInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; |
+ inputAssemblyInfo->pNext = nullptr; |
+ inputAssemblyInfo->flags = 0; |
+ inputAssemblyInfo->primitiveRestartEnable = false; |
+ inputAssemblyInfo->topology = gPrimitiveType2VkTopology[primitiveType]; |
+} |
+ |
+ |
+VkStencilOp stencil_op_to_vk_stencil_op(GrStencilOp op) { |
+ static const VkStencilOp gTable[] = { |
+ VK_STENCIL_OP_KEEP, // kKeep_StencilOp |
+ VK_STENCIL_OP_REPLACE, // kReplace_StencilOp |
+ VK_STENCIL_OP_INCREMENT_AND_WRAP, // kIncWrap_StencilOp |
+ VK_STENCIL_OP_INCREMENT_AND_CLAMP, // kIncClamp_StencilOp |
+ VK_STENCIL_OP_DECREMENT_AND_WRAP, // kDecWrap_StencilOp |
+ VK_STENCIL_OP_DECREMENT_AND_CLAMP, // kDecClamp_StencilOp |
+ VK_STENCIL_OP_ZERO, // kZero_StencilOp |
+ VK_STENCIL_OP_INVERT, // kInvert_StencilOp |
+ }; |
+ GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kStencilOpCount); |
+ GR_STATIC_ASSERT(0 == kKeep_StencilOp); |
+ GR_STATIC_ASSERT(1 == kReplace_StencilOp); |
+ GR_STATIC_ASSERT(2 == kIncWrap_StencilOp); |
+ GR_STATIC_ASSERT(3 == kIncClamp_StencilOp); |
+ GR_STATIC_ASSERT(4 == kDecWrap_StencilOp); |
+ GR_STATIC_ASSERT(5 == kDecClamp_StencilOp); |
+ GR_STATIC_ASSERT(6 == kZero_StencilOp); |
+ GR_STATIC_ASSERT(7 == kInvert_StencilOp); |
+ SkASSERT((unsigned)op < kStencilOpCount); |
+ return gTable[op]; |
+} |
+ |
+VkCompareOp stencil_func_to_vk_compare_op(GrStencilFunc basicFunc) { |
+ static const VkCompareOp gTable[] = { |
+ VK_COMPARE_OP_ALWAYS, // kAlways_StencilFunc |
+ VK_COMPARE_OP_NEVER, // kNever_StencilFunc |
+ VK_COMPARE_OP_GREATER, // kGreater_StencilFunc |
+ VK_COMPARE_OP_GREATER_OR_EQUAL, // kGEqual_StencilFunc |
+ VK_COMPARE_OP_LESS, // kLess_StencilFunc |
+ VK_COMPARE_OP_LESS_OR_EQUAL, // kLEqual_StencilFunc, |
+ VK_COMPARE_OP_EQUAL, // kEqual_StencilFunc, |
+ VK_COMPARE_OP_NOT_EQUAL, // kNotEqual_StencilFunc, |
+ }; |
+ GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kBasicStencilFuncCount); |
+ GR_STATIC_ASSERT(0 == kAlways_StencilFunc); |
+ GR_STATIC_ASSERT(1 == kNever_StencilFunc); |
+ GR_STATIC_ASSERT(2 == kGreater_StencilFunc); |
+ GR_STATIC_ASSERT(3 == kGEqual_StencilFunc); |
+ GR_STATIC_ASSERT(4 == kLess_StencilFunc); |
+ GR_STATIC_ASSERT(5 == kLEqual_StencilFunc); |
+ GR_STATIC_ASSERT(6 == kEqual_StencilFunc); |
+ GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc); |
+ SkASSERT((unsigned)basicFunc < kBasicStencilFuncCount); |
+ |
+ return gTable[basicFunc]; |
+} |
+ |
+void setup_depth_stencil_state(const GrVkGpu* gpu, |
+ const GrStencilSettings& stencilSettings, |
+ VkPipelineDepthStencilStateCreateInfo* stencilInfo) { |
+ memset(stencilInfo, 0, sizeof(VkPipelineDepthStencilStateCreateInfo)); |
+ stencilInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; |
+ stencilInfo->pNext = nullptr; |
+ stencilInfo->flags = 0; |
+ // set depth testing defaults |
+ stencilInfo->depthTestEnable = VK_FALSE; |
+ stencilInfo->depthWriteEnable = VK_FALSE; |
+ stencilInfo->depthCompareOp = VK_COMPARE_OP_ALWAYS; |
+ stencilInfo->depthBoundsTestEnable = VK_FALSE; |
+ stencilInfo->stencilTestEnable = !stencilSettings.isDisabled(); |
+ if (!stencilSettings.isDisabled()) { |
+ // Set front face |
+ GrStencilSettings::Face face = GrStencilSettings::kFront_Face; |
+ stencilInfo->front.failOp = stencil_op_to_vk_stencil_op(stencilSettings.failOp(face)); |
+ stencilInfo->front.passOp = stencil_op_to_vk_stencil_op(stencilSettings.passOp(face)); |
+ stencilInfo->front.depthFailOp = stencilInfo->front.failOp; |
+ stencilInfo->front.compareOp = stencil_func_to_vk_compare_op(stencilSettings.func(face)); |
+ stencilInfo->front.compareMask = stencilSettings.funcMask(face); |
+ stencilInfo->front.writeMask = stencilSettings.writeMask(face); |
+ stencilInfo->front.reference = stencilSettings.funcRef(face); |
+ |
+ // Set back face |
+ face = GrStencilSettings::kBack_Face; |
+ stencilInfo->back.failOp = stencil_op_to_vk_stencil_op(stencilSettings.failOp(face)); |
+ stencilInfo->back.passOp = stencil_op_to_vk_stencil_op(stencilSettings.passOp(face)); |
+ stencilInfo->back.depthFailOp = stencilInfo->front.failOp; |
+ stencilInfo->back.compareOp = stencil_func_to_vk_compare_op(stencilSettings.func(face)); |
+ stencilInfo->back.compareMask = stencilSettings.funcMask(face); |
+ stencilInfo->back.writeMask = stencilSettings.writeMask(face); |
+ stencilInfo->back.reference = stencilSettings.funcRef(face); |
+ } |
+ stencilInfo->minDepthBounds = 0.0f; |
+ stencilInfo->maxDepthBounds = 1.0f; |
+} |
+ |
+void setup_viewport_scissor_state(const GrVkGpu* gpu, |
+ const GrPipeline& pipeline, |
+ const GrVkRenderTarget* vkRT, |
+ VkPipelineViewportStateCreateInfo* viewportInfo, |
+ VkViewport* viewport, |
+ VkRect2D* scissor) { |
+ memset(viewportInfo, 0, sizeof(VkPipelineViewportStateCreateInfo)); |
+ viewportInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; |
+ viewportInfo->pNext = nullptr; |
+ viewportInfo->flags = 0; |
+ |
+ viewport->x = 0.0f; |
+ viewport->y = 0.0f; |
+ viewport->width = SkIntToScalar(vkRT->width()); |
+ viewport->height = SkIntToScalar(vkRT->height()); |
+ viewport->minDepth = 0.0f; |
+ viewport->maxDepth = 1.0f; |
+ viewportInfo->viewportCount = 1; |
+ viewportInfo->pViewports = viewport; |
+ |
+ const GrScissorState& scissorState = pipeline.getScissorState(); |
+ if (scissorState.enabled() && |
+ !scissorState.rect().contains(0, 0, vkRT->width(), vkRT->height())) { |
+ // This all assumes the scissorState has previously been clipped to the device space render |
+ // target. |
+ scissor->offset.x = scissorState.rect().fLeft; |
+ scissor->extent.width = scissorState.rect().width(); |
+ if (kTopLeft_GrSurfaceOrigin == vkRT->origin()) { |
+ scissor->offset.y = scissorState.rect().fTop; |
+ } else { |
+ SkASSERT(kBottomLeft_GrSurfaceOrigin == vkRT->origin()); |
+ scissor->offset.y = vkRT->height() - scissorState.rect().fBottom; |
+ } |
+ scissor->extent.height = scissorState.rect().height(); |
+ |
+ viewportInfo->scissorCount = 1; |
+ viewportInfo->pScissors = scissor; |
+ SkASSERT(scissor->offset.x >= 0); |
+ SkASSERT(scissor->offset.x + scissor->extent.width <= (uint32_t)vkRT->width()); |
+ SkASSERT(scissor->offset.y >= 0); |
+ SkASSERT(scissor->offset.y + scissor->extent.height <= (uint32_t)vkRT->height()); |
+ } else { |
+ scissor->extent.width = vkRT->width(); |
+ scissor->extent.height = vkRT->height(); |
+ scissor->offset.x = 0; |
+ scissor->offset.y = 0; |
+ viewportInfo->scissorCount = 1; |
+ viewportInfo->pScissors = scissor; |
+ } |
+ SkASSERT(viewportInfo->viewportCount == viewportInfo->scissorCount); |
+} |
+ |
+void setup_multisample_state(const GrPipeline& pipeline, |
+ VkPipelineMultisampleStateCreateInfo* multisampleInfo) { |
+ memset(multisampleInfo, 0, sizeof(VkPipelineMultisampleStateCreateInfo)); |
+ multisampleInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; |
+ multisampleInfo->pNext = nullptr; |
+ multisampleInfo->flags = 0; |
+ int numSamples = pipeline.getRenderTarget()->numColorSamples(); |
+ SkAssertResult(GrSampleCountToVkSampleCount(numSamples, |
+ &multisampleInfo->rasterizationSamples)); |
+ multisampleInfo->sampleShadingEnable = VK_FALSE; |
+ multisampleInfo->minSampleShading = 0; |
+ multisampleInfo->pSampleMask = nullptr; |
+ multisampleInfo->alphaToCoverageEnable = VK_FALSE; |
+ multisampleInfo->alphaToOneEnable = VK_FALSE; |
+} |
+ |
+static VkBlendFactor blend_coeff_to_vk_blend(GrBlendCoeff coeff) { |
+ static const VkBlendFactor gTable[] = { |
+ VK_BLEND_FACTOR_ZERO, // kZero_GrBlendCoeff |
+ VK_BLEND_FACTOR_ONE, // kOne_GrBlendCoeff |
+ VK_BLEND_FACTOR_SRC_COLOR, // kSC_GrBlendCoeff |
+ VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, // kISC_GrBlendCoeff |
+ VK_BLEND_FACTOR_DST_COLOR, // kDC_GrBlendCoeff |
+ VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, // kIDC_GrBlendCoeff |
+ VK_BLEND_FACTOR_SRC_ALPHA, // kSA_GrBlendCoeff |
+ VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // kISA_GrBlendCoeff |
+ VK_BLEND_FACTOR_DST_ALPHA, // kDA_GrBlendCoeff |
+ VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, // kIDA_GrBlendCoeff |
+ VK_BLEND_FACTOR_CONSTANT_COLOR, // kConstC_GrBlendCoeff |
+ VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, // kIConstC_GrBlendCoeff |
+ VK_BLEND_FACTOR_CONSTANT_ALPHA, // kConstA_GrBlendCoeff |
+ VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA, // kIConstA_GrBlendCoeff |
+ VK_BLEND_FACTOR_SRC1_COLOR, // kS2C_GrBlendCoeff |
+ VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR, // kIS2C_GrBlendCoeff |
+ VK_BLEND_FACTOR_SRC1_ALPHA, // kS2A_GrBlendCoeff |
+ VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, // kIS2A_GrBlendCoeff |
+ |
+ }; |
+ GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kGrBlendCoeffCnt); |
+ GR_STATIC_ASSERT(0 == kZero_GrBlendCoeff); |
+ GR_STATIC_ASSERT(1 == kOne_GrBlendCoeff); |
+ GR_STATIC_ASSERT(2 == kSC_GrBlendCoeff); |
+ GR_STATIC_ASSERT(3 == kISC_GrBlendCoeff); |
+ GR_STATIC_ASSERT(4 == kDC_GrBlendCoeff); |
+ GR_STATIC_ASSERT(5 == kIDC_GrBlendCoeff); |
+ GR_STATIC_ASSERT(6 == kSA_GrBlendCoeff); |
+ GR_STATIC_ASSERT(7 == kISA_GrBlendCoeff); |
+ GR_STATIC_ASSERT(8 == kDA_GrBlendCoeff); |
+ GR_STATIC_ASSERT(9 == kIDA_GrBlendCoeff); |
+ GR_STATIC_ASSERT(10 == kConstC_GrBlendCoeff); |
+ GR_STATIC_ASSERT(11 == kIConstC_GrBlendCoeff); |
+ GR_STATIC_ASSERT(12 == kConstA_GrBlendCoeff); |
+ GR_STATIC_ASSERT(13 == kIConstA_GrBlendCoeff); |
+ GR_STATIC_ASSERT(14 == kS2C_GrBlendCoeff); |
+ GR_STATIC_ASSERT(15 == kIS2C_GrBlendCoeff); |
+ GR_STATIC_ASSERT(16 == kS2A_GrBlendCoeff); |
+ GR_STATIC_ASSERT(17 == kIS2A_GrBlendCoeff); |
+ |
+ SkASSERT((unsigned)coeff < kGrBlendCoeffCnt); |
+ return gTable[coeff]; |
+} |
+ |
+ |
+static VkBlendOp blend_equation_to_vk_blend_op(GrBlendEquation equation) { |
+ static const VkBlendOp gTable[] = { |
+ VK_BLEND_OP_ADD, // kAdd_GrBlendEquation |
+ VK_BLEND_OP_SUBTRACT, // kSubtract_GrBlendEquation |
+ VK_BLEND_OP_REVERSE_SUBTRACT, // kReverseSubtract_GrBlendEquation |
+ }; |
+ GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kFirstAdvancedGrBlendEquation); |
+ GR_STATIC_ASSERT(0 == kAdd_GrBlendEquation); |
+ GR_STATIC_ASSERT(1 == kSubtract_GrBlendEquation); |
+ GR_STATIC_ASSERT(2 == kReverseSubtract_GrBlendEquation); |
+ |
+ SkASSERT((unsigned)equation < kGrBlendCoeffCnt); |
+ return gTable[equation]; |
+} |
+ |
+bool blend_coeff_refs_constant(GrBlendCoeff coeff) { |
+ static const bool gCoeffReferencesBlendConst[] = { |
+ false, |
+ false, |
+ false, |
+ false, |
+ false, |
+ false, |
+ false, |
+ false, |
+ false, |
+ false, |
+ true, |
+ true, |
+ true, |
+ true, |
+ |
+ // extended blend coeffs |
+ false, |
+ false, |
+ false, |
+ false, |
+ }; |
+ return gCoeffReferencesBlendConst[coeff]; |
+ GR_STATIC_ASSERT(kGrBlendCoeffCnt == SK_ARRAY_COUNT(gCoeffReferencesBlendConst)); |
+ // Individual enum asserts already made in blend_coeff_to_vk_blend |
+} |
+ |
+void setup_color_blend_state(const GrVkGpu* gpu, |
+ const GrPipeline& pipeline, |
+ VkPipelineColorBlendStateCreateInfo* colorBlendInfo, |
+ VkPipelineColorBlendAttachmentState* attachmentState) { |
+ GrXferProcessor::BlendInfo blendInfo; |
+ pipeline.getXferProcessor().getBlendInfo(&blendInfo); |
+ |
+ GrBlendEquation equation = blendInfo.fEquation; |
+ GrBlendCoeff srcCoeff = blendInfo.fSrcBlend; |
+ GrBlendCoeff dstCoeff = blendInfo.fDstBlend; |
+ bool blendOff = (kAdd_GrBlendEquation == equation || kSubtract_GrBlendEquation == equation) && |
+ kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff; |
+ |
+ memset(attachmentState, 0, sizeof(VkPipelineColorBlendAttachmentState)); |
+ attachmentState->blendEnable = !blendOff; |
+ if (!blendOff) { |
+ attachmentState->srcColorBlendFactor = blend_coeff_to_vk_blend(srcCoeff); |
+ attachmentState->dstColorBlendFactor = blend_coeff_to_vk_blend(dstCoeff); |
+ attachmentState->colorBlendOp = blend_equation_to_vk_blend_op(equation); |
+ attachmentState->srcAlphaBlendFactor = blend_coeff_to_vk_blend(srcCoeff); |
+ attachmentState->dstAlphaBlendFactor = blend_coeff_to_vk_blend(dstCoeff); |
+ attachmentState->alphaBlendOp = blend_equation_to_vk_blend_op(equation); |
+ } |
+ |
+ if (!blendInfo.fWriteColor) { |
+ attachmentState->colorWriteMask = 0; |
+ } else { |
+ attachmentState->colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | |
+ VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; |
+ } |
+ |
+ memset(colorBlendInfo, 0, sizeof(VkPipelineColorBlendStateCreateInfo)); |
+ colorBlendInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; |
+ colorBlendInfo->pNext = nullptr; |
+ colorBlendInfo->flags = 0; |
+ colorBlendInfo->logicOpEnable = VK_FALSE; |
+ colorBlendInfo->attachmentCount = 1; |
+ colorBlendInfo->pAttachments = attachmentState; |
+ if (blend_coeff_refs_constant(srcCoeff) || blend_coeff_refs_constant(dstCoeff)) { |
+ GrColorToRGBAFloat(blendInfo.fBlendConstant, colorBlendInfo->blendConstants); |
+ } |
+} |
+ |
+VkCullModeFlags draw_face_to_vk_cull_mode(GrPipelineBuilder::DrawFace drawFace) { |
+ // Assumes that we've set the front face to be ccw |
+ static const VkCullModeFlags gTable[] = { |
+ VK_CULL_MODE_NONE, // kBoth_DrawFace |
+ VK_CULL_MODE_BACK_BIT, // kCCW_DrawFace, cull back face |
+ VK_CULL_MODE_FRONT_BIT, // kCW_DrawFace, cull front face |
+ }; |
+ GR_STATIC_ASSERT(0 == GrPipelineBuilder::kBoth_DrawFace); |
+ GR_STATIC_ASSERT(1 == GrPipelineBuilder::kCCW_DrawFace); |
+ GR_STATIC_ASSERT(2 == GrPipelineBuilder::kCW_DrawFace); |
+ SkASSERT((unsigned)drawFace <= 2); |
+ |
+ return gTable[drawFace]; |
+} |
+ |
+void setup_raster_state(const GrVkGpu* gpu, |
+ const GrPipeline& pipeline, |
+ VkPipelineRasterizationStateCreateInfo* rasterInfo) { |
+ memset(rasterInfo, 0, sizeof(VkPipelineRasterizationStateCreateInfo)); |
+ rasterInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; |
+ rasterInfo->pNext = nullptr; |
+ rasterInfo->flags = 0; |
+ rasterInfo->depthClampEnable = VK_FALSE; |
+ rasterInfo->rasterizerDiscardEnable = VK_FALSE; |
+ rasterInfo->polygonMode = VK_POLYGON_MODE_FILL; |
+ rasterInfo->cullMode = draw_face_to_vk_cull_mode(pipeline.getDrawFace()); |
+ rasterInfo->frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; |
+ rasterInfo->depthBiasEnable = VK_FALSE; |
+ rasterInfo->depthBiasConstantFactor = 0.0f; |
+ rasterInfo->depthBiasClamp = 0.0f; |
+ rasterInfo->depthBiasSlopeFactor = 0.0f; |
+ rasterInfo->lineWidth = 1.0f; |
+} |
+ |
+void setup_dynamic_state(const GrVkGpu* gpu, |
+ const GrPipeline& pipeline, |
+ VkPipelineDynamicStateCreateInfo* dynamicInfo) { |
+ memset(dynamicInfo, 0, sizeof(VkPipelineDynamicStateCreateInfo)); |
+ dynamicInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; |
+ // TODO: mask out any state we might want to set dynamically |
+ dynamicInfo->dynamicStateCount = 0; |
+} |
+ |
+GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, const GrPipeline& pipeline, |
+ const GrPrimitiveProcessor& primProc, |
+ VkPipelineShaderStageCreateInfo* shaderStageInfo, |
+ int shaderStageCount, |
+ GrPrimitiveType primitiveType, |
+ const GrVkRenderPass& renderPass, |
+ VkPipelineLayout layout, |
+ VkPipelineCache cache) { |
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo; |
+ VkVertexInputBindingDescription bindingDesc; |
+ // TODO: allocate this based on VkPhysicalDeviceLimits::maxVertexInputAttributes |
+ static const int kMaxVertexAttributes = 16; |
+ static VkVertexInputAttributeDescription attributeDesc[kMaxVertexAttributes]; |
+ setup_vertex_input_state(primProc, &vertexInputInfo, &bindingDesc, 1, |
+ attributeDesc, kMaxVertexAttributes); |
+ |
+ VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo; |
+ setup_input_assembly_state(primitiveType, &inputAssemblyInfo); |
+ |
+ VkPipelineDepthStencilStateCreateInfo depthStencilInfo; |
+ setup_depth_stencil_state(gpu, pipeline.getStencil(), &depthStencilInfo); |
+ |
+ GrRenderTarget* rt = pipeline.getRenderTarget(); |
+ GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt); |
+ VkPipelineViewportStateCreateInfo viewportInfo; |
+ VkViewport viewport; |
+ VkRect2D scissor; |
+ setup_viewport_scissor_state(gpu, pipeline, vkRT, &viewportInfo, &viewport, &scissor); |
+ |
+ VkPipelineMultisampleStateCreateInfo multisampleInfo; |
+ setup_multisample_state(pipeline, &multisampleInfo); |
+ |
+ // We will only have one color attachment per pipeline. |
+ VkPipelineColorBlendAttachmentState attachmentStates[1]; |
+ VkPipelineColorBlendStateCreateInfo colorBlendInfo; |
+ setup_color_blend_state(gpu, pipeline, &colorBlendInfo, attachmentStates); |
+ |
+ VkPipelineRasterizationStateCreateInfo rasterInfo; |
+ setup_raster_state(gpu, pipeline, &rasterInfo); |
+ |
+ VkPipelineDynamicStateCreateInfo dynamicInfo; |
+ setup_dynamic_state(gpu, pipeline, &dynamicInfo); |
+ |
+ VkGraphicsPipelineCreateInfo pipelineCreateInfo; |
+ memset(&pipelineCreateInfo, 0, sizeof(VkGraphicsPipelineCreateInfo)); |
+ pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; |
+ pipelineCreateInfo.pNext = nullptr; |
+ pipelineCreateInfo.flags = 0; |
+ pipelineCreateInfo.stageCount = shaderStageCount; |
+ pipelineCreateInfo.pStages = shaderStageInfo; |
+ pipelineCreateInfo.pVertexInputState = &vertexInputInfo; |
+ pipelineCreateInfo.pInputAssemblyState = &inputAssemblyInfo; |
+ pipelineCreateInfo.pTessellationState = nullptr; |
+ pipelineCreateInfo.pViewportState = &viewportInfo; |
+ pipelineCreateInfo.pRasterizationState = &rasterInfo; |
+ pipelineCreateInfo.pMultisampleState = &multisampleInfo; |
+ pipelineCreateInfo.pDepthStencilState = &depthStencilInfo; |
+ pipelineCreateInfo.pColorBlendState = &colorBlendInfo; |
+ pipelineCreateInfo.pDynamicState = &dynamicInfo; |
+ pipelineCreateInfo.layout = layout; |
+ pipelineCreateInfo.renderPass = renderPass.vkRenderPass(); |
+ pipelineCreateInfo.subpass = 0; |
+ pipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE; |
+ pipelineCreateInfo.basePipelineIndex = -1; |
+ |
+ VkPipeline vkPipeline; |
+ VkResult err = GR_VK_CALL(gpu->vkInterface(), CreateGraphicsPipelines(gpu->device(), |
+ cache, 1, |
+ &pipelineCreateInfo, |
+ nullptr, &vkPipeline)); |
+ if (err) { |
+ return nullptr; |
+ } |
+ |
+ return new GrVkPipeline(vkPipeline); |
+} |
+ |
+void GrVkPipeline::freeGPUData(const GrVkGpu* gpu) const { |
+ GR_VK_CALL(gpu->vkInterface(), DestroyPipeline(gpu->device(), fPipeline, nullptr)); |
+} |
+ |
+ |