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