1 // Copyright 2018 The SwiftShader Authors. All Rights Reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 #include "VkPipeline.hpp"
16 #include "VkPipelineLayout.hpp"
17 #include "VkShaderModule.hpp"
18 #include "Pipeline/SpirvShader.hpp"
20 #include "spirv-tools/optimizer.hpp"
25 sw::DrawType Convert(VkPrimitiveTopology topology)
29 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
30 return sw::DRAW_POINTLIST;
31 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
32 return sw::DRAW_LINELIST;
33 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
34 return sw::DRAW_LINESTRIP;
35 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
36 return sw::DRAW_TRIANGLELIST;
37 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
38 return sw::DRAW_TRIANGLESTRIP;
39 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
40 return sw::DRAW_TRIANGLEFAN;
41 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
42 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
43 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
44 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
45 // geometry shader specific
48 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
49 // tesselation shader specific
56 return sw::DRAW_TRIANGLELIST;
59 sw::Rect Convert(const VkRect2D& rect)
61 return sw::Rect(rect.offset.x, rect.offset.y, rect.offset.x + rect.extent.width, rect.offset.y + rect.extent.height);
64 sw::StreamType getStreamType(VkFormat format)
68 case VK_FORMAT_R8_UNORM:
69 case VK_FORMAT_R8G8_UNORM:
70 case VK_FORMAT_R8G8B8A8_UNORM:
71 case VK_FORMAT_R8_UINT:
72 case VK_FORMAT_R8G8_UINT:
73 case VK_FORMAT_R8G8B8A8_UINT:
74 case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
75 case VK_FORMAT_A8B8G8R8_UINT_PACK32:
76 return sw::STREAMTYPE_BYTE;
77 case VK_FORMAT_B8G8R8A8_UNORM:
78 return sw::STREAMTYPE_COLOR;
79 case VK_FORMAT_R8_SNORM:
80 case VK_FORMAT_R8_SINT:
81 case VK_FORMAT_R8G8_SNORM:
82 case VK_FORMAT_R8G8_SINT:
83 case VK_FORMAT_R8G8B8A8_SNORM:
84 case VK_FORMAT_R8G8B8A8_SINT:
85 case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
86 case VK_FORMAT_A8B8G8R8_SINT_PACK32:
87 return sw::STREAMTYPE_SBYTE;
88 case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
89 return sw::STREAMTYPE_2_10_10_10_UINT;
90 case VK_FORMAT_R16_UNORM:
91 case VK_FORMAT_R16_UINT:
92 case VK_FORMAT_R16G16_UNORM:
93 case VK_FORMAT_R16G16_UINT:
94 case VK_FORMAT_R16G16B16A16_UNORM:
95 case VK_FORMAT_R16G16B16A16_UINT:
96 return sw::STREAMTYPE_USHORT;
97 case VK_FORMAT_R16_SNORM:
98 case VK_FORMAT_R16_SINT:
99 case VK_FORMAT_R16G16_SNORM:
100 case VK_FORMAT_R16G16_SINT:
101 case VK_FORMAT_R16G16B16A16_SNORM:
102 case VK_FORMAT_R16G16B16A16_SINT:
103 return sw::STREAMTYPE_SHORT;
104 case VK_FORMAT_R16_SFLOAT:
105 case VK_FORMAT_R16G16_SFLOAT:
106 case VK_FORMAT_R16G16B16A16_SFLOAT:
107 return sw::STREAMTYPE_HALF;
108 case VK_FORMAT_R32_UINT:
109 case VK_FORMAT_R32G32_UINT:
110 case VK_FORMAT_R32G32B32_UINT:
111 case VK_FORMAT_R32G32B32A32_UINT:
112 return sw::STREAMTYPE_UINT;
113 case VK_FORMAT_R32_SINT:
114 case VK_FORMAT_R32G32_SINT:
115 case VK_FORMAT_R32G32B32_SINT:
116 case VK_FORMAT_R32G32B32A32_SINT:
117 return sw::STREAMTYPE_INT;
118 case VK_FORMAT_R32_SFLOAT:
119 case VK_FORMAT_R32G32_SFLOAT:
120 case VK_FORMAT_R32G32B32_SFLOAT:
121 case VK_FORMAT_R32G32B32A32_SFLOAT:
122 return sw::STREAMTYPE_FLOAT;
127 return sw::STREAMTYPE_BYTE;
130 uint32_t getNumberOfChannels(VkFormat format)
134 case VK_FORMAT_R8_UNORM:
135 case VK_FORMAT_R8_SNORM:
136 case VK_FORMAT_R8_UINT:
137 case VK_FORMAT_R8_SINT:
138 case VK_FORMAT_R16_UNORM:
139 case VK_FORMAT_R16_SNORM:
140 case VK_FORMAT_R16_UINT:
141 case VK_FORMAT_R16_SINT:
142 case VK_FORMAT_R16_SFLOAT:
143 case VK_FORMAT_R32_UINT:
144 case VK_FORMAT_R32_SINT:
145 case VK_FORMAT_R32_SFLOAT:
147 case VK_FORMAT_R8G8_UNORM:
148 case VK_FORMAT_R8G8_SNORM:
149 case VK_FORMAT_R8G8_UINT:
150 case VK_FORMAT_R8G8_SINT:
151 case VK_FORMAT_R16G16_UNORM:
152 case VK_FORMAT_R16G16_SNORM:
153 case VK_FORMAT_R16G16_UINT:
154 case VK_FORMAT_R16G16_SINT:
155 case VK_FORMAT_R16G16_SFLOAT:
156 case VK_FORMAT_R32G32_UINT:
157 case VK_FORMAT_R32G32_SINT:
158 case VK_FORMAT_R32G32_SFLOAT:
160 case VK_FORMAT_R32G32B32_UINT:
161 case VK_FORMAT_R32G32B32_SINT:
162 case VK_FORMAT_R32G32B32_SFLOAT:
164 case VK_FORMAT_R8G8B8A8_UNORM:
165 case VK_FORMAT_R8G8B8A8_SNORM:
166 case VK_FORMAT_R8G8B8A8_UINT:
167 case VK_FORMAT_R8G8B8A8_SINT:
168 case VK_FORMAT_B8G8R8A8_UNORM:
169 case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
170 case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
171 case VK_FORMAT_A8B8G8R8_UINT_PACK32:
172 case VK_FORMAT_A8B8G8R8_SINT_PACK32:
173 case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
174 case VK_FORMAT_R16G16B16A16_UNORM:
175 case VK_FORMAT_R16G16B16A16_SNORM:
176 case VK_FORMAT_R16G16B16A16_UINT:
177 case VK_FORMAT_R16G16B16A16_SINT:
178 case VK_FORMAT_R16G16B16A16_SFLOAT:
179 case VK_FORMAT_R32G32B32A32_UINT:
180 case VK_FORMAT_R32G32B32A32_SINT:
181 case VK_FORMAT_R32G32B32A32_SFLOAT:
195 Pipeline::Pipeline(PipelineLayout const *layout) : layout(layout) {}
197 GraphicsPipeline::GraphicsPipeline(const VkGraphicsPipelineCreateInfo* pCreateInfo, void* mem)
198 : Pipeline(Cast(pCreateInfo->layout))
200 if((pCreateInfo->flags != 0) ||
201 (pCreateInfo->stageCount != 2) ||
202 (pCreateInfo->pTessellationState != nullptr) ||
203 (pCreateInfo->pDynamicState != nullptr) ||
204 (pCreateInfo->subpass != 0) ||
205 (pCreateInfo->basePipelineHandle != VK_NULL_HANDLE) ||
206 (pCreateInfo->basePipelineIndex != 0))
211 const VkPipelineShaderStageCreateInfo& vertexStage = pCreateInfo->pStages[0];
212 if((vertexStage.stage != VK_SHADER_STAGE_VERTEX_BIT) ||
213 (vertexStage.flags != 0) ||
214 !((vertexStage.pSpecializationInfo == nullptr) ||
215 ((vertexStage.pSpecializationInfo->mapEntryCount == 0) &&
216 (vertexStage.pSpecializationInfo->dataSize == 0))))
221 const VkPipelineShaderStageCreateInfo& fragmentStage = pCreateInfo->pStages[1];
222 if((fragmentStage.stage != VK_SHADER_STAGE_FRAGMENT_BIT) ||
223 (fragmentStage.flags != 0) ||
224 !((fragmentStage.pSpecializationInfo == nullptr) ||
225 ((fragmentStage.pSpecializationInfo->mapEntryCount == 0) &&
226 (fragmentStage.pSpecializationInfo->dataSize == 0))))
231 const VkPipelineVertexInputStateCreateInfo* vertexInputState = pCreateInfo->pVertexInputState;
232 if(vertexInputState->flags != 0)
237 // Context must always have a PipelineLayout set.
238 context.pipelineLayout = layout;
240 // Temporary in-binding-order representation of buffer strides, to be consumed below
241 // when considering attributes. TODO: unfuse buffers from attributes in backend, is old GL model.
242 uint32_t bufferStrides[MAX_VERTEX_INPUT_BINDINGS];
243 for(uint32_t i = 0; i < vertexInputState->vertexBindingDescriptionCount; i++)
245 auto const & desc = vertexInputState->pVertexBindingDescriptions[i];
246 bufferStrides[desc.binding] = desc.stride;
247 if(desc.inputRate != VK_VERTEX_INPUT_RATE_VERTEX)
253 for(uint32_t i = 0; i < vertexInputState->vertexAttributeDescriptionCount; i++)
255 auto const & desc = vertexInputState->pVertexAttributeDescriptions[i];
256 sw::Stream& input = context.input[desc.location];
257 input.count = getNumberOfChannels(desc.format);
258 input.type = getStreamType(desc.format);
259 input.normalized = !sw::Surface::isNonNormalizedInteger(desc.format);
260 input.offset = desc.offset;
261 input.binding = desc.binding;
262 input.stride = bufferStrides[desc.binding];
265 const VkPipelineInputAssemblyStateCreateInfo* assemblyState = pCreateInfo->pInputAssemblyState;
266 if((assemblyState->flags != 0) ||
267 (assemblyState->primitiveRestartEnable != 0))
272 context.drawType = Convert(assemblyState->topology);
274 const VkPipelineViewportStateCreateInfo* viewportState = pCreateInfo->pViewportState;
277 if((viewportState->flags != 0) ||
278 (viewportState->viewportCount != 1) ||
279 (viewportState->scissorCount != 1))
284 scissor = Convert(viewportState->pScissors[0]);
285 viewport = viewportState->pViewports[0];
288 const VkPipelineRasterizationStateCreateInfo* rasterizationState = pCreateInfo->pRasterizationState;
289 if((rasterizationState->flags != 0) ||
290 (rasterizationState->depthClampEnable != 0) ||
291 (rasterizationState->polygonMode != VK_POLYGON_MODE_FILL))
296 context.rasterizerDiscard = rasterizationState->rasterizerDiscardEnable;
297 context.cullMode = rasterizationState->cullMode;
298 context.frontFacingCCW = rasterizationState->frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE;
299 context.depthBias = (rasterizationState->depthBiasEnable ? rasterizationState->depthBiasConstantFactor : 0.0f);
300 context.slopeDepthBias = (rasterizationState->depthBiasEnable ? rasterizationState->depthBiasSlopeFactor : 0.0f);
302 const VkPipelineMultisampleStateCreateInfo* multisampleState = pCreateInfo->pMultisampleState;
305 switch (multisampleState->rasterizationSamples) {
306 case VK_SAMPLE_COUNT_1_BIT:
307 context.sampleCount = 1;
309 case VK_SAMPLE_COUNT_4_BIT:
310 context.sampleCount = 4;
313 UNIMPLEMENTED("Unsupported sample count");
316 if((multisampleState->flags != 0) ||
317 (multisampleState->sampleShadingEnable != 0) ||
318 !((multisampleState->pSampleMask == nullptr) ||
319 (*(multisampleState->pSampleMask) == 0xFFFFFFFFu)) ||
320 (multisampleState->alphaToCoverageEnable != 0) ||
321 (multisampleState->alphaToOneEnable != 0))
328 context.sampleCount = 1;
331 const VkPipelineDepthStencilStateCreateInfo* depthStencilState = pCreateInfo->pDepthStencilState;
332 if(depthStencilState)
334 if((depthStencilState->flags != 0) ||
335 (depthStencilState->depthBoundsTestEnable != 0) ||
336 (depthStencilState->minDepthBounds != 0.0f) ||
337 (depthStencilState->maxDepthBounds != 1.0f))
342 context.depthBufferEnable = depthStencilState->depthTestEnable;
343 context.depthWriteEnable = depthStencilState->depthWriteEnable;
344 context.depthCompareMode = depthStencilState->depthCompareOp;
346 context.stencilEnable = context.twoSidedStencil = depthStencilState->stencilTestEnable;
347 if(context.stencilEnable)
349 context.stencilMask = depthStencilState->front.compareMask;
350 context.stencilCompareMode = depthStencilState->front.compareOp;
351 context.stencilZFailOperation = depthStencilState->front.depthFailOp;
352 context.stencilFailOperation = depthStencilState->front.failOp;
353 context.stencilPassOperation = depthStencilState->front.passOp;
354 context.stencilReference = depthStencilState->front.reference;
355 context.stencilWriteMask = depthStencilState->front.writeMask;
357 context.stencilMaskCCW = depthStencilState->back.compareMask;
358 context.stencilCompareModeCCW = depthStencilState->back.compareOp;
359 context.stencilZFailOperationCCW = depthStencilState->back.depthFailOp;
360 context.stencilFailOperationCCW = depthStencilState->back.failOp;
361 context.stencilPassOperationCCW = depthStencilState->back.passOp;
362 context.stencilReferenceCCW = depthStencilState->back.reference;
363 context.stencilWriteMaskCCW = depthStencilState->back.writeMask;
367 const VkPipelineColorBlendStateCreateInfo* colorBlendState = pCreateInfo->pColorBlendState;
370 if((colorBlendState->flags != 0) ||
371 ((colorBlendState->logicOpEnable != 0) &&
372 (colorBlendState->attachmentCount > 1)))
377 blendConstants.r = colorBlendState->blendConstants[0];
378 blendConstants.g = colorBlendState->blendConstants[1];
379 blendConstants.b = colorBlendState->blendConstants[2];
380 blendConstants.a = colorBlendState->blendConstants[3];
382 if(colorBlendState->attachmentCount == 1)
384 const VkPipelineColorBlendAttachmentState& attachment = colorBlendState->pAttachments[0];
385 if(attachment.colorWriteMask != (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT))
390 context.alphaBlendEnable = attachment.blendEnable;
391 context.separateAlphaBlendEnable = (attachment.alphaBlendOp != attachment.colorBlendOp) ||
392 (attachment.dstAlphaBlendFactor != attachment.dstColorBlendFactor) ||
393 (attachment.srcAlphaBlendFactor != attachment.srcColorBlendFactor);
394 context.blendOperationStateAlpha = attachment.alphaBlendOp;
395 context.blendOperationState = attachment.colorBlendOp;
396 context.destBlendFactorStateAlpha = attachment.dstAlphaBlendFactor;
397 context.destBlendFactorState = attachment.dstColorBlendFactor;
398 context.sourceBlendFactorStateAlpha = attachment.srcAlphaBlendFactor;
399 context.sourceBlendFactorState = attachment.srcColorBlendFactor;
404 void GraphicsPipeline::destroyPipeline(const VkAllocationCallbacks* pAllocator)
407 delete fragmentShader;
410 size_t GraphicsPipeline::ComputeRequiredAllocationSize(const VkGraphicsPipelineCreateInfo* pCreateInfo)
415 void GraphicsPipeline::compileShaders(const VkAllocationCallbacks* pAllocator, const VkGraphicsPipelineCreateInfo* pCreateInfo)
417 for (auto pStage = pCreateInfo->pStages; pStage != pCreateInfo->pStages + pCreateInfo->stageCount; pStage++)
419 auto module = Cast(pStage->module);
421 auto code = module->getCode();
422 spvtools::Optimizer opt{SPV_ENV_VULKAN_1_1};
423 opt.RegisterPass(spvtools::CreateInlineExhaustivePass());
425 // If the pipeline uses specialization, apply the specializations before freezing
426 if (pStage->pSpecializationInfo)
428 std::unordered_map<uint32_t, std::vector<uint32_t>> specializations;
429 for (auto i = 0u; i < pStage->pSpecializationInfo->mapEntryCount; ++i)
431 auto const &e = pStage->pSpecializationInfo->pMapEntries[i];
433 static_cast<uint32_t const *>(pStage->pSpecializationInfo->pData) + e.offset / sizeof(uint32_t);
434 specializations.emplace(e.constantID,
435 std::vector<uint32_t>{value_ptr, value_ptr + e.size / sizeof(uint32_t)});
437 opt.RegisterPass(spvtools::CreateSetSpecConstantDefaultValuePass(specializations));
439 // Freeze specialization constants into normal constants, and propagate through
440 opt.RegisterPass(spvtools::CreateFreezeSpecConstantValuePass());
441 opt.RegisterPass(spvtools::CreateFoldSpecConstantOpAndCompositePass());
443 std::vector<uint32_t> postOptCode;
444 opt.Run(code.data(), code.size(), &postOptCode);
446 // TODO: also pass in any pipeline state which will affect shader compilation
447 auto spirvShader = new sw::SpirvShader{postOptCode};
449 switch (pStage->stage)
451 case VK_SHADER_STAGE_VERTEX_BIT:
452 context.vertexShader = vertexShader = spirvShader;
455 case VK_SHADER_STAGE_FRAGMENT_BIT:
456 context.pixelShader = fragmentShader = spirvShader;
460 UNIMPLEMENTED("Unsupported stage");
465 uint32_t GraphicsPipeline::computePrimitiveCount(uint32_t vertexCount) const
467 switch(context.drawType)
469 case sw::DRAW_POINTLIST:
471 case sw::DRAW_LINELIST:
472 return vertexCount / 2;
473 case sw::DRAW_LINESTRIP:
474 return vertexCount - 1;
475 case sw::DRAW_TRIANGLELIST:
476 return vertexCount / 3;
477 case sw::DRAW_TRIANGLESTRIP:
478 return vertexCount - 2;
479 case sw::DRAW_TRIANGLEFAN:
480 return vertexCount - 2;
488 const sw::Context& GraphicsPipeline::getContext() const
493 const sw::Rect& GraphicsPipeline::getScissor() const
498 const VkViewport& GraphicsPipeline::getViewport() const
503 const sw::Color<float>& GraphicsPipeline::getBlendConstants() const
505 return blendConstants;
508 ComputePipeline::ComputePipeline(const VkComputePipelineCreateInfo* pCreateInfo, void* mem)
509 : Pipeline(Cast(pCreateInfo->layout))
513 void ComputePipeline::destroyPipeline(const VkAllocationCallbacks* pAllocator)
517 size_t ComputePipeline::ComputeRequiredAllocationSize(const VkComputePipelineCreateInfo* pCreateInfo)