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