Skip to content

Commit ffef044

Browse files
committed
Added custom createRenderPass implementation to resolve Vulkan Validation Error.
1 parent 0823d32 commit ffef044

File tree

1 file changed

+176
-17
lines changed

1 file changed

+176
-17
lines changed

examples/app/vsgheadless/vsgheadless.cpp

Lines changed: 176 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,178 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
2323
#include <iostream>
2424
#include <thread>
2525

26+
namespace vsg
27+
{
28+
29+
ref_ptr<RenderPass> createOffscreenRenderPass(Device* device, VkFormat imageFormat, VkFormat depthFormat, bool requiresDepthRead)
30+
{
31+
auto colorAttachment = defaultColorAttachment(imageFormat);
32+
auto depthAttachment = defaultDepthAttachment(depthFormat);
33+
34+
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; // difference from createRenderPass
35+
36+
if (requiresDepthRead)
37+
{
38+
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
39+
}
40+
41+
RenderPass::Attachments attachments{colorAttachment, depthAttachment};
42+
43+
AttachmentReference colorAttachmentRef = {};
44+
colorAttachmentRef.attachment = 0;
45+
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
46+
47+
AttachmentReference depthAttachmentRef = {};
48+
depthAttachmentRef.attachment = 1;
49+
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
50+
51+
SubpassDescription subpass = {};
52+
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
53+
subpass.colorAttachments.emplace_back(colorAttachmentRef);
54+
subpass.depthStencilAttachments.emplace_back(depthAttachmentRef);
55+
56+
RenderPass::Subpasses subpasses{subpass};
57+
58+
// image layout transition
59+
SubpassDependency colorDependency = {};
60+
colorDependency.srcSubpass = VK_SUBPASS_EXTERNAL;
61+
colorDependency.dstSubpass = 0;
62+
colorDependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
63+
colorDependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
64+
colorDependency.srcAccessMask = 0;
65+
colorDependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
66+
colorDependency.dependencyFlags = 0;
67+
68+
// depth buffer is shared between swap chain images
69+
SubpassDependency depthDependency = {};
70+
depthDependency.srcSubpass = VK_SUBPASS_EXTERNAL;
71+
depthDependency.dstSubpass = 0;
72+
depthDependency.srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
73+
depthDependency.dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
74+
depthDependency.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
75+
depthDependency.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
76+
depthDependency.dependencyFlags = 0;
77+
78+
RenderPass::Dependencies dependencies{colorDependency, depthDependency};
79+
80+
return RenderPass::create(device, attachments, subpasses, dependencies);
81+
}
82+
83+
ref_ptr<RenderPass> createOffscreenMultisampledRenderPass(Device* device, VkFormat imageFormat, VkFormat depthFormat, VkSampleCountFlagBits samples, bool requiresDepthRead)
84+
{
85+
if (samples == VK_SAMPLE_COUNT_1_BIT)
86+
{
87+
return createOffscreenRenderPass(device, imageFormat, depthFormat, requiresDepthRead);
88+
}
89+
90+
// First attachment is multisampled target.
91+
AttachmentDescription colorAttachment = {};
92+
colorAttachment.format = imageFormat;
93+
colorAttachment.samples = samples;
94+
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
95+
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
96+
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
97+
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
98+
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
99+
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
100+
101+
// Second attachment is the resolved image which will be presented.
102+
AttachmentDescription resolveAttachment = {};
103+
resolveAttachment.format = imageFormat;
104+
resolveAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
105+
resolveAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
106+
resolveAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
107+
resolveAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
108+
resolveAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
109+
resolveAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
110+
resolveAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
111+
112+
resolveAttachment.finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; // difference from createMultisampledRenderPass
113+
114+
115+
// Multisampled depth attachment. It won't be resolved.
116+
AttachmentDescription depthAttachment = {};
117+
depthAttachment.format = depthFormat;
118+
depthAttachment.samples = samples;
119+
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
120+
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
121+
depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
122+
depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
123+
depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
124+
depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
125+
126+
RenderPass::Attachments attachments{colorAttachment, resolveAttachment, depthAttachment};
127+
128+
if (requiresDepthRead)
129+
{
130+
AttachmentDescription depthResolveAttachment = {};
131+
depthResolveAttachment.format = depthFormat;
132+
depthResolveAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
133+
depthResolveAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
134+
depthResolveAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
135+
depthResolveAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
136+
depthResolveAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
137+
depthResolveAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
138+
depthResolveAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
139+
attachments.push_back(depthResolveAttachment);
140+
}
141+
142+
AttachmentReference colorAttachmentRef = {};
143+
colorAttachmentRef.attachment = 0;
144+
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
145+
146+
AttachmentReference resolveAttachmentRef = {};
147+
resolveAttachmentRef.attachment = 1;
148+
resolveAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
149+
150+
AttachmentReference depthAttachmentRef = {};
151+
depthAttachmentRef.attachment = 2;
152+
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
153+
154+
SubpassDescription subpass;
155+
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
156+
subpass.colorAttachments.emplace_back(colorAttachmentRef);
157+
subpass.resolveAttachments.emplace_back(resolveAttachmentRef);
158+
subpass.depthStencilAttachments.emplace_back(depthAttachmentRef);
159+
160+
if (requiresDepthRead)
161+
{
162+
AttachmentReference depthResolveAttachmentRef = {};
163+
depthResolveAttachmentRef.attachment = 3;
164+
depthResolveAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
165+
166+
subpass.depthResolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
167+
subpass.stencilResolveMode = VK_RESOLVE_MODE_NONE;
168+
subpass.depthStencilResolveAttachments.emplace_back(depthResolveAttachmentRef);
169+
}
170+
171+
RenderPass::Subpasses subpasses{subpass};
172+
173+
SubpassDependency dependency = {};
174+
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
175+
dependency.dstSubpass = 0;
176+
dependency.srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
177+
dependency.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
178+
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
179+
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
180+
dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
181+
182+
SubpassDependency dependency2 = {};
183+
dependency2.srcSubpass = 0;
184+
dependency2.dstSubpass = VK_SUBPASS_EXTERNAL;
185+
dependency2.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
186+
dependency2.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
187+
dependency2.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
188+
dependency2.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
189+
dependency2.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
190+
191+
RenderPass::Dependencies dependencies{dependency, dependency2};
192+
193+
return RenderPass::create(device, attachments, subpasses, dependencies);
194+
}
195+
196+
}
197+
26198
vsg::ref_ptr<vsg::ImageView> createColorImageView(vsg::ref_ptr<vsg::Device> device, const VkExtent2D& extent, VkFormat imageFormat, VkSampleCountFlagBits samples)
27199
{
28200
auto colorImage = vsg::Image::create();
@@ -131,7 +303,7 @@ std::pair<vsg::ref_ptr<vsg::Commands>, vsg::ref_ptr<vsg::Image>> createColorCapt
131303
auto transitionSourceImageToTransferSourceLayoutBarrier = vsg::ImageMemoryBarrier::create(
132304
VK_ACCESS_MEMORY_READ_BIT, // srcAccessMask
133305
VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask
134-
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // oldLayout
306+
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // oldLayout
135307
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout
136308
VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
137309
VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex
@@ -207,24 +379,11 @@ std::pair<vsg::ref_ptr<vsg::Commands>, vsg::ref_ptr<vsg::Image>> createColorCapt
207379
VkImageSubresourceRange{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1} // subresourceRange
208380
);
209381

210-
// 3.e) transition swap chain image back to present
211-
auto transitionSourceImageBackToPresentBarrier = vsg::ImageMemoryBarrier::create(
212-
VK_ACCESS_TRANSFER_READ_BIT, // srcAccessMask
213-
VK_ACCESS_MEMORY_READ_BIT, // dstAccessMask
214-
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // oldLayout
215-
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // newLayout
216-
VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
217-
VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex
218-
sourceImage, // image
219-
VkImageSubresourceRange{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1} // subresourceRange
220-
);
221-
222382
auto cmd_transitionFromTransferBarrier = vsg::PipelineBarrier::create(
223383
VK_PIPELINE_STAGE_TRANSFER_BIT, // srcStageMask
224384
VK_PIPELINE_STAGE_TRANSFER_BIT, // dstStageMask
225385
0, // dependencyFlags
226-
transitionDestinationImageToMemoryReadBarrier, // barrier
227-
transitionSourceImageBackToPresentBarrier // barrier
386+
transitionDestinationImageToMemoryReadBarrier // barrier
228387
);
229388

230389
commands->addChild(cmd_transitionFromTransferBarrier);
@@ -453,15 +612,15 @@ int main(int argc, char** argv)
453612
depthImageView = createDepthImageView(device, extent, depthFormat, VK_SAMPLE_COUNT_1_BIT);
454613
if (samples == VK_SAMPLE_COUNT_1_BIT)
455614
{
456-
auto renderPass = vsg::createRenderPass(device, imageFormat, depthFormat, true);
615+
auto renderPass = vsg::createOffscreenRenderPass(device, imageFormat, depthFormat, true);
457616
framebuffer = vsg::Framebuffer::create(renderPass, vsg::ImageViews{colorImageView, depthImageView}, extent.width, extent.height, 1);
458617
}
459618
else
460619
{
461620
auto msaa_colorImageView = createColorImageView(device, extent, imageFormat, samples);
462621
auto msaa_depthImageView = createDepthImageView(device, extent, depthFormat, samples);
463622

464-
auto renderPass = vsg::createMultisampledRenderPass(device, imageFormat, depthFormat, samples, true);
623+
auto renderPass = vsg::createOffscreenMultisampledRenderPass(device, imageFormat, depthFormat, samples, true);
465624
framebuffer = vsg::Framebuffer::create(renderPass, vsg::ImageViews{msaa_colorImageView, colorImageView, msaa_depthImageView, depthImageView}, extent.width, extent.height, 1);
466625
}
467626

0 commit comments

Comments
 (0)