载入中...
搜索中...
未找到
GraphicsOffscreenPipeline.cpp
浏览该文件的文档.
3#include "graphics/shaders/color_vert_spv.inc"
4#include "graphics/shaders/color_frag_spv.inc"
6#include "graphics/shaders/textured_vert_spv.inc"
7#include "graphics/shaders/textured_frag_spv.inc"
8#include "graphics/shaders/lit2d_vert_spv.inc"
9#include "graphics/shaders/lit2d_frag_spv.inc"
10#include "graphics/shaders/particle_distortion_frag_spv.inc"
11#include "graphics/shaders/scene_tonemap_frag_spv.inc"
12namespace eve::graphics::vulkan {
13vk::Pipeline createSolidColorPipeline(vkb::Device &device, const vkb::BuiltRenderPass &renderPass,
14 vk::PipelineLayout layout,
15 BlendMode mode) {
16 if (mode == BlendMode::Additive || mode == BlendMode::Premultiplied ||
17 mode == BlendMode::Multiply) {
18 // cbs/attachments must outlive build(); the builder must stay a single
19 // expression — copying the builder into a named local leaves its
20 // shader-stage pName pointers dangling into the temporary's storage.
21 std::vector<vk::PipelineColorBlendAttachmentState> attachments(1,
22 makeBlendAttachment(mode));
23 vk::PipelineColorBlendStateCreateInfo cbs{};
24 cbs.logicOpEnable = false;
25 cbs.attachmentCount = 1;
26 cbs.pAttachments = attachments.data();
27 return device.createPipeline()
28 .useClassicPipeline(embeddedSpirv(color_vert_spv), embeddedSpirv(color_frag_spv))
29 .setPipelineLayout(layout)
30 .setVertexInputState(vkb::VertexInputStateBuilder()
31 .addInputBinding<ColorVertex>()
32 .addAttributeDescription<ColorVertex>())
33 .setDynamicStatesViewportScissor()
34 .setRasterizer(vk::PolygonMode::eFill, false, false, 1.0f,
35 vk::CullModeFlagBits::eNone, vk::FrontFace::eCounterClockwise)
36 .setDepthStencil(false, false)
37 .setColorBlending(cbs)
38 .build(renderPass);
39 }
40 if (mode == BlendMode::Alpha) {
41 return device.createPipeline()
42 .useClassicPipeline(embeddedSpirv(color_vert_spv), embeddedSpirv(color_frag_spv))
43 .setPipelineLayout(layout)
44 .setVertexInputState(vkb::VertexInputStateBuilder()
45 .addInputBinding<ColorVertex>()
46 .addAttributeDescription<ColorVertex>())
47 .setDynamicStatesViewportScissor()
48 .setRasterizer(vk::PolygonMode::eFill, false, false, 1.0f,
49 vk::CullModeFlagBits::eNone, vk::FrontFace::eCounterClockwise)
50 .setDepthStencil(false, false)
51 .setAlphaBlending(1)
52 .build(renderPass);
53 }
54 // Opaque: keep the original single-expression chain (no explicit blend state).
55 return device.createPipeline()
56 .useClassicPipeline(embeddedSpirv(color_vert_spv), embeddedSpirv(color_frag_spv))
57 .setPipelineLayout(layout)
58 .setVertexInputState(vkb::VertexInputStateBuilder()
59 .addInputBinding<ColorVertex>()
60 .addAttributeDescription<ColorVertex>())
61 .setDynamicStatesViewportScissor()
62 .setRasterizer(vk::PolygonMode::eFill, false, false, 1.0f, vk::CullModeFlagBits::eNone,
63 vk::FrontFace::eCounterClockwise)
64 .setDepthStencil(false, false)
65 .build(renderPass);
66}
67
68
69namespace {
70vkb::BuiltRenderPass persistentColorPass(vkb::Device& device, vk::Format format) {
71 vk::AttachmentDescription color{};
72 color.format = format;
73 color.samples = vk::SampleCountFlagBits::e1;
74 color.loadOp = vk::AttachmentLoadOp::eLoad;
75 color.storeOp = vk::AttachmentStoreOp::eStore;
76 color.stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
77 color.stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
78 color.initialLayout = vk::ImageLayout::eColorAttachmentOptimal;
79 color.finalLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
80 auto pass = device.createRenderPass().addAttachment(color)
81 .addSubpass(vkb::SubpassBuilder().addAttachmentRef(0, vk::ImageLayout::eColorAttachmentOptimal))
82 .addDependency(VK_SUBPASS_EXTERNAL, 0,
83 vk::PipelineStageFlagBits::eFragmentShader | vk::PipelineStageFlagBits::eColorAttachmentOutput,
84 vk::PipelineStageFlagBits::eColorAttachmentOutput,
85 vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eColorAttachmentWrite,
86 vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite)
87 .addDependency(0, VK_SUBPASS_EXTERNAL, vk::PipelineStageFlagBits::eColorAttachmentOutput,
88 vk::PipelineStageFlagBits::eFragmentShader, vk::AccessFlagBits::eColorAttachmentWrite,
89 vk::AccessFlagBits::eShaderRead).build();
90 // addAttachment preserves the explicit initial layout; supply its role metadata.
91 pass.colorAttachmentCount = 1;
92 pass.colorsSampledAfter = true;
93 pass.colorFinalLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
94 return pass;
95}
96} // namespace
97void Graphics::ensureOffscreenPipelines() {
98 if (offscreenRenderPass) return;
99
100 offscreenRenderPass = persistentColorPass(device, vk::Format::eR8G8B8A8Unorm);
101
102 offscreenSolidPipeline =
103 createSolidColorPipeline(device, offscreenRenderPass, pipelineLayout);
104 offscreenSolidAlphaPipeline =
105 createSolidColorPipeline(device, offscreenRenderPass, pipelineLayout, BlendMode::Alpha);
106 offscreenAdditiveSolidPipeline =
107 createSolidColorPipeline(device, offscreenRenderPass, pipelineLayout, BlendMode::Additive);
108 offscreenPremultipliedSolidPipeline = createSolidColorPipeline(
109 device, offscreenRenderPass, pipelineLayout, BlendMode::Premultiplied);
110 offscreenMultiplySolidPipeline = createSolidColorPipeline(
111 device, offscreenRenderPass, pipelineLayout, BlendMode::Multiply);
112
113 // Textured offscreen pipeline mirrors createTexturedPipeline but with offscreen RP.
114 auto tvert = embeddedSpirv(textured_vert_spv);
115 auto tfrag = embeddedSpirv(textured_frag_spv);
116 offscreenTexPipeline =
117 createTexturedStylePipeline(tvert, tfrag, offscreenRenderPass, texPipelineLayout);
118 offscreenAdditiveTexPipeline =
119 createTexturedStylePipeline(tvert, tfrag, offscreenRenderPass, texPipelineLayout,
121 offscreenPremultipliedTexPipeline = createTexturedStylePipeline(
122 tvert, tfrag, offscreenRenderPass, texPipelineLayout, BlendMode::Premultiplied);
123 offscreenMultiplyTexPipeline = createTexturedStylePipeline(
124 tvert, tfrag, offscreenRenderPass, texPipelineLayout, BlendMode::Multiply);
125 offscreenOpaqueTexPipeline =
126 createTexturedStylePipeline(tvert, tfrag, offscreenRenderPass, texPipelineLayout,
128
129 if (lit2dPipelineLayout) {
130 auto lvert = embeddedSpirv(lit2d_vert_spv);
131 auto lfrag = embeddedSpirv(lit2d_frag_spv);
132 offscreenLitPipeline =
133 createTexturedStylePipeline(lvert, lfrag, offscreenRenderPass, lit2dPipelineLayout);
134 offscreenLitAdditivePipeline =
135 createTexturedStylePipeline(lvert, lfrag, offscreenRenderPass, lit2dPipelineLayout, BlendMode::Additive);
136 offscreenLitPremultipliedPipeline = createTexturedStylePipeline(lvert, lfrag, offscreenRenderPass,
137 lit2dPipelineLayout, BlendMode::Premultiplied);
138 offscreenLitMultiplyPipeline =
139 createTexturedStylePipeline(lvert, lfrag, offscreenRenderPass, lit2dPipelineLayout, BlendMode::Multiply);
140 offscreenLitOpaquePipeline =
141 createTexturedStylePipeline(lvert, lfrag, offscreenRenderPass, lit2dPipelineLayout, BlendMode::Opaque);
142 }
143
144 // Lazily create offscreen pipelines for any custom shaders already loaded.
145 for (auto &sh : ownedShaders) ensureShaderOffscreenPipeline(sh.get());
146}
147
148void Graphics::ensureShaderOffscreenPipeline(Shader *shader) {
149 if (!shader || !shader->gpuHandle || !offscreenRenderPass) return;
150 // Mesh3D SPIR-V / layout is incompatible with the 2D textured offscreen pass.
151 if (shader->getKind() == Shader::Kind::eMesh3D) return;
152 auto *gpu = static_cast<GpuShader *>(shader->gpuHandle);
153 if (gpu->isMesh3D || gpu->offscreenPipeline) return;
154 gpu->offscreenPipeline = createTexturedStylePipeline(shader->vertexSpirv(), shader->fragmentSpirv(),
155 offscreenRenderPass, shaderPipelineLayout);
156 gpu->offscreenOpaquePipeline = createTexturedStylePipeline(
157 shader->vertexSpirv(), shader->fragmentSpirv(), offscreenRenderPass,
158 shaderPipelineLayout, BlendMode::Opaque);
159}
160
161void Graphics::ensureHdrOffscreenPipelines() {
162 if (!hdrOffscreenRenderPass) {
163 hdrOffscreenRenderPass =
164 device.createRenderPass()
165 .addSampledColorAttachment(vk::Format::eR16G16B16A16Sfloat)
166 .addSubpass(vkb::SubpassBuilder().addAttachmentRef(
167 0, vk::ImageLayout::eColorAttachmentOptimal))
168 .addExternalShaderReadDependencies()
169 .build();
170 }
171 if (!pipelineLayout) pipelineLayout = createPipelineLayout(device);
172 if (!hdrOffscreenSolidPipeline) {
173 hdrOffscreenSolidPipeline =
174 createSolidColorPipeline(device, hdrOffscreenRenderPass, pipelineLayout);
175 hdrOffscreenSolidAlphaPipeline =
176 createSolidColorPipeline(device, hdrOffscreenRenderPass, pipelineLayout, BlendMode::Alpha);
177 hdrOffscreenAdditiveSolidPipeline = createSolidColorPipeline(
178 device, hdrOffscreenRenderPass, pipelineLayout, BlendMode::Additive);
179 hdrOffscreenPremultipliedSolidPipeline = createSolidColorPipeline(
180 device, hdrOffscreenRenderPass, pipelineLayout, BlendMode::Premultiplied);
181 hdrOffscreenMultiplySolidPipeline = createSolidColorPipeline(
182 device, hdrOffscreenRenderPass, pipelineLayout, BlendMode::Multiply);
183 }
184 if (!hdrOffscreenTexPipeline && texPipelineLayout) {
185 auto vert = embeddedSpirv(textured_vert_spv);
186 auto frag = embeddedSpirv(textured_frag_spv);
187 hdrOffscreenTexPipeline = createTexturedStylePipeline(
188 vert, frag, hdrOffscreenRenderPass, texPipelineLayout);
189 hdrOffscreenOpaqueTexPipeline = createTexturedStylePipeline(
190 vert, frag, hdrOffscreenRenderPass, texPipelineLayout, BlendMode::Opaque);
191 hdrOffscreenAdditiveTexPipeline = createTexturedStylePipeline(
192 vert, frag, hdrOffscreenRenderPass, texPipelineLayout, BlendMode::Additive);
193 hdrOffscreenPremultipliedTexPipeline = createTexturedStylePipeline(
194 vert, frag, hdrOffscreenRenderPass, texPipelineLayout, BlendMode::Premultiplied);
195 hdrOffscreenMultiplyTexPipeline = createTexturedStylePipeline(
196 vert, frag, hdrOffscreenRenderPass, texPipelineLayout, BlendMode::Multiply);
197 hdrOffscreenParticleDistortionPipeline = createTexturedStylePipeline(
198 vert, embeddedSpirv(particle_distortion_frag_spv), hdrOffscreenRenderPass, texPipelineLayout,
200 hdrOffscreenTonemapPipeline = createTexturedStylePipeline(
201 vert, embeddedSpirv(scene_tonemap_frag_spv), hdrOffscreenRenderPass, texPipelineLayout,
203 }
204 if (!hdrOffscreenLitPipeline && lit2dPipelineLayout) {
205 auto lvert = embeddedSpirv(lit2d_vert_spv);
206 auto lfrag = embeddedSpirv(lit2d_frag_spv);
207 hdrOffscreenLitPipeline =
208 createTexturedStylePipeline(lvert, lfrag, hdrOffscreenRenderPass, lit2dPipelineLayout);
209 hdrOffscreenLitAdditivePipeline =
210 createTexturedStylePipeline(lvert, lfrag, hdrOffscreenRenderPass, lit2dPipelineLayout, BlendMode::Additive);
211 hdrOffscreenLitPremultipliedPipeline = createTexturedStylePipeline(
212 lvert, lfrag, hdrOffscreenRenderPass, lit2dPipelineLayout, BlendMode::Premultiplied);
213 hdrOffscreenLitMultiplyPipeline =
214 createTexturedStylePipeline(lvert, lfrag, hdrOffscreenRenderPass, lit2dPipelineLayout, BlendMode::Multiply);
215 hdrOffscreenLitOpaquePipeline =
216 createTexturedStylePipeline(lvert, lfrag, hdrOffscreenRenderPass, lit2dPipelineLayout, BlendMode::Opaque);
217 }
218 ensureHdrGpuParticleDrawPipelines();
219 for (auto &shader : ownedShaders) ensureShaderHdrOffscreenPipeline(shader.get());
220}
221
222void Graphics::ensureShaderHdrOffscreenPipeline(Shader *shader) {
223 if (!shader || !shader->gpuHandle || !hdrOffscreenRenderPass) return;
224 if (shader->getKind() == Shader::Kind::eMesh3D) return;
225 auto *gpu = static_cast<GpuShader *>(shader->gpuHandle);
226 if (gpu->isMesh3D || gpu->hdrOffscreenPipeline) return;
227 gpu->hdrOffscreenPipeline = createTexturedStylePipeline(
228 shader->vertexSpirv(), shader->fragmentSpirv(), hdrOffscreenRenderPass,
229 shaderPipelineLayout);
230 gpu->hdrOffscreenOpaquePipeline = createTexturedStylePipeline(
231 shader->vertexSpirv(), shader->fragmentSpirv(), hdrOffscreenRenderPass,
232 shaderPipelineLayout, BlendMode::Opaque);
233}
234
235
236} // namespace eve::graphics::vulkan
std::string layout
vkb::Device & device
vk::ShaderModule vert
vk::ShaderModule frag
Shader * shader
vk::Pipeline createSolidColorPipeline(vkb::Device &device, const vkb::BuiltRenderPass &renderPass, vk::PipelineLayout layout, BlendMode mode)
Internal synchronous pipeline factory; caller destroys the returned Vulkan pipeline.
BlendMode
Render-neutral 2D blend mode shared by graphics-facing modules.
Definition RenderTypes.h:11
glm::vec4 color