@@ -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+
26198vsg::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