Handle other ignored garbage substates in vulkan graphics PSO creation

This commit is contained in:
baldurk
2019-09-17 12:02:37 +01:00
parent 3005172aa5
commit a6aa0ac5d0
2 changed files with 105 additions and 15 deletions
+56 -5
View File
@@ -2660,24 +2660,75 @@ void DoSerialise(SerialiserType &ser, VkGraphicsPipelineCreateInfo &el)
SERIALISE_MEMBER(stageCount);
SERIALISE_MEMBER_ARRAY(pStages, stageCount);
bool hasTess = false;
for(uint32_t i = 0; i < el.stageCount; i++)
hasTess |= (el.pStages[i].stage & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) != 0;
SERIALISE_MEMBER_OPT(pVertexInputState);
SERIALISE_MEMBER_OPT(pInputAssemblyState);
SERIALISE_MEMBER_OPT(pTessellationState);
SERIALISE_MEMBER_OPT(pViewportState);
// if we don't have tessellation shaders, pTessellationState is ignored and may be garbage
if(hasTess)
{
SERIALISE_MEMBER_OPT(pTessellationState);
}
else
{
SERIALISE_MEMBER_OPT_EMPTY(pTessellationState);
}
// this gets messy. We need to ignore pViewportState, pMultisampleState, pDepthStencilState, and
// pColorBlendState if rasterization is disabled. Unfortunately... pViewportState is BEFORE the
// pRasterization state so we can't check it on read.
// Instead we rely on the fact that while writing we can check it and serialise an explicit NULL
// indicating that it's not present. Then on read we can just read it as if it's either NULL or
// present.
// this bool just means "we can use SERIALISE_MEMBER_OPT" - i.e. the struct is present, or NULL.
const bool hasValidRasterization =
ser.IsReading() || (ser.IsWriting() && el.pRasterizationState &&
el.pRasterizationState->rasterizerDiscardEnable == VK_FALSE);
if(hasValidRasterization)
{
SERIALISE_MEMBER_OPT(pViewportState);
}
else
{
SERIALISE_MEMBER_OPT_EMPTY(pViewportState);
}
SERIALISE_MEMBER_OPT(pRasterizationState);
SERIALISE_MEMBER_OPT(pMultisampleState);
SERIALISE_MEMBER_OPT(pDepthStencilState);
SERIALISE_MEMBER_OPT(pColorBlendState);
if(hasValidRasterization)
{
SERIALISE_MEMBER_OPT(pMultisampleState);
SERIALISE_MEMBER_OPT(pDepthStencilState);
SERIALISE_MEMBER_OPT(pColorBlendState);
}
else
{
SERIALISE_MEMBER_OPT_EMPTY(pMultisampleState);
SERIALISE_MEMBER_OPT_EMPTY(pDepthStencilState);
SERIALISE_MEMBER_OPT_EMPTY(pColorBlendState);
}
SERIALISE_MEMBER_OPT(pDynamicState);
SERIALISE_MEMBER(layout);
SERIALISE_MEMBER(renderPass);
SERIALISE_MEMBER(subpass);
// handle must be explicitly ignored if the flag isn't set, since it could be garbage
if(el.flags & VK_PIPELINE_CREATE_DERIVATIVE_BIT)
{
SERIALISE_MEMBER(basePipelineHandle);
}
else
{
SERIALISE_MEMBER_EMPTY(basePipelineHandle);
}
SERIALISE_MEMBER(basePipelineIndex);
}
+49 -10
View File
@@ -139,21 +139,60 @@ void main()
CompileShaderModule(common + pixel, ShaderLang::glsl, ShaderStage::frag, "main"),
};
VkPipeline pipe;
VkPipeline pipe = createGraphicsPipeline(pipeCreateInfo);
// invalid handle - should not be used because the flag for derived pipelines is not used
pipeCreateInfo.basePipelineHandle = (VkPipeline)0x1234;
{
// invalid handle - should not be used because the flag for derived pipelines is not used
pipeCreateInfo.basePipelineHandle = (VkPipeline)0x1234;
CHECK_VKR(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, pipeCreateInfo, NULL, &pipe));
vkDestroyPipeline(device, pipe, NULL);
VkPipeline dummy;
CHECK_VKR(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, pipeCreateInfo, NULL, &dummy));
vkDestroyPipeline(device, dummy, NULL);
pipeCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
pipeCreateInfo.basePipelineIndex = 3;
// invalid index - again should not be used
pipeCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
pipeCreateInfo.basePipelineIndex = 3;
CHECK_VKR(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, pipeCreateInfo, NULL, &pipe));
vkDestroyPipeline(device, pipe, NULL);
CHECK_VKR(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, pipeCreateInfo, NULL, &dummy));
vkDestroyPipeline(device, dummy, NULL);
pipe = createGraphicsPipeline(pipeCreateInfo);
pipeCreateInfo.basePipelineIndex = -1;
// bake the pipeline info so we can mess with the pointers it normally doesn't handle
VkGraphicsPipelineCreateInfo *baked =
(VkGraphicsPipelineCreateInfo *)(const VkGraphicsPipelineCreateInfo *)pipeCreateInfo;
// NULL should be fine, we have no tessellation shaders
baked->pTessellationState = NULL;
CHECK_VKR(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, baked, NULL, &dummy));
vkDestroyPipeline(device, dummy, NULL);
// same with a garbage pointer
baked->pTessellationState = (VkPipelineTessellationStateCreateInfo *)0x1234;
CHECK_VKR(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, baked, NULL, &dummy));
vkDestroyPipeline(device, dummy, NULL);
// if we disable rasterization, tons of things can be NULL/garbage
pipeCreateInfo.rasterizationState.rasterizerDiscardEnable = VK_TRUE;
baked->pViewportState = NULL;
baked->pMultisampleState = NULL;
baked->pDepthStencilState = NULL;
baked->pColorBlendState = NULL;
CHECK_VKR(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, baked, NULL, &dummy));
vkDestroyPipeline(device, dummy, NULL);
baked->pViewportState = (VkPipelineViewportStateCreateInfo *)0x1234;
baked->pMultisampleState = (VkPipelineMultisampleStateCreateInfo *)0x1234;
baked->pDepthStencilState = (VkPipelineDepthStencilStateCreateInfo *)0x1234;
baked->pColorBlendState = (VkPipelineColorBlendStateCreateInfo *)0x1234;
CHECK_VKR(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, baked, NULL, &dummy));
vkDestroyPipeline(device, dummy, NULL);
}
AllocatedBuffer vb(
allocator, vkh::BufferCreateInfo(sizeof(DefaultTri), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |