• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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