// Copyright 2020 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "Context.hpp"

#include "Vulkan/VkBuffer.hpp"
#include "Vulkan/VkDevice.hpp"
#include "Vulkan/VkImageView.hpp"
#include "Vulkan/VkRenderPass.hpp"
#include "Vulkan/VkStringify.hpp"

namespace {

uint32_t ComputePrimitiveCount(VkPrimitiveTopology topology, uint32_t vertexCount)
{
	switch(topology)
	{
	case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
		return vertexCount;
	case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
		return vertexCount / 2;
	case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
		return std::max<uint32_t>(vertexCount, 1) - 1;
	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
		return vertexCount / 3;
	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
		return std::max<uint32_t>(vertexCount, 2) - 2;
	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
		return std::max<uint32_t>(vertexCount, 2) - 2;
	default:
		UNSUPPORTED("VkPrimitiveTopology %d", int(topology));
	}

	return 0;
}

template<typename T>
void ProcessPrimitiveRestart(T *indexBuffer,
                             VkPrimitiveTopology topology,
                             uint32_t count,
                             std::vector<std::pair<uint32_t, void *>> *indexBuffers)
{
	static const T RestartIndex = static_cast<T>(-1);
	T *indexBufferStart = indexBuffer;
	uint32_t vertexCount = 0;
	for(uint32_t i = 0; i < count; i++)
	{
		if(indexBuffer[i] == RestartIndex)
		{
			// Record previous segment
			if(vertexCount > 0)
			{
				uint32_t primitiveCount = ComputePrimitiveCount(topology, vertexCount);
				if(primitiveCount > 0)
				{
					indexBuffers->push_back({ primitiveCount, indexBufferStart });
				}
			}
			vertexCount = 0;
		}
		else
		{
			if(vertexCount == 0)
			{
				indexBufferStart = indexBuffer + i;
			}
			vertexCount++;
		}
	}

	// Record last segment
	if(vertexCount > 0)
	{
		uint32_t primitiveCount = ComputePrimitiveCount(topology, vertexCount);
		if(primitiveCount > 0)
		{
			indexBuffers->push_back({ primitiveCount, indexBufferStart });
		}
	}
}

vk::DynamicStateFlags ParseDynamicStateFlags(const VkPipelineDynamicStateCreateInfo *dynamicStateCreateInfo)
{
	vk::DynamicStateFlags dynamicStateFlags = {};

	if(dynamicStateCreateInfo == nullptr)
	{
		return dynamicStateFlags;
	}

	if(dynamicStateCreateInfo->flags != 0)
	{
		// Vulkan 1.3: "flags is reserved for future use." "flags must be 0"
		UNSUPPORTED("dynamicStateCreateInfo->flags 0x%08X", int(dynamicStateCreateInfo->flags));
	}

	for(uint32_t i = 0; i < dynamicStateCreateInfo->dynamicStateCount; i++)
	{
		VkDynamicState dynamicState = dynamicStateCreateInfo->pDynamicStates[i];
		switch(dynamicState)
		{
		// Vertex input interface:
		case VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE:
			dynamicStateFlags.vertexInputInterface.dynamicPrimitiveRestartEnable = true;
			break;
		case VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY:
			dynamicStateFlags.vertexInputInterface.dynamicPrimitiveTopology = true;
			break;
		case VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE:
			dynamicStateFlags.vertexInputInterface.dynamicVertexInputBindingStride = true;
			break;

		// Pre-rasterization:
		case VK_DYNAMIC_STATE_LINE_WIDTH:
			dynamicStateFlags.preRasterization.dynamicLineWidth = true;
			break;
		case VK_DYNAMIC_STATE_DEPTH_BIAS:
			dynamicStateFlags.preRasterization.dynamicDepthBias = true;
			break;
		case VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE:
			dynamicStateFlags.preRasterization.dynamicDepthBiasEnable = true;
			break;
		case VK_DYNAMIC_STATE_CULL_MODE:
			dynamicStateFlags.preRasterization.dynamicCullMode = true;
			break;
		case VK_DYNAMIC_STATE_FRONT_FACE:
			dynamicStateFlags.preRasterization.dynamicFrontFace = true;
			break;
		case VK_DYNAMIC_STATE_VIEWPORT:
			dynamicStateFlags.preRasterization.dynamicViewport = true;
			break;
		case VK_DYNAMIC_STATE_SCISSOR:
			dynamicStateFlags.preRasterization.dynamicScissor = true;
			break;
		case VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT:
			dynamicStateFlags.preRasterization.dynamicViewportWithCount = true;
			break;
		case VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT:
			dynamicStateFlags.preRasterization.dynamicScissorWithCount = true;
			break;
		case VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE:
			dynamicStateFlags.preRasterization.dynamicRasterizerDiscardEnable = true;
			break;

		// Fragment:
		case VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE:
			dynamicStateFlags.fragment.dynamicDepthTestEnable = true;
			break;
		case VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE:
			dynamicStateFlags.fragment.dynamicDepthWriteEnable = true;
			break;
		case VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE:
			dynamicStateFlags.fragment.dynamicDepthBoundsTestEnable = true;
			break;
		case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
			dynamicStateFlags.fragment.dynamicDepthBounds = true;
			break;
		case VK_DYNAMIC_STATE_DEPTH_COMPARE_OP:
			dynamicStateFlags.fragment.dynamicDepthCompareOp = true;
			break;
		case VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE:
			dynamicStateFlags.fragment.dynamicStencilTestEnable = true;
			break;
		case VK_DYNAMIC_STATE_STENCIL_OP:
			dynamicStateFlags.fragment.dynamicStencilOp = true;
			break;
		case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
			dynamicStateFlags.fragment.dynamicStencilCompareMask = true;
			break;
		case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
			dynamicStateFlags.fragment.dynamicStencilWriteMask = true;
			break;
		case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
			dynamicStateFlags.fragment.dynamicStencilReference = true;
			break;

		// Fragment output interface:
		case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
			dynamicStateFlags.fragmentOutputInterface.dynamicBlendConstants = true;
			break;

		default:
			UNSUPPORTED("VkDynamicState %d", int(dynamicState));
		}
	}

	return dynamicStateFlags;
}

}  // namespace

namespace vk {

int IndexBuffer::bytesPerIndex() const
{
	return indexType == VK_INDEX_TYPE_UINT16 ? 2 : 4;
}

void IndexBuffer::setIndexBufferBinding(const VertexInputBinding &indexBufferBinding, VkIndexType type)
{
	binding = indexBufferBinding;
	indexType = type;
}

void IndexBuffer::getIndexBuffers(VkPrimitiveTopology topology, uint32_t count, uint32_t first, bool indexed, bool hasPrimitiveRestartEnable, std::vector<std::pair<uint32_t, void *>> *indexBuffers) const
{
	if(indexed)
	{
		void *indexBuffer = binding.buffer->getOffsetPointer(binding.offset + first * bytesPerIndex());
		if(hasPrimitiveRestartEnable)
		{
			switch(indexType)
			{
			case VK_INDEX_TYPE_UINT16:
				ProcessPrimitiveRestart(static_cast<uint16_t *>(indexBuffer), topology, count, indexBuffers);
				break;
			case VK_INDEX_TYPE_UINT32:
				ProcessPrimitiveRestart(static_cast<uint32_t *>(indexBuffer), topology, count, indexBuffers);
				break;
			default:
				UNSUPPORTED("VkIndexType %d", int(indexType));
			}
		}
		else
		{
			indexBuffers->push_back({ ComputePrimitiveCount(topology, count), indexBuffer });
		}
	}
	else
	{
		indexBuffers->push_back({ ComputePrimitiveCount(topology, count), nullptr });
	}
}

VkFormat Attachments::colorFormat(int index) const
{
	ASSERT((index >= 0) && (index < sw::MAX_COLOR_BUFFERS));

	if(colorBuffer[index])
	{
		return colorBuffer[index]->getFormat();
	}
	else
	{
		return VK_FORMAT_UNDEFINED;
	}
}

VkFormat Attachments::depthFormat() const
{
	if(depthBuffer)
	{
		return depthBuffer->getFormat();
	}
	else
	{
		return VK_FORMAT_UNDEFINED;
	}
}

Inputs::Inputs(const VkPipelineVertexInputStateCreateInfo *vertexInputState)
{
	if(vertexInputState->flags != 0)
	{
		// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
		UNSUPPORTED("vertexInputState->flags");
	}

	// Temporary in-binding-order representation of buffer strides, to be consumed below
	// when considering attributes. TODO: unfuse buffers from attributes in backend, is old GL model.
	uint32_t vertexStrides[MAX_VERTEX_INPUT_BINDINGS];
	uint32_t instanceStrides[MAX_VERTEX_INPUT_BINDINGS];
	VkVertexInputRate inputRates[MAX_VERTEX_INPUT_BINDINGS];
	for(uint32_t i = 0; i < vertexInputState->vertexBindingDescriptionCount; i++)
	{
		auto const &desc = vertexInputState->pVertexBindingDescriptions[i];
		inputRates[desc.binding] = desc.inputRate;
		vertexStrides[desc.binding] = desc.inputRate == VK_VERTEX_INPUT_RATE_VERTEX ? desc.stride : 0;
		instanceStrides[desc.binding] = desc.inputRate == VK_VERTEX_INPUT_RATE_INSTANCE ? desc.stride : 0;
	}

	for(uint32_t i = 0; i < vertexInputState->vertexAttributeDescriptionCount; i++)
	{
		auto const &desc = vertexInputState->pVertexAttributeDescriptions[i];
		sw::Stream &input = stream[desc.location];
		input.format = desc.format;
		input.offset = desc.offset;
		input.binding = desc.binding;
		input.inputRate = inputRates[desc.binding];
		input.vertexStride = vertexStrides[desc.binding];
		input.instanceStride = instanceStrides[desc.binding];
	}
}

void Inputs::updateDescriptorSets(const DescriptorSet::Array &dso,
                                  const DescriptorSet::Bindings &ds,
                                  const DescriptorSet::DynamicOffsets &ddo)
{
	descriptorSetObjects = dso;
	descriptorSets = ds;
	descriptorDynamicOffsets = ddo;
}

void Inputs::bindVertexInputs(int firstInstance, bool dynamicInstanceStride)
{
	for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; i++)
	{
		auto &attrib = stream[i];
		if(attrib.format != VK_FORMAT_UNDEFINED)
		{
			const auto &vertexInput = vertexInputBindings[attrib.binding];
			VkDeviceSize offset = attrib.offset + vertexInput.offset +
			                      getInstanceStride(i, dynamicInstanceStride) * firstInstance;
			attrib.buffer = vertexInput.buffer ? vertexInput.buffer->getOffsetPointer(offset) : nullptr;

			VkDeviceSize size = vertexInput.buffer ? vertexInput.buffer->getSize() : 0;
			attrib.robustnessSize = (size > offset) ? size - offset : 0;
		}
	}
}

void Inputs::setVertexInputBinding(const VertexInputBinding bindings[])
{
	for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; ++i)
	{
		vertexInputBindings[i] = bindings[i];
	}
}

// TODO(b/137740918): Optimize instancing to use a single draw call.
void Inputs::advanceInstanceAttributes(bool dynamicInstanceStride)
{
	for(uint32_t i = 0; i < vk::MAX_VERTEX_INPUT_BINDINGS; i++)
	{
		auto &attrib = stream[i];

		VkDeviceSize instanceStride = getInstanceStride(i, dynamicInstanceStride);
		if((attrib.format != VK_FORMAT_UNDEFINED) && instanceStride && (instanceStride < attrib.robustnessSize))
		{
			// Under the casts: attrib.buffer += instanceStride
			attrib.buffer = (void const *)((uintptr_t)attrib.buffer + instanceStride);
			attrib.robustnessSize -= instanceStride;
		}
	}
}

VkDeviceSize Inputs::getVertexStride(uint32_t i, bool dynamicVertexStride) const
{
	auto &attrib = stream[i];
	if(attrib.format != VK_FORMAT_UNDEFINED && attrib.inputRate == VK_VERTEX_INPUT_RATE_VERTEX)
	{
		if(dynamicVertexStride)
		{
			return vertexInputBindings[attrib.binding].stride;
		}
		else
		{
			return attrib.vertexStride;
		}
	}

	return 0;
}

VkDeviceSize Inputs::getInstanceStride(uint32_t i, bool dynamicInstanceStride) const
{
	auto &attrib = stream[i];
	if(attrib.format != VK_FORMAT_UNDEFINED && attrib.inputRate == VK_VERTEX_INPUT_RATE_INSTANCE)
	{
		if(dynamicInstanceStride)
		{
			return vertexInputBindings[attrib.binding].stride;
		}
		else
		{
			return attrib.instanceStride;
		}
	}

	return 0;
}

void MultisampleState::set(const VkPipelineMultisampleStateCreateInfo *multisampleState)
{
	if(multisampleState->flags != 0)
	{
		// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
		UNSUPPORTED("pCreateInfo->pMultisampleState->flags 0x%08X", int(multisampleState->flags));
	}

	sampleShadingEnable = (multisampleState->sampleShadingEnable != VK_FALSE);
	if(sampleShadingEnable)
	{
		minSampleShading = multisampleState->minSampleShading;
	}

	if(multisampleState->alphaToOneEnable != VK_FALSE)
	{
		UNSUPPORTED("VkPhysicalDeviceFeatures::alphaToOne");
	}

	switch(multisampleState->rasterizationSamples)
	{
	case VK_SAMPLE_COUNT_1_BIT:
		sampleCount = 1;
		break;
	case VK_SAMPLE_COUNT_4_BIT:
		sampleCount = 4;
		break;
	default:
		UNSUPPORTED("Unsupported sample count");
	}

	VkSampleMask sampleMask;
	if(multisampleState->pSampleMask)
	{
		sampleMask = multisampleState->pSampleMask[0];
	}
	else  // "If pSampleMask is NULL, it is treated as if the mask has all bits set to 1."
	{
		sampleMask = ~0;
	}

	alphaToCoverage = (multisampleState->alphaToCoverageEnable != VK_FALSE);
	multiSampleMask = sampleMask & ((unsigned)0xFFFFFFFF >> (32 - sampleCount));
}

void VertexInputInterfaceState::initialize(const VkPipelineVertexInputStateCreateInfo *vertexInputState,
                                           const VkPipelineInputAssemblyStateCreateInfo *inputAssemblyState,
                                           const DynamicStateFlags &allDynamicStateFlags)
{
	dynamicStateFlags = allDynamicStateFlags.vertexInputInterface;

	if(vertexInputState->flags != 0)
	{
		// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
		UNSUPPORTED("vertexInputState->flags");
	}

	if(inputAssemblyState->flags != 0)
	{
		// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
		UNSUPPORTED("pCreateInfo->pInputAssemblyState->flags 0x%08X", int(inputAssemblyState->flags));
	}

	primitiveRestartEnable = (inputAssemblyState->primitiveRestartEnable != VK_FALSE);
	topology = inputAssemblyState->topology;
}

void VertexInputInterfaceState::applyState(const DynamicState &dynamicState)
{
	if(dynamicStateFlags.dynamicPrimitiveRestartEnable)
	{
		primitiveRestartEnable = dynamicState.primitiveRestartEnable;
	}

	if(dynamicStateFlags.dynamicPrimitiveTopology)
	{
		topology = dynamicState.primitiveTopology;
	}
}

bool VertexInputInterfaceState::isDrawPoint(bool polygonModeAware, VkPolygonMode polygonMode) const
{
	switch(topology)
	{
	case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
		return true;
	case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
	case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
		return false;
	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
		return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_POINT) : false;
	default:
		UNSUPPORTED("topology %d", int(topology));
	}
	return false;
}

bool VertexInputInterfaceState::isDrawLine(bool polygonModeAware, VkPolygonMode polygonMode) const
{
	switch(topology)
	{
	case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
		return false;
	case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
	case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
		return true;
	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
		return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_LINE) : false;
	default:
		UNSUPPORTED("topology %d", int(topology));
	}
	return false;
}

bool VertexInputInterfaceState::isDrawTriangle(bool polygonModeAware, VkPolygonMode polygonMode) const
{
	switch(topology)
	{
	case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
	case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
	case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
		return false;
	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
	case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
		return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_FILL) : true;
	default:
		UNSUPPORTED("topology %d", int(topology));
	}
	return false;
}

void PreRasterizationState::initialize(const vk::Device *device,
                                       const VkPipelineViewportStateCreateInfo *viewportState,
                                       const VkPipelineRasterizationStateCreateInfo *rasterizationState,
                                       const vk::RenderPass *renderPass, uint32_t subpassIndex,
                                       const VkPipelineRenderingCreateInfo *rendering,
                                       const DynamicStateFlags &allDynamicStateFlags)
{
	dynamicStateFlags = allDynamicStateFlags.preRasterization;

	if(rasterizationState->flags != 0)
	{
		// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
		UNSUPPORTED("pCreateInfo->pRasterizationState->flags 0x%08X", int(rasterizationState->flags));
	}

	rasterizerDiscard = rasterizationState->rasterizerDiscardEnable != VK_FALSE;
	cullMode = rasterizationState->cullMode;
	frontFace = rasterizationState->frontFace;
	polygonMode = rasterizationState->polygonMode;
	depthBiasEnable = rasterizationState->depthBiasEnable;
	constantDepthBias = rasterizationState->depthBiasConstantFactor;
	slopeDepthBias = rasterizationState->depthBiasSlopeFactor;
	depthBiasClamp = rasterizationState->depthBiasClamp;
	depthRangeUnrestricted = device->hasExtension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME);
	depthClampEnable = rasterizationState->depthClampEnable != VK_FALSE;
	depthClipEnable = !depthClampEnable;

	// From the Vulkan spec for vkCmdSetDepthBias:
	//    The bias value O for a polygon is:
	//        O = dbclamp(...)
	//    where dbclamp(x) =
	//        * x                       depthBiasClamp = 0 or NaN
	//        * min(x, depthBiasClamp)  depthBiasClamp > 0
	//        * max(x, depthBiasClamp)  depthBiasClamp < 0
	// So it should be safe to resolve NaNs to 0.0f.
	if(std::isnan(depthBiasClamp))
	{
		depthBiasClamp = 0.0f;
	}

	if(!dynamicStateFlags.dynamicLineWidth)
	{
		lineWidth = rasterizationState->lineWidth;
	}

	const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(rasterizationState->pNext);
	while(extensionCreateInfo)
	{
		switch(extensionCreateInfo->sType)
		{
		case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT:
			{
				const VkPipelineRasterizationLineStateCreateInfoEXT *lineStateCreateInfo = reinterpret_cast<const VkPipelineRasterizationLineStateCreateInfoEXT *>(extensionCreateInfo);
				lineRasterizationMode = lineStateCreateInfo->lineRasterizationMode;
			}
			break;
		case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT:
			{
				const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *provokingVertexModeCreateInfo =
				    reinterpret_cast<const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *>(extensionCreateInfo);
				provokingVertexMode = provokingVertexModeCreateInfo->provokingVertexMode;
			}
			break;
		case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT:
			{
				const auto *depthClipInfo = reinterpret_cast<const VkPipelineRasterizationDepthClipStateCreateInfoEXT *>(extensionCreateInfo);
				// Reserved for future use.
				ASSERT(depthClipInfo->flags == 0);
				depthClipEnable = depthClipInfo->depthClipEnable != VK_FALSE;
			}
			break;
		case VK_STRUCTURE_TYPE_APPLICATION_INFO:
			// SwiftShader doesn't interact with application info, but dEQP includes it
			break;
		case VK_STRUCTURE_TYPE_MAX_ENUM:
			// dEQP tests that this value is ignored.
			break;
		default:
			UNSUPPORTED("pCreateInfo->pRasterizationState->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str());
			break;
		}

		extensionCreateInfo = extensionCreateInfo->pNext;
	}

	if(!rasterizerDiscard || dynamicStateFlags.dynamicRasterizerDiscardEnable)
	{
		extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(viewportState->pNext);
		while(extensionCreateInfo != nullptr)
		{
			switch(extensionCreateInfo->sType)
			{
			case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT:
				{
					const auto *depthClipControl = reinterpret_cast<const VkPipelineViewportDepthClipControlCreateInfoEXT *>(extensionCreateInfo);
					depthClipNegativeOneToOne = depthClipControl->negativeOneToOne != VK_FALSE;
				}
				break;
			case VK_STRUCTURE_TYPE_MAX_ENUM:
				// dEQP passes this value expecting the driver to ignore it.
				break;
			default:
				UNSUPPORTED("pCreateInfo->pViewportState->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str());
				break;
			}
			extensionCreateInfo = extensionCreateInfo->pNext;
		}

		if(viewportState->flags != 0)
		{
			// Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
			UNSUPPORTED("pCreateInfo->pViewportState->flags 0x%08X", int(viewportState->flags));
		}

		if((viewportState->viewportCount > 1) ||
		   (viewportState->scissorCount > 1))
		{
			UNSUPPORTED("VkPhysicalDeviceFeatures::multiViewport");
		}

		if(!dynamicStateFlags.dynamicScissor && !dynamicStateFlags.dynamicScissorWithCount)
		{
			scissor = viewportState->pScissors[0];
		}

		if(!dynamicStateFlags.dynamicViewport && !dynamicStateFlags.dynamicViewportWithCount)
		{
			viewport = viewportState->pViewports[0];
		}
	}
}

void PreRasterizationState::applyState(const DynamicState &dynamicState)
{
	if(dynamicStateFlags.dynamicLineWidth)
	{
		lineWidth = dynamicState.lineWidth;
	}

	if(dynamicStateFlags.dynamicDepthBias)
	{
		constantDepthBias = dynamicState.depthBiasConstantFactor;
		slopeDepthBias = dynamicState.depthBiasSlopeFactor;
		depthBiasClamp = dynamicState.depthBiasClamp;
	}

	if(dynamicStateFlags.dynamicDepthBiasEnable)
	{
		depthBiasEnable = dynamicState.depthBiasEnable;
	}

	if(dynamicStateFlags.dynamicCullMode)
	{
		cullMode = dynamicState.cullMode;
	}

	if(dynamicStateFlags.dynamicFrontFace)
	{
		frontFace = dynamicState.frontFace;
	}

	if(dynamicStateFlags.dynamicViewport)
	{
		viewport = dynamicState.viewport;
	}

	if(dynamicStateFlags.dynamicScissor)
	{
		scissor = dynamicState.scissor;
	}

	if(dynamicStateFlags.dynamicViewportWithCount && dynamicState.viewportCount > 0)
	{
		viewport.width = static_cast<float>(dynamicState.viewports[0].extent.width);
		viewport.height = static_cast<float>(dynamicState.viewports[0].extent.height);
		viewport.x = static_cast<float>(dynamicState.viewports[0].offset.x);
		viewport.y = static_cast<float>(dynamicState.viewports[0].offset.y);
	}

	if(dynamicStateFlags.dynamicScissorWithCount && dynamicState.scissorCount > 0)
	{
		scissor = dynamicState.scissors[0];
	}

	if(dynamicStateFlags.dynamicRasterizerDiscardEnable)
	{
		rasterizerDiscard = dynamicState.rasterizerDiscardEnable;
	}
}

void FragmentState::initialize(const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
                               const vk::RenderPass *renderPass, uint32_t subpassIndex,
                               const VkPipelineRenderingCreateInfo *rendering,
                               const DynamicStateFlags &allDynamicStateFlags)
{
	dynamicStateFlags = allDynamicStateFlags.fragment;

	if(renderPass)
	{
		const VkSubpassDescription &subpass = renderPass->getSubpass(subpassIndex);

		// Ignore pDepthStencilState when "the subpass of the render pass the pipeline
		// is created against does not use a depth/stencil attachment"
		if(subpass.pDepthStencilAttachment &&
		   subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)
		{
			setDepthStencilState(depthStencilState);
		}
	}
	else  // No render pass
	{
		// When a pipeline is created without a VkRenderPass, if the VkPipelineRenderingCreateInfo structure
		// is present in the pNext chain of VkGraphicsPipelineCreateInfo, it specifies the view mask and
		// format of attachments used for rendering. If this structure is not specified, and the pipeline
		// does not include a VkRenderPass, viewMask and colorAttachmentCount are 0, and
		// depthAttachmentFormat and stencilAttachmentFormat are VK_FORMAT_UNDEFINED. If a graphics pipeline
		// is created with a valid VkRenderPass, parameters of this structure are ignored.

		if(rendering)
		{
			if((rendering->depthAttachmentFormat != VK_FORMAT_UNDEFINED) ||
			   (rendering->stencilAttachmentFormat != VK_FORMAT_UNDEFINED))
			{
				// If renderPass is VK_NULL_HANDLE, the pipeline is being created with fragment
				// shader state, and either of VkPipelineRenderingCreateInfo::depthAttachmentFormat
				// or VkPipelineRenderingCreateInfo::stencilAttachmentFormat are not
				// VK_FORMAT_UNDEFINED, pDepthStencilState must be a valid pointer to a valid
				// VkPipelineDepthStencilStateCreateInfo structure
				ASSERT(depthStencilState);

				setDepthStencilState(depthStencilState);
			}
		}
	}
}

void FragmentState::applyState(const DynamicState &dynamicState)
{
	if(dynamicStateFlags.dynamicDepthTestEnable)
	{
		depthTestEnable = dynamicState.depthTestEnable;
	}

	if(dynamicStateFlags.dynamicDepthWriteEnable)
	{
		depthWriteEnable = dynamicState.depthWriteEnable;
	}

	if(dynamicStateFlags.dynamicDepthBoundsTestEnable)
	{
		depthBoundsTestEnable = dynamicState.depthBoundsTestEnable;
	}

	if(dynamicStateFlags.dynamicDepthBounds && depthBoundsTestEnable)
	{
		minDepthBounds = dynamicState.minDepthBounds;
		maxDepthBounds = dynamicState.maxDepthBounds;
	}

	if(dynamicStateFlags.dynamicDepthCompareOp)
	{
		depthCompareMode = dynamicState.depthCompareOp;
	}

	if(dynamicStateFlags.dynamicStencilTestEnable)
	{
		stencilEnable = dynamicState.stencilTestEnable;
	}

	if(dynamicStateFlags.dynamicStencilOp && stencilEnable)
	{
		if(dynamicState.faceMask & VK_STENCIL_FACE_FRONT_BIT)
		{
			frontStencil.compareOp = dynamicState.frontStencil.compareOp;
			frontStencil.depthFailOp = dynamicState.frontStencil.depthFailOp;
			frontStencil.failOp = dynamicState.frontStencil.failOp;
			frontStencil.passOp = dynamicState.frontStencil.passOp;
		}

		if(dynamicState.faceMask & VK_STENCIL_FACE_BACK_BIT)
		{
			backStencil.compareOp = dynamicState.backStencil.compareOp;
			backStencil.depthFailOp = dynamicState.backStencil.depthFailOp;
			backStencil.failOp = dynamicState.backStencil.failOp;
			backStencil.passOp = dynamicState.backStencil.passOp;
		}
	}

	if(dynamicStateFlags.dynamicStencilCompareMask && stencilEnable)
	{
		frontStencil.compareMask = dynamicState.frontStencil.compareMask;
		backStencil.compareMask = dynamicState.backStencil.compareMask;
	}

	if(dynamicStateFlags.dynamicStencilWriteMask && stencilEnable)
	{
		frontStencil.writeMask = dynamicState.frontStencil.writeMask;
		backStencil.writeMask = dynamicState.backStencil.writeMask;
	}

	if(dynamicStateFlags.dynamicStencilReference && stencilEnable)
	{
		frontStencil.reference = dynamicState.frontStencil.reference;
		backStencil.reference = dynamicState.backStencil.reference;
	}
}

bool FragmentState::depthWriteActive(const Attachments &attachments) const
{
	// "Depth writes are always disabled when depthTestEnable is VK_FALSE."
	return depthTestActive(attachments) && depthWriteEnable;
}

bool FragmentState::depthTestActive(const Attachments &attachments) const
{
	return attachments.depthBuffer && depthTestEnable;
}

bool FragmentState::stencilActive(const Attachments &attachments) const
{
	return attachments.stencilBuffer && stencilEnable;
}

bool FragmentState::depthBoundsTestActive(const Attachments &attachments) const
{
	return attachments.depthBuffer && depthBoundsTestEnable;
}

void FragmentState::setDepthStencilState(const VkPipelineDepthStencilStateCreateInfo *depthStencilState)
{
	if((depthStencilState->flags &
	    ~(VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT |
	      VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT)) != 0)
	{
		UNSUPPORTED("depthStencilState->flags 0x%08X", int(depthStencilState->flags));
	}

	depthBoundsTestEnable = (depthStencilState->depthBoundsTestEnable != VK_FALSE);
	minDepthBounds = depthStencilState->minDepthBounds;
	maxDepthBounds = depthStencilState->maxDepthBounds;

	depthTestEnable = (depthStencilState->depthTestEnable != VK_FALSE);
	depthWriteEnable = (depthStencilState->depthWriteEnable != VK_FALSE);
	depthCompareMode = depthStencilState->depthCompareOp;

	stencilEnable = (depthStencilState->stencilTestEnable != VK_FALSE);
	if(stencilEnable)
	{
		frontStencil = depthStencilState->front;
		backStencil = depthStencilState->back;
	}
}

void FragmentOutputInterfaceState::initialize(const VkPipelineColorBlendStateCreateInfo *colorBlendState,
                                              const VkPipelineMultisampleStateCreateInfo *multisampleState,
                                              const vk::RenderPass *renderPass, uint32_t subpassIndex,
                                              const VkPipelineRenderingCreateInfo *rendering,
                                              const DynamicStateFlags &allDynamicStateFlags)
{
	dynamicStateFlags = allDynamicStateFlags.fragmentOutputInterface;

	multisample.set(multisampleState);

	if(renderPass)
	{
		const VkSubpassDescription &subpass = renderPass->getSubpass(subpassIndex);

		// Ignore pColorBlendState when "the subpass of the render pass the pipeline
		// is created against does not use any color attachments"
		for(uint32_t i = 0; i < subpass.colorAttachmentCount; i++)
		{
			if(subpass.pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED)
			{
				setColorBlendState(colorBlendState);
				break;
			}
		}
	}
	else  // No render pass
	{
		// When a pipeline is created without a VkRenderPass, if the VkPipelineRenderingCreateInfo structure
		// is present in the pNext chain of VkGraphicsPipelineCreateInfo, it specifies the view mask and
		// format of attachments used for rendering. If this structure is not specified, and the pipeline
		// does not include a VkRenderPass, viewMask and colorAttachmentCount are 0, and
		// depthAttachmentFormat and stencilAttachmentFormat are VK_FORMAT_UNDEFINED. If a graphics pipeline
		// is created with a valid VkRenderPass, parameters of this structure are ignored.

		if(rendering)
		{
			if(rendering->colorAttachmentCount > 0)
			{
				// If renderPass is VK_NULL_HANDLE, the pipeline is being created with fragment
				// output interface state, and VkPipelineRenderingCreateInfo::colorAttachmentCount
				// is not equal to 0, pColorBlendState must be a valid pointer to a valid
				// VkPipelineColorBlendStateCreateInfo structure
				ASSERT(colorBlendState);

				setColorBlendState(colorBlendState);
			}
		}
	}
}

void FragmentOutputInterfaceState::applyState(const DynamicState &dynamicState)
{
	if(dynamicStateFlags.dynamicBlendConstants)
	{
		blendConstants = dynamicState.blendConstants;
	}
}

void FragmentOutputInterfaceState::setColorBlendState(const VkPipelineColorBlendStateCreateInfo *colorBlendState)
{
	if(colorBlendState->flags != 0 &&
	   colorBlendState->flags != VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT)
	{
		UNSUPPORTED("colorBlendState->flags 0x%08X", int(colorBlendState->flags));
	}

	if(colorBlendState->logicOpEnable != VK_FALSE)
	{
		UNSUPPORTED("VkPhysicalDeviceFeatures::logicOp");
	}

	if(!dynamicStateFlags.dynamicBlendConstants)
	{
		blendConstants.x = colorBlendState->blendConstants[0];
		blendConstants.y = colorBlendState->blendConstants[1];
		blendConstants.z = colorBlendState->blendConstants[2];
		blendConstants.w = colorBlendState->blendConstants[3];
	}

	const VkBaseInStructure *extensionColorBlendInfo = reinterpret_cast<const VkBaseInStructure *>(colorBlendState->pNext);
	while(extensionColorBlendInfo)
	{
		switch(extensionColorBlendInfo->sType)
		{
		case VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT:
			{
				const VkPipelineColorBlendAdvancedStateCreateInfoEXT *colorBlendAdvancedCreateInfo = reinterpret_cast<const VkPipelineColorBlendAdvancedStateCreateInfoEXT *>(extensionColorBlendInfo);
				ASSERT(colorBlendAdvancedCreateInfo->blendOverlap == VK_BLEND_OVERLAP_UNCORRELATED_EXT);
				ASSERT(colorBlendAdvancedCreateInfo->dstPremultiplied == VK_TRUE);
				ASSERT(colorBlendAdvancedCreateInfo->srcPremultiplied == VK_TRUE);
			}
			break;
		case VK_STRUCTURE_TYPE_MAX_ENUM:
			// dEQP tests that this value is ignored.
			break;
		default:
			UNSUPPORTED("colorBlendState->pNext sType = %s", vk::Stringify(extensionColorBlendInfo->sType).c_str());
			break;
		}

		extensionColorBlendInfo = extensionColorBlendInfo->pNext;
	}

	ASSERT(colorBlendState->attachmentCount <= sw::MAX_COLOR_BUFFERS);
	for(auto i = 0u; i < colorBlendState->attachmentCount; i++)
	{
		const VkPipelineColorBlendAttachmentState &attachment = colorBlendState->pAttachments[i];
		colorWriteMask[i] = attachment.colorWriteMask;
		blendState[i] = { (attachment.blendEnable != VK_FALSE),
			              attachment.srcColorBlendFactor, attachment.dstColorBlendFactor, attachment.colorBlendOp,
			              attachment.srcAlphaBlendFactor, attachment.dstAlphaBlendFactor, attachment.alphaBlendOp };
	}
}

BlendState FragmentOutputInterfaceState::getBlendState(int index, const Attachments &attachments, bool fragmentContainsKill) const
{
	ASSERT((index >= 0) && (index < sw::MAX_COLOR_BUFFERS));
	auto &state = blendState[index];

	BlendState activeBlendState = {};
	activeBlendState.alphaBlendEnable = alphaBlendActive(index, attachments, fragmentContainsKill);

	if(activeBlendState.alphaBlendEnable)
	{
		vk::Format format = attachments.colorBuffer[index]->getFormat(VK_IMAGE_ASPECT_COLOR_BIT);

		activeBlendState.sourceBlendFactor = blendFactor(state.blendOperation, state.sourceBlendFactor);
		activeBlendState.destBlendFactor = blendFactor(state.blendOperation, state.destBlendFactor);
		activeBlendState.blendOperation = blendOperation(state.blendOperation, state.sourceBlendFactor, state.destBlendFactor, format);
		activeBlendState.sourceBlendFactorAlpha = blendFactor(state.blendOperationAlpha, state.sourceBlendFactorAlpha);
		activeBlendState.destBlendFactorAlpha = blendFactor(state.blendOperationAlpha, state.destBlendFactorAlpha);
		activeBlendState.blendOperationAlpha = blendOperation(state.blendOperationAlpha, state.sourceBlendFactorAlpha, state.destBlendFactorAlpha, format);
	}

	return activeBlendState;
}

bool FragmentOutputInterfaceState::alphaBlendActive(int index, const Attachments &attachments, bool fragmentContainsKill) const
{
	ASSERT((index >= 0) && (index < sw::MAX_COLOR_BUFFERS));
	auto &state = blendState[index];

	if(!attachments.colorBuffer[index] || !blendState[index].alphaBlendEnable)
	{
		return false;
	}

	if(!(colorWriteActive(attachments) || fragmentContainsKill))
	{
		return false;
	}

	vk::Format format = attachments.colorBuffer[index]->getFormat(VK_IMAGE_ASPECT_COLOR_BIT);
	bool colorBlend = blendOperation(state.blendOperation, state.sourceBlendFactor, state.destBlendFactor, format) != VK_BLEND_OP_SRC_EXT;
	bool alphaBlend = blendOperation(state.blendOperationAlpha, state.sourceBlendFactorAlpha, state.destBlendFactorAlpha, format) != VK_BLEND_OP_SRC_EXT;

	return colorBlend || alphaBlend;
}

VkBlendFactor FragmentOutputInterfaceState::blendFactor(VkBlendOp blendOperation, VkBlendFactor blendFactor) const
{
	switch(blendOperation)
	{
	case VK_BLEND_OP_ADD:
	case VK_BLEND_OP_SUBTRACT:
	case VK_BLEND_OP_REVERSE_SUBTRACT:
		return blendFactor;
	case VK_BLEND_OP_MIN:
	case VK_BLEND_OP_MAX:
	case VK_BLEND_OP_MULTIPLY_EXT:
	case VK_BLEND_OP_SCREEN_EXT:
	case VK_BLEND_OP_OVERLAY_EXT:
	case VK_BLEND_OP_DARKEN_EXT:
	case VK_BLEND_OP_LIGHTEN_EXT:
	case VK_BLEND_OP_COLORDODGE_EXT:
	case VK_BLEND_OP_COLORBURN_EXT:
	case VK_BLEND_OP_HARDLIGHT_EXT:
	case VK_BLEND_OP_SOFTLIGHT_EXT:
	case VK_BLEND_OP_DIFFERENCE_EXT:
	case VK_BLEND_OP_EXCLUSION_EXT:
	case VK_BLEND_OP_HSL_HUE_EXT:
	case VK_BLEND_OP_HSL_SATURATION_EXT:
	case VK_BLEND_OP_HSL_COLOR_EXT:
	case VK_BLEND_OP_HSL_LUMINOSITY_EXT:
		return VK_BLEND_FACTOR_ONE;
	default:
		ASSERT(false);
		return blendFactor;
	}
}

VkBlendOp FragmentOutputInterfaceState::blendOperation(VkBlendOp blendOperation, VkBlendFactor sourceBlendFactor, VkBlendFactor destBlendFactor, vk::Format format) const
{
	switch(blendOperation)
	{
	case VK_BLEND_OP_ADD:
		if(sourceBlendFactor == VK_BLEND_FACTOR_ZERO)
		{
			if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
			{
				return VK_BLEND_OP_ZERO_EXT;
			}
			else if(destBlendFactor == VK_BLEND_FACTOR_ONE)
			{
				return VK_BLEND_OP_DST_EXT;
			}
		}
		else if(sourceBlendFactor == VK_BLEND_FACTOR_ONE)
		{
			if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
			{
				return VK_BLEND_OP_SRC_EXT;
			}
		}
		break;
	case VK_BLEND_OP_SUBTRACT:
		if(sourceBlendFactor == VK_BLEND_FACTOR_ZERO)
		{
			if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
			{
				return VK_BLEND_OP_ZERO_EXT;
			}
			else if(format.isUnsignedNormalized())
			{
				return VK_BLEND_OP_ZERO_EXT;  // Negative, clamped to zero
			}
		}
		else if(sourceBlendFactor == VK_BLEND_FACTOR_ONE)
		{
			if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
			{
				return VK_BLEND_OP_SRC_EXT;
			}
		}
		break;
	case VK_BLEND_OP_REVERSE_SUBTRACT:
		if(sourceBlendFactor == VK_BLEND_FACTOR_ZERO)
		{
			if(destBlendFactor == VK_BLEND_FACTOR_ZERO)
			{
				return VK_BLEND_OP_ZERO_EXT;
			}
			else if(destBlendFactor == VK_BLEND_FACTOR_ONE)
			{
				return VK_BLEND_OP_DST_EXT;
			}
		}
		else
		{
			if(destBlendFactor == VK_BLEND_FACTOR_ZERO && format.isUnsignedNormalized())
			{
				return VK_BLEND_OP_ZERO_EXT;  // Negative, clamped to zero
			}
		}
		break;
	case VK_BLEND_OP_MIN:
		return VK_BLEND_OP_MIN;
	case VK_BLEND_OP_MAX:
		return VK_BLEND_OP_MAX;
	case VK_BLEND_OP_MULTIPLY_EXT:
	case VK_BLEND_OP_SCREEN_EXT:
	case VK_BLEND_OP_OVERLAY_EXT:
	case VK_BLEND_OP_DARKEN_EXT:
	case VK_BLEND_OP_LIGHTEN_EXT:
	case VK_BLEND_OP_COLORDODGE_EXT:
	case VK_BLEND_OP_COLORBURN_EXT:
	case VK_BLEND_OP_HARDLIGHT_EXT:
	case VK_BLEND_OP_SOFTLIGHT_EXT:
	case VK_BLEND_OP_DIFFERENCE_EXT:
	case VK_BLEND_OP_EXCLUSION_EXT:
	case VK_BLEND_OP_HSL_HUE_EXT:
	case VK_BLEND_OP_HSL_SATURATION_EXT:
	case VK_BLEND_OP_HSL_COLOR_EXT:
	case VK_BLEND_OP_HSL_LUMINOSITY_EXT:
		return blendOperation;
	default:
		ASSERT(false);
	}

	return blendOperation;
}

bool FragmentOutputInterfaceState::colorWriteActive(const Attachments &attachments) const
{
	for(int i = 0; i < sw::MAX_COLOR_BUFFERS; i++)
	{
		if(colorWriteActive(i, attachments))
		{
			return true;
		}
	}

	return false;
}

int FragmentOutputInterfaceState::colorWriteActive(int index, const Attachments &attachments) const
{
	ASSERT((index >= 0) && (index < sw::MAX_COLOR_BUFFERS));
	auto &state = blendState[index];

	if(!attachments.colorBuffer[index] || attachments.colorBuffer[index]->getFormat() == VK_FORMAT_UNDEFINED)
	{
		return 0;
	}

	vk::Format format = attachments.colorBuffer[index]->getFormat(VK_IMAGE_ASPECT_COLOR_BIT);

	if(blendOperation(state.blendOperation, state.sourceBlendFactor, state.destBlendFactor, format) == VK_BLEND_OP_DST_EXT &&
	   blendOperation(state.blendOperationAlpha, state.sourceBlendFactorAlpha, state.destBlendFactorAlpha, format) == VK_BLEND_OP_DST_EXT)
	{
		return 0;
	}

	return colorWriteMask[index];
}

GraphicsState::GraphicsState(const Device *device, const VkGraphicsPipelineCreateInfo *pCreateInfo,
                             const PipelineLayout *layout)
    : pipelineLayout(layout)
{
	if((pCreateInfo->flags &
	    ~(VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT |
	      VK_PIPELINE_CREATE_DERIVATIVE_BIT |
	      VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT |
	      VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT |
	      VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT)) != 0)
	{
		UNSUPPORTED("pCreateInfo->flags 0x%08X", int(pCreateInfo->flags));
	}

	DynamicStateFlags dynamicStateFlags = ParseDynamicStateFlags(pCreateInfo->pDynamicState);
	const auto *rendering = GetExtendedStruct<VkPipelineRenderingCreateInfo>(pCreateInfo, VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO);

	vertexInputInterfaceState.initialize(pCreateInfo->pVertexInputState,
	                                     pCreateInfo->pInputAssemblyState,
	                                     dynamicStateFlags);
	preRasterizationState.initialize(device,
	                                 pCreateInfo->pViewportState,
	                                 pCreateInfo->pRasterizationState,
	                                 vk::Cast(pCreateInfo->renderPass),
	                                 pCreateInfo->subpass,
	                                 rendering,
	                                 dynamicStateFlags);

	if(!pCreateInfo->pRasterizationState->rasterizerDiscardEnable || dynamicStateFlags.preRasterization.dynamicRasterizerDiscardEnable)
	{
		fragmentState.initialize(pCreateInfo->pDepthStencilState,
		                         vk::Cast(pCreateInfo->renderPass),
		                         pCreateInfo->subpass,
		                         rendering,
		                         dynamicStateFlags);
		fragmentOutputInterfaceState.initialize(pCreateInfo->pColorBlendState,
		                                        pCreateInfo->pMultisampleState,
		                                        vk::Cast(pCreateInfo->renderPass),
		                                        pCreateInfo->subpass,
		                                        rendering,
		                                        dynamicStateFlags);
	}
}

GraphicsState GraphicsState::combineStates(const DynamicState &dynamicState) const
{
	GraphicsState combinedState = *this;

	// Make a copy of the states for modification, then either keep the pipeline state or apply the dynamic state.
	combinedState.vertexInputInterfaceState.applyState(dynamicState);
	combinedState.preRasterizationState.applyState(dynamicState);
	combinedState.fragmentState.applyState(dynamicState);
	combinedState.fragmentOutputInterfaceState.applyState(dynamicState);

	return combinedState;
}

}  // namespace vk
