1 // Copyright 2020 The SwiftShader Authors. All Rights Reserved.
2 //
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
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
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.
14
15 #include "Context.hpp"
16
17 #include "Vulkan/VkBuffer.hpp"
18 #include "Vulkan/VkDevice.hpp"
19 #include "Vulkan/VkImageView.hpp"
20 #include "Vulkan/VkPipeline.hpp"
21 #include "Vulkan/VkRenderPass.hpp"
22 #include "Vulkan/VkStringify.hpp"
23
24 namespace {
25
ComputePrimitiveCount(VkPrimitiveTopology topology,uint32_t vertexCount)26 uint32_t ComputePrimitiveCount(VkPrimitiveTopology topology, uint32_t vertexCount)
27 {
28 switch(topology)
29 {
30 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
31 return vertexCount;
32 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
33 return vertexCount / 2;
34 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
35 return std::max<uint32_t>(vertexCount, 1) - 1;
36 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
37 return vertexCount / 3;
38 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
39 return std::max<uint32_t>(vertexCount, 2) - 2;
40 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
41 return std::max<uint32_t>(vertexCount, 2) - 2;
42 default:
43 UNSUPPORTED("VkPrimitiveTopology %d", int(topology));
44 }
45
46 return 0;
47 }
48
49 template<typename T>
ProcessPrimitiveRestart(T * indexBuffer,VkPrimitiveTopology topology,uint32_t count,std::vector<std::pair<uint32_t,void * >> * indexBuffers)50 void ProcessPrimitiveRestart(T *indexBuffer,
51 VkPrimitiveTopology topology,
52 uint32_t count,
53 std::vector<std::pair<uint32_t, void *>> *indexBuffers)
54 {
55 static const T RestartIndex = static_cast<T>(-1);
56 T *indexBufferStart = indexBuffer;
57 uint32_t vertexCount = 0;
58 for(uint32_t i = 0; i < count; i++)
59 {
60 if(indexBuffer[i] == RestartIndex)
61 {
62 // Record previous segment
63 if(vertexCount > 0)
64 {
65 uint32_t primitiveCount = ComputePrimitiveCount(topology, vertexCount);
66 if(primitiveCount > 0)
67 {
68 indexBuffers->push_back({ primitiveCount, indexBufferStart });
69 }
70 }
71 vertexCount = 0;
72 }
73 else
74 {
75 if(vertexCount == 0)
76 {
77 indexBufferStart = indexBuffer + i;
78 }
79 vertexCount++;
80 }
81 }
82
83 // Record last segment
84 if(vertexCount > 0)
85 {
86 uint32_t primitiveCount = ComputePrimitiveCount(topology, vertexCount);
87 if(primitiveCount > 0)
88 {
89 indexBuffers->push_back({ primitiveCount, indexBufferStart });
90 }
91 }
92 }
93
ParseDynamicStateFlags(const VkPipelineDynamicStateCreateInfo * dynamicStateCreateInfo)94 vk::DynamicStateFlags ParseDynamicStateFlags(const VkPipelineDynamicStateCreateInfo *dynamicStateCreateInfo)
95 {
96 vk::DynamicStateFlags dynamicStateFlags = {};
97
98 if(dynamicStateCreateInfo == nullptr)
99 {
100 return dynamicStateFlags;
101 }
102
103 if(dynamicStateCreateInfo->flags != 0)
104 {
105 // Vulkan 1.3: "flags is reserved for future use." "flags must be 0"
106 UNSUPPORTED("dynamicStateCreateInfo->flags 0x%08X", int(dynamicStateCreateInfo->flags));
107 }
108
109 for(uint32_t i = 0; i < dynamicStateCreateInfo->dynamicStateCount; i++)
110 {
111 VkDynamicState dynamicState = dynamicStateCreateInfo->pDynamicStates[i];
112 switch(dynamicState)
113 {
114 // Vertex input interface:
115 case VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE:
116 dynamicStateFlags.vertexInputInterface.dynamicPrimitiveRestartEnable = true;
117 break;
118 case VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY:
119 dynamicStateFlags.vertexInputInterface.dynamicPrimitiveTopology = true;
120 break;
121 case VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE:
122 dynamicStateFlags.vertexInputInterface.dynamicVertexInputBindingStride = true;
123 break;
124
125 // Pre-rasterization:
126 case VK_DYNAMIC_STATE_LINE_WIDTH:
127 dynamicStateFlags.preRasterization.dynamicLineWidth = true;
128 break;
129 case VK_DYNAMIC_STATE_DEPTH_BIAS:
130 dynamicStateFlags.preRasterization.dynamicDepthBias = true;
131 break;
132 case VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE:
133 dynamicStateFlags.preRasterization.dynamicDepthBiasEnable = true;
134 break;
135 case VK_DYNAMIC_STATE_CULL_MODE:
136 dynamicStateFlags.preRasterization.dynamicCullMode = true;
137 break;
138 case VK_DYNAMIC_STATE_FRONT_FACE:
139 dynamicStateFlags.preRasterization.dynamicFrontFace = true;
140 break;
141 case VK_DYNAMIC_STATE_VIEWPORT:
142 dynamicStateFlags.preRasterization.dynamicViewport = true;
143 break;
144 case VK_DYNAMIC_STATE_SCISSOR:
145 dynamicStateFlags.preRasterization.dynamicScissor = true;
146 break;
147 case VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT:
148 dynamicStateFlags.preRasterization.dynamicViewportWithCount = true;
149 break;
150 case VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT:
151 dynamicStateFlags.preRasterization.dynamicScissorWithCount = true;
152 break;
153 case VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE:
154 dynamicStateFlags.preRasterization.dynamicRasterizerDiscardEnable = true;
155 break;
156
157 // Fragment:
158 case VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE:
159 dynamicStateFlags.fragment.dynamicDepthTestEnable = true;
160 break;
161 case VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE:
162 dynamicStateFlags.fragment.dynamicDepthWriteEnable = true;
163 break;
164 case VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE:
165 dynamicStateFlags.fragment.dynamicDepthBoundsTestEnable = true;
166 break;
167 case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
168 dynamicStateFlags.fragment.dynamicDepthBounds = true;
169 break;
170 case VK_DYNAMIC_STATE_DEPTH_COMPARE_OP:
171 dynamicStateFlags.fragment.dynamicDepthCompareOp = true;
172 break;
173 case VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE:
174 dynamicStateFlags.fragment.dynamicStencilTestEnable = true;
175 break;
176 case VK_DYNAMIC_STATE_STENCIL_OP:
177 dynamicStateFlags.fragment.dynamicStencilOp = true;
178 break;
179 case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
180 dynamicStateFlags.fragment.dynamicStencilCompareMask = true;
181 break;
182 case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
183 dynamicStateFlags.fragment.dynamicStencilWriteMask = true;
184 break;
185 case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
186 dynamicStateFlags.fragment.dynamicStencilReference = true;
187 break;
188
189 // Fragment output interface:
190 case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
191 dynamicStateFlags.fragmentOutputInterface.dynamicBlendConstants = true;
192 break;
193
194 default:
195 UNSUPPORTED("VkDynamicState %d", int(dynamicState));
196 }
197 }
198
199 return dynamicStateFlags;
200 }
201 } // namespace
202
203 namespace vk {
204
bytesPerIndex() const205 uint32_t IndexBuffer::bytesPerIndex() const
206 {
207 return indexType == VK_INDEX_TYPE_UINT16 ? 2u : 4u;
208 }
209
setIndexBufferBinding(const VertexInputBinding & indexBufferBinding,VkIndexType type)210 void IndexBuffer::setIndexBufferBinding(const VertexInputBinding &indexBufferBinding, VkIndexType type)
211 {
212 binding = indexBufferBinding;
213 indexType = type;
214 }
215
getIndexBuffers(VkPrimitiveTopology topology,uint32_t count,uint32_t first,bool indexed,bool hasPrimitiveRestartEnable,std::vector<std::pair<uint32_t,void * >> * indexBuffers) const216 void IndexBuffer::getIndexBuffers(VkPrimitiveTopology topology, uint32_t count, uint32_t first, bool indexed, bool hasPrimitiveRestartEnable, std::vector<std::pair<uint32_t, void *>> *indexBuffers) const
217 {
218 if(indexed)
219 {
220 const VkDeviceSize bufferSize = binding.buffer->getSize();
221 if(binding.offset >= bufferSize)
222 {
223 return; // Nothing to draw
224 }
225
226 const VkDeviceSize maxIndices = (bufferSize - binding.offset) / bytesPerIndex();
227 if(first > maxIndices)
228 {
229 return; // Nothing to draw
230 }
231
232 void *indexBuffer = binding.buffer->getOffsetPointer(binding.offset + first * bytesPerIndex());
233 if(hasPrimitiveRestartEnable)
234 {
235 switch(indexType)
236 {
237 case VK_INDEX_TYPE_UINT16:
238 ProcessPrimitiveRestart(static_cast<uint16_t *>(indexBuffer), topology, count, indexBuffers);
239 break;
240 case VK_INDEX_TYPE_UINT32:
241 ProcessPrimitiveRestart(static_cast<uint32_t *>(indexBuffer), topology, count, indexBuffers);
242 break;
243 default:
244 UNSUPPORTED("VkIndexType %d", int(indexType));
245 }
246 }
247 else
248 {
249 indexBuffers->push_back({ ComputePrimitiveCount(topology, count), indexBuffer });
250 }
251 }
252 else
253 {
254 indexBuffers->push_back({ ComputePrimitiveCount(topology, count), nullptr });
255 }
256 }
257
colorFormat(int index) const258 VkFormat Attachments::colorFormat(int index) const
259 {
260 ASSERT((index >= 0) && (index < sw::MAX_COLOR_BUFFERS));
261
262 if(colorBuffer[index])
263 {
264 return colorBuffer[index]->getFormat();
265 }
266 else
267 {
268 return VK_FORMAT_UNDEFINED;
269 }
270 }
271
depthFormat() const272 VkFormat Attachments::depthFormat() const
273 {
274 if(depthBuffer)
275 {
276 return depthBuffer->getFormat();
277 }
278 else
279 {
280 return VK_FORMAT_UNDEFINED;
281 }
282 }
283
initialize(const VkPipelineVertexInputStateCreateInfo * vertexInputState)284 void Inputs::initialize(const VkPipelineVertexInputStateCreateInfo *vertexInputState)
285 {
286 if(vertexInputState->flags != 0)
287 {
288 // Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
289 UNSUPPORTED("vertexInputState->flags");
290 }
291
292 // Temporary in-binding-order representation of buffer strides, to be consumed below
293 // when considering attributes. TODO: unfuse buffers from attributes in backend, is old GL model.
294 uint32_t vertexStrides[MAX_VERTEX_INPUT_BINDINGS];
295 uint32_t instanceStrides[MAX_VERTEX_INPUT_BINDINGS];
296 VkVertexInputRate inputRates[MAX_VERTEX_INPUT_BINDINGS];
297 for(uint32_t i = 0; i < vertexInputState->vertexBindingDescriptionCount; i++)
298 {
299 const auto &desc = vertexInputState->pVertexBindingDescriptions[i];
300 inputRates[desc.binding] = desc.inputRate;
301 vertexStrides[desc.binding] = desc.inputRate == VK_VERTEX_INPUT_RATE_VERTEX ? desc.stride : 0;
302 instanceStrides[desc.binding] = desc.inputRate == VK_VERTEX_INPUT_RATE_INSTANCE ? desc.stride : 0;
303 }
304
305 for(uint32_t i = 0; i < vertexInputState->vertexAttributeDescriptionCount; i++)
306 {
307 const auto &desc = vertexInputState->pVertexAttributeDescriptions[i];
308 sw::Stream &input = stream[desc.location];
309 input.format = desc.format;
310 input.offset = desc.offset;
311 input.binding = desc.binding;
312 input.inputRate = inputRates[desc.binding];
313 input.vertexStride = vertexStrides[desc.binding];
314 input.instanceStride = instanceStrides[desc.binding];
315 }
316 }
317
updateDescriptorSets(const DescriptorSet::Array & dso,const DescriptorSet::Bindings & ds,const DescriptorSet::DynamicOffsets & ddo)318 void Inputs::updateDescriptorSets(const DescriptorSet::Array &dso,
319 const DescriptorSet::Bindings &ds,
320 const DescriptorSet::DynamicOffsets &ddo)
321 {
322 descriptorSetObjects = dso;
323 descriptorSets = ds;
324 descriptorDynamicOffsets = ddo;
325 }
326
bindVertexInputs(int firstInstance,bool dynamicInstanceStride)327 void Inputs::bindVertexInputs(int firstInstance, bool dynamicInstanceStride)
328 {
329 for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; i++)
330 {
331 auto &attrib = stream[i];
332 if(attrib.format != VK_FORMAT_UNDEFINED)
333 {
334 const auto &vertexInput = vertexInputBindings[attrib.binding];
335 VkDeviceSize offset = attrib.offset + vertexInput.offset +
336 getInstanceStride(i, dynamicInstanceStride) * firstInstance;
337 attrib.buffer = vertexInput.buffer ? vertexInput.buffer->getOffsetPointer(offset) : nullptr;
338
339 VkDeviceSize size = vertexInput.buffer ? vertexInput.buffer->getSize() : 0;
340 attrib.robustnessSize = (size > offset) ? size - offset : 0;
341 }
342 }
343 }
344
setVertexInputBinding(const VertexInputBinding bindings[])345 void Inputs::setVertexInputBinding(const VertexInputBinding bindings[])
346 {
347 for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; ++i)
348 {
349 vertexInputBindings[i] = bindings[i];
350 }
351 }
352
advanceInstanceAttributes(bool dynamicInstanceStride)353 void Inputs::advanceInstanceAttributes(bool dynamicInstanceStride)
354 {
355 for(uint32_t i = 0; i < vk::MAX_VERTEX_INPUT_BINDINGS; i++)
356 {
357 auto &attrib = stream[i];
358
359 VkDeviceSize instanceStride = getInstanceStride(i, dynamicInstanceStride);
360 if((attrib.format != VK_FORMAT_UNDEFINED) && instanceStride && (instanceStride < attrib.robustnessSize))
361 {
362 // Under the casts: attrib.buffer += instanceStride
363 attrib.buffer = (const void *)((uintptr_t)attrib.buffer + instanceStride);
364 attrib.robustnessSize -= instanceStride;
365 }
366 }
367 }
368
getVertexStride(uint32_t i,bool dynamicVertexStride) const369 VkDeviceSize Inputs::getVertexStride(uint32_t i, bool dynamicVertexStride) const
370 {
371 auto &attrib = stream[i];
372 if(attrib.format != VK_FORMAT_UNDEFINED && attrib.inputRate == VK_VERTEX_INPUT_RATE_VERTEX)
373 {
374 if(dynamicVertexStride)
375 {
376 return vertexInputBindings[attrib.binding].stride;
377 }
378 else
379 {
380 return attrib.vertexStride;
381 }
382 }
383
384 return 0;
385 }
386
getInstanceStride(uint32_t i,bool dynamicInstanceStride) const387 VkDeviceSize Inputs::getInstanceStride(uint32_t i, bool dynamicInstanceStride) const
388 {
389 auto &attrib = stream[i];
390 if(attrib.format != VK_FORMAT_UNDEFINED && attrib.inputRate == VK_VERTEX_INPUT_RATE_INSTANCE)
391 {
392 if(dynamicInstanceStride)
393 {
394 return vertexInputBindings[attrib.binding].stride;
395 }
396 else
397 {
398 return attrib.instanceStride;
399 }
400 }
401
402 return 0;
403 }
404
set(const VkPipelineMultisampleStateCreateInfo * multisampleState)405 void MultisampleState::set(const VkPipelineMultisampleStateCreateInfo *multisampleState)
406 {
407 if(multisampleState->flags != 0)
408 {
409 // Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
410 UNSUPPORTED("pCreateInfo->pMultisampleState->flags 0x%08X", int(multisampleState->flags));
411 }
412
413 sampleShadingEnable = (multisampleState->sampleShadingEnable != VK_FALSE);
414 if(sampleShadingEnable)
415 {
416 minSampleShading = multisampleState->minSampleShading;
417 }
418
419 if(multisampleState->alphaToOneEnable != VK_FALSE)
420 {
421 UNSUPPORTED("VkPhysicalDeviceFeatures::alphaToOne");
422 }
423
424 switch(multisampleState->rasterizationSamples)
425 {
426 case VK_SAMPLE_COUNT_1_BIT:
427 sampleCount = 1;
428 break;
429 case VK_SAMPLE_COUNT_4_BIT:
430 sampleCount = 4;
431 break;
432 default:
433 UNSUPPORTED("Unsupported sample count");
434 }
435
436 VkSampleMask sampleMask;
437 if(multisampleState->pSampleMask)
438 {
439 sampleMask = multisampleState->pSampleMask[0];
440 }
441 else // "If pSampleMask is NULL, it is treated as if the mask has all bits set to 1."
442 {
443 sampleMask = ~0;
444 }
445
446 alphaToCoverage = (multisampleState->alphaToCoverageEnable != VK_FALSE);
447 multiSampleMask = sampleMask & ((unsigned)0xFFFFFFFF >> (32 - sampleCount));
448 }
449
initialize(const VkPipelineVertexInputStateCreateInfo * vertexInputState,const VkPipelineInputAssemblyStateCreateInfo * inputAssemblyState,const DynamicStateFlags & allDynamicStateFlags)450 void VertexInputInterfaceState::initialize(const VkPipelineVertexInputStateCreateInfo *vertexInputState,
451 const VkPipelineInputAssemblyStateCreateInfo *inputAssemblyState,
452 const DynamicStateFlags &allDynamicStateFlags)
453 {
454 dynamicStateFlags = allDynamicStateFlags.vertexInputInterface;
455
456 if(vertexInputState->flags != 0)
457 {
458 // Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
459 UNSUPPORTED("vertexInputState->flags");
460 }
461
462 if(inputAssemblyState->flags != 0)
463 {
464 // Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
465 UNSUPPORTED("pCreateInfo->pInputAssemblyState->flags 0x%08X", int(inputAssemblyState->flags));
466 }
467
468 primitiveRestartEnable = (inputAssemblyState->primitiveRestartEnable != VK_FALSE);
469 topology = inputAssemblyState->topology;
470 }
471
applyState(const DynamicState & dynamicState)472 void VertexInputInterfaceState::applyState(const DynamicState &dynamicState)
473 {
474 if(dynamicStateFlags.dynamicPrimitiveRestartEnable)
475 {
476 primitiveRestartEnable = dynamicState.primitiveRestartEnable;
477 }
478
479 if(dynamicStateFlags.dynamicPrimitiveTopology)
480 {
481 topology = dynamicState.primitiveTopology;
482 }
483 }
484
isDrawPoint(bool polygonModeAware,VkPolygonMode polygonMode) const485 bool VertexInputInterfaceState::isDrawPoint(bool polygonModeAware, VkPolygonMode polygonMode) const
486 {
487 switch(topology)
488 {
489 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
490 return true;
491 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
492 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
493 return false;
494 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
495 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
496 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
497 return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_POINT) : false;
498 default:
499 UNSUPPORTED("topology %d", int(topology));
500 }
501 return false;
502 }
503
isDrawLine(bool polygonModeAware,VkPolygonMode polygonMode) const504 bool VertexInputInterfaceState::isDrawLine(bool polygonModeAware, VkPolygonMode polygonMode) const
505 {
506 switch(topology)
507 {
508 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
509 return false;
510 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
511 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
512 return true;
513 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
514 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
515 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
516 return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_LINE) : false;
517 default:
518 UNSUPPORTED("topology %d", int(topology));
519 }
520 return false;
521 }
522
isDrawTriangle(bool polygonModeAware,VkPolygonMode polygonMode) const523 bool VertexInputInterfaceState::isDrawTriangle(bool polygonModeAware, VkPolygonMode polygonMode) const
524 {
525 switch(topology)
526 {
527 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
528 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
529 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
530 return false;
531 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
532 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
533 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
534 return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_FILL) : true;
535 default:
536 UNSUPPORTED("topology %d", int(topology));
537 }
538 return false;
539 }
540
initialize(const vk::Device * device,const PipelineLayout * layout,const VkPipelineViewportStateCreateInfo * viewportState,const VkPipelineRasterizationStateCreateInfo * rasterizationState,const vk::RenderPass * renderPass,uint32_t subpassIndex,const VkPipelineRenderingCreateInfo * rendering,const DynamicStateFlags & allDynamicStateFlags)541 void PreRasterizationState::initialize(const vk::Device *device,
542 const PipelineLayout *layout,
543 const VkPipelineViewportStateCreateInfo *viewportState,
544 const VkPipelineRasterizationStateCreateInfo *rasterizationState,
545 const vk::RenderPass *renderPass, uint32_t subpassIndex,
546 const VkPipelineRenderingCreateInfo *rendering,
547 const DynamicStateFlags &allDynamicStateFlags)
548 {
549 pipelineLayout = layout;
550 dynamicStateFlags = allDynamicStateFlags.preRasterization;
551
552 if(rasterizationState->flags != 0)
553 {
554 // Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
555 UNSUPPORTED("pCreateInfo->pRasterizationState->flags 0x%08X", int(rasterizationState->flags));
556 }
557
558 rasterizerDiscard = rasterizationState->rasterizerDiscardEnable != VK_FALSE;
559 cullMode = rasterizationState->cullMode;
560 frontFace = rasterizationState->frontFace;
561 polygonMode = rasterizationState->polygonMode;
562 depthBiasEnable = rasterizationState->depthBiasEnable;
563 constantDepthBias = rasterizationState->depthBiasConstantFactor;
564 slopeDepthBias = rasterizationState->depthBiasSlopeFactor;
565 depthBiasClamp = rasterizationState->depthBiasClamp;
566 depthRangeUnrestricted = device->hasExtension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME);
567 depthClampEnable = rasterizationState->depthClampEnable != VK_FALSE;
568 depthClipEnable = !depthClampEnable;
569
570 // From the Vulkan spec for vkCmdSetDepthBias:
571 // The bias value O for a polygon is:
572 // O = dbclamp(...)
573 // where dbclamp(x) =
574 // * x depthBiasClamp = 0 or NaN
575 // * min(x, depthBiasClamp) depthBiasClamp > 0
576 // * max(x, depthBiasClamp) depthBiasClamp < 0
577 // So it should be safe to resolve NaNs to 0.0f.
578 if(std::isnan(depthBiasClamp))
579 {
580 depthBiasClamp = 0.0f;
581 }
582
583 if(!dynamicStateFlags.dynamicLineWidth)
584 {
585 lineWidth = rasterizationState->lineWidth;
586 }
587
588 const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(rasterizationState->pNext);
589 while(extensionCreateInfo)
590 {
591 switch(extensionCreateInfo->sType)
592 {
593 case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT:
594 {
595 const VkPipelineRasterizationLineStateCreateInfoEXT *lineStateCreateInfo = reinterpret_cast<const VkPipelineRasterizationLineStateCreateInfoEXT *>(extensionCreateInfo);
596 lineRasterizationMode = lineStateCreateInfo->lineRasterizationMode;
597 }
598 break;
599 case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT:
600 {
601 const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *provokingVertexModeCreateInfo =
602 reinterpret_cast<const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *>(extensionCreateInfo);
603 provokingVertexMode = provokingVertexModeCreateInfo->provokingVertexMode;
604 }
605 break;
606 case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT:
607 {
608 const auto *depthClipInfo = reinterpret_cast<const VkPipelineRasterizationDepthClipStateCreateInfoEXT *>(extensionCreateInfo);
609 // Reserved for future use.
610 ASSERT(depthClipInfo->flags == 0);
611 depthClipEnable = depthClipInfo->depthClipEnable != VK_FALSE;
612 }
613 break;
614 case VK_STRUCTURE_TYPE_APPLICATION_INFO:
615 // SwiftShader doesn't interact with application info, but dEQP includes it
616 break;
617 case VK_STRUCTURE_TYPE_MAX_ENUM:
618 // dEQP tests that this value is ignored.
619 break;
620 default:
621 UNSUPPORTED("pCreateInfo->pRasterizationState->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str());
622 break;
623 }
624
625 extensionCreateInfo = extensionCreateInfo->pNext;
626 }
627
628 if(!rasterizerDiscard || dynamicStateFlags.dynamicRasterizerDiscardEnable)
629 {
630 extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(viewportState->pNext);
631 while(extensionCreateInfo != nullptr)
632 {
633 switch(extensionCreateInfo->sType)
634 {
635 case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT:
636 {
637 const auto *depthClipControl = reinterpret_cast<const VkPipelineViewportDepthClipControlCreateInfoEXT *>(extensionCreateInfo);
638 depthClipNegativeOneToOne = depthClipControl->negativeOneToOne != VK_FALSE;
639 }
640 break;
641 case VK_STRUCTURE_TYPE_MAX_ENUM:
642 // dEQP passes this value expecting the driver to ignore it.
643 break;
644 default:
645 UNSUPPORTED("pCreateInfo->pViewportState->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str());
646 break;
647 }
648 extensionCreateInfo = extensionCreateInfo->pNext;
649 }
650
651 if(viewportState->flags != 0)
652 {
653 // Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
654 UNSUPPORTED("pCreateInfo->pViewportState->flags 0x%08X", int(viewportState->flags));
655 }
656
657 if((viewportState->viewportCount > 1) ||
658 (viewportState->scissorCount > 1))
659 {
660 UNSUPPORTED("VkPhysicalDeviceFeatures::multiViewport");
661 }
662
663 if(!dynamicStateFlags.dynamicScissor && !dynamicStateFlags.dynamicScissorWithCount)
664 {
665 scissor = viewportState->pScissors[0];
666 }
667
668 if(!dynamicStateFlags.dynamicViewport && !dynamicStateFlags.dynamicViewportWithCount)
669 {
670 viewport = viewportState->pViewports[0];
671 }
672 }
673 }
674
applyState(const DynamicState & dynamicState)675 void PreRasterizationState::applyState(const DynamicState &dynamicState)
676 {
677 if(dynamicStateFlags.dynamicLineWidth)
678 {
679 lineWidth = dynamicState.lineWidth;
680 }
681
682 if(dynamicStateFlags.dynamicDepthBias)
683 {
684 constantDepthBias = dynamicState.depthBiasConstantFactor;
685 slopeDepthBias = dynamicState.depthBiasSlopeFactor;
686 depthBiasClamp = dynamicState.depthBiasClamp;
687 }
688
689 if(dynamicStateFlags.dynamicDepthBiasEnable)
690 {
691 depthBiasEnable = dynamicState.depthBiasEnable;
692 }
693
694 if(dynamicStateFlags.dynamicCullMode)
695 {
696 cullMode = dynamicState.cullMode;
697 }
698
699 if(dynamicStateFlags.dynamicFrontFace)
700 {
701 frontFace = dynamicState.frontFace;
702 }
703
704 if(dynamicStateFlags.dynamicViewport)
705 {
706 viewport = dynamicState.viewport;
707 }
708
709 if(dynamicStateFlags.dynamicScissor)
710 {
711 scissor = dynamicState.scissor;
712 }
713
714 if(dynamicStateFlags.dynamicViewportWithCount && dynamicState.viewportCount > 0)
715 {
716 viewport.width = static_cast<float>(dynamicState.viewports[0].extent.width);
717 viewport.height = static_cast<float>(dynamicState.viewports[0].extent.height);
718 viewport.x = static_cast<float>(dynamicState.viewports[0].offset.x);
719 viewport.y = static_cast<float>(dynamicState.viewports[0].offset.y);
720 }
721
722 if(dynamicStateFlags.dynamicScissorWithCount && dynamicState.scissorCount > 0)
723 {
724 scissor = dynamicState.scissors[0];
725 }
726
727 if(dynamicStateFlags.dynamicRasterizerDiscardEnable)
728 {
729 rasterizerDiscard = dynamicState.rasterizerDiscardEnable;
730 }
731 }
732
initialize(const PipelineLayout * layout,const VkPipelineDepthStencilStateCreateInfo * depthStencilState,const vk::RenderPass * renderPass,uint32_t subpassIndex,const VkPipelineRenderingCreateInfo * rendering,const DynamicStateFlags & allDynamicStateFlags)733 void FragmentState::initialize(
734 const PipelineLayout *layout,
735 const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
736 const vk::RenderPass *renderPass, uint32_t subpassIndex,
737 const VkPipelineRenderingCreateInfo *rendering,
738 const DynamicStateFlags &allDynamicStateFlags)
739 {
740 pipelineLayout = layout;
741 dynamicStateFlags = allDynamicStateFlags.fragment;
742
743 if(renderPass)
744 {
745 const VkSubpassDescription &subpass = renderPass->getSubpass(subpassIndex);
746
747 // Ignore pDepthStencilState when "the subpass of the render pass the pipeline
748 // is created against does not use a depth/stencil attachment"
749 if(subpass.pDepthStencilAttachment &&
750 subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)
751 {
752 setDepthStencilState(depthStencilState);
753 }
754 }
755 else // No render pass
756 {
757 // When a pipeline is created without a VkRenderPass, if the VkPipelineRenderingCreateInfo structure
758 // is present in the pNext chain of VkGraphicsPipelineCreateInfo, it specifies the view mask and
759 // format of attachments used for rendering. If this structure is not specified, and the pipeline
760 // does not include a VkRenderPass, viewMask and colorAttachmentCount are 0, and
761 // depthAttachmentFormat and stencilAttachmentFormat are VK_FORMAT_UNDEFINED. If a graphics pipeline
762 // is created with a valid VkRenderPass, parameters of this structure are ignored.
763
764 if(rendering)
765 {
766 if((rendering->depthAttachmentFormat != VK_FORMAT_UNDEFINED) ||
767 (rendering->stencilAttachmentFormat != VK_FORMAT_UNDEFINED))
768 {
769 // If renderPass is VK_NULL_HANDLE, the pipeline is being created with fragment
770 // shader state, and either of VkPipelineRenderingCreateInfo::depthAttachmentFormat
771 // or VkPipelineRenderingCreateInfo::stencilAttachmentFormat are not
772 // VK_FORMAT_UNDEFINED, pDepthStencilState must be a valid pointer to a valid
773 // VkPipelineDepthStencilStateCreateInfo structure
774 ASSERT(depthStencilState);
775
776 setDepthStencilState(depthStencilState);
777 }
778 }
779 }
780 }
781
applyState(const DynamicState & dynamicState)782 void FragmentState::applyState(const DynamicState &dynamicState)
783 {
784 if(dynamicStateFlags.dynamicDepthTestEnable)
785 {
786 depthTestEnable = dynamicState.depthTestEnable;
787 }
788
789 if(dynamicStateFlags.dynamicDepthWriteEnable)
790 {
791 depthWriteEnable = dynamicState.depthWriteEnable;
792 }
793
794 if(dynamicStateFlags.dynamicDepthBoundsTestEnable)
795 {
796 depthBoundsTestEnable = dynamicState.depthBoundsTestEnable;
797 }
798
799 if(dynamicStateFlags.dynamicDepthBounds && depthBoundsTestEnable)
800 {
801 minDepthBounds = dynamicState.minDepthBounds;
802 maxDepthBounds = dynamicState.maxDepthBounds;
803 }
804
805 if(dynamicStateFlags.dynamicDepthCompareOp)
806 {
807 depthCompareMode = dynamicState.depthCompareOp;
808 }
809
810 if(dynamicStateFlags.dynamicStencilTestEnable)
811 {
812 stencilEnable = dynamicState.stencilTestEnable;
813 }
814
815 if(dynamicStateFlags.dynamicStencilOp && stencilEnable)
816 {
817 if(dynamicState.faceMask & VK_STENCIL_FACE_FRONT_BIT)
818 {
819 frontStencil.compareOp = dynamicState.frontStencil.compareOp;
820 frontStencil.depthFailOp = dynamicState.frontStencil.depthFailOp;
821 frontStencil.failOp = dynamicState.frontStencil.failOp;
822 frontStencil.passOp = dynamicState.frontStencil.passOp;
823 }
824
825 if(dynamicState.faceMask & VK_STENCIL_FACE_BACK_BIT)
826 {
827 backStencil.compareOp = dynamicState.backStencil.compareOp;
828 backStencil.depthFailOp = dynamicState.backStencil.depthFailOp;
829 backStencil.failOp = dynamicState.backStencil.failOp;
830 backStencil.passOp = dynamicState.backStencil.passOp;
831 }
832 }
833
834 if(dynamicStateFlags.dynamicStencilCompareMask && stencilEnable)
835 {
836 frontStencil.compareMask = dynamicState.frontStencil.compareMask;
837 backStencil.compareMask = dynamicState.backStencil.compareMask;
838 }
839
840 if(dynamicStateFlags.dynamicStencilWriteMask && stencilEnable)
841 {
842 frontStencil.writeMask = dynamicState.frontStencil.writeMask;
843 backStencil.writeMask = dynamicState.backStencil.writeMask;
844 }
845
846 if(dynamicStateFlags.dynamicStencilReference && stencilEnable)
847 {
848 frontStencil.reference = dynamicState.frontStencil.reference;
849 backStencil.reference = dynamicState.backStencil.reference;
850 }
851 }
852
depthWriteActive(const Attachments & attachments) const853 bool FragmentState::depthWriteActive(const Attachments &attachments) const
854 {
855 // "Depth writes are always disabled when depthTestEnable is VK_FALSE."
856 return depthTestActive(attachments) && depthWriteEnable;
857 }
858
depthTestActive(const Attachments & attachments) const859 bool FragmentState::depthTestActive(const Attachments &attachments) const
860 {
861 return attachments.depthBuffer && depthTestEnable;
862 }
863
stencilActive(const Attachments & attachments) const864 bool FragmentState::stencilActive(const Attachments &attachments) const
865 {
866 return attachments.stencilBuffer && stencilEnable;
867 }
868
depthBoundsTestActive(const Attachments & attachments) const869 bool FragmentState::depthBoundsTestActive(const Attachments &attachments) const
870 {
871 return attachments.depthBuffer && depthBoundsTestEnable;
872 }
873
setDepthStencilState(const VkPipelineDepthStencilStateCreateInfo * depthStencilState)874 void FragmentState::setDepthStencilState(const VkPipelineDepthStencilStateCreateInfo *depthStencilState)
875 {
876 if((depthStencilState->flags &
877 ~(VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT |
878 VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT)) != 0)
879 {
880 UNSUPPORTED("depthStencilState->flags 0x%08X", int(depthStencilState->flags));
881 }
882
883 depthBoundsTestEnable = (depthStencilState->depthBoundsTestEnable != VK_FALSE);
884 minDepthBounds = depthStencilState->minDepthBounds;
885 maxDepthBounds = depthStencilState->maxDepthBounds;
886
887 depthTestEnable = (depthStencilState->depthTestEnable != VK_FALSE);
888 depthWriteEnable = (depthStencilState->depthWriteEnable != VK_FALSE);
889 depthCompareMode = depthStencilState->depthCompareOp;
890
891 stencilEnable = (depthStencilState->stencilTestEnable != VK_FALSE);
892 if(stencilEnable)
893 {
894 frontStencil = depthStencilState->front;
895 backStencil = depthStencilState->back;
896 }
897 }
898
initialize(const VkPipelineColorBlendStateCreateInfo * colorBlendState,const VkPipelineMultisampleStateCreateInfo * multisampleState,const vk::RenderPass * renderPass,uint32_t subpassIndex,const VkPipelineRenderingCreateInfo * rendering,const DynamicStateFlags & allDynamicStateFlags)899 void FragmentOutputInterfaceState::initialize(const VkPipelineColorBlendStateCreateInfo *colorBlendState,
900 const VkPipelineMultisampleStateCreateInfo *multisampleState,
901 const vk::RenderPass *renderPass, uint32_t subpassIndex,
902 const VkPipelineRenderingCreateInfo *rendering,
903 const DynamicStateFlags &allDynamicStateFlags)
904 {
905 dynamicStateFlags = allDynamicStateFlags.fragmentOutputInterface;
906
907 multisample.set(multisampleState);
908
909 if(renderPass)
910 {
911 const VkSubpassDescription &subpass = renderPass->getSubpass(subpassIndex);
912
913 // Ignore pColorBlendState when "the subpass of the render pass the pipeline
914 // is created against does not use any color attachments"
915 for(uint32_t i = 0; i < subpass.colorAttachmentCount; i++)
916 {
917 if(subpass.pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED)
918 {
919 setColorBlendState(colorBlendState);
920 break;
921 }
922 }
923 }
924 else // No render pass
925 {
926 // When a pipeline is created without a VkRenderPass, if the VkPipelineRenderingCreateInfo structure
927 // is present in the pNext chain of VkGraphicsPipelineCreateInfo, it specifies the view mask and
928 // format of attachments used for rendering. If this structure is not specified, and the pipeline
929 // does not include a VkRenderPass, viewMask and colorAttachmentCount are 0, and
930 // depthAttachmentFormat and stencilAttachmentFormat are VK_FORMAT_UNDEFINED. If a graphics pipeline
931 // is created with a valid VkRenderPass, parameters of this structure are ignored.
932
933 if(rendering)
934 {
935 if(rendering->colorAttachmentCount > 0)
936 {
937 // If renderPass is VK_NULL_HANDLE, the pipeline is being created with fragment
938 // output interface state, and VkPipelineRenderingCreateInfo::colorAttachmentCount
939 // is not equal to 0, pColorBlendState must be a valid pointer to a valid
940 // VkPipelineColorBlendStateCreateInfo structure
941 ASSERT(colorBlendState);
942
943 setColorBlendState(colorBlendState);
944 }
945 }
946 }
947 }
948
applyState(const DynamicState & dynamicState)949 void FragmentOutputInterfaceState::applyState(const DynamicState &dynamicState)
950 {
951 if(dynamicStateFlags.dynamicBlendConstants)
952 {
953 blendConstants = dynamicState.blendConstants;
954 }
955 }
956
setColorBlendState(const VkPipelineColorBlendStateCreateInfo * colorBlendState)957 void FragmentOutputInterfaceState::setColorBlendState(const VkPipelineColorBlendStateCreateInfo *colorBlendState)
958 {
959 if(colorBlendState->flags != 0 &&
960 colorBlendState->flags != VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT)
961 {
962 UNSUPPORTED("colorBlendState->flags 0x%08X", int(colorBlendState->flags));
963 }
964
965 if(colorBlendState->logicOpEnable != VK_FALSE)
966 {
967 UNSUPPORTED("VkPhysicalDeviceFeatures::logicOp");
968 }
969
970 if(!dynamicStateFlags.dynamicBlendConstants)
971 {
972 blendConstants.x = colorBlendState->blendConstants[0];
973 blendConstants.y = colorBlendState->blendConstants[1];
974 blendConstants.z = colorBlendState->blendConstants[2];
975 blendConstants.w = colorBlendState->blendConstants[3];
976 }
977
978 const VkBaseInStructure *extensionColorBlendInfo = reinterpret_cast<const VkBaseInStructure *>(colorBlendState->pNext);
979 while(extensionColorBlendInfo)
980 {
981 switch(extensionColorBlendInfo->sType)
982 {
983 case VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT:
984 {
985 const VkPipelineColorBlendAdvancedStateCreateInfoEXT *colorBlendAdvancedCreateInfo = reinterpret_cast<const VkPipelineColorBlendAdvancedStateCreateInfoEXT *>(extensionColorBlendInfo);
986 ASSERT(colorBlendAdvancedCreateInfo->blendOverlap == VK_BLEND_OVERLAP_UNCORRELATED_EXT);
987 ASSERT(colorBlendAdvancedCreateInfo->dstPremultiplied == VK_TRUE);
988 ASSERT(colorBlendAdvancedCreateInfo->srcPremultiplied == VK_TRUE);
989 }
990 break;
991 case VK_STRUCTURE_TYPE_MAX_ENUM:
992 // dEQP tests that this value is ignored.
993 break;
994 default:
995 UNSUPPORTED("colorBlendState->pNext sType = %s", vk::Stringify(extensionColorBlendInfo->sType).c_str());
996 break;
997 }
998
999 extensionColorBlendInfo = extensionColorBlendInfo->pNext;
1000 }
1001
1002 ASSERT(colorBlendState->attachmentCount <= sw::MAX_COLOR_BUFFERS);
1003 for(auto i = 0u; i < colorBlendState->attachmentCount; i++)
1004 {
1005 const VkPipelineColorBlendAttachmentState &attachment = colorBlendState->pAttachments[i];
1006 colorWriteMask[i] = attachment.colorWriteMask;
1007 blendState[i] = { (attachment.blendEnable != VK_FALSE),
1008 attachment.srcColorBlendFactor, attachment.dstColorBlendFactor, attachment.colorBlendOp,
1009 attachment.srcAlphaBlendFactor, attachment.dstAlphaBlendFactor, attachment.alphaBlendOp };
1010 }
1011 }
1012
getBlendState(int index,const Attachments & attachments,bool fragmentContainsKill) const1013 BlendState FragmentOutputInterfaceState::getBlendState(int index, const Attachments &attachments, bool fragmentContainsKill) const
1014 {
1015 ASSERT((index >= 0) && (index < sw::MAX_COLOR_BUFFERS));
1016 auto &state = blendState[index];
1017
1018 BlendState activeBlendState = {};
1019 activeBlendState.alphaBlendEnable = alphaBlendActive(index, attachments, fragmentContainsKill);
1020
1021 if(activeBlendState.alphaBlendEnable)
1022 {
1023 vk::Format format = attachments.colorBuffer[index]->getFormat(VK_IMAGE_ASPECT_COLOR_BIT);
1024
1025 activeBlendState.sourceBlendFactor = blendFactor(state.blendOperation, state.sourceBlendFactor);
1026 activeBlendState.destBlendFactor = blendFactor(state.blendOperation, state.destBlendFactor);
1027 activeBlendState.blendOperation = blendOperation(state.blendOperation, state.sourceBlendFactor, state.destBlendFactor, format);
1028 activeBlendState.sourceBlendFactorAlpha = blendFactor(state.blendOperationAlpha, state.sourceBlendFactorAlpha);
1029 activeBlendState.destBlendFactorAlpha = blendFactor(state.blendOperationAlpha, state.destBlendFactorAlpha);
1030 activeBlendState.blendOperationAlpha = blendOperation(state.blendOperationAlpha, state.sourceBlendFactorAlpha, state.destBlendFactorAlpha, format);
1031 }
1032
1033 return activeBlendState;
1034 }
1035
alphaBlendActive(int index,const Attachments & attachments,bool fragmentContainsKill) const1036 bool FragmentOutputInterfaceState::alphaBlendActive(int index, const Attachments &attachments, bool fragmentContainsKill) const
1037 {
1038 ASSERT((index >= 0) && (index < sw::MAX_COLOR_BUFFERS));
1039 auto &state = blendState[index];
1040
1041 if(!attachments.colorBuffer[index] || !blendState[index].alphaBlendEnable)
1042 {
1043 return false;
1044 }
1045
1046 if(!(colorWriteActive(attachments) || fragmentContainsKill))
1047 {
1048 return false;
1049 }
1050
1051 vk::Format format = attachments.colorBuffer[index]->getFormat(VK_IMAGE_ASPECT_COLOR_BIT);
1052 bool colorBlend = blendOperation(state.blendOperation, state.sourceBlendFactor, state.destBlendFactor, format) != VK_BLEND_OP_SRC_EXT;
1053 bool alphaBlend = blendOperation(state.blendOperationAlpha, state.sourceBlendFactorAlpha, state.destBlendFactorAlpha, format) != VK_BLEND_OP_SRC_EXT;
1054
1055 return colorBlend || alphaBlend;
1056 }
1057
blendFactor(VkBlendOp blendOperation,VkBlendFactor blendFactor) const1058 VkBlendFactor FragmentOutputInterfaceState::blendFactor(VkBlendOp blendOperation, VkBlendFactor blendFactor) const
1059 {
1060 switch(blendOperation)
1061 {
1062 case VK_BLEND_OP_ADD:
1063 case VK_BLEND_OP_SUBTRACT:
1064 case VK_BLEND_OP_REVERSE_SUBTRACT:
1065 return blendFactor;
1066 case VK_BLEND_OP_MIN:
1067 case VK_BLEND_OP_MAX:
1068 case VK_BLEND_OP_MULTIPLY_EXT:
1069 case VK_BLEND_OP_SCREEN_EXT:
1070 case VK_BLEND_OP_OVERLAY_EXT:
1071 case VK_BLEND_OP_DARKEN_EXT:
1072 case VK_BLEND_OP_LIGHTEN_EXT:
1073 case VK_BLEND_OP_COLORDODGE_EXT:
1074 case VK_BLEND_OP_COLORBURN_EXT:
1075 case VK_BLEND_OP_HARDLIGHT_EXT:
1076 case VK_BLEND_OP_SOFTLIGHT_EXT:
1077 case VK_BLEND_OP_DIFFERENCE_EXT:
1078 case VK_BLEND_OP_EXCLUSION_EXT:
1079 case VK_BLEND_OP_HSL_HUE_EXT:
1080 case VK_BLEND_OP_HSL_SATURATION_EXT:
1081 case VK_BLEND_OP_HSL_COLOR_EXT:
1082 case VK_BLEND_OP_HSL_LUMINOSITY_EXT:
1083 return VK_BLEND_FACTOR_ONE;
1084 default:
1085 ASSERT(false);
1086 return blendFactor;
1087 }
1088 }
1089
blendOperation(VkBlendOp blendOperation,VkBlendFactor sourceBlendFactor,VkBlendFactor destBlendFactor,vk::Format format) const1090 VkBlendOp FragmentOutputInterfaceState::blendOperation(VkBlendOp blendOperation, VkBlendFactor sourceBlendFactor, VkBlendFactor destBlendFactor, vk::Format format) const
1091 {
1092 switch(blendOperation)
1093 {
1094 case VK_BLEND_OP_ADD:
1095 if(sourceBlendFactor == VK_BLEND_FACTOR_ZERO)
1096 {
1097 if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
1098 {
1099 return VK_BLEND_OP_ZERO_EXT;
1100 }
1101 else if(destBlendFactor == VK_BLEND_FACTOR_ONE)
1102 {
1103 return VK_BLEND_OP_DST_EXT;
1104 }
1105 }
1106 else if(sourceBlendFactor == VK_BLEND_FACTOR_ONE)
1107 {
1108 if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
1109 {
1110 return VK_BLEND_OP_SRC_EXT;
1111 }
1112 }
1113 break;
1114 case VK_BLEND_OP_SUBTRACT:
1115 if(sourceBlendFactor == VK_BLEND_FACTOR_ZERO)
1116 {
1117 if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
1118 {
1119 return VK_BLEND_OP_ZERO_EXT;
1120 }
1121 else if(format.isUnsignedNormalized())
1122 {
1123 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
1124 }
1125 }
1126 else if(sourceBlendFactor == VK_BLEND_FACTOR_ONE)
1127 {
1128 if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
1129 {
1130 return VK_BLEND_OP_SRC_EXT;
1131 }
1132 }
1133 break;
1134 case VK_BLEND_OP_REVERSE_SUBTRACT:
1135 if(sourceBlendFactor == VK_BLEND_FACTOR_ZERO)
1136 {
1137 if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
1138 {
1139 return VK_BLEND_OP_ZERO_EXT;
1140 }
1141 else if(destBlendFactor == VK_BLEND_FACTOR_ONE)
1142 {
1143 return VK_BLEND_OP_DST_EXT;
1144 }
1145 }
1146 else
1147 {
1148 if(destBlendFactor == VK_BLEND_FACTOR_ZERO && format.isUnsignedNormalized())
1149 {
1150 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
1151 }
1152 }
1153 break;
1154 case VK_BLEND_OP_MIN:
1155 return VK_BLEND_OP_MIN;
1156 case VK_BLEND_OP_MAX:
1157 return VK_BLEND_OP_MAX;
1158 case VK_BLEND_OP_MULTIPLY_EXT:
1159 case VK_BLEND_OP_SCREEN_EXT:
1160 case VK_BLEND_OP_OVERLAY_EXT:
1161 case VK_BLEND_OP_DARKEN_EXT:
1162 case VK_BLEND_OP_LIGHTEN_EXT:
1163 case VK_BLEND_OP_COLORDODGE_EXT:
1164 case VK_BLEND_OP_COLORBURN_EXT:
1165 case VK_BLEND_OP_HARDLIGHT_EXT:
1166 case VK_BLEND_OP_SOFTLIGHT_EXT:
1167 case VK_BLEND_OP_DIFFERENCE_EXT:
1168 case VK_BLEND_OP_EXCLUSION_EXT:
1169 case VK_BLEND_OP_HSL_HUE_EXT:
1170 case VK_BLEND_OP_HSL_SATURATION_EXT:
1171 case VK_BLEND_OP_HSL_COLOR_EXT:
1172 case VK_BLEND_OP_HSL_LUMINOSITY_EXT:
1173 return blendOperation;
1174 default:
1175 ASSERT(false);
1176 }
1177
1178 return blendOperation;
1179 }
1180
colorWriteActive(const Attachments & attachments) const1181 bool FragmentOutputInterfaceState::colorWriteActive(const Attachments &attachments) const
1182 {
1183 for(int i = 0; i < sw::MAX_COLOR_BUFFERS; i++)
1184 {
1185 if(colorWriteActive(i, attachments))
1186 {
1187 return true;
1188 }
1189 }
1190
1191 return false;
1192 }
1193
colorWriteActive(int index,const Attachments & attachments) const1194 int FragmentOutputInterfaceState::colorWriteActive(int index, const Attachments &attachments) const
1195 {
1196 ASSERT((index >= 0) && (index < sw::MAX_COLOR_BUFFERS));
1197 auto &state = blendState[index];
1198
1199 if(!attachments.colorBuffer[index] || attachments.colorBuffer[index]->getFormat() == VK_FORMAT_UNDEFINED)
1200 {
1201 return 0;
1202 }
1203
1204 vk::Format format = attachments.colorBuffer[index]->getFormat(VK_IMAGE_ASPECT_COLOR_BIT);
1205
1206 if(blendOperation(state.blendOperation, state.sourceBlendFactor, state.destBlendFactor, format) == VK_BLEND_OP_DST_EXT &&
1207 blendOperation(state.blendOperationAlpha, state.sourceBlendFactorAlpha, state.destBlendFactorAlpha, format) == VK_BLEND_OP_DST_EXT)
1208 {
1209 return 0;
1210 }
1211
1212 return colorWriteMask[index];
1213 }
1214
GraphicsState(const Device * device,const VkGraphicsPipelineCreateInfo * pCreateInfo,const PipelineLayout * layout)1215 GraphicsState::GraphicsState(const Device *device, const VkGraphicsPipelineCreateInfo *pCreateInfo,
1216 const PipelineLayout *layout)
1217 {
1218 if((pCreateInfo->flags &
1219 ~(VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT |
1220 VK_PIPELINE_CREATE_DERIVATIVE_BIT |
1221 VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT |
1222 VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT |
1223 VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT |
1224 VK_PIPELINE_CREATE_LIBRARY_BIT_KHR |
1225 VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT |
1226 VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT)) != 0)
1227 {
1228 UNSUPPORTED("pCreateInfo->flags 0x%08X", int(pCreateInfo->flags));
1229 }
1230
1231 DynamicStateFlags dynamicStateFlags = ParseDynamicStateFlags(pCreateInfo->pDynamicState);
1232 const auto *rendering = GetExtendedStruct<VkPipelineRenderingCreateInfo>(pCreateInfo, VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO);
1233
1234 // First, get the subset of state specified in pCreateInfo itself.
1235 validSubset = GraphicsPipeline::GetGraphicsPipelineSubset(pCreateInfo);
1236
1237 // If rasterizer discard is enabled (and not dynamically overridable), ignore the fragment
1238 // and fragment output subsets, as they will not be used.
1239 if((validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) != 0 &&
1240 pCreateInfo->pRasterizationState->rasterizerDiscardEnable &&
1241 !dynamicStateFlags.preRasterization.dynamicRasterizerDiscardEnable)
1242 {
1243 validSubset &= ~(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT | VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT);
1244 }
1245
1246 if((validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT) != 0)
1247 {
1248 vertexInputInterfaceState.initialize(pCreateInfo->pVertexInputState,
1249 pCreateInfo->pInputAssemblyState,
1250 dynamicStateFlags);
1251 }
1252 if((validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) != 0)
1253 {
1254 preRasterizationState.initialize(device,
1255 layout,
1256 pCreateInfo->pViewportState,
1257 pCreateInfo->pRasterizationState,
1258 vk::Cast(pCreateInfo->renderPass),
1259 pCreateInfo->subpass,
1260 rendering,
1261 dynamicStateFlags);
1262 }
1263 if((validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) != 0)
1264 {
1265 fragmentState.initialize(layout,
1266 pCreateInfo->pDepthStencilState,
1267 vk::Cast(pCreateInfo->renderPass),
1268 pCreateInfo->subpass,
1269 rendering,
1270 dynamicStateFlags);
1271 }
1272 if((validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT) != 0)
1273 {
1274 fragmentOutputInterfaceState.initialize(pCreateInfo->pColorBlendState,
1275 pCreateInfo->pMultisampleState,
1276 vk::Cast(pCreateInfo->renderPass),
1277 pCreateInfo->subpass,
1278 rendering,
1279 dynamicStateFlags);
1280 }
1281
1282 // Then, apply state coming from pipeline libraries.
1283 const auto *libraryCreateInfo = vk::GetExtendedStruct<VkPipelineLibraryCreateInfoKHR>(pCreateInfo->pNext, VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR);
1284 if(libraryCreateInfo)
1285 {
1286 for(uint32_t i = 0; i < libraryCreateInfo->libraryCount; ++i)
1287 {
1288 const auto *library = static_cast<const GraphicsPipeline *>(vk::Cast(libraryCreateInfo->pLibraries[i]));
1289 const GraphicsState &libraryState = library->getState();
1290 const VkGraphicsPipelineLibraryFlagsEXT librarySubset = libraryState.validSubset;
1291
1292 // The library subsets should be disjoint
1293 ASSERT((libraryState.validSubset & validSubset) == 0);
1294
1295 if((librarySubset & VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT) != 0)
1296 {
1297 vertexInputInterfaceState = libraryState.vertexInputInterfaceState;
1298 }
1299 if((librarySubset & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) != 0)
1300 {
1301 preRasterizationState = libraryState.preRasterizationState;
1302 if(layout)
1303 {
1304 preRasterizationState.overridePipelineLayout(layout);
1305 }
1306 }
1307 if((librarySubset & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) != 0)
1308 {
1309 fragmentState = libraryState.fragmentState;
1310 if(layout)
1311 {
1312 fragmentState.overridePipelineLayout(layout);
1313 }
1314 }
1315 if((librarySubset & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT) != 0)
1316 {
1317 fragmentOutputInterfaceState = libraryState.fragmentOutputInterfaceState;
1318 }
1319
1320 validSubset |= libraryState.validSubset;
1321 }
1322 }
1323 }
1324
combineStates(const DynamicState & dynamicState) const1325 GraphicsState GraphicsState::combineStates(const DynamicState &dynamicState) const
1326 {
1327 GraphicsState combinedState = *this;
1328
1329 // Make a copy of the states for modification, then either keep the pipeline state or apply the dynamic state.
1330 combinedState.vertexInputInterfaceState.applyState(dynamicState);
1331 combinedState.preRasterizationState.applyState(dynamicState);
1332 combinedState.fragmentState.applyState(dynamicState);
1333 combinedState.fragmentOutputInterfaceState.applyState(dynamicState);
1334
1335 return combinedState;
1336 }
1337
1338 } // namespace vk
1339