[vulkan] Enable synchronization validation

And clean up the resulting errors. While some were tricky, there weren't
all that many: just some attachment issues and the multi-stage image
copy for scraps.

Fixing scraps required a barrier between copies. It might be overkill,
but a transfer_dst to transfer_dst image barrier worked.

Fixing attachments was a bit trickier:
 - depth needed early and late fragment tests to be treated as one stage
 - all attachments that were read later needed storeOp = none (using the
   extension)
 - and then finalLayout needed to be correct to avoid ghost transitions
 - as well, for some reason the deffered gbuffer subpass needed a depth
   dependency on the translucent pass even though neither one writes to
   the depth attachment (possibly a validation bug, needs more
   investigation).
This commit is contained in:
Bill Currie 2024-01-24 17:35:28 +09:00
parent 2203e2b4fd
commit 17b00a3d05
8 changed files with 58 additions and 38 deletions

View file

@ -23,6 +23,7 @@ enum {
qfv_LT_Undefined_to_TransferDst, qfv_LT_Undefined_to_TransferDst,
qfv_LT_Undefined_to_General, qfv_LT_Undefined_to_General,
qfv_LT_Undefined_to_ShaderReadOnly, qfv_LT_Undefined_to_ShaderReadOnly,
qfv_LT_TransferDst_to_TransferDst,
qfv_LT_TransferDst_to_TransferSrc, qfv_LT_TransferDst_to_TransferSrc,
qfv_LT_TransferDst_to_General, qfv_LT_TransferDst_to_General,
qfv_LT_TransferDst_to_ShaderReadOnly, qfv_LT_TransferDst_to_ShaderReadOnly,

View file

@ -70,6 +70,19 @@ const qfv_imagebarrier_t imageBarriers[] = {
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
}, },
}, },
[qfv_LT_TransferDst_to_TransferDst] = {
.srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT,
.dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT,
.barrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0,
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
},
},
[qfv_LT_TransferDst_to_TransferSrc] = { [qfv_LT_TransferDst_to_TransferSrc] = {
.srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT, .srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT,
.dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT, .dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT,

View file

@ -217,6 +217,7 @@ QFV_CreateInstance (vulkan_ctx_t *ctx,
}; };
VkValidationFeatureEnableEXT valfeat_enable[] = { VkValidationFeatureEnableEXT valfeat_enable[] = {
// VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT, // VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
}; };
#define valfeat_count sizeof(valfeat_enable)/sizeof(valfeat_enable[0]) #define valfeat_count sizeof(valfeat_enable)/sizeof(valfeat_enable[0])
VkValidationFeaturesEXT validation_features= { VkValidationFeaturesEXT validation_features= {

View file

@ -191,6 +191,8 @@ QFV_RunRenderPassCmd (VkCommandBuffer cmd, vulkan_ctx_t *ctx,
//the attachments won't be transitioned correctly. //the attachments won't be transitioned correctly.
//However, only if not the last (or only) subpass. //However, only if not the last (or only) subpass.
if (i < rp->subpass_count - 1) { if (i < rp->subpass_count - 1) {
//auto np = &rp->subpasses[i + 1];
//printf ("%s -> %s\n", sp->label.name, np->label.name);
dfunc->vkCmdNextSubpass (cmd, rp->subpassContents); dfunc->vkCmdNextSubpass (cmd, rp->subpassContents);
} }
} }

View file

@ -27,11 +27,11 @@ properties = {
}; };
depth_dependency = { depth_dependency = {
src = { src = {
stage = late_fragment_tests; stage = early_fragment_tests|late_fragment_tests;
access = depth_stencil_attachment_write; access = depth_stencil_attachment_write;
}; };
dst = { dst = {
stage = fragment_shader|early_fragment_tests; stage = fragment_shader|early_fragment_tests|late_fragment_tests;
access = input_attachment_read|depth_stencil_attachment_read; access = input_attachment_read|depth_stencil_attachment_read;
}; };
flags = by_region; flags = by_region;
@ -83,13 +83,19 @@ properties = {
attachment_base = { attachment_base = {
samples = 1; samples = 1;
loadOp = dont_care; loadOp = dont_care;
storeOp = dont_care; storeOp = none_ext;
stencilLoadOp = dont_care; stencilLoadOp = dont_care;
stencilStoreOp = dont_care; stencilStoreOp = none_ext;
initialLayout = undefined; initialLayout = undefined;
finalLayout = color_attachment_optimal; finalLayout = shader_read_only_optimal;
clearValue = { color = "[0, 0, 0, 1]"; }; clearValue = { color = "[0, 0, 0, 1]"; };
}; };
depth_base = {
@inherit = $attachment_base;
loadOp = clear;
finalLayout = depth_stencil_read_only_optimal;
clearValue = { depthStencil = { depth = 0; stencil = 0; }; };
};
no_cull = { no_cull = {
depthClampEnable = false; depthClampEnable = false;
@ -1324,11 +1330,8 @@ renderpasses = {
layers = 1; layers = 1;
attachments = { attachments = {
depth = { depth = {
@inherit = $attachment_base; @inherit = $depth_base;
format = $images.depth.format; format = $images.depth.format;
loadOp = clear;
finalLayout = depth_stencil_attachment_optimal;
clearValue = { depthStencil = { depth = 0; stencil = 0; }; };
view = occlusion_depth; view = occlusion_depth;
}; };
}; };
@ -1426,11 +1429,8 @@ renderpasses = {
layers = 1; layers = 1;
attachments = { attachments = {
depth = { depth = {
@inherit = $attachment_base; @inherit = $depth_base;
format = $images.cube_depth.format; format = $images.cube_depth.format;
loadOp = clear;
finalLayout = depth_stencil_attachment_optimal;
clearValue = { depthStencil = { depth = 0; stencil = 0; }; };
view = occlusion_cube_depth; view = occlusion_cube_depth;
}; };
}; };
@ -1444,11 +1444,8 @@ renderpasses = {
layers = 1; layers = 1;
attachments = { attachments = {
depth = { depth = {
@inherit = $attachment_base; @inherit = $depth_base;
format = $images.depth.format; format = $images.depth.format;
loadOp = clear;
finalLayout = depth_stencil_attachment_optimal;
clearValue = { depthStencil = { depth = 0; stencil = 0; }; };
view = depth; view = depth;
}; };
color = { color = {
@ -1704,6 +1701,7 @@ renderpasses = {
color = "[ 0.3, 0.7, 0.3, 1]"; color = "[ 0.3, 0.7, 0.3, 1]";
dependencies = { dependencies = {
depth = $depth_dependency; depth = $depth_dependency;
translucent = $depth_dependency;//FIXME why?
}; };
attachments = { attachments = {
color = { color = {
@ -2051,11 +2049,8 @@ renderpasses = {
layers = 1; layers = 1;
attachments = { attachments = {
depth = { depth = {
@inherit = $attachment_base; @inherit = $depth_base;
format = $images.cube_depth.format; format = $images.cube_depth.format;
loadOp = clear;
finalLayout = depth_stencil_attachment_optimal;
clearValue = { depthStencil = { depth = 0; stencil = 0; }; };
view = cube_depth; view = cube_depth;
}; };
color = { color = {

View file

@ -27,11 +27,11 @@ properties = {
}; };
depth_dependency = { depth_dependency = {
src = { src = {
stage = late_fragment_tests; stage = early_fragment_tests|late_fragment_tests;
access = depth_stencil_attachment_write; access = depth_stencil_attachment_write;
}; };
dst = { dst = {
stage = fragment_shader|early_fragment_tests; stage = fragment_shader|early_fragment_tests|late_fragment_tests;
access = input_attachment_read|depth_stencil_attachment_read; access = input_attachment_read|depth_stencil_attachment_read;
}; };
flags = by_region; flags = by_region;
@ -84,13 +84,19 @@ properties = {
attachment_base = { attachment_base = {
samples = 1; samples = 1;
loadOp = dont_care; loadOp = dont_care;
storeOp = dont_care; storeOp = none_ext;
stencilLoadOp = dont_care; stencilLoadOp = dont_care;
stencilStoreOp = dont_care; stencilStoreOp = none_ext;
initialLayout = undefined; initialLayout = undefined;
finalLayout = color_attachment_optimal; finalLayout = shader_read_only_optimal;
clearValue = { color = "[0, 0, 0, 1]"; }; clearValue = { color = "[0, 0, 0, 1]"; };
}; };
depth_base = {
@inherit = $attachment_base;
loadOp = clear;
finalLayout = depth_stencil_read_only_optimal;
clearValue = { depthStencil = { depth = 0; stencil = 0; }; };
};
no_cull = { no_cull = {
depthClampEnable = false; depthClampEnable = false;
@ -1062,19 +1068,14 @@ renderpasses = {
layers = 1; layers = 1;
attachments = { attachments = {
depth = { depth = {
@inherit = $attachment_base; @inherit = $depth_base;
format = $images.depth.format; format = $images.depth.format;
loadOp = clear;
finalLayout = depth_stencil_attachment_optimal;
clearValue = { depthStencil = { depth = 0; stencil = 0; }; };
view = depth; view = depth;
}; };
color = { color = {
@inherit = $attachment_base; @inherit = $attachment_base;
format = $images.color.format; format = $images.color.format;
loadOp = clear; loadOp = clear;
storeOp = store;
finalLayout = $render_output.finalLayout;
view = color; view = color;
}; };
output = { output = {
@ -1299,11 +1300,8 @@ renderpasses = {
layers = 1; layers = 1;
attachments = { attachments = {
depth = { depth = {
@inherit = $attachment_base; @inherit = $depth_base;
format = $images.cube_depth.format; format = $images.cube_depth.format;
loadOp = clear;
finalLayout = depth_stencil_attachment_optimal;
clearValue = { depthStencil = { depth = 0; stencil = 0; }; };
view = cube_depth; view = cube_depth;
}; };
color = { color = {

View file

@ -311,11 +311,14 @@ QFV_ScrapFlush (scrap_t *scrap)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, &ib.barrier); 1, &ib.barrier);
size_t offset = packet->offset, size; auto sb = imageBarriers[qfv_LT_TransferDst_to_TransferDst];
sb.barrier.image = scrap->image;
size_t offset = packet->offset;
vrect_t *batch = scrap->batch; vrect_t *batch = scrap->batch;
while (scrap->batch_count) { while (scrap->batch_count) {
for (i = 0; i < scrap->batch_count && i < 128; i++) { for (i = 0; i < scrap->batch_count && i < 128; i++) {
size = batch->width * batch->height * scrap->bpp; size_t size = batch->width * batch->height * scrap->bpp;
copy->a[i].bufferOffset = offset; copy->a[i].bufferOffset = offset;
copy->a[i].imageOffset.x = batch->x; copy->a[i].imageOffset.x = batch->x;
@ -330,6 +333,12 @@ QFV_ScrapFlush (scrap_t *scrap)
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
i, copy->a); i, copy->a);
scrap->batch_count -= i; scrap->batch_count -= i;
if (scrap->batch_count) {
dfunc->vkCmdPipelineBarrier (packet->cmd,
sb.srcStages, sb.dstStages,
0, 0, 0, 0, 0,
1, &sb.barrier);
}
} }
ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly];

View file

@ -97,6 +97,7 @@ static const char *instance_extensions[] = {
static const char *device_extensions[] = { static const char *device_extensions[] = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME,
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME, VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME,
#endif #endif