mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-24 20:51:35 +00:00
[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:
parent
2203e2b4fd
commit
17b00a3d05
8 changed files with 58 additions and 38 deletions
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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= {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue