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 #include "Vulkan/VkBuffer.hpp"
17 #include "Vulkan/VkDevice.hpp"
18 #include "Vulkan/VkImageView.hpp"
19 #include "Vulkan/VkRenderPass.hpp"
20 #include "Vulkan/VkStringify.hpp"
21
22 namespace {
23
ComputePrimitiveCount(VkPrimitiveTopology topology,uint32_t vertexCount)24 uint32_t ComputePrimitiveCount(VkPrimitiveTopology topology, uint32_t vertexCount)
25 {
26 switch(topology)
27 {
28 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
29 return vertexCount;
30 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
31 return vertexCount / 2;
32 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
33 return std::max<uint32_t>(vertexCount, 1) - 1;
34 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
35 return vertexCount / 3;
36 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
37 return std::max<uint32_t>(vertexCount, 2) - 2;
38 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
39 return std::max<uint32_t>(vertexCount, 2) - 2;
40 default:
41 UNSUPPORTED("VkPrimitiveTopology %d", int(topology));
42 }
43
44 return 0;
45 }
46
47 template<typename T>
ProcessPrimitiveRestart(T * indexBuffer,VkPrimitiveTopology topology,uint32_t count,std::vector<std::pair<uint32_t,void * >> * indexBuffers)48 void ProcessPrimitiveRestart(T *indexBuffer,
49 VkPrimitiveTopology topology,
50 uint32_t count,
51 std::vector<std::pair<uint32_t, void *>> *indexBuffers)
52 {
53 static const T RestartIndex = static_cast<T>(-1);
54 T *indexBufferStart = indexBuffer;
55 uint32_t vertexCount = 0;
56 for(uint32_t i = 0; i < count; i++)
57 {
58 if(indexBuffer[i] == RestartIndex)
59 {
60 // Record previous segment
61 if(vertexCount > 0)
62 {
63 uint32_t primitiveCount = ComputePrimitiveCount(topology, vertexCount);
64 if(primitiveCount > 0)
65 {
66 indexBuffers->push_back({ primitiveCount, indexBufferStart });
67 }
68 }
69 vertexCount = 0;
70 }
71 else
72 {
73 if(vertexCount == 0)
74 {
75 indexBufferStart = indexBuffer + i;
76 }
77 vertexCount++;
78 }
79 }
80
81 // Record last segment
82 if(vertexCount > 0)
83 {
84 uint32_t primitiveCount = ComputePrimitiveCount(topology, vertexCount);
85 if(primitiveCount > 0)
86 {
87 indexBuffers->push_back({ primitiveCount, indexBufferStart });
88 }
89 }
90 }
91
92 } // namespace
93
94 namespace vk {
95
bytesPerIndex() const96 int IndexBuffer::bytesPerIndex() const
97 {
98 return indexType == VK_INDEX_TYPE_UINT16 ? 2 : 4;
99 }
100
setIndexBufferBinding(const VertexInputBinding & indexBufferBinding,VkIndexType type)101 void IndexBuffer::setIndexBufferBinding(const VertexInputBinding &indexBufferBinding, VkIndexType type)
102 {
103 binding = indexBufferBinding;
104 indexType = type;
105 }
106
getIndexBuffers(VkPrimitiveTopology topology,uint32_t count,uint32_t first,bool indexed,bool hasPrimitiveRestartEnable,std::vector<std::pair<uint32_t,void * >> * indexBuffers) const107 void IndexBuffer::getIndexBuffers(VkPrimitiveTopology topology, uint32_t count, uint32_t first, bool indexed, bool hasPrimitiveRestartEnable, std::vector<std::pair<uint32_t, void *>> *indexBuffers) const
108 {
109
110 if(indexed)
111 {
112 void *indexBuffer = binding.buffer->getOffsetPointer(binding.offset + first * bytesPerIndex());
113 if(hasPrimitiveRestartEnable)
114 {
115 switch(indexType)
116 {
117 case VK_INDEX_TYPE_UINT16:
118 ProcessPrimitiveRestart(static_cast<uint16_t *>(indexBuffer), topology, count, indexBuffers);
119 break;
120 case VK_INDEX_TYPE_UINT32:
121 ProcessPrimitiveRestart(static_cast<uint32_t *>(indexBuffer), topology, count, indexBuffers);
122 break;
123 default:
124 UNSUPPORTED("VkIndexType %d", int(indexType));
125 }
126 }
127 else
128 {
129 indexBuffers->push_back({ ComputePrimitiveCount(topology, count), indexBuffer });
130 }
131 }
132 else
133 {
134 indexBuffers->push_back({ ComputePrimitiveCount(topology, count), nullptr });
135 }
136 }
137
isColorClamped(int index) const138 bool Attachments::isColorClamped(int index) const
139 {
140 if(renderTarget[index] && renderTarget[index]->getFormat().isFloatFormat())
141 {
142 return false;
143 }
144
145 return true;
146 }
147
renderTargetInternalFormat(int index) const148 VkFormat Attachments::renderTargetInternalFormat(int index) const
149 {
150 ASSERT((index >= 0) && (index < sw::RENDERTARGETS));
151
152 if(renderTarget[index])
153 {
154 return renderTarget[index]->getFormat();
155 }
156 else
157 {
158 return VK_FORMAT_UNDEFINED;
159 }
160 }
161
Inputs(const VkPipelineVertexInputStateCreateInfo * vertexInputState)162 Inputs::Inputs(const VkPipelineVertexInputStateCreateInfo *vertexInputState)
163 {
164 if(vertexInputState->flags != 0)
165 {
166 // Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
167 UNSUPPORTED("vertexInputState->flags");
168 }
169
170 // Temporary in-binding-order representation of buffer strides, to be consumed below
171 // when considering attributes. TODO: unfuse buffers from attributes in backend, is old GL model.
172 uint32_t vertexStrides[MAX_VERTEX_INPUT_BINDINGS];
173 uint32_t instanceStrides[MAX_VERTEX_INPUT_BINDINGS];
174 for(uint32_t i = 0; i < vertexInputState->vertexBindingDescriptionCount; i++)
175 {
176 auto const &desc = vertexInputState->pVertexBindingDescriptions[i];
177 vertexStrides[desc.binding] = desc.inputRate == VK_VERTEX_INPUT_RATE_VERTEX ? desc.stride : 0;
178 instanceStrides[desc.binding] = desc.inputRate == VK_VERTEX_INPUT_RATE_INSTANCE ? desc.stride : 0;
179 }
180
181 for(uint32_t i = 0; i < vertexInputState->vertexAttributeDescriptionCount; i++)
182 {
183 auto const &desc = vertexInputState->pVertexAttributeDescriptions[i];
184 sw::Stream &input = stream[desc.location];
185 input.format = desc.format;
186 input.offset = desc.offset;
187 input.binding = desc.binding;
188 input.vertexStride = vertexStrides[desc.binding];
189 input.instanceStride = instanceStrides[desc.binding];
190 }
191 }
192
updateDescriptorSets(const DescriptorSet::Array & dso,const DescriptorSet::Bindings & ds,const DescriptorSet::DynamicOffsets & ddo)193 void Inputs::updateDescriptorSets(const DescriptorSet::Array &dso,
194 const DescriptorSet::Bindings &ds,
195 const DescriptorSet::DynamicOffsets &ddo)
196 {
197 descriptorSetObjects = dso;
198 descriptorSets = ds;
199 descriptorDynamicOffsets = ddo;
200 }
201
bindVertexInputs(int firstInstance)202 void Inputs::bindVertexInputs(int firstInstance)
203 {
204 for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; i++)
205 {
206 auto &attrib = stream[i];
207 if(attrib.format != VK_FORMAT_UNDEFINED)
208 {
209 const auto &vertexInput = vertexInputBindings[attrib.binding];
210 VkDeviceSize offset = attrib.offset + vertexInput.offset +
211 attrib.instanceStride * firstInstance;
212 attrib.buffer = vertexInput.buffer ? vertexInput.buffer->getOffsetPointer(offset) : nullptr;
213
214 VkDeviceSize size = vertexInput.buffer ? vertexInput.buffer->getSize() : 0;
215 attrib.robustnessSize = (size > offset) ? size - offset : 0;
216 }
217 }
218 }
219
setVertexInputBinding(const VertexInputBinding bindings[])220 void Inputs::setVertexInputBinding(const VertexInputBinding bindings[])
221 {
222 for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; ++i)
223 {
224 vertexInputBindings[i] = bindings[i];
225 }
226 }
227
228 // TODO(b/137740918): Optimize instancing to use a single draw call.
advanceInstanceAttributes()229 void Inputs::advanceInstanceAttributes()
230 {
231 for(uint32_t i = 0; i < vk::MAX_VERTEX_INPUT_BINDINGS; i++)
232 {
233 auto &attrib = stream[i];
234 if((attrib.format != VK_FORMAT_UNDEFINED) && attrib.instanceStride && (attrib.instanceStride < attrib.robustnessSize))
235 {
236 // Under the casts: attrib.buffer += attrib.instanceStride
237 attrib.buffer = (void const *)((uintptr_t)attrib.buffer + attrib.instanceStride);
238 attrib.robustnessSize -= attrib.instanceStride;
239 }
240 }
241 }
242
GraphicsState(const Device * device,const VkGraphicsPipelineCreateInfo * pCreateInfo,const PipelineLayout * layout,bool robustBufferAccess)243 GraphicsState::GraphicsState(const Device *device, const VkGraphicsPipelineCreateInfo *pCreateInfo,
244 const PipelineLayout *layout, bool robustBufferAccess)
245 : pipelineLayout(layout)
246 , robustBufferAccess(robustBufferAccess)
247 {
248 if((pCreateInfo->flags &
249 ~(VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT |
250 VK_PIPELINE_CREATE_DERIVATIVE_BIT |
251 VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT)) != 0)
252 {
253 UNSUPPORTED("pCreateInfo->flags %d", int(pCreateInfo->flags));
254 }
255
256 if(pCreateInfo->pDynamicState)
257 {
258 if(pCreateInfo->pDynamicState->flags != 0)
259 {
260 // Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
261 UNSUPPORTED("pCreateInfo->pDynamicState->flags %d", int(pCreateInfo->pDynamicState->flags));
262 }
263
264 for(uint32_t i = 0; i < pCreateInfo->pDynamicState->dynamicStateCount; i++)
265 {
266 VkDynamicState dynamicState = pCreateInfo->pDynamicState->pDynamicStates[i];
267 switch(dynamicState)
268 {
269 case VK_DYNAMIC_STATE_VIEWPORT:
270 case VK_DYNAMIC_STATE_SCISSOR:
271 case VK_DYNAMIC_STATE_LINE_WIDTH:
272 case VK_DYNAMIC_STATE_DEPTH_BIAS:
273 case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
274 case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
275 case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
276 case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
277 case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
278 ASSERT(dynamicState < (sizeof(dynamicStateFlags) * 8));
279 dynamicStateFlags |= (1 << dynamicState);
280 break;
281 default:
282 UNSUPPORTED("VkDynamicState %d", int(dynamicState));
283 }
284 }
285 }
286
287 const VkPipelineVertexInputStateCreateInfo *vertexInputState = pCreateInfo->pVertexInputState;
288
289 if(vertexInputState->flags != 0)
290 {
291 // Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
292 UNSUPPORTED("vertexInputState->flags");
293 }
294
295 const VkPipelineInputAssemblyStateCreateInfo *inputAssemblyState = pCreateInfo->pInputAssemblyState;
296
297 if(inputAssemblyState->flags != 0)
298 {
299 // Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
300 UNSUPPORTED("pCreateInfo->pInputAssemblyState->flags %d", int(pCreateInfo->pInputAssemblyState->flags));
301 }
302
303 primitiveRestartEnable = (inputAssemblyState->primitiveRestartEnable != VK_FALSE);
304 topology = inputAssemblyState->topology;
305
306 const VkPipelineRasterizationStateCreateInfo *rasterizationState = pCreateInfo->pRasterizationState;
307
308 if(rasterizationState->flags != 0)
309 {
310 // Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
311 UNSUPPORTED("pCreateInfo->pRasterizationState->flags %d", int(pCreateInfo->pRasterizationState->flags));
312 }
313
314 if(rasterizationState->depthClampEnable != VK_FALSE)
315 {
316 UNSUPPORTED("VkPhysicalDeviceFeatures::depthClamp");
317 }
318
319 rasterizerDiscard = (rasterizationState->rasterizerDiscardEnable != VK_FALSE);
320 cullMode = rasterizationState->cullMode;
321 frontFace = rasterizationState->frontFace;
322 polygonMode = rasterizationState->polygonMode;
323 constantDepthBias = (rasterizationState->depthBiasEnable != VK_FALSE) ? rasterizationState->depthBiasConstantFactor : 0.0f;
324 slopeDepthBias = (rasterizationState->depthBiasEnable != VK_FALSE) ? rasterizationState->depthBiasSlopeFactor : 0.0f;
325 depthBiasClamp = (rasterizationState->depthBiasEnable != VK_FALSE) ? rasterizationState->depthBiasClamp : 0.0f;
326 depthRangeUnrestricted = device->hasExtension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME);
327
328 // From the Vulkan spec for vkCmdSetDepthBias:
329 // The bias value O for a polygon is:
330 // O = dbclamp(...)
331 // where dbclamp(x) =
332 // * x depthBiasClamp = 0 or NaN
333 // * min(x, depthBiasClamp) depthBiasClamp > 0
334 // * max(x, depthBiasClamp) depthBiasClamp < 0
335 // So it should be safe to resolve NaNs to 0.0f.
336 if(std::isnan(depthBiasClamp))
337 {
338 depthBiasClamp = 0.0f;
339 }
340
341 lineWidth = rasterizationState->lineWidth;
342
343 const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(rasterizationState->pNext);
344 while(extensionCreateInfo)
345 {
346 // Casting to a long since some structures, such as
347 // VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT
348 // are not enumerated in the official Vulkan header
349 switch((long)(extensionCreateInfo->sType))
350 {
351 case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT:
352 {
353 const VkPipelineRasterizationLineStateCreateInfoEXT *lineStateCreateInfo = reinterpret_cast<const VkPipelineRasterizationLineStateCreateInfoEXT *>(extensionCreateInfo);
354 lineRasterizationMode = lineStateCreateInfo->lineRasterizationMode;
355 }
356 break;
357 case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT:
358 {
359 const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *provokingVertexModeCreateInfo =
360 reinterpret_cast<const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *>(extensionCreateInfo);
361 provokingVertexMode = provokingVertexModeCreateInfo->provokingVertexMode;
362 }
363 break;
364 default:
365 WARN("pCreateInfo->pRasterizationState->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str());
366 break;
367 }
368
369 extensionCreateInfo = extensionCreateInfo->pNext;
370 }
371
372 // The sample count affects the batch size, so it needs initialization even if rasterization is disabled.
373 // TODO(b/147812380): Eliminate the dependency between multisampling and batch size.
374 sampleCount = 1;
375
376 // Only access rasterization state if rasterization is not disabled.
377 if(rasterizationState->rasterizerDiscardEnable == VK_FALSE)
378 {
379 const VkPipelineViewportStateCreateInfo *viewportState = pCreateInfo->pViewportState;
380 const VkPipelineMultisampleStateCreateInfo *multisampleState = pCreateInfo->pMultisampleState;
381 const VkPipelineDepthStencilStateCreateInfo *depthStencilState = pCreateInfo->pDepthStencilState;
382 const VkPipelineColorBlendStateCreateInfo *colorBlendState = pCreateInfo->pColorBlendState;
383
384 if(viewportState->flags != 0)
385 {
386 // Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
387 UNSUPPORTED("pCreateInfo->pViewportState->flags %d", int(pCreateInfo->pViewportState->flags));
388 }
389
390 if((viewportState->viewportCount != 1) ||
391 (viewportState->scissorCount != 1))
392 {
393 UNSUPPORTED("VkPhysicalDeviceFeatures::multiViewport");
394 }
395
396 if(!hasDynamicState(VK_DYNAMIC_STATE_SCISSOR))
397 {
398 scissor = viewportState->pScissors[0];
399 }
400
401 if(!hasDynamicState(VK_DYNAMIC_STATE_VIEWPORT))
402 {
403 viewport = viewportState->pViewports[0];
404 }
405
406 if(multisampleState->flags != 0)
407 {
408 // Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
409 UNSUPPORTED("pCreateInfo->pMultisampleState->flags %d", int(pCreateInfo->pMultisampleState->flags));
410 }
411
412 sampleShadingEnable = (multisampleState->sampleShadingEnable != VK_FALSE);
413 if(sampleShadingEnable)
414 {
415 minSampleShading = multisampleState->minSampleShading;
416 }
417
418 if(multisampleState->alphaToOneEnable != VK_FALSE)
419 {
420 UNSUPPORTED("VkPhysicalDeviceFeatures::alphaToOne");
421 }
422
423 switch(multisampleState->rasterizationSamples)
424 {
425 case VK_SAMPLE_COUNT_1_BIT:
426 sampleCount = 1;
427 break;
428 case VK_SAMPLE_COUNT_4_BIT:
429 sampleCount = 4;
430 break;
431 default:
432 UNSUPPORTED("Unsupported sample count");
433 }
434
435 VkSampleMask sampleMask;
436 if(multisampleState->pSampleMask)
437 {
438 sampleMask = multisampleState->pSampleMask[0];
439 }
440 else // "If pSampleMask is NULL, it is treated as if the mask has all bits set to 1."
441 {
442 sampleMask = ~0;
443 }
444
445 alphaToCoverage = (multisampleState->alphaToCoverageEnable != VK_FALSE);
446 multiSampleMask = sampleMask & ((unsigned)0xFFFFFFFF >> (32 - sampleCount));
447
448 const vk::RenderPass *renderPass = vk::Cast(pCreateInfo->renderPass);
449 const VkSubpassDescription &subpass = renderPass->getSubpass(pCreateInfo->subpass);
450
451 // Ignore pDepthStencilState when "the subpass of the render pass the pipeline is created against does not use a depth/stencil attachment"
452 if(subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)
453 {
454 if(depthStencilState->flags != 0)
455 {
456 // Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
457 UNSUPPORTED("pCreateInfo->pDepthStencilState->flags %d", int(pCreateInfo->pDepthStencilState->flags));
458 }
459
460 if(depthStencilState->depthBoundsTestEnable != VK_FALSE)
461 {
462 UNSUPPORTED("VkPhysicalDeviceFeatures::depthBounds");
463 }
464
465 depthBoundsTestEnable = (depthStencilState->depthBoundsTestEnable != VK_FALSE);
466 depthBufferEnable = (depthStencilState->depthTestEnable != VK_FALSE);
467 depthWriteEnable = (depthStencilState->depthWriteEnable != VK_FALSE);
468 depthCompareMode = depthStencilState->depthCompareOp;
469
470 stencilEnable = (depthStencilState->stencilTestEnable != VK_FALSE);
471 if(stencilEnable)
472 {
473 frontStencil = depthStencilState->front;
474 backStencil = depthStencilState->back;
475 }
476 }
477
478 bool colorAttachmentUsed = false;
479 for(uint32_t i = 0; i < subpass.colorAttachmentCount; i++)
480 {
481 if(subpass.pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED)
482 {
483 colorAttachmentUsed = true;
484 break;
485 }
486 }
487
488 // Ignore pColorBlendState when "the subpass of the render pass the pipeline is created against does not use any color attachments"
489 if(colorAttachmentUsed)
490 {
491 if(colorBlendState->flags != 0)
492 {
493 // Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
494 UNSUPPORTED("pCreateInfo->pColorBlendState->flags %d", int(pCreateInfo->pColorBlendState->flags));
495 }
496
497 if(colorBlendState->logicOpEnable != VK_FALSE)
498 {
499 UNSUPPORTED("VkPhysicalDeviceFeatures::logicOp");
500 }
501
502 if(!hasDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS))
503 {
504 blendConstants.x = colorBlendState->blendConstants[0];
505 blendConstants.y = colorBlendState->blendConstants[1];
506 blendConstants.z = colorBlendState->blendConstants[2];
507 blendConstants.w = colorBlendState->blendConstants[3];
508 }
509
510 ASSERT(colorBlendState->attachmentCount <= sw::RENDERTARGETS);
511 for(auto i = 0u; i < colorBlendState->attachmentCount; i++)
512 {
513 const VkPipelineColorBlendAttachmentState &attachment = colorBlendState->pAttachments[i];
514 colorWriteMask[i] = attachment.colorWriteMask;
515 blendState[i] = { (attachment.blendEnable != VK_FALSE),
516 attachment.srcColorBlendFactor, attachment.dstColorBlendFactor, attachment.colorBlendOp,
517 attachment.srcAlphaBlendFactor, attachment.dstAlphaBlendFactor, attachment.alphaBlendOp };
518 }
519 }
520 }
521 }
522
isDrawPoint(bool polygonModeAware) const523 bool GraphicsState::isDrawPoint(bool polygonModeAware) const
524 {
525 switch(topology)
526 {
527 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
528 return true;
529 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
530 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
531 return false;
532 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
533 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
534 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
535 return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_POINT) : false;
536 default:
537 UNSUPPORTED("topology %d", int(topology));
538 }
539 return false;
540 }
541
isDrawLine(bool polygonModeAware) const542 bool GraphicsState::isDrawLine(bool polygonModeAware) const
543 {
544 switch(topology)
545 {
546 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
547 return false;
548 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
549 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
550 return true;
551 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
552 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
553 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
554 return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_LINE) : false;
555 default:
556 UNSUPPORTED("topology %d", int(topology));
557 }
558 return false;
559 }
560
isDrawTriangle(bool polygonModeAware) const561 bool GraphicsState::isDrawTriangle(bool polygonModeAware) const
562 {
563 switch(topology)
564 {
565 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
566 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
567 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
568 return false;
569 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
570 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
571 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
572 return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_FILL) : true;
573 default:
574 UNSUPPORTED("topology %d", int(topology));
575 }
576 return false;
577 }
578
depthWriteActive(const Attachments & attachments) const579 bool GraphicsState::depthWriteActive(const Attachments &attachments) const
580 {
581 if(!depthBufferActive(attachments)) return false;
582
583 return depthWriteEnable;
584 }
585
depthBufferActive(const Attachments & attachments) const586 bool GraphicsState::depthBufferActive(const Attachments &attachments) const
587 {
588 return attachments.depthBuffer && depthBufferEnable;
589 }
590
stencilActive(const Attachments & attachments) const591 bool GraphicsState::stencilActive(const Attachments &attachments) const
592 {
593 return attachments.stencilBuffer && stencilEnable;
594 }
595
combineStates(const DynamicState & dynamicState) const596 const GraphicsState GraphicsState::combineStates(const DynamicState &dynamicState) const
597 {
598 GraphicsState combinedState = *this;
599
600 // Apply either pipeline state or dynamic state
601 if(hasDynamicState(VK_DYNAMIC_STATE_SCISSOR))
602 {
603 combinedState.scissor = dynamicState.scissor;
604 }
605
606 if(hasDynamicState(VK_DYNAMIC_STATE_VIEWPORT))
607 {
608 combinedState.viewport = dynamicState.viewport;
609 }
610
611 if(hasDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS))
612 {
613 combinedState.blendConstants = dynamicState.blendConstants;
614 }
615
616 if(hasDynamicState(VK_DYNAMIC_STATE_DEPTH_BIAS))
617 {
618 combinedState.constantDepthBias = dynamicState.depthBiasConstantFactor;
619 combinedState.slopeDepthBias = dynamicState.depthBiasSlopeFactor;
620 combinedState.depthBiasClamp = dynamicState.depthBiasClamp;
621 }
622
623 if(hasDynamicState(VK_DYNAMIC_STATE_DEPTH_BOUNDS) && depthBoundsTestEnable)
624 {
625 // Unless the VK_EXT_depth_range_unrestricted extension is enabled,
626 // minDepthBounds and maxDepthBounds must be between 0.0 and 1.0, inclusive
627 ASSERT(dynamicState.minDepthBounds >= 0.0f && dynamicState.minDepthBounds <= 1.0f);
628 ASSERT(dynamicState.maxDepthBounds >= 0.0f && dynamicState.maxDepthBounds <= 1.0f);
629
630 UNSUPPORTED("VkPhysicalDeviceFeatures::depthBounds");
631 }
632
633 if(hasDynamicState(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK) && stencilEnable)
634 {
635 combinedState.frontStencil.compareMask = dynamicState.compareMask[0];
636 combinedState.backStencil.compareMask = dynamicState.compareMask[1];
637 }
638
639 if(hasDynamicState(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK) && stencilEnable)
640 {
641 combinedState.frontStencil.writeMask = dynamicState.writeMask[0];
642 combinedState.backStencil.writeMask = dynamicState.writeMask[1];
643 }
644
645 if(hasDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE) && stencilEnable)
646 {
647 combinedState.frontStencil.reference = dynamicState.reference[0];
648 combinedState.backStencil.reference = dynamicState.reference[1];
649 }
650
651 return combinedState;
652 }
653
getBlendState(int index,const Attachments & attachments,bool fragmentContainsKill) const654 BlendState GraphicsState::getBlendState(int index, const Attachments &attachments, bool fragmentContainsKill) const
655 {
656 ASSERT((index >= 0) && (index < sw::RENDERTARGETS));
657
658 BlendState activeBlendState;
659 activeBlendState.alphaBlendEnable = alphaBlendActive(index, attachments, fragmentContainsKill);
660 activeBlendState.sourceBlendFactor = sourceBlendFactor(index);
661 activeBlendState.destBlendFactor = destBlendFactor(index);
662 activeBlendState.blendOperation = blendOperation(index, attachments);
663 activeBlendState.sourceBlendFactorAlpha = sourceBlendFactorAlpha(index);
664 activeBlendState.destBlendFactorAlpha = destBlendFactorAlpha(index);
665 activeBlendState.blendOperationAlpha = blendOperationAlpha(index, attachments);
666 return activeBlendState;
667 }
668
alphaBlendActive(int index,const Attachments & attachments,bool fragmentContainsKill) const669 bool GraphicsState::alphaBlendActive(int index, const Attachments &attachments, bool fragmentContainsKill) const
670 {
671 ASSERT((index >= 0) && (index < sw::RENDERTARGETS));
672
673 if(!blendState[index].alphaBlendEnable)
674 {
675 return false;
676 }
677
678 if(!(colorWriteActive(attachments) || fragmentContainsKill))
679 {
680 return false;
681 }
682
683 bool colorBlend = !(blendOperation(index, attachments) == VK_BLEND_OP_SRC_EXT &&
684 sourceBlendFactor(index) == VK_BLEND_FACTOR_ONE);
685 bool alphaBlend = !(blendOperationAlpha(index, attachments) == VK_BLEND_OP_SRC_EXT &&
686 sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ONE);
687
688 return colorBlend || alphaBlend;
689 }
690
sourceBlendFactor(int index) const691 VkBlendFactor GraphicsState::sourceBlendFactor(int index) const
692 {
693 ASSERT((index >= 0) && (index < sw::RENDERTARGETS));
694
695 if(!blendState[index].alphaBlendEnable) return VK_BLEND_FACTOR_ONE;
696
697 switch(blendState[index].blendOperation)
698 {
699 case VK_BLEND_OP_ADD:
700 case VK_BLEND_OP_SUBTRACT:
701 case VK_BLEND_OP_REVERSE_SUBTRACT:
702 return blendState[index].sourceBlendFactor;
703 case VK_BLEND_OP_MIN:
704 return VK_BLEND_FACTOR_ONE;
705 case VK_BLEND_OP_MAX:
706 return VK_BLEND_FACTOR_ONE;
707 default:
708 ASSERT(false);
709 }
710
711 return blendState[index].sourceBlendFactor;
712 }
713
destBlendFactor(int index) const714 VkBlendFactor GraphicsState::destBlendFactor(int index) const
715 {
716 ASSERT((index >= 0) && (index < sw::RENDERTARGETS));
717
718 if(!blendState[index].alphaBlendEnable) return VK_BLEND_FACTOR_ONE;
719
720 switch(blendState[index].blendOperation)
721 {
722 case VK_BLEND_OP_ADD:
723 case VK_BLEND_OP_SUBTRACT:
724 case VK_BLEND_OP_REVERSE_SUBTRACT:
725 return blendState[index].destBlendFactor;
726 case VK_BLEND_OP_MIN:
727 return VK_BLEND_FACTOR_ONE;
728 case VK_BLEND_OP_MAX:
729 return VK_BLEND_FACTOR_ONE;
730 default:
731 ASSERT(false);
732 }
733
734 return blendState[index].destBlendFactor;
735 }
736
blendOperation(int index,const Attachments & attachments) const737 VkBlendOp GraphicsState::blendOperation(int index, const Attachments &attachments) const
738 {
739 ASSERT((index >= 0) && (index < sw::RENDERTARGETS));
740
741 if(!blendState[index].alphaBlendEnable) return VK_BLEND_OP_SRC_EXT;
742
743 switch(blendState[index].blendOperation)
744 {
745 case VK_BLEND_OP_ADD:
746 if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
747 {
748 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
749 {
750 return VK_BLEND_OP_ZERO_EXT;
751 }
752 else
753 {
754 return VK_BLEND_OP_DST_EXT;
755 }
756 }
757 else if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ONE)
758 {
759 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
760 {
761 return VK_BLEND_OP_SRC_EXT;
762 }
763 else
764 {
765 return VK_BLEND_OP_ADD;
766 }
767 }
768 else
769 {
770 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
771 {
772 return VK_BLEND_OP_SRC_EXT;
773 }
774 else
775 {
776 return VK_BLEND_OP_ADD;
777 }
778 }
779 case VK_BLEND_OP_SUBTRACT:
780 if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ZERO && attachments.isColorClamped(index))
781 {
782 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
783 }
784 else if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ONE)
785 {
786 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
787 {
788 return VK_BLEND_OP_SRC_EXT;
789 }
790 else
791 {
792 return VK_BLEND_OP_SUBTRACT;
793 }
794 }
795 else
796 {
797 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
798 {
799 return VK_BLEND_OP_SRC_EXT;
800 }
801 else
802 {
803 return VK_BLEND_OP_SUBTRACT;
804 }
805 }
806 case VK_BLEND_OP_REVERSE_SUBTRACT:
807 if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
808 {
809 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO)
810 {
811 return VK_BLEND_OP_ZERO_EXT;
812 }
813 else
814 {
815 return VK_BLEND_OP_DST_EXT;
816 }
817 }
818 else if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ONE)
819 {
820 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO && attachments.isColorClamped(index))
821 {
822 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
823 }
824 else
825 {
826 return VK_BLEND_OP_REVERSE_SUBTRACT;
827 }
828 }
829 else
830 {
831 if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO && attachments.isColorClamped(index))
832 {
833 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
834 }
835 else
836 {
837 return VK_BLEND_OP_REVERSE_SUBTRACT;
838 }
839 }
840 case VK_BLEND_OP_MIN:
841 return VK_BLEND_OP_MIN;
842 case VK_BLEND_OP_MAX:
843 return VK_BLEND_OP_MAX;
844 default:
845 ASSERT(false);
846 }
847
848 return blendState[index].blendOperation;
849 }
850
sourceBlendFactorAlpha(int index) const851 VkBlendFactor GraphicsState::sourceBlendFactorAlpha(int index) const
852 {
853 ASSERT((index >= 0) && (index < sw::RENDERTARGETS));
854
855 switch(blendState[index].blendOperationAlpha)
856 {
857 case VK_BLEND_OP_ADD:
858 case VK_BLEND_OP_SUBTRACT:
859 case VK_BLEND_OP_REVERSE_SUBTRACT:
860 return blendState[index].sourceBlendFactorAlpha;
861 case VK_BLEND_OP_MIN:
862 return VK_BLEND_FACTOR_ONE;
863 case VK_BLEND_OP_MAX:
864 return VK_BLEND_FACTOR_ONE;
865 default:
866 ASSERT(false);
867 }
868
869 return blendState[index].sourceBlendFactorAlpha;
870 }
871
destBlendFactorAlpha(int index) const872 VkBlendFactor GraphicsState::destBlendFactorAlpha(int index) const
873 {
874 ASSERT((index >= 0) && (index < sw::RENDERTARGETS));
875
876 switch(blendState[index].blendOperationAlpha)
877 {
878 case VK_BLEND_OP_ADD:
879 case VK_BLEND_OP_SUBTRACT:
880 case VK_BLEND_OP_REVERSE_SUBTRACT:
881 return blendState[index].destBlendFactorAlpha;
882 case VK_BLEND_OP_MIN:
883 return VK_BLEND_FACTOR_ONE;
884 case VK_BLEND_OP_MAX:
885 return VK_BLEND_FACTOR_ONE;
886 default:
887 ASSERT(false);
888 }
889
890 return blendState[index].destBlendFactorAlpha;
891 }
892
blendOperationAlpha(int index,const Attachments & attachments) const893 VkBlendOp GraphicsState::blendOperationAlpha(int index, const Attachments &attachments) const
894 {
895 ASSERT((index >= 0) && (index < sw::RENDERTARGETS));
896
897 switch(blendState[index].blendOperationAlpha)
898 {
899 case VK_BLEND_OP_ADD:
900 if(sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
901 {
902 if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
903 {
904 return VK_BLEND_OP_ZERO_EXT;
905 }
906 else
907 {
908 return VK_BLEND_OP_DST_EXT;
909 }
910 }
911 else if(sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ONE)
912 {
913 if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
914 {
915 return VK_BLEND_OP_SRC_EXT;
916 }
917 else
918 {
919 return VK_BLEND_OP_ADD;
920 }
921 }
922 else
923 {
924 if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
925 {
926 return VK_BLEND_OP_SRC_EXT;
927 }
928 else
929 {
930 return VK_BLEND_OP_ADD;
931 }
932 }
933 case VK_BLEND_OP_SUBTRACT:
934 if(sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO && attachments.isColorClamped(index))
935 {
936 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
937 }
938 else if(sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ONE)
939 {
940 if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
941 {
942 return VK_BLEND_OP_SRC_EXT;
943 }
944 else
945 {
946 return VK_BLEND_OP_SUBTRACT;
947 }
948 }
949 else
950 {
951 if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
952 {
953 return VK_BLEND_OP_SRC_EXT;
954 }
955 else
956 {
957 return VK_BLEND_OP_SUBTRACT;
958 }
959 }
960 case VK_BLEND_OP_REVERSE_SUBTRACT:
961 if(sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
962 {
963 if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO)
964 {
965 return VK_BLEND_OP_ZERO_EXT;
966 }
967 else
968 {
969 return VK_BLEND_OP_DST_EXT;
970 }
971 }
972 else if(sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ONE)
973 {
974 if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO && attachments.isColorClamped(index))
975 {
976 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
977 }
978 else
979 {
980 return VK_BLEND_OP_REVERSE_SUBTRACT;
981 }
982 }
983 else
984 {
985 if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO && attachments.isColorClamped(index))
986 {
987 return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero
988 }
989 else
990 {
991 return VK_BLEND_OP_REVERSE_SUBTRACT;
992 }
993 }
994 case VK_BLEND_OP_MIN:
995 return VK_BLEND_OP_MIN;
996 case VK_BLEND_OP_MAX:
997 return VK_BLEND_OP_MAX;
998 default:
999 ASSERT(false);
1000 }
1001
1002 return blendState[index].blendOperationAlpha;
1003 }
1004
colorWriteActive(const Attachments & attachments) const1005 bool GraphicsState::colorWriteActive(const Attachments &attachments) const
1006 {
1007 for(int i = 0; i < sw::RENDERTARGETS; i++)
1008 {
1009 if(colorWriteActive(i, attachments))
1010 {
1011 return true;
1012 }
1013 }
1014
1015 return false;
1016 }
1017
colorWriteActive(int index,const Attachments & attachments) const1018 int GraphicsState::colorWriteActive(int index, const Attachments &attachments) const
1019 {
1020 ASSERT((index >= 0) && (index < sw::RENDERTARGETS));
1021
1022 if(!attachments.renderTarget[index] || attachments.renderTarget[index]->getFormat() == VK_FORMAT_UNDEFINED)
1023 {
1024 return 0;
1025 }
1026
1027 if(blendOperation(index, attachments) == VK_BLEND_OP_DST_EXT && destBlendFactor(index) == VK_BLEND_FACTOR_ONE &&
1028 (blendOperationAlpha(index, attachments) == VK_BLEND_OP_DST_EXT && destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ONE))
1029 {
1030 return 0;
1031 }
1032
1033 return colorWriteMask[index];
1034 }
1035
1036 } // namespace vk