46 auto cs_shader = am.get_asset<
gfx::shader>(
"engine:/data/shaders/assao/" + cs +
".sc");
48 auto prog = std::make_shared<gpu_program>(cs_shader);
49 m_programs.emplace_back(prog);
54 u_rect = bgfx::createUniform(
"u_rect", bgfx::UniformType::Vec4);
58 s_normal = bgfx::createUniform(
"s_normal", bgfx::UniformType::Sampler);
59 s_depth = bgfx::createUniform(
"s_depth", bgfx::UniformType::Sampler);
62 s_ao = bgfx::createUniform(
"s_ao", bgfx::UniformType::Sampler);
63 s_blurInput = bgfx::createUniform(
"s_blurInput", bgfx::UniformType::Sampler);
64 s_finalSSAO = bgfx::createUniform(
"s_finalSSAO", bgfx::UniformType::Sampler);
65 s_depthSource = bgfx::createUniform(
"s_depthSource", bgfx::UniformType::Sampler);
66 s_viewspaceDepthSource = bgfx::createUniform(
"s_viewspaceDepthSource", bgfx::UniformType::Sampler);
67 s_viewspaceDepthSourceMirror = bgfx::createUniform(
"s_viewspaceDepthSourceMirror", bgfx::UniformType::Sampler);
68 s_importanceMap = bgfx::createUniform(
"s_importanceMap", bgfx::UniformType::Sampler);
74 m_prepareDepthsProgram =
loadProgram(
"cs_assao_prepare_depths");
75 m_prepareDepthsAndNormalsProgram =
loadProgram(
"cs_assao_prepare_depths_and_normals");
76 m_prepareDepthsHalfProgram =
loadProgram(
"cs_assao_prepare_depths_half");
77 m_prepareDepthsAndNormalsHalfProgram =
loadProgram(
"cs_assao_prepare_depths_and_normals_half");
78 m_prepareDepthMipProgram =
loadProgram(
"cs_assao_prepare_depth_mip");
79 m_generateQ0Program =
loadProgram(
"cs_assao_generate_q0");
80 m_generateQ1Program =
loadProgram(
"cs_assao_generate_q1");
81 m_generateQ2Program =
loadProgram(
"cs_assao_generate_q2");
82 m_generateQ3Program =
loadProgram(
"cs_assao_generate_q3");
83 m_generateQ3BaseProgram =
loadProgram(
"cs_assao_generate_q3base");
84 m_generateQ0ProgramRgba16f =
loadProgram(
"cs_assao_generate_q0_normal_rgba16f");
85 m_generateQ1ProgramRgba16f =
loadProgram(
"cs_assao_generate_q1_normal_rgba16f");
86 m_generateQ2ProgramRgba16f =
loadProgram(
"cs_assao_generate_q2_normal_rgba16f");
87 m_generateQ3ProgramRgba16f =
loadProgram(
"cs_assao_generate_q3_normal_rgba16f");
88 m_generateQ3BaseProgramRgba16f =
loadProgram(
"cs_assao_generate_q3base_normal_rgba16f");
89 m_smartBlurProgram =
loadProgram(
"cs_assao_smart_blur");
90 m_smartBlurWideProgram =
loadProgram(
"cs_assao_smart_blur_wide");
91 m_nonSmartBlurProgram =
loadProgram(
"cs_assao_non_smart_blur");
93 m_nonSmartApplyProgram =
loadProgram(
"cs_assao_non_smart_apply");
94 m_nonSmartHalfApplyProgram =
loadProgram(
"cs_assao_non_smart_half_apply");
95 m_generateImportanceMapProgram =
loadProgram(
"cs_assao_generate_importance_map");
96 m_postprocessImportanceMapAProgram =
loadProgram(
"cs_assao_postprocess_importance_map_a");
97 m_postprocessImportanceMapBProgram =
loadProgram(
"cs_assao_postprocess_importance_map_b");
98 m_loadCounterClearProgram =
loadProgram(
"cs_assao_load_counter_clear");
99 m_updateGBufferProgram =
loadProgram(
"cs_assao_update_g_buffer");
102 m_loadCounter = bgfx::createDynamicIndexBuffer(1, BGFX_BUFFER_COMPUTE_READ_WRITE | BGFX_BUFFER_INDEX32);
109 m_settings = params.
params;
116 if(m_size[0] != (int32_t)m_width - 2 * m_border || m_size[1] != (int32_t)m_height - 2 * m_border)
118 destroy_frame_buffers();
119 create_frame_buffers();
122 const float* viewMtx = cam.
get_view();
131 bx::mtxProj(projMtx, fovy,
float(m_size[0]) /
float(m_size[1]), n, f,
false);
136 const frect_t rect = {-(float(m_size[0]) / 2.0f) * zoom,
137 (
float(m_size[1]) / 2.0f) * zoom,
138 (float(m_size[0]) / 2.0f) * zoom,
139 -(
float(m_size[1]) / 2.0f) * zoom};
146 update_uniforms(0, viewMtx, projMtx);
157 bgfx::setImage(5, m_normals, 0, bgfx::Access::Write);
162 for(int32_t j = 0; j < 2; ++j)
164 bgfx::setImage((uint8_t)(j + 1), m_halfDepths[j == 0 ? 0 : 3], 0, bgfx::Access::Write);
169 : m_prepareDepthsHalfProgram,
170 (m_halfSize[0] + 7) / 8,
171 (m_halfSize[1] + 7) / 8);
175 for(int32_t j = 0; j < 4; ++j)
177 bgfx::setImage((uint8_t)(j + 1), m_halfDepths[j], 0, bgfx::Access::Write);
181 m_settings.
generate_normals ? m_prepareDepthsAndNormalsProgram : m_prepareDepthsProgram,
182 (m_halfSize[0] + 7) / 8,
183 (m_halfSize[1] + 7) / 8);
190 uint16_t mipWidth = (uint16_t)m_halfSize[0];
191 uint16_t mipHeight = (uint16_t)m_halfSize[1];
195 mipWidth = (uint16_t)bx::max(1, mipWidth >> 1);
196 mipHeight = (uint16_t)bx::max(1, mipHeight >> 1);
198 for(uint8_t j = 0; j < 4; ++j)
200 bgfx::setImage(j, m_halfDepths[j], i - 1, bgfx::Access::Read);
201 bgfx::setImage(j + 4, m_halfDepths[j], i, bgfx::Access::Write);
205 float rect[4] = {0.0f, 0.0f, (float)mipWidth, (
float)mipHeight};
206 bgfx::setUniform(u_rect,
rect);
208 bgfx::dispatch(view, m_prepareDepthMipProgram, (mipWidth + 7) / 8, (mipHeight + 7) / 8);
213 for(int32_t ssaoPass = 0; ssaoPass < 2; ++ssaoPass)
222 gfx::render_pass pass(fmt::format(
"importance map pass {}", ssaoPass).c_str());
226 bool adaptiveBasePass = (ssaoPass == 0);
228 BX_UNUSED(adaptiveBasePass);
230 int32_t passCount = 4;
232 int32_t halfResNumX = (m_halfResOutScissorRect[2] - m_halfResOutScissorRect[0] + 7) / 8;
233 int32_t halfResNumY = (m_halfResOutScissorRect[3] - m_halfResOutScissorRect[1] + 7) / 8;
234 float halfResRect[4] = {(float)m_halfResOutScissorRect[0],
235 (
float)m_halfResOutScissorRect[1],
236 (float)m_halfResOutScissorRect[2],
237 (
float)m_halfResOutScissorRect[3]};
239 for(int32_t pass = 0; pass < passCount; pass++)
247 blurPasses = bx::min(blurPasses, cMaxBlurPassCount);
259 blurPasses = bx::max(1, blurPasses);
268 update_uniforms(pass, viewMtx, projMtx);
270 bgfx::TextureHandle pPingRT = m_pingPongHalfResultA;
271 bgfx::TextureHandle pPongRT = m_pingPongHalfResultB;
275 bgfx::setImage(6, blurPasses == 0 ? m_finalResults : pPingRT, 0, bgfx::Access::Write);
277 bgfx::setUniform(u_rect, halfResRect);
283 bgfx::setImage(2, m_normals, 0, bgfx::Access::Read);
292 bgfx::setBuffer(3, m_loadCounter, bgfx::Access::Read);
294 bgfx::setImage(5, m_finalResults, 0, bgfx::Access::Read);
297 bgfx::ProgramHandle programsNormal[5] = {m_generateQ0Program,
301 m_generateQ3BaseProgram};
303 bgfx::ProgramHandle programsRgba16f[5] = {m_generateQ0ProgramRgba16f,
304 m_generateQ1ProgramRgba16f,
305 m_generateQ2ProgramRgba16f,
306 m_generateQ3ProgramRgba16f,
307 m_generateQ3BaseProgramRgba16f};
309 bgfx::ProgramHandle* programs = programsNormal;
313 programs = programsRgba16f;
316 int32_t programIndex = bx::max(0, (!adaptiveBasePass) ? (m_settings.
quality_level) : (4));
318 m_uniforms.m_layer = blurPasses == 0 ? (float)pass : 0.0f;
320 bgfx::dispatch(view, programs[programIndex], halfResNumX, halfResNumY);
326 int32_t wideBlursRemaining = bx::max(0, blurPasses - 2);
328 for(int32_t i = 0; i < blurPasses; i++)
330 bgfx::setViewFrameBuffer(view, BGFX_INVALID_HANDLE);
333 m_uniforms.m_layer = ((i == (blurPasses - 1)) ? (float)pass : 0.0f);
336 bgfx::setUniform(u_rect, halfResRect);
338 bgfx::setImage(0, i == (blurPasses - 1) ? m_finalResults : pPongRT, 0, bgfx::Access::Write);
346 if(wideBlursRemaining > 0)
348 bgfx::dispatch(view, m_smartBlurWideProgram, halfResNumX, halfResNumY);
349 wideBlursRemaining--;
353 bgfx::dispatch(view, m_smartBlurProgram, halfResNumX, halfResNumY);
359 m_nonSmartBlurProgram,
364 bgfx::TextureHandle temp = pPingRT;
374 bgfx::setImage(0, m_importanceMap, 0, bgfx::Access::Write);
377 m_generateImportanceMapProgram,
378 (m_quarterSize[0] + 7) / 8,
379 (m_quarterSize[1] + 7) / 8);
382 bgfx::setImage(0, m_importanceMapPong, 0, bgfx::Access::Write);
383 bgfx::setTexture(1, s_importanceMap, m_importanceMap);
385 m_postprocessImportanceMapAProgram,
386 (m_quarterSize[0] + 7) / 8,
387 (m_quarterSize[1] + 7) / 8);
389 bgfx::setBuffer(0, m_loadCounter, bgfx::Access::ReadWrite);
390 bgfx::dispatch(view, m_loadCounterClearProgram, 1, 1);
393 bgfx::setImage(0, m_importanceMap, 0, bgfx::Access::Write);
394 bgfx::setTexture(1, s_importanceMap, m_importanceMapPong);
395 bgfx::setBuffer(2, m_loadCounter, bgfx::Access::ReadWrite);
397 m_postprocessImportanceMapBProgram,
398 (m_quarterSize[0] + 7) / 8,
399 (m_quarterSize[1] + 7) / 8);
406 bgfx::setImage(0, m_aoMap, 0, bgfx::Access::Write);
407 bgfx::setTexture(1, s_finalSSAO, m_finalResults);
411 float rect[4] = {(float)m_fullResOutScissorRect[0],
412 (
float)m_fullResOutScissorRect[1],
413 (float)m_fullResOutScissorRect[2],
414 (
float)m_fullResOutScissorRect[3]};
415 bgfx::setUniform(u_rect,
rect);
417 bgfx::ProgramHandle program;
419 program = m_nonSmartHalfApplyProgram;
421 program = m_nonSmartApplyProgram;
423 program = m_applyProgram;
426 (m_fullResOutScissorRect[2] - m_fullResOutScissorRect[0] + 7) / 8,
427 (m_fullResOutScissorRect[3] - m_fullResOutScissorRect[1] + 7) / 8);
435 bgfx::setImage(1, m_aoMap, 0, bgfx::Access::Read);
437 bgfx::dispatch(pass.
id, m_updateGBufferProgram, (m_size[0] + 7) / 8, (m_size[1] + 7) / 8);