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