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