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