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