mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 17:10:47 +00:00
Don't overlap storage with multiple inline UBO updates in one template
* Previously we were writing the inline UBO data to the same byte storage meaning the last update's data would write over all updates.
This commit is contained in:
@@ -2949,6 +2949,8 @@ void DescUpdateTemplate::Apply(const void *pData, DescUpdateTemplateApplication
|
||||
void *dst = application.inlineData.data() + inlineOffset;
|
||||
memcpy(dst, src, inlineWrite.dataSize);
|
||||
inlineWrite.pData = dst;
|
||||
inlineOffset += inlineWrite.dataSize;
|
||||
inlineOffset = AlignUp4(inlineOffset);
|
||||
|
||||
write.pNext = &inlineWrite;
|
||||
write.descriptorCount = entry.descriptorCount;
|
||||
|
||||
@@ -742,16 +742,14 @@ float4 main() : SV_Target0
|
||||
|
||||
if(hasExt(VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME))
|
||||
{
|
||||
VkWriteDescriptorSetInlineUniformBlockEXT inlineUpdate = {};
|
||||
inlineUpdate.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT;
|
||||
inlineUpdate.pData = &inlinedata;
|
||||
inlineUpdate.dataSize = sizeof(inlinedata);
|
||||
vkh::updateDescriptorSets(
|
||||
device, {
|
||||
vkh::WriteDescriptorSet(
|
||||
descset, 1, inlineUpdate,
|
||||
vkh::DescriptorBufferInfo(cb.buffer, bindOffset * sizeof(Vec4f))),
|
||||
});
|
||||
device,
|
||||
{
|
||||
vkh::WriteDescriptorSet(
|
||||
descset, 1,
|
||||
vkh::WriteDescriptorSetInlineUniformBlockEXT(&inlinedata, sizeof(inlinedata)),
|
||||
vkh::DescriptorBufferInfo(cb.buffer, bindOffset * sizeof(Vec4f))),
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -922,6 +922,19 @@ struct DescriptorImageInfo : public VkDescriptorImageInfo
|
||||
}
|
||||
};
|
||||
|
||||
struct WriteDescriptorSetInlineUniformBlockEXT : public VkWriteDescriptorSetInlineUniformBlockEXT
|
||||
{
|
||||
WriteDescriptorSetInlineUniformBlockEXT(void *data, uint32_t size)
|
||||
{
|
||||
sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT;
|
||||
pNext = NULL;
|
||||
this->pData = data;
|
||||
this->dataSize = size;
|
||||
}
|
||||
|
||||
operator const VkWriteDescriptorSetInlineUniformBlockEXT *() const { return this; }
|
||||
};
|
||||
|
||||
struct WriteDescriptorSet : public VkWriteDescriptorSet
|
||||
{
|
||||
WriteDescriptorSet(VkDescriptorSet dstSet, uint32_t dstBinding, uint32_t dstArrayElement,
|
||||
|
||||
@@ -104,6 +104,28 @@ void main()
|
||||
Color = ubos[7].data;
|
||||
}
|
||||
|
||||
)EOSHADER";
|
||||
|
||||
const std::string inlineubopixel = R"EOSHADER(
|
||||
#version 450 core
|
||||
|
||||
layout(location = 0, index = 0) out vec4 Color;
|
||||
|
||||
layout(binding=0) uniform ubo_block1
|
||||
{
|
||||
vec4 col;
|
||||
} ubo1;
|
||||
|
||||
layout(binding=1) uniform ubo_block2
|
||||
{
|
||||
vec4 col;
|
||||
} ubo2;
|
||||
|
||||
void main()
|
||||
{
|
||||
Color = ubo1.col + ubo2.col;
|
||||
}
|
||||
|
||||
)EOSHADER";
|
||||
|
||||
const std::string refpixel = R"EOSHADER(
|
||||
@@ -263,6 +285,7 @@ void main()
|
||||
void Prepare(int argc, char **argv)
|
||||
{
|
||||
optDevExts.push_back(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME);
|
||||
optDevExts.push_back(VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME);
|
||||
optDevExts.push_back(VK_EXT_TOOLING_INFO_EXTENSION_NAME);
|
||||
optDevExts.push_back(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME);
|
||||
optDevExts.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME);
|
||||
@@ -363,6 +386,17 @@ void main()
|
||||
dyn.pNext = (void *)devInfoNext;
|
||||
devInfoNext = &dyn;
|
||||
}
|
||||
|
||||
static VkPhysicalDeviceInlineUniformBlockFeaturesEXT inlineFeats = {
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT,
|
||||
};
|
||||
|
||||
if(hasExt(VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME))
|
||||
{
|
||||
inlineFeats.inlineUniformBlock = VK_TRUE;
|
||||
inlineFeats.pNext = (void *)devInfoNext;
|
||||
devInfoNext = &inlineFeats;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -566,6 +600,27 @@ void main()
|
||||
VkPipelineLayout dynamicarraylayout =
|
||||
createPipelineLayout(vkh::PipelineLayoutCreateInfo({dynamicarraysetlayout}));
|
||||
|
||||
VkDescriptorSetLayout inlineubosetlayout = VK_NULL_HANDLE;
|
||||
|
||||
if(hasExt(VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME))
|
||||
{
|
||||
inlineubosetlayout = createDescriptorSetLayout(vkh::DescriptorSetLayoutCreateInfo({
|
||||
{0, VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK, 16, VK_SHADER_STAGE_FRAGMENT_BIT},
|
||||
{1, VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK, 16, VK_SHADER_STAGE_FRAGMENT_BIT},
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
// dummy, won't be tested
|
||||
inlineubosetlayout = createDescriptorSetLayout(vkh::DescriptorSetLayoutCreateInfo({
|
||||
{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
|
||||
{1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
|
||||
}));
|
||||
}
|
||||
|
||||
VkPipelineLayout inlineubolayout =
|
||||
createPipelineLayout(vkh::PipelineLayoutCreateInfo({inlineubosetlayout}));
|
||||
|
||||
VkDescriptorSet descset2 = allocateDescriptorSet(setlayout2);
|
||||
|
||||
VkDescriptorSetLayout asm_setlayout =
|
||||
@@ -682,6 +737,15 @@ void main()
|
||||
|
||||
VkPipeline dynarraypipe = createGraphicsPipeline(pipeCreateInfo);
|
||||
|
||||
pipeCreateInfo.layout = inlineubolayout;
|
||||
|
||||
pipeCreateInfo.stages = {
|
||||
CompileShaderModule(VKDefaultVertex, ShaderLang::glsl, ShaderStage::vert, "main"),
|
||||
CompileShaderModule(inlineubopixel, ShaderLang::glsl, ShaderStage::frag, "main"),
|
||||
};
|
||||
|
||||
VkPipeline inlineubopipe = createGraphicsPipeline(pipeCreateInfo);
|
||||
|
||||
pipeCreateInfo.stages = {
|
||||
CompileShaderModule(VKDefaultVertex, ShaderLang::glsl, ShaderStage::vert, "main"),
|
||||
CompileShaderModule(pixel2, ShaderLang::glsl, ShaderStage::frag, "main"),
|
||||
@@ -1201,6 +1265,53 @@ void main()
|
||||
vkCreateDescriptorUpdateTemplateKHR(device, &createInfo, NULL, &refpushtempl);
|
||||
}
|
||||
|
||||
Vec4f inlinetemplData[2] = {
|
||||
Vec4f(1.0f, 0.0f, 0.0f, 0.0f),
|
||||
Vec4f(0.0f, 0.0f, 1.0f, 1.0f),
|
||||
};
|
||||
|
||||
VkDescriptorUpdateTemplateKHR inlinetempl = VK_NULL_HANDLE;
|
||||
VkDescriptorSet inlineuboset = allocateDescriptorSet(inlineubosetlayout);
|
||||
VkDescriptorSet inlineuboset_templ = allocateDescriptorSet(inlineubosetlayout);
|
||||
VkDescriptorSet inlineuboset_templ_dyn = allocateDescriptorSet(inlineubosetlayout);
|
||||
|
||||
if(hasExt(VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME))
|
||||
{
|
||||
vkh::updateDescriptorSets(
|
||||
device, {
|
||||
vkh::WriteDescriptorSet(inlineuboset, 0,
|
||||
vkh::WriteDescriptorSetInlineUniformBlockEXT(
|
||||
&inlinetemplData[0], sizeof(Vec4f)),
|
||||
vkh::DescriptorBufferInfo(validBuffer)),
|
||||
vkh::WriteDescriptorSet(inlineuboset, 1,
|
||||
vkh::WriteDescriptorSetInlineUniformBlockEXT(
|
||||
&inlinetemplData[1], sizeof(Vec4f)),
|
||||
vkh::DescriptorBufferInfo(validBuffer)),
|
||||
});
|
||||
|
||||
if(KHR_descriptor_update_template)
|
||||
{
|
||||
std::vector<VkDescriptorUpdateTemplateEntryKHR> entries = {
|
||||
{0, 0, sizeof(Vec4f), VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK, 0, sizeof(Vec4f) * 2},
|
||||
{1, 0, sizeof(Vec4f), VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK, sizeof(Vec4f),
|
||||
sizeof(Vec4f) * 2},
|
||||
};
|
||||
|
||||
VkDescriptorUpdateTemplateCreateInfoKHR createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR;
|
||||
createInfo.descriptorUpdateEntryCount = (uint32_t)entries.size();
|
||||
createInfo.pDescriptorUpdateEntries = entries.data();
|
||||
createInfo.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR;
|
||||
createInfo.descriptorSetLayout = setlayout;
|
||||
createInfo.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
|
||||
vkCreateDescriptorUpdateTemplateKHR(device, &createInfo, NULL, &inlinetempl);
|
||||
|
||||
vkUpdateDescriptorSetWithTemplateKHR(device, inlineuboset_templ, inlinetempl,
|
||||
&inlinetemplData);
|
||||
}
|
||||
}
|
||||
|
||||
// check that stale views in descriptors don't cause problems if the handle is re-used
|
||||
|
||||
VkImageView view1, view2;
|
||||
@@ -1619,6 +1730,10 @@ void main()
|
||||
if(KHR_descriptor_update_template)
|
||||
vkUpdateDescriptorSetWithTemplateKHR(device, reftempldescset, reftempl, &reftempldata);
|
||||
|
||||
if(hasExt(VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME) && KHR_descriptor_update_template)
|
||||
vkUpdateDescriptorSetWithTemplateKHR(device, inlineuboset_templ_dyn, inlinetempl,
|
||||
&inlinetemplData);
|
||||
|
||||
VkCommandBuffer cmd = GetCommandBuffer();
|
||||
|
||||
vkBeginCommandBuffer(cmd, vkh::CommandBufferBeginInfo());
|
||||
@@ -1800,6 +1915,33 @@ void main()
|
||||
setMarker(cmd, "Dynamic Array Draw");
|
||||
vkCmdDraw(cmd, 3, 1, 0, 0);
|
||||
|
||||
if(hasExt(VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME))
|
||||
{
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, inlineubopipe);
|
||||
vkh::cmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, inlineubolayout, 0,
|
||||
{inlineuboset}, {});
|
||||
|
||||
setMarker(cmd, "Inline UBO Draw");
|
||||
vkCmdDraw(cmd, 3, 1, 0, 0);
|
||||
|
||||
if(KHR_descriptor_update_template)
|
||||
{
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, inlineubopipe);
|
||||
vkh::cmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, inlineubolayout, 0,
|
||||
{inlineuboset_templ}, {});
|
||||
|
||||
setMarker(cmd, "Inline UBO + Templ Draw");
|
||||
vkCmdDraw(cmd, 3, 1, 0, 0);
|
||||
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, inlineubopipe);
|
||||
vkh::cmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, inlineubolayout, 0,
|
||||
{inlineuboset_templ_dyn}, {});
|
||||
|
||||
setMarker(cmd, "Inline UBO + Templ Dyn Draw");
|
||||
vkCmdDraw(cmd, 3, 1, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe2);
|
||||
vkh::cmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout2, 0, {descset2}, {});
|
||||
|
||||
@@ -1881,8 +2023,13 @@ void main()
|
||||
}
|
||||
|
||||
if(KHR_descriptor_update_template)
|
||||
{
|
||||
vkDestroyDescriptorUpdateTemplateKHR(device, reftempl, NULL);
|
||||
|
||||
if(hasExt(VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME))
|
||||
vkDestroyDescriptorUpdateTemplateKHR(device, inlinetempl, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -217,6 +217,56 @@ class VK_Parameter_Zoo(rdtest.TestCase):
|
||||
|
||||
rdtest.log.success("ASM Draw is as expected")
|
||||
|
||||
inline_ubo_actions = [
|
||||
self.find_action("Inline UBO Draw"),
|
||||
self.find_action("Inline UBO + Templ Draw"),
|
||||
self.find_action("Inline UBO + Templ Dyn Draw"),
|
||||
]
|
||||
action = self.find_action("Inline UBO Draw")
|
||||
|
||||
for action in inline_ubo_actions:
|
||||
if action is None:
|
||||
continue
|
||||
|
||||
rdtest.log.print(f"Checking {action.customName}")
|
||||
|
||||
self.controller.SetFrameEvent(action.next.eventId, False)
|
||||
|
||||
self.check_triangle(fore=[1.0, 0.0, 1.0, 1.0])
|
||||
|
||||
stage = rd.ShaderStage.Pixel
|
||||
|
||||
pipe = self.controller.GetPipelineState()
|
||||
ubo1 = pipe.GetConstantBlock(stage, 0, 0).descriptor
|
||||
ubo2 = pipe.GetConstantBlock(stage, 1, 0).descriptor
|
||||
|
||||
ubo1_vars = self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
|
||||
pipe.GetShader(
|
||||
stage), stage,
|
||||
pipe.GetShaderEntryPoint(
|
||||
stage), 0,
|
||||
ubo1.resource, ubo1.byteOffset, ubo1.byteSize)
|
||||
ubo2_vars = self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
|
||||
pipe.GetShader(
|
||||
stage), stage,
|
||||
pipe.GetShaderEntryPoint(
|
||||
stage), 1,
|
||||
ubo2.resource, ubo2.byteOffset, ubo2.byteSize)
|
||||
|
||||
if len(ubo1_vars) != 1 or ubo1_vars[0].name != "col":
|
||||
raise rdtest.TestFailureException("Didn't find ubo1 col variable")
|
||||
|
||||
if len(ubo2_vars) != 1 or ubo2_vars[0].name != "col":
|
||||
raise rdtest.TestFailureException("Didn't find ubo2 col variable")
|
||||
|
||||
if ubo1_vars[0].value.f32v[0:4] != (1.0, 0.0, 0.0, 0.0):
|
||||
raise rdtest.TestFailureException(f"ubo1 col value incorrect: {ubo1_vars[0].value.f32v[0:4]}")
|
||||
|
||||
if ubo2_vars[0].value.f32v[0:4] != (0.0, 0.0, 1.0, 1.0):
|
||||
raise rdtest.TestFailureException(f"ubo2 col value incorrect: {ubo2_vars[0].value.f32v[0:4]}")
|
||||
|
||||
rdtest.log.success(f"{action.customName} is as expected")
|
||||
|
||||
action = self.find_action("Immutable Draw")
|
||||
|
||||
self.check(action is not None)
|
||||
|
||||
Reference in New Issue
Block a user