mirror of
https://github.com/love2d/love.git
synced 2026-08-20 04:30:09 +02:00
vulkan: optionally use extended dynamic state
This should cut down on the number of pipeline permutations needed when this extension is available.
This commit is contained in:
@@ -365,6 +365,12 @@ void Graphics::setFrontFaceWinding(Winding winding) {
|
|||||||
flushBatchedDraws();
|
flushBatchedDraws();
|
||||||
|
|
||||||
states.back().winding = winding;
|
states.back().winding = winding;
|
||||||
|
|
||||||
|
if (optionalDeviceFeatures.extendedDynamicState) {
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetFrontFaceEXT(
|
||||||
|
commandBuffers.at(currentFrame),
|
||||||
|
Vulkan::getFrontFace(winding));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::setColorMask(ColorChannelMask mask) {
|
void Graphics::setColorMask(ColorChannelMask mask) {
|
||||||
@@ -514,6 +520,18 @@ void Graphics::setScissor() {
|
|||||||
void Graphics::setStencilMode(StencilAction action, CompareMode compare, int value, love::uint32 readmask, love::uint32 writemask) {
|
void Graphics::setStencilMode(StencilAction action, CompareMode compare, int value, love::uint32 readmask, love::uint32 writemask) {
|
||||||
flushBatchedDraws();
|
flushBatchedDraws();
|
||||||
|
|
||||||
|
vkCmdSetStencilWriteMask(commandBuffers.at(currentFrame), VK_STENCIL_FACE_FRONT_AND_BACK, writemask);
|
||||||
|
vkCmdSetStencilCompareMask(commandBuffers.at(currentFrame), VK_STENCIL_FACE_FRONT_AND_BACK, readmask);
|
||||||
|
vkCmdSetStencilReference(commandBuffers.at(currentFrame), VK_STENCIL_FACE_FRONT_AND_BACK, value);
|
||||||
|
|
||||||
|
if (optionalDeviceFeatures.extendedDynamicState) {
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetStencilOpEXT(
|
||||||
|
commandBuffers.at(currentFrame),
|
||||||
|
VK_STENCIL_FACE_FRONT_AND_BACK,
|
||||||
|
VK_STENCIL_OP_KEEP, Vulkan::getStencilOp(action),
|
||||||
|
VK_STENCIL_OP_KEEP, Vulkan::getCompareOp(compare));
|
||||||
|
}
|
||||||
|
|
||||||
states.back().stencil.action = action;
|
states.back().stencil.action = action;
|
||||||
states.back().stencil.compare = compare;
|
states.back().stencil.compare = compare;
|
||||||
states.back().stencil.value = value;
|
states.back().stencil.value = value;
|
||||||
@@ -524,6 +542,14 @@ void Graphics::setStencilMode(StencilAction action, CompareMode compare, int val
|
|||||||
void Graphics::setDepthMode(CompareMode compare, bool write) {
|
void Graphics::setDepthMode(CompareMode compare, bool write) {
|
||||||
flushBatchedDraws();
|
flushBatchedDraws();
|
||||||
|
|
||||||
|
if (optionalDeviceFeatures.extendedDynamicState) {
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetDepthCompareOpEXT(
|
||||||
|
commandBuffers.at(currentFrame), Vulkan::getCompareOp(compare));
|
||||||
|
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetDepthWriteEnableEXT(
|
||||||
|
commandBuffers.at(currentFrame), Vulkan::getBool(write));
|
||||||
|
}
|
||||||
|
|
||||||
states.back().depthTest = compare;
|
states.back().depthTest = compare;
|
||||||
states.back().depthWrite = write;
|
states.back().depthWrite = write;
|
||||||
}
|
}
|
||||||
@@ -586,6 +612,37 @@ void Graphics::initDynamicState() {
|
|||||||
} else {
|
} else {
|
||||||
setScissor();
|
setScissor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkViewport viewport{};
|
||||||
|
viewport.x = 0.0f;
|
||||||
|
viewport.y = 0.0f;
|
||||||
|
viewport.width = swapChainExtent.width;
|
||||||
|
viewport.height = swapChainExtent.height;
|
||||||
|
viewport.minDepth = 0.0f;
|
||||||
|
viewport.maxDepth = 1.0f;
|
||||||
|
|
||||||
|
vkCmdSetViewport(commandBuffers.at(currentFrame), 0, 1, &viewport);
|
||||||
|
|
||||||
|
vkCmdSetStencilWriteMask(commandBuffers.at(currentFrame), VK_STENCIL_FACE_FRONT_AND_BACK, states.back().stencil.writeMask);
|
||||||
|
vkCmdSetStencilCompareMask(commandBuffers.at(currentFrame), VK_STENCIL_FACE_FRONT_AND_BACK, states.back().stencil.readMask);
|
||||||
|
vkCmdSetStencilReference(commandBuffers.at(currentFrame), VK_STENCIL_FACE_FRONT_AND_BACK, states.back().stencil.value);
|
||||||
|
|
||||||
|
if (optionalDeviceFeatures.extendedDynamicState) {
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetStencilOpEXT(
|
||||||
|
commandBuffers.at(currentFrame),
|
||||||
|
VK_STENCIL_FACE_FRONT_AND_BACK,
|
||||||
|
VK_STENCIL_OP_KEEP, Vulkan::getStencilOp(states.back().stencil.action),
|
||||||
|
VK_STENCIL_OP_KEEP, Vulkan::getCompareOp(states.back().stencil.compare));
|
||||||
|
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetDepthCompareOpEXT(
|
||||||
|
commandBuffers.at(currentFrame), Vulkan::getCompareOp(states.back().depthTest));
|
||||||
|
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetDepthWriteEnableEXT(
|
||||||
|
commandBuffers.at(currentFrame), Vulkan::getBool(states.back().depthWrite));
|
||||||
|
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetFrontFaceEXT(
|
||||||
|
commandBuffers.at(currentFrame), Vulkan::getFrontFace(states.back().winding));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::startRecordingGraphicsCommands() {
|
void Graphics::startRecordingGraphicsCommands() {
|
||||||
@@ -928,6 +985,20 @@ QueueFamilyIndices Graphics::findQueueFamilies(VkPhysicalDevice device) {
|
|||||||
return indices;
|
return indices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void findOptionalDeviceExtensions(VkPhysicalDevice physicalDevice, OptionalDeviceFeatures &optionalDeviceFeatures) {
|
||||||
|
uint32_t extensionCount;
|
||||||
|
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, nullptr);
|
||||||
|
|
||||||
|
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
|
||||||
|
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, availableExtensions.data());
|
||||||
|
|
||||||
|
for (const auto& extension : availableExtensions) {
|
||||||
|
if (strcmp(extension.extensionName, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME) == 0) {
|
||||||
|
optionalDeviceFeatures.extendedDynamicState = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Graphics::createLogicalDevice() {
|
void Graphics::createLogicalDevice() {
|
||||||
QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
|
QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
|
||||||
|
|
||||||
@@ -944,6 +1015,8 @@ void Graphics::createLogicalDevice() {
|
|||||||
queueCreateInfos.push_back(queueCreateInfo);
|
queueCreateInfos.push_back(queueCreateInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
findOptionalDeviceExtensions(physicalDevice, optionalDeviceFeatures);
|
||||||
|
|
||||||
VkPhysicalDeviceFeatures deviceFeatures{};
|
VkPhysicalDeviceFeatures deviceFeatures{};
|
||||||
deviceFeatures.samplerAnisotropy = VK_TRUE;
|
deviceFeatures.samplerAnisotropy = VK_TRUE;
|
||||||
deviceFeatures.fillModeNonSolid = VK_TRUE;
|
deviceFeatures.fillModeNonSolid = VK_TRUE;
|
||||||
@@ -954,8 +1027,14 @@ void Graphics::createLogicalDevice() {
|
|||||||
createInfo.pQueueCreateInfos = queueCreateInfos.data();
|
createInfo.pQueueCreateInfos = queueCreateInfos.data();
|
||||||
createInfo.pEnabledFeatures = &deviceFeatures;
|
createInfo.pEnabledFeatures = &deviceFeatures;
|
||||||
|
|
||||||
createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
|
std::vector<const char*> enabledExtensions(deviceExtensions.begin(), deviceExtensions.end());
|
||||||
createInfo.ppEnabledExtensionNames = deviceExtensions.data();
|
|
||||||
|
if (optionalDeviceFeatures.extendedDynamicState) {
|
||||||
|
enabledExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledExtensions.size());
|
||||||
|
createInfo.ppEnabledExtensionNames = enabledExtensions.data();
|
||||||
|
|
||||||
// can this be removed?
|
// can this be removed?
|
||||||
if (enableValidationLayers) {
|
if (enableValidationLayers) {
|
||||||
@@ -966,6 +1045,13 @@ void Graphics::createLogicalDevice() {
|
|||||||
createInfo.enabledLayerCount = 0;
|
createInfo.enabledLayerCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkPhysicalDeviceExtendedDynamicStateFeaturesEXT extendedDynamicStateFeatures{};
|
||||||
|
extendedDynamicStateFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT;
|
||||||
|
extendedDynamicStateFeatures.extendedDynamicState = Vulkan::getBool(optionalDeviceFeatures.extendedDynamicState);
|
||||||
|
extendedDynamicStateFeatures.pNext = nullptr;
|
||||||
|
|
||||||
|
createInfo.pNext = &extendedDynamicStateFeatures;
|
||||||
|
|
||||||
if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
|
if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
|
||||||
throw love::Exception("failed to create logical device");
|
throw love::Exception("failed to create logical device");
|
||||||
}
|
}
|
||||||
@@ -976,6 +1062,34 @@ void Graphics::createLogicalDevice() {
|
|||||||
|
|
||||||
vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue);
|
vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue);
|
||||||
vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue);
|
vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue);
|
||||||
|
|
||||||
|
if (optionalDeviceFeatures.extendedDynamicState) {
|
||||||
|
#ifdef LOVE_ANDROID
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetCullModeEXT = vkCmdSetCullModeEXT;
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetDepthBoundsTestEnableEXT = vkCmdSetDepthBoundsTestEnableEXT;
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetDepthBoundsTestEnableEXT = vkCmdSetCullModeEXT;
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetDepthTestEnableEXT = vkCmdSetDepthTestEnableEXT;
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetDepthWriteEnableEXT = vkCmdSetDepthWriteEnableEXT;
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetFrontFaceEXT = vkCmdSetFrontFaceEXT;
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetPrimitiveTopologyEXT = vkCmdSetPrimitiveTopologyEXT;
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetScissorWithCountEXT = vkCmdSetScissorWithCountEXT;
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetStencilOpEXT = vkCmdSetStencilOpEXT;
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetStencilTestEnableEXT = vkCmdSetStencilTestEnableEXT;
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetViewportWithCountEXT = vkCmdSetViewportWithCountEXT;
|
||||||
|
#else
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetCullModeEXT = (PFN_vkCmdSetCullModeEXT)vkGetDeviceProcAddr(device, "vkCmdSetCullModeEXT");
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetDepthBoundsTestEnableEXT = (PFN_vkCmdSetDepthBoundsTestEnableEXT)vkGetDeviceProcAddr(device, "vkCmdSetDepthBoundsTestEnableEXT");
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetDepthCompareOpEXT = (PFN_vkCmdSetDepthCompareOpEXT)vkGetDeviceProcAddr(device, "vkCmdSetDepthCompareOpEXT");
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetDepthTestEnableEXT = (PFN_vkCmdSetDepthTestEnableEXT)vkGetDeviceProcAddr(device, "vkCmdSetDepthTestEnableEXT");
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetDepthWriteEnableEXT = (PFN_vkCmdSetDepthWriteEnableEXT)vkGetDeviceProcAddr(device, "vkCmdSetDepthWriteEnableEXT");
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetFrontFaceEXT = (PFN_vkCmdSetFrontFaceEXT)vkGetDeviceProcAddr(device, "vkCmdSetFrontFaceEXT");
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetPrimitiveTopologyEXT = (PFN_vkCmdSetPrimitiveTopologyEXT)vkGetDeviceProcAddr(device, "vkCmdSetPrimitiveTopologyEXT");
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetScissorWithCountEXT = (PFN_vkCmdSetScissorWithCountEXT)vkGetDeviceProcAddr(device, "vkCmdSetScissorWithCountEXT");
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetStencilOpEXT = (PFN_vkCmdSetStencilOpEXT)vkGetDeviceProcAddr(device, "vkCmdSetStencilOpEXT");
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetStencilTestEnableEXT = (PFN_vkCmdSetStencilTestEnableEXT)vkGetDeviceProcAddr(device, "vkCmdSetStencilTestEnableEXT");
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetViewportWithCountEXT = (PFN_vkCmdSetViewportWithCountEXT)vkGetDeviceProcAddr(device, "vkCmdSetViewportWithCountEXT");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::initVMA() {
|
void Graphics::initVMA() {
|
||||||
@@ -1497,23 +1611,28 @@ void Graphics::createVulkanVertexFormat(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::prepareDraw(const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture, PrimitiveType primitiveType, CullMode cullmode) {
|
void Graphics::prepareDraw(const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture, PrimitiveType primitiveType, CullMode cullmode) {
|
||||||
GraphicsPipelineConfiguration configuration;
|
GraphicsPipelineConfiguration configuration{};
|
||||||
|
|
||||||
configuration.renderPass = currentRenderPass;
|
configuration.renderPass = currentRenderPass;
|
||||||
configuration.vertexAttributes = attributes;
|
configuration.vertexAttributes = attributes;
|
||||||
configuration.shader = (Shader*)Shader::current;
|
configuration.shader = (Shader*)Shader::current;
|
||||||
configuration.primitiveType = primitiveType;
|
|
||||||
configuration.wireFrame = states.back().wireframe;
|
configuration.wireFrame = states.back().wireframe;
|
||||||
configuration.blendState = states.back().blend;
|
configuration.blendState = states.back().blend;
|
||||||
configuration.colorChannelMask = states.back().colorMask;
|
configuration.colorChannelMask = states.back().colorMask;
|
||||||
configuration.winding = states.back().winding;
|
|
||||||
configuration.stencil = states.back().stencil;
|
|
||||||
configuration.depthState.compare = states.back().depthTest;
|
|
||||||
configuration.depthState.write = states.back().depthWrite;
|
|
||||||
configuration.cullmode = cullmode;
|
|
||||||
configuration.viewportWidth = currentViewportWidth;
|
|
||||||
configuration.viewportHeight = currentViewportHeight;
|
|
||||||
configuration.msaaSamples = currentMsaaSamples;
|
configuration.msaaSamples = currentMsaaSamples;
|
||||||
configuration.numColorAttachments = currentNumColorAttachments;
|
configuration.numColorAttachments = currentNumColorAttachments;
|
||||||
|
configuration.primitiveType = primitiveType;
|
||||||
|
|
||||||
|
if (optionalDeviceFeatures.extendedDynamicState) {
|
||||||
|
extendedDynamicStateFunctions.vkCmdSetCullModeEXT(commandBuffers.at(currentFrame), Vulkan::getCullMode(cullmode));
|
||||||
|
} else {
|
||||||
|
configuration.dynamicState.winding = states.back().winding;
|
||||||
|
configuration.dynamicState.depthState.compare = states.back().depthTest;
|
||||||
|
configuration.dynamicState.depthState.write = states.back().depthWrite;
|
||||||
|
configuration.dynamicState.stencilAction = states.back().stencil.action;
|
||||||
|
configuration.dynamicState.stencilCompare = states.back().stencil.compare;
|
||||||
|
configuration.dynamicState.cullmode = cullmode;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<VkBuffer> bufferVector;
|
std::vector<VkBuffer> bufferVector;
|
||||||
std::vector<VkDeviceSize> offsets;
|
std::vector<VkDeviceSize> offsets;
|
||||||
@@ -1565,6 +1684,16 @@ void Graphics::startDefaultRenderPass() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::startRenderPass(const RenderTargets& rts, int pixelw, int pixelh, bool hasSRGBtexture) {
|
void Graphics::startRenderPass(const RenderTargets& rts, int pixelw, int pixelh, bool hasSRGBtexture) {
|
||||||
|
VkViewport viewport{};
|
||||||
|
viewport.x = 0.0f;
|
||||||
|
viewport.y = 0.0f;
|
||||||
|
viewport.width = static_cast<float>(pixelw);
|
||||||
|
viewport.height = static_cast<float>(pixelh);
|
||||||
|
viewport.minDepth = 0.0f;
|
||||||
|
viewport.maxDepth = 1.0f;
|
||||||
|
|
||||||
|
vkCmdSetViewport(commandBuffers.at(currentFrame), 0, 1, &viewport);
|
||||||
|
|
||||||
auto currentCommandBuffer = commandBuffers.at(currentFrame);
|
auto currentCommandBuffer = commandBuffers.at(currentFrame);
|
||||||
|
|
||||||
// fixme: hasSRGBtexture
|
// fixme: hasSRGBtexture
|
||||||
@@ -1695,6 +1824,9 @@ VkSampler Graphics::getCachedSampler(const SamplerState& samplerState) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VkPipeline Graphics::createGraphicsPipeline(GraphicsPipelineConfiguration configuration) {
|
VkPipeline Graphics::createGraphicsPipeline(GraphicsPipelineConfiguration configuration) {
|
||||||
|
VkGraphicsPipelineCreateInfo pipelineInfo{};
|
||||||
|
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||||
|
|
||||||
auto &shaderStages = configuration.shader->getShaderStages();
|
auto &shaderStages = configuration.shader->getShaderStages();
|
||||||
|
|
||||||
std::vector<VkVertexInputBindingDescription> bindingDescriptions;
|
std::vector<VkVertexInputBindingDescription> bindingDescriptions;
|
||||||
@@ -1709,38 +1841,11 @@ VkPipeline Graphics::createGraphicsPipeline(GraphicsPipelineConfiguration config
|
|||||||
vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());
|
vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());
|
||||||
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
|
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
|
||||||
|
|
||||||
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
|
|
||||||
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
|
||||||
inputAssembly.topology = Vulkan::getPrimitiveTypeTopology(configuration.primitiveType);
|
|
||||||
inputAssembly.primitiveRestartEnable = VK_FALSE;
|
|
||||||
|
|
||||||
VkViewport viewport{};
|
|
||||||
viewport.x = 0.0f;
|
|
||||||
viewport.y = 0.0f;
|
|
||||||
viewport.width = configuration.viewportWidth;
|
|
||||||
viewport.height = configuration.viewportHeight;
|
|
||||||
viewport.minDepth = 0.0f;
|
|
||||||
viewport.maxDepth = 1.0f;
|
|
||||||
|
|
||||||
VkPipelineViewportStateCreateInfo viewportState{};
|
VkPipelineViewportStateCreateInfo viewportState{};
|
||||||
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||||
viewportState.viewportCount = 1;
|
viewportState.viewportCount = 1;
|
||||||
viewportState.pViewports = &viewport;
|
|
||||||
viewportState.scissorCount = 1;
|
viewportState.scissorCount = 1;
|
||||||
|
|
||||||
VkPipelineRasterizationStateCreateInfo rasterizer{};
|
|
||||||
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
|
||||||
rasterizer.depthClampEnable = VK_FALSE;
|
|
||||||
rasterizer.rasterizerDiscardEnable = VK_FALSE;
|
|
||||||
rasterizer.polygonMode = Vulkan::getPolygonMode(configuration.wireFrame);
|
|
||||||
rasterizer.lineWidth = 1.0f;
|
|
||||||
rasterizer.cullMode = Vulkan::getCullMode(configuration.cullmode);
|
|
||||||
rasterizer.frontFace = Vulkan::getFrontFace(configuration.winding);
|
|
||||||
rasterizer.depthBiasEnable = VK_FALSE;
|
|
||||||
rasterizer.depthBiasConstantFactor = 0.0f;
|
|
||||||
rasterizer.depthBiasClamp = 0.0f;
|
|
||||||
rasterizer.depthBiasSlopeFactor = 0.0f;
|
|
||||||
|
|
||||||
VkPipelineMultisampleStateCreateInfo multisampling{};
|
VkPipelineMultisampleStateCreateInfo multisampling{};
|
||||||
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||||
multisampling.sampleShadingEnable = VK_FALSE;
|
multisampling.sampleShadingEnable = VK_FALSE;
|
||||||
@@ -1750,31 +1855,53 @@ VkPipeline Graphics::createGraphicsPipeline(GraphicsPipelineConfiguration config
|
|||||||
multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
|
multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
|
||||||
multisampling.alphaToOneEnable = VK_FALSE; // Optional
|
multisampling.alphaToOneEnable = VK_FALSE; // Optional
|
||||||
|
|
||||||
|
VkPipelineRasterizationStateCreateInfo rasterizer{};
|
||||||
|
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||||
|
rasterizer.depthClampEnable = VK_FALSE;
|
||||||
|
rasterizer.rasterizerDiscardEnable = VK_FALSE;
|
||||||
|
rasterizer.polygonMode = Vulkan::getPolygonMode(configuration.wireFrame);
|
||||||
|
rasterizer.lineWidth = 1.0f;
|
||||||
|
if (!optionalDeviceFeatures.extendedDynamicState) {
|
||||||
|
rasterizer.cullMode = Vulkan::getCullMode(configuration.dynamicState.cullmode);
|
||||||
|
rasterizer.frontFace = Vulkan::getFrontFace(configuration.dynamicState.winding);
|
||||||
|
}
|
||||||
|
|
||||||
|
rasterizer.depthBiasEnable = VK_FALSE;
|
||||||
|
rasterizer.depthBiasConstantFactor = 0.0f;
|
||||||
|
rasterizer.depthBiasClamp = 0.0f;
|
||||||
|
rasterizer.depthBiasSlopeFactor = 0.0f;
|
||||||
|
|
||||||
|
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
|
||||||
|
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||||
|
inputAssembly.topology = Vulkan::getPrimitiveTypeTopology(configuration.primitiveType);
|
||||||
|
inputAssembly.primitiveRestartEnable = VK_FALSE;
|
||||||
|
|
||||||
VkPipelineDepthStencilStateCreateInfo depthStencil{};
|
VkPipelineDepthStencilStateCreateInfo depthStencil{};
|
||||||
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
||||||
depthStencil.depthTestEnable = VK_TRUE;
|
depthStencil.depthTestEnable = VK_TRUE;
|
||||||
depthStencil.depthWriteEnable = Vulkan::getBool(configuration.depthState.write);
|
if (!optionalDeviceFeatures.extendedDynamicState) {
|
||||||
depthStencil.depthCompareOp = Vulkan::getCompareOp(configuration.depthState.compare);
|
depthStencil.depthWriteEnable = Vulkan::getBool(configuration.dynamicState.depthState.write);
|
||||||
|
depthStencil.depthCompareOp = Vulkan::getCompareOp(configuration.dynamicState.depthState.compare);
|
||||||
|
}
|
||||||
depthStencil.depthBoundsTestEnable = VK_FALSE;
|
depthStencil.depthBoundsTestEnable = VK_FALSE;
|
||||||
depthStencil.minDepthBounds = 0.0f;
|
depthStencil.minDepthBounds = 0.0f;
|
||||||
depthStencil.maxDepthBounds = 1.0f;
|
depthStencil.maxDepthBounds = 1.0f;
|
||||||
|
|
||||||
depthStencil.stencilTestEnable = VK_TRUE;
|
depthStencil.stencilTestEnable = VK_TRUE;
|
||||||
|
|
||||||
depthStencil.front.failOp = VK_STENCIL_OP_KEEP;
|
if (!optionalDeviceFeatures.extendedDynamicState) {
|
||||||
depthStencil.front.passOp = Vulkan::getStencilOp(configuration.stencil.action);
|
depthStencil.front.failOp = VK_STENCIL_OP_KEEP;
|
||||||
depthStencil.front.depthFailOp = VK_STENCIL_OP_KEEP;
|
depthStencil.front.passOp = Vulkan::getStencilOp(configuration.dynamicState.stencilAction);
|
||||||
depthStencil.front.compareOp = Vulkan::getCompareOp(configuration.stencil.compare);
|
depthStencil.front.depthFailOp = VK_STENCIL_OP_KEEP;
|
||||||
depthStencil.front.compareMask = configuration.stencil.readMask;
|
depthStencil.front.compareOp = Vulkan::getCompareOp(configuration.dynamicState.stencilCompare);
|
||||||
depthStencil.front.writeMask = configuration.stencil.writeMask;
|
|
||||||
depthStencil.front.reference = configuration.stencil.value;
|
|
||||||
|
|
||||||
depthStencil.back.failOp = VK_STENCIL_OP_KEEP;
|
depthStencil.back.failOp = VK_STENCIL_OP_KEEP;
|
||||||
depthStencil.back.passOp = Vulkan::getStencilOp(configuration.stencil.action);
|
depthStencil.back.passOp = Vulkan::getStencilOp(configuration.dynamicState.stencilAction);
|
||||||
depthStencil.back.depthFailOp = VK_STENCIL_OP_KEEP;
|
depthStencil.back.depthFailOp = VK_STENCIL_OP_KEEP;
|
||||||
depthStencil.back.compareOp = Vulkan::getCompareOp(configuration.stencil.compare);
|
depthStencil.back.compareOp = Vulkan::getCompareOp(configuration.dynamicState.stencilCompare);
|
||||||
depthStencil.back.compareMask = configuration.stencil.readMask;
|
}
|
||||||
depthStencil.back.writeMask = configuration.stencil.writeMask;
|
|
||||||
depthStencil.back.reference = static_cast<uint32_t>(configuration.stencil.value);
|
pipelineInfo.pDepthStencilState = &depthStencil;
|
||||||
|
|
||||||
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
|
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
|
||||||
colorBlendAttachment.colorWriteMask = Vulkan::getColorMask(configuration.colorChannelMask);
|
colorBlendAttachment.colorWriteMask = Vulkan::getColorMask(configuration.colorChannelMask);
|
||||||
@@ -1799,17 +1926,36 @@ VkPipeline Graphics::createGraphicsPipeline(GraphicsPipelineConfiguration config
|
|||||||
colorBlending.blendConstants[2] = 0.0f;
|
colorBlending.blendConstants[2] = 0.0f;
|
||||||
colorBlending.blendConstants[3] = 0.0f;
|
colorBlending.blendConstants[3] = 0.0f;
|
||||||
|
|
||||||
std::array<VkDynamicState, 1> dynamicStates = {
|
std::vector<VkDynamicState> dynamicStates;
|
||||||
VK_DYNAMIC_STATE_SCISSOR
|
|
||||||
};
|
if (optionalDeviceFeatures.extendedDynamicState) {
|
||||||
|
dynamicStates = {
|
||||||
|
VK_DYNAMIC_STATE_SCISSOR,
|
||||||
|
VK_DYNAMIC_STATE_VIEWPORT,
|
||||||
|
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
|
||||||
|
VK_DYNAMIC_STATE_STENCIL_REFERENCE,
|
||||||
|
|
||||||
|
VK_DYNAMIC_STATE_CULL_MODE_EXT,
|
||||||
|
VK_DYNAMIC_STATE_FRONT_FACE_EXT,
|
||||||
|
VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
|
||||||
|
VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,
|
||||||
|
VK_DYNAMIC_STATE_STENCIL_OP_EXT,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dynamicStates = {
|
||||||
|
VK_DYNAMIC_STATE_SCISSOR,
|
||||||
|
VK_DYNAMIC_STATE_VIEWPORT,
|
||||||
|
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
|
||||||
|
VK_DYNAMIC_STATE_STENCIL_REFERENCE,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
VkPipelineDynamicStateCreateInfo dynamicState{};
|
VkPipelineDynamicStateCreateInfo dynamicState{};
|
||||||
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||||
dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
|
dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
|
||||||
dynamicState.pDynamicStates = dynamicStates.data();
|
dynamicState.pDynamicStates = dynamicStates.data();
|
||||||
|
|
||||||
VkGraphicsPipelineCreateInfo pipelineInfo{};
|
|
||||||
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
|
||||||
pipelineInfo.stageCount = static_cast<uint32_t>(shaderStages.size());
|
pipelineInfo.stageCount = static_cast<uint32_t>(shaderStages.size());
|
||||||
pipelineInfo.pStages = shaderStages.data();
|
pipelineInfo.pStages = shaderStages.data();
|
||||||
pipelineInfo.pVertexInputState = &vertexInputInfo;
|
pipelineInfo.pVertexInputState = &vertexInputInfo;
|
||||||
@@ -1817,7 +1963,6 @@ VkPipeline Graphics::createGraphicsPipeline(GraphicsPipelineConfiguration config
|
|||||||
pipelineInfo.pViewportState = &viewportState;
|
pipelineInfo.pViewportState = &viewportState;
|
||||||
pipelineInfo.pRasterizationState = &rasterizer;
|
pipelineInfo.pRasterizationState = &rasterizer;
|
||||||
pipelineInfo.pMultisampleState = &multisampling;
|
pipelineInfo.pMultisampleState = &multisampling;
|
||||||
pipelineInfo.pDepthStencilState = &depthStencil;
|
|
||||||
pipelineInfo.pColorBlendState = &colorBlending;
|
pipelineInfo.pColorBlendState = &colorBlending;
|
||||||
pipelineInfo.pDynamicState = &dynamicState;
|
pipelineInfo.pDynamicState = &dynamicState;
|
||||||
pipelineInfo.layout = configuration.shader->getGraphicsPipelineLayout();
|
pipelineInfo.layout = configuration.shader->getGraphicsPipelineLayout();
|
||||||
|
|||||||
@@ -79,22 +79,42 @@ struct FramebufferConfigurationHasher {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct OptionalDeviceFeatures {
|
||||||
|
bool extendedDynamicState = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExtendedDynamicStateFunctions {
|
||||||
|
PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT = nullptr;
|
||||||
|
PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT = nullptr;
|
||||||
|
PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT = nullptr;
|
||||||
|
PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT = nullptr;
|
||||||
|
PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT = nullptr;
|
||||||
|
PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT = nullptr;
|
||||||
|
PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT = nullptr;
|
||||||
|
PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT = nullptr;
|
||||||
|
PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT = nullptr;
|
||||||
|
PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT = nullptr;
|
||||||
|
PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
struct GraphicsPipelineConfiguration {
|
struct GraphicsPipelineConfiguration {
|
||||||
VkRenderPass renderPass;
|
VkRenderPass renderPass;
|
||||||
VertexAttributes vertexAttributes;
|
VertexAttributes vertexAttributes;
|
||||||
Shader* shader = nullptr;
|
Shader* shader = nullptr;
|
||||||
PrimitiveType primitiveType = PRIMITIVE_MAX_ENUM;
|
|
||||||
bool wireFrame;
|
bool wireFrame;
|
||||||
BlendState blendState;
|
BlendState blendState;
|
||||||
ColorChannelMask colorChannelMask;
|
ColorChannelMask colorChannelMask;
|
||||||
Winding winding;
|
|
||||||
CullMode cullmode;
|
|
||||||
float viewportWidth;
|
|
||||||
float viewportHeight;
|
|
||||||
StencilState stencil;
|
|
||||||
DepthState depthState;
|
|
||||||
VkSampleCountFlagBits msaaSamples;
|
VkSampleCountFlagBits msaaSamples;
|
||||||
uint32_t numColorAttachments;
|
uint32_t numColorAttachments;
|
||||||
|
PrimitiveType primitiveType;
|
||||||
|
|
||||||
|
struct DynamicState {
|
||||||
|
CullMode cullmode = CULL_NONE;
|
||||||
|
Winding winding = WINDING_MAX_ENUM;
|
||||||
|
StencilAction stencilAction = STENCIL_MAX_ENUM;
|
||||||
|
CompareMode stencilCompare = COMPARE_MAX_ENUM;
|
||||||
|
DepthState depthState{};
|
||||||
|
} dynamicState;
|
||||||
|
|
||||||
GraphicsPipelineConfiguration() {
|
GraphicsPipelineConfiguration() {
|
||||||
memset(this, 0, sizeof(GraphicsPipelineConfiguration));
|
memset(this, 0, sizeof(GraphicsPipelineConfiguration));
|
||||||
@@ -281,6 +301,8 @@ private:
|
|||||||
int requestedMsaa = 0;
|
int requestedMsaa = 0;
|
||||||
int actualMsaa = 0;
|
int actualMsaa = 0;
|
||||||
VkDevice device = VK_NULL_HANDLE;
|
VkDevice device = VK_NULL_HANDLE;
|
||||||
|
OptionalDeviceFeatures optionalDeviceFeatures;
|
||||||
|
ExtendedDynamicStateFunctions extendedDynamicStateFunctions;
|
||||||
VkQueue graphicsQueue = VK_NULL_HANDLE;
|
VkQueue graphicsQueue = VK_NULL_HANDLE;
|
||||||
VkQueue presentQueue = VK_NULL_HANDLE;
|
VkQueue presentQueue = VK_NULL_HANDLE;
|
||||||
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
||||||
|
|||||||
Reference in New Issue
Block a user