• 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/VkPipeline.hpp"
21 #include "Vulkan/VkRenderPass.hpp"
22 #include "Vulkan/VkStringify.hpp"
23 
24 namespace {
25 
ComputePrimitiveCount(VkPrimitiveTopology topology,uint32_t vertexCount)26 uint32_t ComputePrimitiveCount(VkPrimitiveTopology topology, uint32_t vertexCount)
27 {
28 	switch(topology)
29 	{
30 	case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
31 		return vertexCount;
32 	case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
33 		return vertexCount / 2;
34 	case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
35 		return std::max<uint32_t>(vertexCount, 1) - 1;
36 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
37 		return vertexCount / 3;
38 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
39 		return std::max<uint32_t>(vertexCount, 2) - 2;
40 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
41 		return std::max<uint32_t>(vertexCount, 2) - 2;
42 	default:
43 		UNSUPPORTED("VkPrimitiveTopology %d", int(topology));
44 	}
45 
46 	return 0;
47 }
48 
49 template<typename T>
ProcessPrimitiveRestart(T * indexBuffer,VkPrimitiveTopology topology,uint32_t count,std::vector<std::pair<uint32_t,void * >> * indexBuffers)50 void ProcessPrimitiveRestart(T *indexBuffer,
51                              VkPrimitiveTopology topology,
52                              uint32_t count,
53                              std::vector<std::pair<uint32_t, void *>> *indexBuffers)
54 {
55 	static const T RestartIndex = static_cast<T>(-1);
56 	T *indexBufferStart = indexBuffer;
57 	uint32_t vertexCount = 0;
58 	for(uint32_t i = 0; i < count; i++)
59 	{
60 		if(indexBuffer[i] == RestartIndex)
61 		{
62 			// Record previous segment
63 			if(vertexCount > 0)
64 			{
65 				uint32_t primitiveCount = ComputePrimitiveCount(topology, vertexCount);
66 				if(primitiveCount > 0)
67 				{
68 					indexBuffers->push_back({ primitiveCount, indexBufferStart });
69 				}
70 			}
71 			vertexCount = 0;
72 		}
73 		else
74 		{
75 			if(vertexCount == 0)
76 			{
77 				indexBufferStart = indexBuffer + i;
78 			}
79 			vertexCount++;
80 		}
81 	}
82 
83 	// Record last segment
84 	if(vertexCount > 0)
85 	{
86 		uint32_t primitiveCount = ComputePrimitiveCount(topology, vertexCount);
87 		if(primitiveCount > 0)
88 		{
89 			indexBuffers->push_back({ primitiveCount, indexBufferStart });
90 		}
91 	}
92 }
93 
ParseDynamicStateFlags(const VkPipelineDynamicStateCreateInfo * dynamicStateCreateInfo)94 vk::DynamicStateFlags ParseDynamicStateFlags(const VkPipelineDynamicStateCreateInfo *dynamicStateCreateInfo)
95 {
96 	vk::DynamicStateFlags dynamicStateFlags = {};
97 
98 	if(dynamicStateCreateInfo == nullptr)
99 	{
100 		return dynamicStateFlags;
101 	}
102 
103 	if(dynamicStateCreateInfo->flags != 0)
104 	{
105 		// Vulkan 1.3: "flags is reserved for future use." "flags must be 0"
106 		UNSUPPORTED("dynamicStateCreateInfo->flags 0x%08X", int(dynamicStateCreateInfo->flags));
107 	}
108 
109 	for(uint32_t i = 0; i < dynamicStateCreateInfo->dynamicStateCount; i++)
110 	{
111 		VkDynamicState dynamicState = dynamicStateCreateInfo->pDynamicStates[i];
112 		switch(dynamicState)
113 		{
114 		// Vertex input interface:
115 		case VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE:
116 			dynamicStateFlags.vertexInputInterface.dynamicPrimitiveRestartEnable = true;
117 			break;
118 		case VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY:
119 			dynamicStateFlags.vertexInputInterface.dynamicPrimitiveTopology = true;
120 			break;
121 		case VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE:
122 			dynamicStateFlags.vertexInputInterface.dynamicVertexInputBindingStride = true;
123 			break;
124 
125 		// Pre-rasterization:
126 		case VK_DYNAMIC_STATE_LINE_WIDTH:
127 			dynamicStateFlags.preRasterization.dynamicLineWidth = true;
128 			break;
129 		case VK_DYNAMIC_STATE_DEPTH_BIAS:
130 			dynamicStateFlags.preRasterization.dynamicDepthBias = true;
131 			break;
132 		case VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE:
133 			dynamicStateFlags.preRasterization.dynamicDepthBiasEnable = true;
134 			break;
135 		case VK_DYNAMIC_STATE_CULL_MODE:
136 			dynamicStateFlags.preRasterization.dynamicCullMode = true;
137 			break;
138 		case VK_DYNAMIC_STATE_FRONT_FACE:
139 			dynamicStateFlags.preRasterization.dynamicFrontFace = true;
140 			break;
141 		case VK_DYNAMIC_STATE_VIEWPORT:
142 			dynamicStateFlags.preRasterization.dynamicViewport = true;
143 			break;
144 		case VK_DYNAMIC_STATE_SCISSOR:
145 			dynamicStateFlags.preRasterization.dynamicScissor = true;
146 			break;
147 		case VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT:
148 			dynamicStateFlags.preRasterization.dynamicViewportWithCount = true;
149 			break;
150 		case VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT:
151 			dynamicStateFlags.preRasterization.dynamicScissorWithCount = true;
152 			break;
153 		case VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE:
154 			dynamicStateFlags.preRasterization.dynamicRasterizerDiscardEnable = true;
155 			break;
156 
157 		// Fragment:
158 		case VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE:
159 			dynamicStateFlags.fragment.dynamicDepthTestEnable = true;
160 			break;
161 		case VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE:
162 			dynamicStateFlags.fragment.dynamicDepthWriteEnable = true;
163 			break;
164 		case VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE:
165 			dynamicStateFlags.fragment.dynamicDepthBoundsTestEnable = true;
166 			break;
167 		case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
168 			dynamicStateFlags.fragment.dynamicDepthBounds = true;
169 			break;
170 		case VK_DYNAMIC_STATE_DEPTH_COMPARE_OP:
171 			dynamicStateFlags.fragment.dynamicDepthCompareOp = true;
172 			break;
173 		case VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE:
174 			dynamicStateFlags.fragment.dynamicStencilTestEnable = true;
175 			break;
176 		case VK_DYNAMIC_STATE_STENCIL_OP:
177 			dynamicStateFlags.fragment.dynamicStencilOp = true;
178 			break;
179 		case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
180 			dynamicStateFlags.fragment.dynamicStencilCompareMask = true;
181 			break;
182 		case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
183 			dynamicStateFlags.fragment.dynamicStencilWriteMask = true;
184 			break;
185 		case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
186 			dynamicStateFlags.fragment.dynamicStencilReference = true;
187 			break;
188 
189 		// Fragment output interface:
190 		case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
191 			dynamicStateFlags.fragmentOutputInterface.dynamicBlendConstants = true;
192 			break;
193 
194 		default:
195 			UNSUPPORTED("VkDynamicState %d", int(dynamicState));
196 		}
197 	}
198 
199 	return dynamicStateFlags;
200 }
201 }  // namespace
202 
203 namespace vk {
204 
bytesPerIndex() const205 uint32_t IndexBuffer::bytesPerIndex() const
206 {
207 	return indexType == VK_INDEX_TYPE_UINT16 ? 2u : 4u;
208 }
209 
setIndexBufferBinding(const VertexInputBinding & indexBufferBinding,VkIndexType type)210 void IndexBuffer::setIndexBufferBinding(const VertexInputBinding &indexBufferBinding, VkIndexType type)
211 {
212 	binding = indexBufferBinding;
213 	indexType = type;
214 }
215 
getIndexBuffers(VkPrimitiveTopology topology,uint32_t count,uint32_t first,bool indexed,bool hasPrimitiveRestartEnable,std::vector<std::pair<uint32_t,void * >> * indexBuffers) const216 void IndexBuffer::getIndexBuffers(VkPrimitiveTopology topology, uint32_t count, uint32_t first, bool indexed, bool hasPrimitiveRestartEnable, std::vector<std::pair<uint32_t, void *>> *indexBuffers) const
217 {
218 	if(indexed)
219 	{
220 		const VkDeviceSize bufferSize = binding.buffer->getSize();
221 		if(binding.offset >= bufferSize)
222 		{
223 			return;  // Nothing to draw
224 		}
225 
226 		const VkDeviceSize maxIndices = (bufferSize - binding.offset) / bytesPerIndex();
227 		if(first > maxIndices)
228 		{
229 			return;  // Nothing to draw
230 		}
231 
232 		void *indexBuffer = binding.buffer->getOffsetPointer(binding.offset + first * bytesPerIndex());
233 		if(hasPrimitiveRestartEnable)
234 		{
235 			switch(indexType)
236 			{
237 			case VK_INDEX_TYPE_UINT16:
238 				ProcessPrimitiveRestart(static_cast<uint16_t *>(indexBuffer), topology, count, indexBuffers);
239 				break;
240 			case VK_INDEX_TYPE_UINT32:
241 				ProcessPrimitiveRestart(static_cast<uint32_t *>(indexBuffer), topology, count, indexBuffers);
242 				break;
243 			default:
244 				UNSUPPORTED("VkIndexType %d", int(indexType));
245 			}
246 		}
247 		else
248 		{
249 			indexBuffers->push_back({ ComputePrimitiveCount(topology, count), indexBuffer });
250 		}
251 	}
252 	else
253 	{
254 		indexBuffers->push_back({ ComputePrimitiveCount(topology, count), nullptr });
255 	}
256 }
257 
colorFormat(int index) const258 VkFormat Attachments::colorFormat(int index) const
259 {
260 	ASSERT((index >= 0) && (index < sw::MAX_COLOR_BUFFERS));
261 
262 	if(colorBuffer[index])
263 	{
264 		return colorBuffer[index]->getFormat();
265 	}
266 	else
267 	{
268 		return VK_FORMAT_UNDEFINED;
269 	}
270 }
271 
depthFormat() const272 VkFormat Attachments::depthFormat() const
273 {
274 	if(depthBuffer)
275 	{
276 		return depthBuffer->getFormat();
277 	}
278 	else
279 	{
280 		return VK_FORMAT_UNDEFINED;
281 	}
282 }
283 
initialize(const VkPipelineVertexInputStateCreateInfo * vertexInputState)284 void Inputs::initialize(const VkPipelineVertexInputStateCreateInfo *vertexInputState)
285 {
286 	if(vertexInputState->flags != 0)
287 	{
288 		// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
289 		UNSUPPORTED("vertexInputState->flags");
290 	}
291 
292 	// Temporary in-binding-order representation of buffer strides, to be consumed below
293 	// when considering attributes. TODO: unfuse buffers from attributes in backend, is old GL model.
294 	uint32_t vertexStrides[MAX_VERTEX_INPUT_BINDINGS];
295 	uint32_t instanceStrides[MAX_VERTEX_INPUT_BINDINGS];
296 	VkVertexInputRate inputRates[MAX_VERTEX_INPUT_BINDINGS];
297 	for(uint32_t i = 0; i < vertexInputState->vertexBindingDescriptionCount; i++)
298 	{
299 		const auto &desc = vertexInputState->pVertexBindingDescriptions[i];
300 		inputRates[desc.binding] = desc.inputRate;
301 		vertexStrides[desc.binding] = desc.inputRate == VK_VERTEX_INPUT_RATE_VERTEX ? desc.stride : 0;
302 		instanceStrides[desc.binding] = desc.inputRate == VK_VERTEX_INPUT_RATE_INSTANCE ? desc.stride : 0;
303 	}
304 
305 	for(uint32_t i = 0; i < vertexInputState->vertexAttributeDescriptionCount; i++)
306 	{
307 		const auto &desc = vertexInputState->pVertexAttributeDescriptions[i];
308 		sw::Stream &input = stream[desc.location];
309 		input.format = desc.format;
310 		input.offset = desc.offset;
311 		input.binding = desc.binding;
312 		input.inputRate = inputRates[desc.binding];
313 		input.vertexStride = vertexStrides[desc.binding];
314 		input.instanceStride = instanceStrides[desc.binding];
315 	}
316 }
317 
updateDescriptorSets(const DescriptorSet::Array & dso,const DescriptorSet::Bindings & ds,const DescriptorSet::DynamicOffsets & ddo)318 void Inputs::updateDescriptorSets(const DescriptorSet::Array &dso,
319                                   const DescriptorSet::Bindings &ds,
320                                   const DescriptorSet::DynamicOffsets &ddo)
321 {
322 	descriptorSetObjects = dso;
323 	descriptorSets = ds;
324 	descriptorDynamicOffsets = ddo;
325 }
326 
bindVertexInputs(int firstInstance,bool dynamicInstanceStride)327 void Inputs::bindVertexInputs(int firstInstance, bool dynamicInstanceStride)
328 {
329 	for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; i++)
330 	{
331 		auto &attrib = stream[i];
332 		if(attrib.format != VK_FORMAT_UNDEFINED)
333 		{
334 			const auto &vertexInput = vertexInputBindings[attrib.binding];
335 			VkDeviceSize offset = attrib.offset + vertexInput.offset +
336 			                      getInstanceStride(i, dynamicInstanceStride) * firstInstance;
337 			attrib.buffer = vertexInput.buffer ? vertexInput.buffer->getOffsetPointer(offset) : nullptr;
338 
339 			VkDeviceSize size = vertexInput.buffer ? vertexInput.buffer->getSize() : 0;
340 			attrib.robustnessSize = (size > offset) ? size - offset : 0;
341 		}
342 	}
343 }
344 
setVertexInputBinding(const VertexInputBinding bindings[])345 void Inputs::setVertexInputBinding(const VertexInputBinding bindings[])
346 {
347 	for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; ++i)
348 	{
349 		vertexInputBindings[i] = bindings[i];
350 	}
351 }
352 
advanceInstanceAttributes(bool dynamicInstanceStride)353 void Inputs::advanceInstanceAttributes(bool dynamicInstanceStride)
354 {
355 	for(uint32_t i = 0; i < vk::MAX_VERTEX_INPUT_BINDINGS; i++)
356 	{
357 		auto &attrib = stream[i];
358 
359 		VkDeviceSize instanceStride = getInstanceStride(i, dynamicInstanceStride);
360 		if((attrib.format != VK_FORMAT_UNDEFINED) && instanceStride && (instanceStride < attrib.robustnessSize))
361 		{
362 			// Under the casts: attrib.buffer += instanceStride
363 			attrib.buffer = (const void *)((uintptr_t)attrib.buffer + instanceStride);
364 			attrib.robustnessSize -= instanceStride;
365 		}
366 	}
367 }
368 
getVertexStride(uint32_t i,bool dynamicVertexStride) const369 VkDeviceSize Inputs::getVertexStride(uint32_t i, bool dynamicVertexStride) const
370 {
371 	auto &attrib = stream[i];
372 	if(attrib.format != VK_FORMAT_UNDEFINED && attrib.inputRate == VK_VERTEX_INPUT_RATE_VERTEX)
373 	{
374 		if(dynamicVertexStride)
375 		{
376 			return vertexInputBindings[attrib.binding].stride;
377 		}
378 		else
379 		{
380 			return attrib.vertexStride;
381 		}
382 	}
383 
384 	return 0;
385 }
386 
getInstanceStride(uint32_t i,bool dynamicInstanceStride) const387 VkDeviceSize Inputs::getInstanceStride(uint32_t i, bool dynamicInstanceStride) const
388 {
389 	auto &attrib = stream[i];
390 	if(attrib.format != VK_FORMAT_UNDEFINED && attrib.inputRate == VK_VERTEX_INPUT_RATE_INSTANCE)
391 	{
392 		if(dynamicInstanceStride)
393 		{
394 			return vertexInputBindings[attrib.binding].stride;
395 		}
396 		else
397 		{
398 			return attrib.instanceStride;
399 		}
400 	}
401 
402 	return 0;
403 }
404 
set(const VkPipelineMultisampleStateCreateInfo * multisampleState)405 void MultisampleState::set(const VkPipelineMultisampleStateCreateInfo *multisampleState)
406 {
407 	if(multisampleState->flags != 0)
408 	{
409 		// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
410 		UNSUPPORTED("pCreateInfo->pMultisampleState->flags 0x%08X", int(multisampleState->flags));
411 	}
412 
413 	sampleShadingEnable = (multisampleState->sampleShadingEnable != VK_FALSE);
414 	if(sampleShadingEnable)
415 	{
416 		minSampleShading = multisampleState->minSampleShading;
417 	}
418 
419 	if(multisampleState->alphaToOneEnable != VK_FALSE)
420 	{
421 		UNSUPPORTED("VkPhysicalDeviceFeatures::alphaToOne");
422 	}
423 
424 	switch(multisampleState->rasterizationSamples)
425 	{
426 	case VK_SAMPLE_COUNT_1_BIT:
427 		sampleCount = 1;
428 		break;
429 	case VK_SAMPLE_COUNT_4_BIT:
430 		sampleCount = 4;
431 		break;
432 	default:
433 		UNSUPPORTED("Unsupported sample count");
434 	}
435 
436 	VkSampleMask sampleMask;
437 	if(multisampleState->pSampleMask)
438 	{
439 		sampleMask = multisampleState->pSampleMask[0];
440 	}
441 	else  // "If pSampleMask is NULL, it is treated as if the mask has all bits set to 1."
442 	{
443 		sampleMask = ~0;
444 	}
445 
446 	alphaToCoverage = (multisampleState->alphaToCoverageEnable != VK_FALSE);
447 	multiSampleMask = sampleMask & ((unsigned)0xFFFFFFFF >> (32 - sampleCount));
448 }
449 
initialize(const VkPipelineVertexInputStateCreateInfo * vertexInputState,const VkPipelineInputAssemblyStateCreateInfo * inputAssemblyState,const DynamicStateFlags & allDynamicStateFlags)450 void VertexInputInterfaceState::initialize(const VkPipelineVertexInputStateCreateInfo *vertexInputState,
451                                            const VkPipelineInputAssemblyStateCreateInfo *inputAssemblyState,
452                                            const DynamicStateFlags &allDynamicStateFlags)
453 {
454 	dynamicStateFlags = allDynamicStateFlags.vertexInputInterface;
455 
456 	if(vertexInputState->flags != 0)
457 	{
458 		// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
459 		UNSUPPORTED("vertexInputState->flags");
460 	}
461 
462 	if(inputAssemblyState->flags != 0)
463 	{
464 		// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
465 		UNSUPPORTED("pCreateInfo->pInputAssemblyState->flags 0x%08X", int(inputAssemblyState->flags));
466 	}
467 
468 	primitiveRestartEnable = (inputAssemblyState->primitiveRestartEnable != VK_FALSE);
469 	topology = inputAssemblyState->topology;
470 }
471 
applyState(const DynamicState & dynamicState)472 void VertexInputInterfaceState::applyState(const DynamicState &dynamicState)
473 {
474 	if(dynamicStateFlags.dynamicPrimitiveRestartEnable)
475 	{
476 		primitiveRestartEnable = dynamicState.primitiveRestartEnable;
477 	}
478 
479 	if(dynamicStateFlags.dynamicPrimitiveTopology)
480 	{
481 		topology = dynamicState.primitiveTopology;
482 	}
483 }
484 
isDrawPoint(bool polygonModeAware,VkPolygonMode polygonMode) const485 bool VertexInputInterfaceState::isDrawPoint(bool polygonModeAware, VkPolygonMode polygonMode) const
486 {
487 	switch(topology)
488 	{
489 	case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
490 		return true;
491 	case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
492 	case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
493 		return false;
494 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
495 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
496 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
497 		return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_POINT) : false;
498 	default:
499 		UNSUPPORTED("topology %d", int(topology));
500 	}
501 	return false;
502 }
503 
isDrawLine(bool polygonModeAware,VkPolygonMode polygonMode) const504 bool VertexInputInterfaceState::isDrawLine(bool polygonModeAware, VkPolygonMode polygonMode) const
505 {
506 	switch(topology)
507 	{
508 	case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
509 		return false;
510 	case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
511 	case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
512 		return true;
513 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
514 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
515 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
516 		return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_LINE) : false;
517 	default:
518 		UNSUPPORTED("topology %d", int(topology));
519 	}
520 	return false;
521 }
522 
isDrawTriangle(bool polygonModeAware,VkPolygonMode polygonMode) const523 bool VertexInputInterfaceState::isDrawTriangle(bool polygonModeAware, VkPolygonMode polygonMode) const
524 {
525 	switch(topology)
526 	{
527 	case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
528 	case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
529 	case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
530 		return false;
531 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
532 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
533 	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
534 		return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_FILL) : true;
535 	default:
536 		UNSUPPORTED("topology %d", int(topology));
537 	}
538 	return false;
539 }
540 
initialize(const vk::Device * device,const PipelineLayout * layout,const VkPipelineViewportStateCreateInfo * viewportState,const VkPipelineRasterizationStateCreateInfo * rasterizationState,const vk::RenderPass * renderPass,uint32_t subpassIndex,const VkPipelineRenderingCreateInfo * rendering,const DynamicStateFlags & allDynamicStateFlags)541 void PreRasterizationState::initialize(const vk::Device *device,
542                                        const PipelineLayout *layout,
543                                        const VkPipelineViewportStateCreateInfo *viewportState,
544                                        const VkPipelineRasterizationStateCreateInfo *rasterizationState,
545                                        const vk::RenderPass *renderPass, uint32_t subpassIndex,
546                                        const VkPipelineRenderingCreateInfo *rendering,
547                                        const DynamicStateFlags &allDynamicStateFlags)
548 {
549 	pipelineLayout = layout;
550 	dynamicStateFlags = allDynamicStateFlags.preRasterization;
551 
552 	if(rasterizationState->flags != 0)
553 	{
554 		// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
555 		UNSUPPORTED("pCreateInfo->pRasterizationState->flags 0x%08X", int(rasterizationState->flags));
556 	}
557 
558 	rasterizerDiscard = rasterizationState->rasterizerDiscardEnable != VK_FALSE;
559 	cullMode = rasterizationState->cullMode;
560 	frontFace = rasterizationState->frontFace;
561 	polygonMode = rasterizationState->polygonMode;
562 	depthBiasEnable = rasterizationState->depthBiasEnable;
563 	constantDepthBias = rasterizationState->depthBiasConstantFactor;
564 	slopeDepthBias = rasterizationState->depthBiasSlopeFactor;
565 	depthBiasClamp = rasterizationState->depthBiasClamp;
566 	depthRangeUnrestricted = device->hasExtension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME);
567 	depthClampEnable = rasterizationState->depthClampEnable != VK_FALSE;
568 	depthClipEnable = !depthClampEnable;
569 
570 	// From the Vulkan spec for vkCmdSetDepthBias:
571 	//    The bias value O for a polygon is:
572 	//        O = dbclamp(...)
573 	//    where dbclamp(x) =
574 	//        * x                       depthBiasClamp = 0 or NaN
575 	//        * min(x, depthBiasClamp)  depthBiasClamp > 0
576 	//        * max(x, depthBiasClamp)  depthBiasClamp < 0
577 	// So it should be safe to resolve NaNs to 0.0f.
578 	if(std::isnan(depthBiasClamp))
579 	{
580 		depthBiasClamp = 0.0f;
581 	}
582 
583 	if(!dynamicStateFlags.dynamicLineWidth)
584 	{
585 		lineWidth = rasterizationState->lineWidth;
586 	}
587 
588 	const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(rasterizationState->pNext);
589 	while(extensionCreateInfo)
590 	{
591 		switch(extensionCreateInfo->sType)
592 		{
593 		case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT:
594 			{
595 				const VkPipelineRasterizationLineStateCreateInfoEXT *lineStateCreateInfo = reinterpret_cast<const VkPipelineRasterizationLineStateCreateInfoEXT *>(extensionCreateInfo);
596 				lineRasterizationMode = lineStateCreateInfo->lineRasterizationMode;
597 			}
598 			break;
599 		case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT:
600 			{
601 				const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *provokingVertexModeCreateInfo =
602 				    reinterpret_cast<const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *>(extensionCreateInfo);
603 				provokingVertexMode = provokingVertexModeCreateInfo->provokingVertexMode;
604 			}
605 			break;
606 		case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT:
607 			{
608 				const auto *depthClipInfo = reinterpret_cast<const VkPipelineRasterizationDepthClipStateCreateInfoEXT *>(extensionCreateInfo);
609 				// Reserved for future use.
610 				ASSERT(depthClipInfo->flags == 0);
611 				depthClipEnable = depthClipInfo->depthClipEnable != VK_FALSE;
612 			}
613 			break;
614 		case VK_STRUCTURE_TYPE_APPLICATION_INFO:
615 			// SwiftShader doesn't interact with application info, but dEQP includes it
616 			break;
617 		case VK_STRUCTURE_TYPE_MAX_ENUM:
618 			// dEQP tests that this value is ignored.
619 			break;
620 		default:
621 			UNSUPPORTED("pCreateInfo->pRasterizationState->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str());
622 			break;
623 		}
624 
625 		extensionCreateInfo = extensionCreateInfo->pNext;
626 	}
627 
628 	if(!rasterizerDiscard || dynamicStateFlags.dynamicRasterizerDiscardEnable)
629 	{
630 		extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(viewportState->pNext);
631 		while(extensionCreateInfo != nullptr)
632 		{
633 			switch(extensionCreateInfo->sType)
634 			{
635 			case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT:
636 				{
637 					const auto *depthClipControl = reinterpret_cast<const VkPipelineViewportDepthClipControlCreateInfoEXT *>(extensionCreateInfo);
638 					depthClipNegativeOneToOne = depthClipControl->negativeOneToOne != VK_FALSE;
639 				}
640 				break;
641 			case VK_STRUCTURE_TYPE_MAX_ENUM:
642 				// dEQP passes this value expecting the driver to ignore it.
643 				break;
644 			default:
645 				UNSUPPORTED("pCreateInfo->pViewportState->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str());
646 				break;
647 			}
648 			extensionCreateInfo = extensionCreateInfo->pNext;
649 		}
650 
651 		if(viewportState->flags != 0)
652 		{
653 			// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
654 			UNSUPPORTED("pCreateInfo->pViewportState->flags 0x%08X", int(viewportState->flags));
655 		}
656 
657 		if((viewportState->viewportCount > 1) ||
658 		   (viewportState->scissorCount > 1))
659 		{
660 			UNSUPPORTED("VkPhysicalDeviceFeatures::multiViewport");
661 		}
662 
663 		if(!dynamicStateFlags.dynamicScissor && !dynamicStateFlags.dynamicScissorWithCount)
664 		{
665 			scissor = viewportState->pScissors[0];
666 		}
667 
668 		if(!dynamicStateFlags.dynamicViewport && !dynamicStateFlags.dynamicViewportWithCount)
669 		{
670 			viewport = viewportState->pViewports[0];
671 		}
672 	}
673 }
674 
applyState(const DynamicState & dynamicState)675 void PreRasterizationState::applyState(const DynamicState &dynamicState)
676 {
677 	if(dynamicStateFlags.dynamicLineWidth)
678 	{
679 		lineWidth = dynamicState.lineWidth;
680 	}
681 
682 	if(dynamicStateFlags.dynamicDepthBias)
683 	{
684 		constantDepthBias = dynamicState.depthBiasConstantFactor;
685 		slopeDepthBias = dynamicState.depthBiasSlopeFactor;
686 		depthBiasClamp = dynamicState.depthBiasClamp;
687 	}
688 
689 	if(dynamicStateFlags.dynamicDepthBiasEnable)
690 	{
691 		depthBiasEnable = dynamicState.depthBiasEnable;
692 	}
693 
694 	if(dynamicStateFlags.dynamicCullMode)
695 	{
696 		cullMode = dynamicState.cullMode;
697 	}
698 
699 	if(dynamicStateFlags.dynamicFrontFace)
700 	{
701 		frontFace = dynamicState.frontFace;
702 	}
703 
704 	if(dynamicStateFlags.dynamicViewport)
705 	{
706 		viewport = dynamicState.viewport;
707 	}
708 
709 	if(dynamicStateFlags.dynamicScissor)
710 	{
711 		scissor = dynamicState.scissor;
712 	}
713 
714 	if(dynamicStateFlags.dynamicViewportWithCount && dynamicState.viewportCount > 0)
715 	{
716 		viewport.width = static_cast<float>(dynamicState.viewports[0].extent.width);
717 		viewport.height = static_cast<float>(dynamicState.viewports[0].extent.height);
718 		viewport.x = static_cast<float>(dynamicState.viewports[0].offset.x);
719 		viewport.y = static_cast<float>(dynamicState.viewports[0].offset.y);
720 	}
721 
722 	if(dynamicStateFlags.dynamicScissorWithCount && dynamicState.scissorCount > 0)
723 	{
724 		scissor = dynamicState.scissors[0];
725 	}
726 
727 	if(dynamicStateFlags.dynamicRasterizerDiscardEnable)
728 	{
729 		rasterizerDiscard = dynamicState.rasterizerDiscardEnable;
730 	}
731 }
732 
initialize(const PipelineLayout * layout,const VkPipelineDepthStencilStateCreateInfo * depthStencilState,const vk::RenderPass * renderPass,uint32_t subpassIndex,const VkPipelineRenderingCreateInfo * rendering,const DynamicStateFlags & allDynamicStateFlags)733 void FragmentState::initialize(
734     const PipelineLayout *layout,
735     const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
736     const vk::RenderPass *renderPass, uint32_t subpassIndex,
737     const VkPipelineRenderingCreateInfo *rendering,
738     const DynamicStateFlags &allDynamicStateFlags)
739 {
740 	pipelineLayout = layout;
741 	dynamicStateFlags = allDynamicStateFlags.fragment;
742 
743 	if(renderPass)
744 	{
745 		const VkSubpassDescription &subpass = renderPass->getSubpass(subpassIndex);
746 
747 		// Ignore pDepthStencilState when "the subpass of the render pass the pipeline
748 		// is created against does not use a depth/stencil attachment"
749 		if(subpass.pDepthStencilAttachment &&
750 		   subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)
751 		{
752 			setDepthStencilState(depthStencilState);
753 		}
754 	}
755 	else  // No render pass
756 	{
757 		// When a pipeline is created without a VkRenderPass, if the VkPipelineRenderingCreateInfo structure
758 		// is present in the pNext chain of VkGraphicsPipelineCreateInfo, it specifies the view mask and
759 		// format of attachments used for rendering. If this structure is not specified, and the pipeline
760 		// does not include a VkRenderPass, viewMask and colorAttachmentCount are 0, and
761 		// depthAttachmentFormat and stencilAttachmentFormat are VK_FORMAT_UNDEFINED. If a graphics pipeline
762 		// is created with a valid VkRenderPass, parameters of this structure are ignored.
763 
764 		if(rendering)
765 		{
766 			if((rendering->depthAttachmentFormat != VK_FORMAT_UNDEFINED) ||
767 			   (rendering->stencilAttachmentFormat != VK_FORMAT_UNDEFINED))
768 			{
769 				// If renderPass is VK_NULL_HANDLE, the pipeline is being created with fragment
770 				// shader state, and either of VkPipelineRenderingCreateInfo::depthAttachmentFormat
771 				// or VkPipelineRenderingCreateInfo::stencilAttachmentFormat are not
772 				// VK_FORMAT_UNDEFINED, pDepthStencilState must be a valid pointer to a valid
773 				// VkPipelineDepthStencilStateCreateInfo structure
774 				ASSERT(depthStencilState);
775 
776 				setDepthStencilState(depthStencilState);
777 			}
778 		}
779 	}
780 }
781 
applyState(const DynamicState & dynamicState)782 void FragmentState::applyState(const DynamicState &dynamicState)
783 {
784 	if(dynamicStateFlags.dynamicDepthTestEnable)
785 	{
786 		depthTestEnable = dynamicState.depthTestEnable;
787 	}
788 
789 	if(dynamicStateFlags.dynamicDepthWriteEnable)
790 	{
791 		depthWriteEnable = dynamicState.depthWriteEnable;
792 	}
793 
794 	if(dynamicStateFlags.dynamicDepthBoundsTestEnable)
795 	{
796 		depthBoundsTestEnable = dynamicState.depthBoundsTestEnable;
797 	}
798 
799 	if(dynamicStateFlags.dynamicDepthBounds && depthBoundsTestEnable)
800 	{
801 		minDepthBounds = dynamicState.minDepthBounds;
802 		maxDepthBounds = dynamicState.maxDepthBounds;
803 	}
804 
805 	if(dynamicStateFlags.dynamicDepthCompareOp)
806 	{
807 		depthCompareMode = dynamicState.depthCompareOp;
808 	}
809 
810 	if(dynamicStateFlags.dynamicStencilTestEnable)
811 	{
812 		stencilEnable = dynamicState.stencilTestEnable;
813 	}
814 
815 	if(dynamicStateFlags.dynamicStencilOp && stencilEnable)
816 	{
817 		if(dynamicState.faceMask & VK_STENCIL_FACE_FRONT_BIT)
818 		{
819 			frontStencil.compareOp = dynamicState.frontStencil.compareOp;
820 			frontStencil.depthFailOp = dynamicState.frontStencil.depthFailOp;
821 			frontStencil.failOp = dynamicState.frontStencil.failOp;
822 			frontStencil.passOp = dynamicState.frontStencil.passOp;
823 		}
824 
825 		if(dynamicState.faceMask & VK_STENCIL_FACE_BACK_BIT)
826 		{
827 			backStencil.compareOp = dynamicState.backStencil.compareOp;
828 			backStencil.depthFailOp = dynamicState.backStencil.depthFailOp;
829 			backStencil.failOp = dynamicState.backStencil.failOp;
830 			backStencil.passOp = dynamicState.backStencil.passOp;
831 		}
832 	}
833 
834 	if(dynamicStateFlags.dynamicStencilCompareMask && stencilEnable)
835 	{
836 		frontStencil.compareMask = dynamicState.frontStencil.compareMask;
837 		backStencil.compareMask = dynamicState.backStencil.compareMask;
838 	}
839 
840 	if(dynamicStateFlags.dynamicStencilWriteMask && stencilEnable)
841 	{
842 		frontStencil.writeMask = dynamicState.frontStencil.writeMask;
843 		backStencil.writeMask = dynamicState.backStencil.writeMask;
844 	}
845 
846 	if(dynamicStateFlags.dynamicStencilReference && stencilEnable)
847 	{
848 		frontStencil.reference = dynamicState.frontStencil.reference;
849 		backStencil.reference = dynamicState.backStencil.reference;
850 	}
851 }
852 
depthWriteActive(const Attachments & attachments) const853 bool FragmentState::depthWriteActive(const Attachments &attachments) const
854 {
855 	// "Depth writes are always disabled when depthTestEnable is VK_FALSE."
856 	return depthTestActive(attachments) && depthWriteEnable;
857 }
858 
depthTestActive(const Attachments & attachments) const859 bool FragmentState::depthTestActive(const Attachments &attachments) const
860 {
861 	return attachments.depthBuffer && depthTestEnable;
862 }
863 
stencilActive(const Attachments & attachments) const864 bool FragmentState::stencilActive(const Attachments &attachments) const
865 {
866 	return attachments.stencilBuffer && stencilEnable;
867 }
868 
depthBoundsTestActive(const Attachments & attachments) const869 bool FragmentState::depthBoundsTestActive(const Attachments &attachments) const
870 {
871 	return attachments.depthBuffer && depthBoundsTestEnable;
872 }
873 
setDepthStencilState(const VkPipelineDepthStencilStateCreateInfo * depthStencilState)874 void FragmentState::setDepthStencilState(const VkPipelineDepthStencilStateCreateInfo *depthStencilState)
875 {
876 	if((depthStencilState->flags &
877 	    ~(VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT |
878 	      VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT)) != 0)
879 	{
880 		UNSUPPORTED("depthStencilState->flags 0x%08X", int(depthStencilState->flags));
881 	}
882 
883 	depthBoundsTestEnable = (depthStencilState->depthBoundsTestEnable != VK_FALSE);
884 	minDepthBounds = depthStencilState->minDepthBounds;
885 	maxDepthBounds = depthStencilState->maxDepthBounds;
886 
887 	depthTestEnable = (depthStencilState->depthTestEnable != VK_FALSE);
888 	depthWriteEnable = (depthStencilState->depthWriteEnable != VK_FALSE);
889 	depthCompareMode = depthStencilState->depthCompareOp;
890 
891 	stencilEnable = (depthStencilState->stencilTestEnable != VK_FALSE);
892 	if(stencilEnable)
893 	{
894 		frontStencil = depthStencilState->front;
895 		backStencil = depthStencilState->back;
896 	}
897 }
898 
initialize(const VkPipelineColorBlendStateCreateInfo * colorBlendState,const VkPipelineMultisampleStateCreateInfo * multisampleState,const vk::RenderPass * renderPass,uint32_t subpassIndex,const VkPipelineRenderingCreateInfo * rendering,const DynamicStateFlags & allDynamicStateFlags)899 void FragmentOutputInterfaceState::initialize(const VkPipelineColorBlendStateCreateInfo *colorBlendState,
900                                               const VkPipelineMultisampleStateCreateInfo *multisampleState,
901                                               const vk::RenderPass *renderPass, uint32_t subpassIndex,
902                                               const VkPipelineRenderingCreateInfo *rendering,
903                                               const DynamicStateFlags &allDynamicStateFlags)
904 {
905 	dynamicStateFlags = allDynamicStateFlags.fragmentOutputInterface;
906 
907 	multisample.set(multisampleState);
908 
909 	if(renderPass)
910 	{
911 		const VkSubpassDescription &subpass = renderPass->getSubpass(subpassIndex);
912 
913 		// Ignore pColorBlendState when "the subpass of the render pass the pipeline
914 		// is created against does not use any color attachments"
915 		for(uint32_t i = 0; i < subpass.colorAttachmentCount; i++)
916 		{
917 			if(subpass.pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED)
918 			{
919 				setColorBlendState(colorBlendState);
920 				break;
921 			}
922 		}
923 	}
924 	else  // No render pass
925 	{
926 		// When a pipeline is created without a VkRenderPass, if the VkPipelineRenderingCreateInfo structure
927 		// is present in the pNext chain of VkGraphicsPipelineCreateInfo, it specifies the view mask and
928 		// format of attachments used for rendering. If this structure is not specified, and the pipeline
929 		// does not include a VkRenderPass, viewMask and colorAttachmentCount are 0, and
930 		// depthAttachmentFormat and stencilAttachmentFormat are VK_FORMAT_UNDEFINED. If a graphics pipeline
931 		// is created with a valid VkRenderPass, parameters of this structure are ignored.
932 
933 		if(rendering)
934 		{
935 			if(rendering->colorAttachmentCount > 0)
936 			{
937 				// If renderPass is VK_NULL_HANDLE, the pipeline is being created with fragment
938 				// output interface state, and VkPipelineRenderingCreateInfo::colorAttachmentCount
939 				// is not equal to 0, pColorBlendState must be a valid pointer to a valid
940 				// VkPipelineColorBlendStateCreateInfo structure
941 				ASSERT(colorBlendState);
942 
943 				setColorBlendState(colorBlendState);
944 			}
945 		}
946 	}
947 }
948 
applyState(const DynamicState & dynamicState)949 void FragmentOutputInterfaceState::applyState(const DynamicState &dynamicState)
950 {
951 	if(dynamicStateFlags.dynamicBlendConstants)
952 	{
953 		blendConstants = dynamicState.blendConstants;
954 	}
955 }
956 
setColorBlendState(const VkPipelineColorBlendStateCreateInfo * colorBlendState)957 void FragmentOutputInterfaceState::setColorBlendState(const VkPipelineColorBlendStateCreateInfo *colorBlendState)
958 {
959 	if(colorBlendState->flags != 0 &&
960 	   colorBlendState->flags != VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT)
961 	{
962 		UNSUPPORTED("colorBlendState->flags 0x%08X", int(colorBlendState->flags));
963 	}
964 
965 	if(colorBlendState->logicOpEnable != VK_FALSE)
966 	{
967 		UNSUPPORTED("VkPhysicalDeviceFeatures::logicOp");
968 	}
969 
970 	if(!dynamicStateFlags.dynamicBlendConstants)
971 	{
972 		blendConstants.x = colorBlendState->blendConstants[0];
973 		blendConstants.y = colorBlendState->blendConstants[1];
974 		blendConstants.z = colorBlendState->blendConstants[2];
975 		blendConstants.w = colorBlendState->blendConstants[3];
976 	}
977 
978 	const VkBaseInStructure *extensionColorBlendInfo = reinterpret_cast<const VkBaseInStructure *>(colorBlendState->pNext);
979 	while(extensionColorBlendInfo)
980 	{
981 		switch(extensionColorBlendInfo->sType)
982 		{
983 		case VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT:
984 			{
985 				const VkPipelineColorBlendAdvancedStateCreateInfoEXT *colorBlendAdvancedCreateInfo = reinterpret_cast<const VkPipelineColorBlendAdvancedStateCreateInfoEXT *>(extensionColorBlendInfo);
986 				ASSERT(colorBlendAdvancedCreateInfo->blendOverlap == VK_BLEND_OVERLAP_UNCORRELATED_EXT);
987 				ASSERT(colorBlendAdvancedCreateInfo->dstPremultiplied == VK_TRUE);
988 				ASSERT(colorBlendAdvancedCreateInfo->srcPremultiplied == VK_TRUE);
989 			}
990 			break;
991 		case VK_STRUCTURE_TYPE_MAX_ENUM:
992 			// dEQP tests that this value is ignored.
993 			break;
994 		default:
995 			UNSUPPORTED("colorBlendState->pNext sType = %s", vk::Stringify(extensionColorBlendInfo->sType).c_str());
996 			break;
997 		}
998 
999 		extensionColorBlendInfo = extensionColorBlendInfo->pNext;
1000 	}
1001 
1002 	ASSERT(colorBlendState->attachmentCount <= sw::MAX_COLOR_BUFFERS);
1003 	for(auto i = 0u; i < colorBlendState->attachmentCount; i++)
1004 	{
1005 		const VkPipelineColorBlendAttachmentState &attachment = colorBlendState->pAttachments[i];
1006 		colorWriteMask[i] = attachment.colorWriteMask;
1007 		blendState[i] = { (attachment.blendEnable != VK_FALSE),
1008 			              attachment.srcColorBlendFactor, attachment.dstColorBlendFactor, attachment.colorBlendOp,
1009 			              attachment.srcAlphaBlendFactor, attachment.dstAlphaBlendFactor, attachment.alphaBlendOp };
1010 	}
1011 }
1012 
getBlendState(int index,const Attachments & attachments,bool fragmentContainsKill) const1013 BlendState FragmentOutputInterfaceState::getBlendState(int index, const Attachments &attachments, bool fragmentContainsKill) const
1014 {
1015 	ASSERT((index >= 0) && (index < sw::MAX_COLOR_BUFFERS));
1016 	auto &state = blendState[index];
1017 
1018 	BlendState activeBlendState = {};
1019 	activeBlendState.alphaBlendEnable = alphaBlendActive(index, attachments, fragmentContainsKill);
1020 
1021 	if(activeBlendState.alphaBlendEnable)
1022 	{
1023 		vk::Format format = attachments.colorBuffer[index]->getFormat(VK_IMAGE_ASPECT_COLOR_BIT);
1024 
1025 		activeBlendState.sourceBlendFactor = blendFactor(state.blendOperation, state.sourceBlendFactor);
1026 		activeBlendState.destBlendFactor = blendFactor(state.blendOperation, state.destBlendFactor);
1027 		activeBlendState.blendOperation = blendOperation(state.blendOperation, state.sourceBlendFactor, state.destBlendFactor, format);
1028 		activeBlendState.sourceBlendFactorAlpha = blendFactor(state.blendOperationAlpha, state.sourceBlendFactorAlpha);
1029 		activeBlendState.destBlendFactorAlpha = blendFactor(state.blendOperationAlpha, state.destBlendFactorAlpha);
1030 		activeBlendState.blendOperationAlpha = blendOperation(state.blendOperationAlpha, state.sourceBlendFactorAlpha, state.destBlendFactorAlpha, format);
1031 	}
1032 
1033 	return activeBlendState;
1034 }
1035 
alphaBlendActive(int index,const Attachments & attachments,bool fragmentContainsKill) const1036 bool FragmentOutputInterfaceState::alphaBlendActive(int index, const Attachments &attachments, bool fragmentContainsKill) const
1037 {
1038 	ASSERT((index >= 0) && (index < sw::MAX_COLOR_BUFFERS));
1039 	auto &state = blendState[index];
1040 
1041 	if(!attachments.colorBuffer[index] || !blendState[index].alphaBlendEnable)
1042 	{
1043 		return false;
1044 	}
1045 
1046 	if(!(colorWriteActive(attachments) || fragmentContainsKill))
1047 	{
1048 		return false;
1049 	}
1050 
1051 	vk::Format format = attachments.colorBuffer[index]->getFormat(VK_IMAGE_ASPECT_COLOR_BIT);
1052 	bool colorBlend = blendOperation(state.blendOperation, state.sourceBlendFactor, state.destBlendFactor, format) != VK_BLEND_OP_SRC_EXT;
1053 	bool alphaBlend = blendOperation(state.blendOperationAlpha, state.sourceBlendFactorAlpha, state.destBlendFactorAlpha, format) != VK_BLEND_OP_SRC_EXT;
1054 
1055 	return colorBlend || alphaBlend;
1056 }
1057 
blendFactor(VkBlendOp blendOperation,VkBlendFactor blendFactor) const1058 VkBlendFactor FragmentOutputInterfaceState::blendFactor(VkBlendOp blendOperation, VkBlendFactor blendFactor) const
1059 {
1060 	switch(blendOperation)
1061 	{
1062 	case VK_BLEND_OP_ADD:
1063 	case VK_BLEND_OP_SUBTRACT:
1064 	case VK_BLEND_OP_REVERSE_SUBTRACT:
1065 		return blendFactor;
1066 	case VK_BLEND_OP_MIN:
1067 	case VK_BLEND_OP_MAX:
1068 	case VK_BLEND_OP_MULTIPLY_EXT:
1069 	case VK_BLEND_OP_SCREEN_EXT:
1070 	case VK_BLEND_OP_OVERLAY_EXT:
1071 	case VK_BLEND_OP_DARKEN_EXT:
1072 	case VK_BLEND_OP_LIGHTEN_EXT:
1073 	case VK_BLEND_OP_COLORDODGE_EXT:
1074 	case VK_BLEND_OP_COLORBURN_EXT:
1075 	case VK_BLEND_OP_HARDLIGHT_EXT:
1076 	case VK_BLEND_OP_SOFTLIGHT_EXT:
1077 	case VK_BLEND_OP_DIFFERENCE_EXT:
1078 	case VK_BLEND_OP_EXCLUSION_EXT:
1079 	case VK_BLEND_OP_HSL_HUE_EXT:
1080 	case VK_BLEND_OP_HSL_SATURATION_EXT:
1081 	case VK_BLEND_OP_HSL_COLOR_EXT:
1082 	case VK_BLEND_OP_HSL_LUMINOSITY_EXT:
1083 		return VK_BLEND_FACTOR_ONE;
1084 	default:
1085 		ASSERT(false);
1086 		return blendFactor;
1087 	}
1088 }
1089 
blendOperation(VkBlendOp blendOperation,VkBlendFactor sourceBlendFactor,VkBlendFactor destBlendFactor,vk::Format format) const1090 VkBlendOp FragmentOutputInterfaceState::blendOperation(VkBlendOp blendOperation, VkBlendFactor sourceBlendFactor, VkBlendFactor destBlendFactor, vk::Format format) const
1091 {
1092 	switch(blendOperation)
1093 	{
1094 	case VK_BLEND_OP_ADD:
1095 		if(sourceBlendFactor == VK_BLEND_FACTOR_ZERO)
1096 		{
1097 			if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
1098 			{
1099 				return VK_BLEND_OP_ZERO_EXT;
1100 			}
1101 			else if(destBlendFactor == VK_BLEND_FACTOR_ONE)
1102 			{
1103 				return VK_BLEND_OP_DST_EXT;
1104 			}
1105 		}
1106 		else if(sourceBlendFactor == VK_BLEND_FACTOR_ONE)
1107 		{
1108 			if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
1109 			{
1110 				return VK_BLEND_OP_SRC_EXT;
1111 			}
1112 		}
1113 		break;
1114 	case VK_BLEND_OP_SUBTRACT:
1115 		if(sourceBlendFactor == VK_BLEND_FACTOR_ZERO)
1116 		{
1117 			if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
1118 			{
1119 				return VK_BLEND_OP_ZERO_EXT;
1120 			}
1121 			else if(format.isUnsignedNormalized())
1122 			{
1123 				return VK_BLEND_OP_ZERO_EXT;  // Negative, clamped to zero
1124 			}
1125 		}
1126 		else if(sourceBlendFactor == VK_BLEND_FACTOR_ONE)
1127 		{
1128 			if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
1129 			{
1130 				return VK_BLEND_OP_SRC_EXT;
1131 			}
1132 		}
1133 		break;
1134 	case VK_BLEND_OP_REVERSE_SUBTRACT:
1135 		if(sourceBlendFactor == VK_BLEND_FACTOR_ZERO)
1136 		{
1137 			if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
1138 			{
1139 				return VK_BLEND_OP_ZERO_EXT;
1140 			}
1141 			else if(destBlendFactor == VK_BLEND_FACTOR_ONE)
1142 			{
1143 				return VK_BLEND_OP_DST_EXT;
1144 			}
1145 		}
1146 		else
1147 		{
1148 			if(destBlendFactor == VK_BLEND_FACTOR_ZERO && format.isUnsignedNormalized())
1149 			{
1150 				return VK_BLEND_OP_ZERO_EXT;  // Negative, clamped to zero
1151 			}
1152 		}
1153 		break;
1154 	case VK_BLEND_OP_MIN:
1155 		return VK_BLEND_OP_MIN;
1156 	case VK_BLEND_OP_MAX:
1157 		return VK_BLEND_OP_MAX;
1158 	case VK_BLEND_OP_MULTIPLY_EXT:
1159 	case VK_BLEND_OP_SCREEN_EXT:
1160 	case VK_BLEND_OP_OVERLAY_EXT:
1161 	case VK_BLEND_OP_DARKEN_EXT:
1162 	case VK_BLEND_OP_LIGHTEN_EXT:
1163 	case VK_BLEND_OP_COLORDODGE_EXT:
1164 	case VK_BLEND_OP_COLORBURN_EXT:
1165 	case VK_BLEND_OP_HARDLIGHT_EXT:
1166 	case VK_BLEND_OP_SOFTLIGHT_EXT:
1167 	case VK_BLEND_OP_DIFFERENCE_EXT:
1168 	case VK_BLEND_OP_EXCLUSION_EXT:
1169 	case VK_BLEND_OP_HSL_HUE_EXT:
1170 	case VK_BLEND_OP_HSL_SATURATION_EXT:
1171 	case VK_BLEND_OP_HSL_COLOR_EXT:
1172 	case VK_BLEND_OP_HSL_LUMINOSITY_EXT:
1173 		return blendOperation;
1174 	default:
1175 		ASSERT(false);
1176 	}
1177 
1178 	return blendOperation;
1179 }
1180 
colorWriteActive(const Attachments & attachments) const1181 bool FragmentOutputInterfaceState::colorWriteActive(const Attachments &attachments) const
1182 {
1183 	for(int i = 0; i < sw::MAX_COLOR_BUFFERS; i++)
1184 	{
1185 		if(colorWriteActive(i, attachments))
1186 		{
1187 			return true;
1188 		}
1189 	}
1190 
1191 	return false;
1192 }
1193 
colorWriteActive(int index,const Attachments & attachments) const1194 int FragmentOutputInterfaceState::colorWriteActive(int index, const Attachments &attachments) const
1195 {
1196 	ASSERT((index >= 0) && (index < sw::MAX_COLOR_BUFFERS));
1197 	auto &state = blendState[index];
1198 
1199 	if(!attachments.colorBuffer[index] || attachments.colorBuffer[index]->getFormat() == VK_FORMAT_UNDEFINED)
1200 	{
1201 		return 0;
1202 	}
1203 
1204 	vk::Format format = attachments.colorBuffer[index]->getFormat(VK_IMAGE_ASPECT_COLOR_BIT);
1205 
1206 	if(blendOperation(state.blendOperation, state.sourceBlendFactor, state.destBlendFactor, format) == VK_BLEND_OP_DST_EXT &&
1207 	   blendOperation(state.blendOperationAlpha, state.sourceBlendFactorAlpha, state.destBlendFactorAlpha, format) == VK_BLEND_OP_DST_EXT)
1208 	{
1209 		return 0;
1210 	}
1211 
1212 	return colorWriteMask[index];
1213 }
1214 
GraphicsState(const Device * device,const VkGraphicsPipelineCreateInfo * pCreateInfo,const PipelineLayout * layout)1215 GraphicsState::GraphicsState(const Device *device, const VkGraphicsPipelineCreateInfo *pCreateInfo,
1216                              const PipelineLayout *layout)
1217 {
1218 	if((pCreateInfo->flags &
1219 	    ~(VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT |
1220 	      VK_PIPELINE_CREATE_DERIVATIVE_BIT |
1221 	      VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT |
1222 	      VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT |
1223 	      VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT |
1224 	      VK_PIPELINE_CREATE_LIBRARY_BIT_KHR |
1225 	      VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT |
1226 	      VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT)) != 0)
1227 	{
1228 		UNSUPPORTED("pCreateInfo->flags 0x%08X", int(pCreateInfo->flags));
1229 	}
1230 
1231 	DynamicStateFlags dynamicStateFlags = ParseDynamicStateFlags(pCreateInfo->pDynamicState);
1232 	const auto *rendering = GetExtendedStruct<VkPipelineRenderingCreateInfo>(pCreateInfo, VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO);
1233 
1234 	// First, get the subset of state specified in pCreateInfo itself.
1235 	validSubset = GraphicsPipeline::GetGraphicsPipelineSubset(pCreateInfo);
1236 
1237 	// If rasterizer discard is enabled (and not dynamically overridable), ignore the fragment
1238 	// and fragment output subsets, as they will not be used.
1239 	if((validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) != 0 &&
1240 	   pCreateInfo->pRasterizationState->rasterizerDiscardEnable &&
1241 	   !dynamicStateFlags.preRasterization.dynamicRasterizerDiscardEnable)
1242 	{
1243 		validSubset &= ~(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT | VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT);
1244 	}
1245 
1246 	if((validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT) != 0)
1247 	{
1248 		vertexInputInterfaceState.initialize(pCreateInfo->pVertexInputState,
1249 		                                     pCreateInfo->pInputAssemblyState,
1250 		                                     dynamicStateFlags);
1251 	}
1252 	if((validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) != 0)
1253 	{
1254 		preRasterizationState.initialize(device,
1255 		                                 layout,
1256 		                                 pCreateInfo->pViewportState,
1257 		                                 pCreateInfo->pRasterizationState,
1258 		                                 vk::Cast(pCreateInfo->renderPass),
1259 		                                 pCreateInfo->subpass,
1260 		                                 rendering,
1261 		                                 dynamicStateFlags);
1262 	}
1263 	if((validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) != 0)
1264 	{
1265 		fragmentState.initialize(layout,
1266 		                         pCreateInfo->pDepthStencilState,
1267 		                         vk::Cast(pCreateInfo->renderPass),
1268 		                         pCreateInfo->subpass,
1269 		                         rendering,
1270 		                         dynamicStateFlags);
1271 	}
1272 	if((validSubset & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT) != 0)
1273 	{
1274 		fragmentOutputInterfaceState.initialize(pCreateInfo->pColorBlendState,
1275 		                                        pCreateInfo->pMultisampleState,
1276 		                                        vk::Cast(pCreateInfo->renderPass),
1277 		                                        pCreateInfo->subpass,
1278 		                                        rendering,
1279 		                                        dynamicStateFlags);
1280 	}
1281 
1282 	// Then, apply state coming from pipeline libraries.
1283 	const auto *libraryCreateInfo = vk::GetExtendedStruct<VkPipelineLibraryCreateInfoKHR>(pCreateInfo->pNext, VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR);
1284 	if(libraryCreateInfo)
1285 	{
1286 		for(uint32_t i = 0; i < libraryCreateInfo->libraryCount; ++i)
1287 		{
1288 			const auto *library = static_cast<const GraphicsPipeline *>(vk::Cast(libraryCreateInfo->pLibraries[i]));
1289 			const GraphicsState &libraryState = library->getState();
1290 			const VkGraphicsPipelineLibraryFlagsEXT librarySubset = libraryState.validSubset;
1291 
1292 			// The library subsets should be disjoint
1293 			ASSERT((libraryState.validSubset & validSubset) == 0);
1294 
1295 			if((librarySubset & VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT) != 0)
1296 			{
1297 				vertexInputInterfaceState = libraryState.vertexInputInterfaceState;
1298 			}
1299 			if((librarySubset & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) != 0)
1300 			{
1301 				preRasterizationState = libraryState.preRasterizationState;
1302 				if(layout)
1303 				{
1304 					preRasterizationState.overridePipelineLayout(layout);
1305 				}
1306 			}
1307 			if((librarySubset & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) != 0)
1308 			{
1309 				fragmentState = libraryState.fragmentState;
1310 				if(layout)
1311 				{
1312 					fragmentState.overridePipelineLayout(layout);
1313 				}
1314 			}
1315 			if((librarySubset & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT) != 0)
1316 			{
1317 				fragmentOutputInterfaceState = libraryState.fragmentOutputInterfaceState;
1318 			}
1319 
1320 			validSubset |= libraryState.validSubset;
1321 		}
1322 	}
1323 }
1324 
combineStates(const DynamicState & dynamicState) const1325 GraphicsState GraphicsState::combineStates(const DynamicState &dynamicState) const
1326 {
1327 	GraphicsState combinedState = *this;
1328 
1329 	// Make a copy of the states for modification, then either keep the pipeline state or apply the dynamic state.
1330 	combinedState.vertexInputInterfaceState.applyState(dynamicState);
1331 	combinedState.preRasterizationState.applyState(dynamicState);
1332 	combinedState.fragmentState.applyState(dynamicState);
1333 	combinedState.fragmentOutputInterfaceState.applyState(dynamicState);
1334 
1335 	return combinedState;
1336 }
1337 
1338 }  // namespace vk
1339