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