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