• 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 	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 
colorFormat(int index) const138 VkFormat Attachments::colorFormat(int index) const
139 {
140 	ASSERT((index >= 0) && (index < sw::MAX_COLOR_BUFFERS));
141 
142 	if(colorBuffer[index])
143 	{
144 		return colorBuffer[index]->getFormat();
145 	}
146 	else
147 	{
148 		return VK_FORMAT_UNDEFINED;
149 	}
150 }
151 
depthFormat() const152 VkFormat Attachments::depthFormat() const
153 {
154 	if(depthBuffer)
155 	{
156 		return depthBuffer->getFormat();
157 	}
158 	else
159 	{
160 		return VK_FORMAT_UNDEFINED;
161 	}
162 }
163 
Inputs(const VkPipelineVertexInputStateCreateInfo * vertexInputState)164 Inputs::Inputs(const VkPipelineVertexInputStateCreateInfo *vertexInputState)
165 {
166 	if(vertexInputState->flags != 0)
167 	{
168 		// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
169 		UNSUPPORTED("vertexInputState->flags");
170 	}
171 
172 	// Temporary in-binding-order representation of buffer strides, to be consumed below
173 	// when considering attributes. TODO: unfuse buffers from attributes in backend, is old GL model.
174 	uint32_t vertexStrides[MAX_VERTEX_INPUT_BINDINGS];
175 	uint32_t instanceStrides[MAX_VERTEX_INPUT_BINDINGS];
176 	for(uint32_t i = 0; i < vertexInputState->vertexBindingDescriptionCount; i++)
177 	{
178 		auto const &desc = vertexInputState->pVertexBindingDescriptions[i];
179 		vertexStrides[desc.binding] = desc.inputRate == VK_VERTEX_INPUT_RATE_VERTEX ? desc.stride : 0;
180 		instanceStrides[desc.binding] = desc.inputRate == VK_VERTEX_INPUT_RATE_INSTANCE ? desc.stride : 0;
181 	}
182 
183 	for(uint32_t i = 0; i < vertexInputState->vertexAttributeDescriptionCount; i++)
184 	{
185 		auto const &desc = vertexInputState->pVertexAttributeDescriptions[i];
186 		sw::Stream &input = stream[desc.location];
187 		input.format = desc.format;
188 		input.offset = desc.offset;
189 		input.binding = desc.binding;
190 		input.vertexStride = vertexStrides[desc.binding];
191 		input.instanceStride = instanceStrides[desc.binding];
192 	}
193 }
194 
updateDescriptorSets(const DescriptorSet::Array & dso,const DescriptorSet::Bindings & ds,const DescriptorSet::DynamicOffsets & ddo)195 void Inputs::updateDescriptorSets(const DescriptorSet::Array &dso,
196                                   const DescriptorSet::Bindings &ds,
197                                   const DescriptorSet::DynamicOffsets &ddo)
198 {
199 	descriptorSetObjects = dso;
200 	descriptorSets = ds;
201 	descriptorDynamicOffsets = ddo;
202 }
203 
bindVertexInputs(int firstInstance)204 void Inputs::bindVertexInputs(int firstInstance)
205 {
206 	for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; i++)
207 	{
208 		auto &attrib = stream[i];
209 		if(attrib.format != VK_FORMAT_UNDEFINED)
210 		{
211 			const auto &vertexInput = vertexInputBindings[attrib.binding];
212 			VkDeviceSize offset = attrib.offset + vertexInput.offset +
213 			                      attrib.instanceStride * firstInstance;
214 			attrib.buffer = vertexInput.buffer ? vertexInput.buffer->getOffsetPointer(offset) : nullptr;
215 
216 			VkDeviceSize size = vertexInput.buffer ? vertexInput.buffer->getSize() : 0;
217 			attrib.robustnessSize = (size > offset) ? size - offset : 0;
218 		}
219 	}
220 }
221 
setVertexInputBinding(const VertexInputBinding bindings[])222 void Inputs::setVertexInputBinding(const VertexInputBinding bindings[])
223 {
224 	for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; ++i)
225 	{
226 		vertexInputBindings[i] = bindings[i];
227 	}
228 }
229 
230 // TODO(b/137740918): Optimize instancing to use a single draw call.
advanceInstanceAttributes()231 void Inputs::advanceInstanceAttributes()
232 {
233 	for(uint32_t i = 0; i < vk::MAX_VERTEX_INPUT_BINDINGS; i++)
234 	{
235 		auto &attrib = stream[i];
236 		if((attrib.format != VK_FORMAT_UNDEFINED) && attrib.instanceStride && (attrib.instanceStride < attrib.robustnessSize))
237 		{
238 			// Under the casts: attrib.buffer += attrib.instanceStride
239 			attrib.buffer = (void const *)((uintptr_t)attrib.buffer + attrib.instanceStride);
240 			attrib.robustnessSize -= attrib.instanceStride;
241 		}
242 	}
243 }
244 
ParseDynamicStateFlags(const VkPipelineDynamicStateCreateInfo * dynamicStateCreateInfo)245 GraphicsState::DynamicStateFlags GraphicsState::ParseDynamicStateFlags(const VkPipelineDynamicStateCreateInfo *dynamicStateCreateInfo)
246 {
247 	GraphicsState::DynamicStateFlags dynamicStateFlags = {};
248 
249 	if(dynamicStateCreateInfo)
250 	{
251 		if(dynamicStateCreateInfo->flags != 0)
252 		{
253 			// Vulkan 1.3: "flags is reserved for future use." "flags must be 0"
254 			UNSUPPORTED("dynamicStateCreateInfo->flags %d", int(dynamicStateCreateInfo->flags));
255 		}
256 
257 		for(uint32_t i = 0; i < dynamicStateCreateInfo->dynamicStateCount; i++)
258 		{
259 			VkDynamicState dynamicState = dynamicStateCreateInfo->pDynamicStates[i];
260 			switch(dynamicState)
261 			{
262 			case VK_DYNAMIC_STATE_VIEWPORT:
263 				dynamicStateFlags.dynamicViewport = true;
264 				break;
265 			case VK_DYNAMIC_STATE_SCISSOR:
266 				dynamicStateFlags.dynamicScissor = true;
267 				break;
268 			case VK_DYNAMIC_STATE_LINE_WIDTH:
269 				dynamicStateFlags.dynamicLineWidth = true;
270 				break;
271 			case VK_DYNAMIC_STATE_DEPTH_BIAS:
272 				dynamicStateFlags.dynamicDepthBias = true;
273 				break;
274 			case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
275 				dynamicStateFlags.dynamicBlendConstants = true;
276 				break;
277 			case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
278 				dynamicStateFlags.dynamicDepthBounds = true;
279 				break;
280 			case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
281 				dynamicStateFlags.dynamicStencilCompareMask = true;
282 				break;
283 			case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
284 				dynamicStateFlags.dynamicStencilWriteMask = true;
285 				break;
286 			case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
287 				dynamicStateFlags.dynamicStencilReference = true;
288 				break;
289 			case VK_DYNAMIC_STATE_CULL_MODE:
290 				dynamicStateFlags.dynamicCullMode = true;
291 				break;
292 			case VK_DYNAMIC_STATE_FRONT_FACE:
293 				dynamicStateFlags.dynamicFrontFace = true;
294 				break;
295 			case VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY:
296 				dynamicStateFlags.dynamicPrimitiveTopology = true;
297 				break;
298 			case VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT:
299 				dynamicStateFlags.dynamicViewportWithCount = true;
300 				break;
301 			case VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT:
302 				dynamicStateFlags.dynamicScissorWithCount = true;
303 				break;
304 			case VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE:
305 				dynamicStateFlags.dynamicVertexInputBindingStride = true;
306 				break;
307 			case VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE:
308 				dynamicStateFlags.dynamicDepthTestEnable = true;
309 				break;
310 			case VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE:
311 				dynamicStateFlags.dynamicDepthWriteEnable = true;
312 				break;
313 			case VK_DYNAMIC_STATE_DEPTH_COMPARE_OP:
314 				dynamicStateFlags.dynamicDepthCompareOp = true;
315 				break;
316 			case VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE:
317 				dynamicStateFlags.dynamicDepthBoundsTestEnable = true;
318 				break;
319 			case VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE:
320 				dynamicStateFlags.dynamicStencilTestEnable = true;
321 				break;
322 			case VK_DYNAMIC_STATE_STENCIL_OP:
323 				dynamicStateFlags.dynamicStencilOp = true;
324 				break;
325 			case VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE:
326 				dynamicStateFlags.dynamicRasterizerDiscardEnable = true;
327 				break;
328 			case VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE:
329 				dynamicStateFlags.dynamicDepthBiasEnable = true;
330 				break;
331 			case VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE:
332 				dynamicStateFlags.dynamicPrimitiveRestartEnable = true;
333 				break;
334 			default:
335 				UNSUPPORTED("VkDynamicState %d", int(dynamicState));
336 			}
337 		}
338 	}
339 
340 	return dynamicStateFlags;
341 }
342 
getVertexStride(uint32_t i,bool dynamicVertexStride) const343 VkDeviceSize Inputs::getVertexStride(uint32_t i, bool dynamicVertexStride) const
344 {
345 	auto &attrib = stream[i];
346 	if(attrib.format != VK_FORMAT_UNDEFINED)
347 	{
348 		if(dynamicVertexStride)
349 		{
350 			return vertexInputBindings[attrib.binding].stride;
351 		}
352 		else
353 		{
354 			return attrib.vertexStride;
355 		}
356 	}
357 
358 	return 0;
359 }
360 
GraphicsState(const Device * device,const VkGraphicsPipelineCreateInfo * pCreateInfo,const PipelineLayout * layout,bool robustBufferAccess)361 GraphicsState::GraphicsState(const Device *device, const VkGraphicsPipelineCreateInfo *pCreateInfo,
362                              const PipelineLayout *layout, bool robustBufferAccess)
363     : pipelineLayout(layout)
364     , robustBufferAccess(robustBufferAccess)
365     , dynamicStateFlags(ParseDynamicStateFlags(pCreateInfo->pDynamicState))
366 {
367 	if((pCreateInfo->flags &
368 	    ~(VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT |
369 	      VK_PIPELINE_CREATE_DERIVATIVE_BIT |
370 	      VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT |
371 	      VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT |
372 	      VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT)) != 0)
373 	{
374 		UNSUPPORTED("pCreateInfo->flags %d", int(pCreateInfo->flags));
375 	}
376 
377 	const VkPipelineVertexInputStateCreateInfo *vertexInputState = pCreateInfo->pVertexInputState;
378 
379 	if(vertexInputState->flags != 0)
380 	{
381 		// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
382 		UNSUPPORTED("vertexInputState->flags");
383 	}
384 
385 	const VkPipelineInputAssemblyStateCreateInfo *inputAssemblyState = pCreateInfo->pInputAssemblyState;
386 
387 	if(inputAssemblyState->flags != 0)
388 	{
389 		// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
390 		UNSUPPORTED("pCreateInfo->pInputAssemblyState->flags %d", int(pCreateInfo->pInputAssemblyState->flags));
391 	}
392 
393 	primitiveRestartEnable = (inputAssemblyState->primitiveRestartEnable != VK_FALSE);
394 	topology = inputAssemblyState->topology;
395 
396 	const VkPipelineRasterizationStateCreateInfo *rasterizationState = pCreateInfo->pRasterizationState;
397 
398 	if(rasterizationState->flags != 0)
399 	{
400 		// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
401 		UNSUPPORTED("pCreateInfo->pRasterizationState->flags %d", int(pCreateInfo->pRasterizationState->flags));
402 	}
403 
404 	rasterizerDiscard = (rasterizationState->rasterizerDiscardEnable != VK_FALSE);
405 	cullMode = rasterizationState->cullMode;
406 	frontFace = rasterizationState->frontFace;
407 	polygonMode = rasterizationState->polygonMode;
408 	depthBiasEnable = rasterizationState->depthBiasEnable;
409 	constantDepthBias = rasterizationState->depthBiasConstantFactor;
410 	slopeDepthBias = rasterizationState->depthBiasSlopeFactor;
411 	depthBiasClamp = rasterizationState->depthBiasClamp;
412 	depthRangeUnrestricted = device->hasExtension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME);
413 	depthClampEnable = rasterizationState->depthClampEnable != VK_FALSE;
414 	depthClipEnable = !depthClampEnable;
415 
416 	// From the Vulkan spec for vkCmdSetDepthBias:
417 	//    The bias value O for a polygon is:
418 	//        O = dbclamp(...)
419 	//    where dbclamp(x) =
420 	//        * x                       depthBiasClamp = 0 or NaN
421 	//        * min(x, depthBiasClamp)  depthBiasClamp > 0
422 	//        * max(x, depthBiasClamp)  depthBiasClamp < 0
423 	// So it should be safe to resolve NaNs to 0.0f.
424 	if(std::isnan(depthBiasClamp))
425 	{
426 		depthBiasClamp = 0.0f;
427 	}
428 
429 	lineWidth = rasterizationState->lineWidth;
430 
431 	const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(rasterizationState->pNext);
432 	while(extensionCreateInfo)
433 	{
434 		switch(extensionCreateInfo->sType)
435 		{
436 		case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT:
437 			{
438 				const VkPipelineRasterizationLineStateCreateInfoEXT *lineStateCreateInfo = reinterpret_cast<const VkPipelineRasterizationLineStateCreateInfoEXT *>(extensionCreateInfo);
439 				lineRasterizationMode = lineStateCreateInfo->lineRasterizationMode;
440 			}
441 			break;
442 		case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT:
443 			{
444 				const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *provokingVertexModeCreateInfo =
445 				    reinterpret_cast<const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *>(extensionCreateInfo);
446 				provokingVertexMode = provokingVertexModeCreateInfo->provokingVertexMode;
447 			}
448 			break;
449 		case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT:
450 			{
451 				const auto *depthClipInfo = reinterpret_cast<const VkPipelineRasterizationDepthClipStateCreateInfoEXT *>(extensionCreateInfo);
452 				// Reserved for future use.
453 				ASSERT(depthClipInfo->flags == 0);
454 				depthClipEnable = depthClipInfo->depthClipEnable != VK_FALSE;
455 			}
456 			break;
457 		case VK_STRUCTURE_TYPE_APPLICATION_INFO:
458 			// SwiftShader doesn't interact with application info, but dEQP includes it
459 			break;
460 		case VK_STRUCTURE_TYPE_MAX_ENUM:
461 			// dEQP tests that this value is ignored.
462 			break;
463 		default:
464 			UNSUPPORTED("pCreateInfo->pRasterizationState->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str());
465 			break;
466 		}
467 
468 		extensionCreateInfo = extensionCreateInfo->pNext;
469 	}
470 
471 	// The sample count affects the batch size, so it needs initialization even if rasterization is disabled.
472 	// TODO(b/147812380): Eliminate the dependency between multisampling and batch size.
473 	sampleCount = 1;
474 
475 	// Only access rasterization state if rasterization is not disabled.
476 	if(rasterizationState->rasterizerDiscardEnable == VK_FALSE)
477 	{
478 		const VkPipelineViewportStateCreateInfo *viewportState = pCreateInfo->pViewportState;
479 		const VkPipelineMultisampleStateCreateInfo *multisampleState = pCreateInfo->pMultisampleState;
480 		const VkPipelineDepthStencilStateCreateInfo *depthStencilState = pCreateInfo->pDepthStencilState;
481 		const VkPipelineColorBlendStateCreateInfo *colorBlendState = pCreateInfo->pColorBlendState;
482 
483 		if(viewportState->flags != 0)
484 		{
485 			// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
486 			UNSUPPORTED("pCreateInfo->pViewportState->flags %d", int(pCreateInfo->pViewportState->flags));
487 		}
488 
489 		if((viewportState->viewportCount > 1) ||
490 		   (viewportState->scissorCount > 1))
491 		{
492 			UNSUPPORTED("VkPhysicalDeviceFeatures::multiViewport");
493 		}
494 
495 		if(!dynamicStateFlags.dynamicScissor && !dynamicStateFlags.dynamicScissorWithCount)
496 		{
497 			scissor = viewportState->pScissors[0];
498 		}
499 
500 		if(!dynamicStateFlags.dynamicViewport && !dynamicStateFlags.dynamicViewportWithCount)
501 		{
502 			viewport = viewportState->pViewports[0];
503 		}
504 
505 		if(multisampleState->flags != 0)
506 		{
507 			// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
508 			UNSUPPORTED("pCreateInfo->pMultisampleState->flags %d", int(pCreateInfo->pMultisampleState->flags));
509 		}
510 
511 		sampleShadingEnable = (multisampleState->sampleShadingEnable != VK_FALSE);
512 		if(sampleShadingEnable)
513 		{
514 			minSampleShading = multisampleState->minSampleShading;
515 		}
516 
517 		if(multisampleState->alphaToOneEnable != VK_FALSE)
518 		{
519 			UNSUPPORTED("VkPhysicalDeviceFeatures::alphaToOne");
520 		}
521 
522 		switch(multisampleState->rasterizationSamples)
523 		{
524 		case VK_SAMPLE_COUNT_1_BIT:
525 			sampleCount = 1;
526 			break;
527 		case VK_SAMPLE_COUNT_4_BIT:
528 			sampleCount = 4;
529 			break;
530 		default:
531 			UNSUPPORTED("Unsupported sample count");
532 		}
533 
534 		VkSampleMask sampleMask;
535 		if(multisampleState->pSampleMask)
536 		{
537 			sampleMask = multisampleState->pSampleMask[0];
538 		}
539 		else  // "If pSampleMask is NULL, it is treated as if the mask has all bits set to 1."
540 		{
541 			sampleMask = ~0;
542 		}
543 
544 		alphaToCoverage = (multisampleState->alphaToCoverageEnable != VK_FALSE);
545 		multiSampleMask = sampleMask & ((unsigned)0xFFFFFFFF >> (32 - sampleCount));
546 
547 		const vk::RenderPass *renderPass = vk::Cast(pCreateInfo->renderPass);
548 		if(renderPass)
549 		{
550 			const VkSubpassDescription &subpass = renderPass->getSubpass(pCreateInfo->subpass);
551 
552 			// Ignore pDepthStencilState when "the subpass of the render pass the pipeline
553 			// is created against does not use a depth/stencil attachment"
554 			if(subpass.pDepthStencilAttachment &&
555 			   subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)
556 			{
557 				setDepthStencilState(depthStencilState);
558 			}
559 
560 			// Ignore pColorBlendState when "the subpass of the render pass the pipeline
561 			// is created against does not use any color attachments"
562 			for(uint32_t i = 0; i < subpass.colorAttachmentCount; i++)
563 			{
564 				if(subpass.pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED)
565 				{
566 					setColorBlendState(colorBlendState);
567 					break;
568 				}
569 			}
570 		}
571 		else  // No render pass
572 		{
573 			// When a pipeline is created without a VkRenderPass, if the VkPipelineRenderingCreateInfo structure
574 			// is present in the pNext chain of VkGraphicsPipelineCreateInfo, it specifies the view mask and
575 			// format of attachments used for rendering. If this structure is not specified, and the pipeline
576 			// does not include a VkRenderPass, viewMask and colorAttachmentCount are 0, and
577 			// depthAttachmentFormat and stencilAttachmentFormat are VK_FORMAT_UNDEFINED. If a graphics pipeline
578 			// is created with a valid VkRenderPass, parameters of this structure are ignored.
579 
580 			const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
581 			while(extensionCreateInfo)
582 			{
583 				if(extensionCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO)
584 				{
585 					const VkPipelineRenderingCreateInfo *renderingCreateInfo = reinterpret_cast<const VkPipelineRenderingCreateInfo *>(extensionCreateInfo);
586 
587 					if((renderingCreateInfo->depthAttachmentFormat != VK_FORMAT_UNDEFINED) ||
588 					   (renderingCreateInfo->stencilAttachmentFormat != VK_FORMAT_UNDEFINED))
589 					{
590 						// If renderPass is VK_NULL_HANDLE, the pipeline is being created with fragment
591 						// shader state, and either of VkPipelineRenderingCreateInfo::depthAttachmentFormat
592 						// or VkPipelineRenderingCreateInfo::stencilAttachmentFormat are not
593 						// VK_FORMAT_UNDEFINED, pDepthStencilState must be a valid pointer to a valid
594 						// VkPipelineDepthStencilStateCreateInfo structure
595 						ASSERT(depthStencilState);
596 
597 						setDepthStencilState(depthStencilState);
598 					}
599 
600 					if(renderingCreateInfo->colorAttachmentCount > 0)
601 					{
602 						// If renderPass is VK_NULL_HANDLE, the pipeline is being created with fragment
603 						// output interface state, and VkPipelineRenderingCreateInfo::colorAttachmentCount
604 						// is not equal to 0, pColorBlendState must be a valid pointer to a valid
605 						// VkPipelineColorBlendStateCreateInfo structure
606 						ASSERT(colorBlendState);
607 
608 						setColorBlendState(colorBlendState);
609 					}
610 
611 					break;
612 				}
613 
614 				extensionCreateInfo = extensionCreateInfo->pNext;
615 			}
616 		}
617 	}
618 }
619 
setDepthStencilState(const VkPipelineDepthStencilStateCreateInfo * depthStencilState)620 void GraphicsState::setDepthStencilState(const VkPipelineDepthStencilStateCreateInfo *depthStencilState)
621 {
622 	if(depthStencilState->flags != 0)
623 	{
624 		// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
625 		UNSUPPORTED("depthStencilState->flags %d", int(depthStencilState->flags));
626 	}
627 
628 	depthBoundsTestEnable = (depthStencilState->depthBoundsTestEnable != VK_FALSE);
629 	minDepthBounds = depthStencilState->minDepthBounds;
630 	maxDepthBounds = depthStencilState->maxDepthBounds;
631 
632 	depthTestEnable = (depthStencilState->depthTestEnable != VK_FALSE);
633 	depthWriteEnable = (depthStencilState->depthWriteEnable != VK_FALSE);
634 	depthCompareMode = depthStencilState->depthCompareOp;
635 
636 	stencilEnable = (depthStencilState->stencilTestEnable != VK_FALSE);
637 	if(stencilEnable)
638 	{
639 		frontStencil = depthStencilState->front;
640 		backStencil = depthStencilState->back;
641 	}
642 }
643 
setColorBlendState(const VkPipelineColorBlendStateCreateInfo * colorBlendState)644 void GraphicsState::setColorBlendState(const VkPipelineColorBlendStateCreateInfo *colorBlendState)
645 {
646 	if(colorBlendState->flags != 0)
647 	{
648 		// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
649 		UNSUPPORTED("colorBlendState->flags %d", int(colorBlendState->flags));
650 	}
651 
652 	if(colorBlendState->logicOpEnable != VK_FALSE)
653 	{
654 		UNSUPPORTED("VkPhysicalDeviceFeatures::logicOp");
655 	}
656 
657 	if(!dynamicStateFlags.dynamicBlendConstants)
658 	{
659 		blendConstants.x = colorBlendState->blendConstants[0];
660 		blendConstants.y = colorBlendState->blendConstants[1];
661 		blendConstants.z = colorBlendState->blendConstants[2];
662 		blendConstants.w = colorBlendState->blendConstants[3];
663 	}
664 
665 	const VkBaseInStructure *extensionColorBlendInfo = reinterpret_cast<const VkBaseInStructure *>(colorBlendState->pNext);
666 	while(extensionColorBlendInfo)
667 	{
668 		switch(extensionColorBlendInfo->sType)
669 		{
670 		case VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT:
671 			{
672 				const VkPipelineColorBlendAdvancedStateCreateInfoEXT *colorBlendAdvancedCreateInfo = reinterpret_cast<const VkPipelineColorBlendAdvancedStateCreateInfoEXT *>(extensionColorBlendInfo);
673 				ASSERT(colorBlendAdvancedCreateInfo->blendOverlap == VK_BLEND_OVERLAP_UNCORRELATED_EXT);
674 				ASSERT(colorBlendAdvancedCreateInfo->dstPremultiplied == VK_TRUE);
675 				ASSERT(colorBlendAdvancedCreateInfo->srcPremultiplied == VK_TRUE);
676 			}
677 			break;
678 		case VK_STRUCTURE_TYPE_MAX_ENUM:
679 			// dEQP tests that this value is ignored.
680 			break;
681 		default:
682 			UNSUPPORTED("colorBlendState->pNext sType = %s", vk::Stringify(extensionColorBlendInfo->sType).c_str());
683 			break;
684 		}
685 
686 		extensionColorBlendInfo = extensionColorBlendInfo->pNext;
687 	}
688 
689 	ASSERT(colorBlendState->attachmentCount <= sw::MAX_COLOR_BUFFERS);
690 	for(auto i = 0u; i < colorBlendState->attachmentCount; i++)
691 	{
692 		const VkPipelineColorBlendAttachmentState &attachment = colorBlendState->pAttachments[i];
693 		colorWriteMask[i] = attachment.colorWriteMask;
694 		blendState[i] = { (attachment.blendEnable != VK_FALSE),
695 			              attachment.srcColorBlendFactor, attachment.dstColorBlendFactor, attachment.colorBlendOp,
696 			              attachment.srcAlphaBlendFactor, attachment.dstAlphaBlendFactor, attachment.alphaBlendOp };
697 	}
698 }
699 
isDrawPoint(bool polygonModeAware) const700 bool GraphicsState::isDrawPoint(bool polygonModeAware) const
701 {
702 	switch(topology)
703 	{
704 	case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
705 		return true;
706 	case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
707 	case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
708 		return false;
709 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
710 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
711 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
712 		return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_POINT) : false;
713 	default:
714 		UNSUPPORTED("topology %d", int(topology));
715 	}
716 	return false;
717 }
718 
isDrawLine(bool polygonModeAware) const719 bool GraphicsState::isDrawLine(bool polygonModeAware) const
720 {
721 	switch(topology)
722 	{
723 	case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
724 		return false;
725 	case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
726 	case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
727 		return true;
728 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
729 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
730 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
731 		return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_LINE) : false;
732 	default:
733 		UNSUPPORTED("topology %d", int(topology));
734 	}
735 	return false;
736 }
737 
isDrawTriangle(bool polygonModeAware) const738 bool GraphicsState::isDrawTriangle(bool polygonModeAware) const
739 {
740 	switch(topology)
741 	{
742 	case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
743 	case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
744 	case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
745 		return false;
746 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
747 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
748 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
749 		return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_FILL) : true;
750 	default:
751 		UNSUPPORTED("topology %d", int(topology));
752 	}
753 	return false;
754 }
755 
depthWriteActive(const Attachments & attachments) const756 bool GraphicsState::depthWriteActive(const Attachments &attachments) const
757 {
758 	// "Depth writes are always disabled when depthTestEnable is VK_FALSE."
759 	return depthTestActive(attachments) && depthWriteEnable;
760 }
761 
depthTestActive(const Attachments & attachments) const762 bool GraphicsState::depthTestActive(const Attachments &attachments) const
763 {
764 	return attachments.depthBuffer && depthTestEnable;
765 }
766 
stencilActive(const Attachments & attachments) const767 bool GraphicsState::stencilActive(const Attachments &attachments) const
768 {
769 	return attachments.stencilBuffer && stencilEnable;
770 }
771 
depthBoundsTestActive(const Attachments & attachments) const772 bool GraphicsState::depthBoundsTestActive(const Attachments &attachments) const
773 {
774 	return attachments.depthBuffer && depthBoundsTestEnable;
775 }
776 
combineStates(const DynamicState & dynamicState) const777 const GraphicsState GraphicsState::combineStates(const DynamicState &dynamicState) const
778 {
779 	GraphicsState combinedState = *this;
780 
781 	// Apply either pipeline state or dynamic state
782 	if(dynamicStateFlags.dynamicDepthTestEnable)
783 	{
784 		combinedState.depthTestEnable = dynamicState.depthTestEnable;
785 	}
786 
787 	if(dynamicStateFlags.dynamicDepthWriteEnable)
788 	{
789 		combinedState.depthWriteEnable = dynamicState.depthWriteEnable;
790 	}
791 
792 	if(dynamicStateFlags.dynamicDepthCompareOp)
793 	{
794 		combinedState.depthCompareMode = dynamicState.depthCompareOp;
795 	}
796 
797 	if(dynamicStateFlags.dynamicDepthBoundsTestEnable)
798 	{
799 		combinedState.depthBoundsTestEnable = dynamicState.depthBoundsTestEnable;
800 	}
801 
802 	if(dynamicStateFlags.dynamicStencilTestEnable)
803 	{
804 		combinedState.stencilEnable = dynamicState.stencilTestEnable;
805 	}
806 
807 	if(dynamicStateFlags.dynamicRasterizerDiscardEnable)
808 	{
809 		combinedState.rasterizerDiscard = dynamicState.rasterizerDiscardEnable;
810 	}
811 
812 	if(dynamicStateFlags.dynamicDepthBiasEnable)
813 	{
814 		combinedState.depthBiasEnable = dynamicState.depthBiasEnable;
815 	}
816 
817 	if(dynamicStateFlags.dynamicPrimitiveRestartEnable)
818 	{
819 		combinedState.primitiveRestartEnable = dynamicState.primitiveRestartEnable;
820 	}
821 
822 	if(dynamicStateFlags.dynamicScissor)
823 	{
824 		combinedState.scissor = dynamicState.scissor;
825 	}
826 
827 	if(dynamicStateFlags.dynamicViewport)
828 	{
829 		combinedState.viewport = dynamicState.viewport;
830 	}
831 
832 	if(dynamicStateFlags.dynamicBlendConstants)
833 	{
834 		combinedState.blendConstants = dynamicState.blendConstants;
835 	}
836 
837 	if(dynamicStateFlags.dynamicDepthBias)
838 	{
839 		combinedState.constantDepthBias = dynamicState.depthBiasConstantFactor;
840 		combinedState.slopeDepthBias = dynamicState.depthBiasSlopeFactor;
841 		combinedState.depthBiasClamp = dynamicState.depthBiasClamp;
842 	}
843 
844 	if(dynamicStateFlags.dynamicDepthBounds && combinedState.depthBoundsTestEnable)
845 	{
846 		combinedState.minDepthBounds = dynamicState.minDepthBounds;
847 		combinedState.maxDepthBounds = dynamicState.maxDepthBounds;
848 	}
849 
850 	if(dynamicStateFlags.dynamicStencilCompareMask && combinedState.stencilEnable)
851 	{
852 		combinedState.frontStencil.compareMask = dynamicState.frontStencil.compareMask;
853 		combinedState.backStencil.compareMask = dynamicState.backStencil.compareMask;
854 	}
855 
856 	if(dynamicStateFlags.dynamicStencilWriteMask && combinedState.stencilEnable)
857 	{
858 		combinedState.frontStencil.writeMask = dynamicState.frontStencil.writeMask;
859 		combinedState.backStencil.writeMask = dynamicState.backStencil.writeMask;
860 	}
861 
862 	if(dynamicStateFlags.dynamicStencilReference && combinedState.stencilEnable)
863 	{
864 		combinedState.frontStencil.reference = dynamicState.frontStencil.reference;
865 		combinedState.backStencil.reference = dynamicState.backStencil.reference;
866 	}
867 
868 	if(dynamicStateFlags.dynamicStencilOp && combinedState.stencilEnable)
869 	{
870 		if(dynamicState.faceMask & VK_STENCIL_FACE_FRONT_BIT)
871 		{
872 			combinedState.frontStencil.compareOp = dynamicState.frontStencil.compareOp;
873 			combinedState.frontStencil.depthFailOp = dynamicState.frontStencil.depthFailOp;
874 			combinedState.frontStencil.failOp = dynamicState.frontStencil.failOp;
875 			combinedState.frontStencil.passOp = dynamicState.frontStencil.passOp;
876 		}
877 
878 		if(dynamicState.faceMask & VK_STENCIL_FACE_BACK_BIT)
879 		{
880 			combinedState.backStencil.compareOp = dynamicState.backStencil.compareOp;
881 			combinedState.backStencil.depthFailOp = dynamicState.backStencil.depthFailOp;
882 			combinedState.backStencil.failOp = dynamicState.backStencil.failOp;
883 			combinedState.backStencil.passOp = dynamicState.backStencil.passOp;
884 		}
885 	}
886 
887 	if(dynamicStateFlags.dynamicCullMode)
888 	{
889 		combinedState.cullMode = dynamicState.cullMode;
890 	}
891 
892 	if(dynamicStateFlags.dynamicFrontFace)
893 	{
894 		combinedState.frontFace = dynamicState.frontFace;
895 	}
896 
897 	if(dynamicStateFlags.dynamicPrimitiveTopology)
898 	{
899 		combinedState.topology = dynamicState.primitiveTopology;
900 	}
901 
902 	if(dynamicStateFlags.dynamicViewportWithCount && (dynamicState.viewportCount > 0))
903 	{
904 		combinedState.viewport.width = static_cast<float>(dynamicState.viewports[0].extent.width);
905 		combinedState.viewport.height = static_cast<float>(dynamicState.viewports[0].extent.height);
906 		combinedState.viewport.x = static_cast<float>(dynamicState.viewports[0].offset.x);
907 		combinedState.viewport.y = static_cast<float>(dynamicState.viewports[0].offset.y);
908 	}
909 
910 	if(dynamicStateFlags.dynamicScissorWithCount && (dynamicState.scissorCount > 0))
911 	{
912 		combinedState.scissor = dynamicState.scissors[0];
913 	}
914 
915 	return combinedState;
916 }
917 
getBlendState(int index,const Attachments & attachments,bool fragmentContainsKill) const918 BlendState GraphicsState::getBlendState(int index, const Attachments &attachments, bool fragmentContainsKill) const
919 {
920 	ASSERT((index >= 0) && (index < sw::MAX_COLOR_BUFFERS));
921 	auto &state = blendState[index];
922 
923 	BlendState activeBlendState = {};
924 	activeBlendState.alphaBlendEnable = alphaBlendActive(index, attachments, fragmentContainsKill);
925 
926 	if(activeBlendState.alphaBlendEnable)
927 	{
928 		vk::Format format = attachments.colorBuffer[index]->getFormat(VK_IMAGE_ASPECT_COLOR_BIT);
929 
930 		activeBlendState.sourceBlendFactor = blendFactor(state.blendOperation, state.sourceBlendFactor);
931 		activeBlendState.destBlendFactor = blendFactor(state.blendOperation, state.destBlendFactor);
932 		activeBlendState.blendOperation = blendOperation(state.blendOperation, state.sourceBlendFactor, state.destBlendFactor, format);
933 		activeBlendState.sourceBlendFactorAlpha = blendFactor(state.blendOperationAlpha, state.sourceBlendFactorAlpha);
934 		activeBlendState.destBlendFactorAlpha = blendFactor(state.blendOperationAlpha, state.destBlendFactorAlpha);
935 		activeBlendState.blendOperationAlpha = blendOperation(state.blendOperationAlpha, state.sourceBlendFactorAlpha, state.destBlendFactorAlpha, format);
936 	}
937 
938 	return activeBlendState;
939 }
940 
alphaBlendActive(int index,const Attachments & attachments,bool fragmentContainsKill) const941 bool GraphicsState::alphaBlendActive(int index, const Attachments &attachments, bool fragmentContainsKill) const
942 {
943 	ASSERT((index >= 0) && (index < sw::MAX_COLOR_BUFFERS));
944 	auto &state = blendState[index];
945 
946 	if(!attachments.colorBuffer[index] || !blendState[index].alphaBlendEnable)
947 	{
948 		return false;
949 	}
950 
951 	if(!(colorWriteActive(attachments) || fragmentContainsKill))
952 	{
953 		return false;
954 	}
955 
956 	vk::Format format = attachments.colorBuffer[index]->getFormat(VK_IMAGE_ASPECT_COLOR_BIT);
957 	bool colorBlend = blendOperation(state.blendOperation, state.sourceBlendFactor, state.destBlendFactor, format) != VK_BLEND_OP_SRC_EXT;
958 	bool alphaBlend = blendOperation(state.blendOperationAlpha, state.sourceBlendFactorAlpha, state.destBlendFactorAlpha, format) != VK_BLEND_OP_SRC_EXT;
959 
960 	return colorBlend || alphaBlend;
961 }
962 
blendFactor(VkBlendOp blendOperation,VkBlendFactor blendFactor) const963 VkBlendFactor GraphicsState::blendFactor(VkBlendOp blendOperation, VkBlendFactor blendFactor) const
964 {
965 	switch(blendOperation)
966 	{
967 	case VK_BLEND_OP_ADD:
968 	case VK_BLEND_OP_SUBTRACT:
969 	case VK_BLEND_OP_REVERSE_SUBTRACT:
970 		return blendFactor;
971 	case VK_BLEND_OP_MIN:
972 	case VK_BLEND_OP_MAX:
973 	case VK_BLEND_OP_MULTIPLY_EXT:
974 	case VK_BLEND_OP_SCREEN_EXT:
975 	case VK_BLEND_OP_OVERLAY_EXT:
976 	case VK_BLEND_OP_DARKEN_EXT:
977 	case VK_BLEND_OP_LIGHTEN_EXT:
978 	case VK_BLEND_OP_COLORDODGE_EXT:
979 	case VK_BLEND_OP_COLORBURN_EXT:
980 	case VK_BLEND_OP_HARDLIGHT_EXT:
981 	case VK_BLEND_OP_SOFTLIGHT_EXT:
982 	case VK_BLEND_OP_DIFFERENCE_EXT:
983 	case VK_BLEND_OP_EXCLUSION_EXT:
984 	case VK_BLEND_OP_HSL_HUE_EXT:
985 	case VK_BLEND_OP_HSL_SATURATION_EXT:
986 	case VK_BLEND_OP_HSL_COLOR_EXT:
987 	case VK_BLEND_OP_HSL_LUMINOSITY_EXT:
988 		return VK_BLEND_FACTOR_ONE;
989 	default:
990 		ASSERT(false);
991 		return blendFactor;
992 	}
993 }
994 
blendOperation(VkBlendOp blendOperation,VkBlendFactor sourceBlendFactor,VkBlendFactor destBlendFactor,vk::Format format) const995 VkBlendOp GraphicsState::blendOperation(VkBlendOp blendOperation, VkBlendFactor sourceBlendFactor, VkBlendFactor destBlendFactor, vk::Format format) const
996 {
997 	switch(blendOperation)
998 	{
999 	case VK_BLEND_OP_ADD:
1000 		if(sourceBlendFactor == VK_BLEND_FACTOR_ZERO)
1001 		{
1002 			if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
1003 			{
1004 				return VK_BLEND_OP_ZERO_EXT;
1005 			}
1006 			else if(destBlendFactor == VK_BLEND_FACTOR_ONE)
1007 			{
1008 				return VK_BLEND_OP_DST_EXT;
1009 			}
1010 		}
1011 		else if(sourceBlendFactor == VK_BLEND_FACTOR_ONE)
1012 		{
1013 			if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
1014 			{
1015 				return VK_BLEND_OP_SRC_EXT;
1016 			}
1017 		}
1018 		break;
1019 	case VK_BLEND_OP_SUBTRACT:
1020 		if(sourceBlendFactor == VK_BLEND_FACTOR_ZERO)
1021 		{
1022 			if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
1023 			{
1024 				return VK_BLEND_OP_ZERO_EXT;
1025 			}
1026 			else if(format.isUnsignedNormalized())
1027 			{
1028 				return VK_BLEND_OP_ZERO_EXT;  // Negative, clamped to zero
1029 			}
1030 		}
1031 		else if(sourceBlendFactor == VK_BLEND_FACTOR_ONE)
1032 		{
1033 			if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
1034 			{
1035 				return VK_BLEND_OP_SRC_EXT;
1036 			}
1037 		}
1038 		break;
1039 	case VK_BLEND_OP_REVERSE_SUBTRACT:
1040 		if(sourceBlendFactor == VK_BLEND_FACTOR_ZERO)
1041 		{
1042 			if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
1043 			{
1044 				return VK_BLEND_OP_ZERO_EXT;
1045 			}
1046 			else if(destBlendFactor == VK_BLEND_FACTOR_ONE)
1047 			{
1048 				return VK_BLEND_OP_DST_EXT;
1049 			}
1050 		}
1051 		else
1052 		{
1053 			if(destBlendFactor == VK_BLEND_FACTOR_ZERO && format.isUnsignedNormalized())
1054 			{
1055 				return VK_BLEND_OP_ZERO_EXT;  // Negative, clamped to zero
1056 			}
1057 		}
1058 		break;
1059 	case VK_BLEND_OP_MIN:
1060 		return VK_BLEND_OP_MIN;
1061 	case VK_BLEND_OP_MAX:
1062 		return VK_BLEND_OP_MAX;
1063 	case VK_BLEND_OP_MULTIPLY_EXT:
1064 	case VK_BLEND_OP_SCREEN_EXT:
1065 	case VK_BLEND_OP_OVERLAY_EXT:
1066 	case VK_BLEND_OP_DARKEN_EXT:
1067 	case VK_BLEND_OP_LIGHTEN_EXT:
1068 	case VK_BLEND_OP_COLORDODGE_EXT:
1069 	case VK_BLEND_OP_COLORBURN_EXT:
1070 	case VK_BLEND_OP_HARDLIGHT_EXT:
1071 	case VK_BLEND_OP_SOFTLIGHT_EXT:
1072 	case VK_BLEND_OP_DIFFERENCE_EXT:
1073 	case VK_BLEND_OP_EXCLUSION_EXT:
1074 	case VK_BLEND_OP_HSL_HUE_EXT:
1075 	case VK_BLEND_OP_HSL_SATURATION_EXT:
1076 	case VK_BLEND_OP_HSL_COLOR_EXT:
1077 	case VK_BLEND_OP_HSL_LUMINOSITY_EXT:
1078 		return blendOperation;
1079 	default:
1080 		ASSERT(false);
1081 	}
1082 
1083 	return blendOperation;
1084 }
1085 
colorWriteActive(const Attachments & attachments) const1086 bool GraphicsState::colorWriteActive(const Attachments &attachments) const
1087 {
1088 	for(int i = 0; i < sw::MAX_COLOR_BUFFERS; i++)
1089 	{
1090 		if(colorWriteActive(i, attachments))
1091 		{
1092 			return true;
1093 		}
1094 	}
1095 
1096 	return false;
1097 }
1098 
colorWriteActive(int index,const Attachments & attachments) const1099 int GraphicsState::colorWriteActive(int index, const Attachments &attachments) const
1100 {
1101 	ASSERT((index >= 0) && (index < sw::MAX_COLOR_BUFFERS));
1102 	auto &state = blendState[index];
1103 
1104 	if(!attachments.colorBuffer[index] || attachments.colorBuffer[index]->getFormat() == VK_FORMAT_UNDEFINED)
1105 	{
1106 		return 0;
1107 	}
1108 
1109 	vk::Format format = attachments.colorBuffer[index]->getFormat(VK_IMAGE_ASPECT_COLOR_BIT);
1110 
1111 	if(blendOperation(state.blendOperation, state.sourceBlendFactor, state.destBlendFactor, format) == VK_BLEND_OP_DST_EXT &&
1112 	   blendOperation(state.blendOperationAlpha, state.sourceBlendFactorAlpha, state.destBlendFactorAlpha, format) == VK_BLEND_OP_DST_EXT)
1113 	{
1114 		return 0;
1115 	}
1116 
1117 	return colorWriteMask[index];
1118 }
1119 
1120 }  // namespace vk