Skip to content

Commit 24a72ca

Browse files
committed
Prevent dynamic memory allocations during root-constant setup in program bindings
1 parent b0bfccd commit 24a72ca

File tree

6 files changed

+78
-61
lines changed

6 files changed

+78
-61
lines changed

Apps/02-HelloCube/HelloCubeApp.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ using namespace Methane::Graphics;
4747
struct HelloCubeFrame final : AppFrame
4848
{
4949
#ifdef UNIFORMS_ENABLED
50-
Rhi::ProgramBindings program_bindings;
50+
Rhi::ProgramBindings program_bindings;
51+
rhi::IProgramArgumentBinding* uniforms_binding_ptr = nullptr;
5152
#else
5253
Rhi::BufferSet vertex_buffer_set;
5354
#endif
@@ -195,6 +196,7 @@ class HelloCubeApp final // NOSONAR - destructor required
195196
// Configure program resource bindings
196197
frame.program_bindings = m_render_state.GetProgram().CreateBindings({ }, frame.index);
197198
frame.program_bindings.SetName(fmt::format("Cube Bindings {}", frame.index));
199+
frame.uniforms_binding_ptr = &frame.program_bindings.Get({ Rhi::ShaderType::Vertex, "g_uniforms" });
198200
#else
199201
// Create vertex buffers for each frame
200202
Rhi::Buffer vertex_buffer = GetRenderContext().CreateBuffer(Rhi::BufferSettings::ForVertexBuffer(m_cube_mesh.GetVertexDataSize(), m_cube_mesh.GetVertexSize(), true));
@@ -232,11 +234,10 @@ class HelloCubeApp final // NOSONAR - destructor required
232234
#ifdef UNIFORMS_ENABLED
233235
// Save transposed camera Model-View-Projection matrix in shader uniforms
234236
// Before frame rendering set uniforms to root constant buffer to be uploaded to GPU
235-
hlslpp::Uniforms shader_uniforms{ hlslpp::transpose(mvp_matrix) };
237+
const hlslpp::Uniforms shader_uniforms{ hlslpp::transpose(mvp_matrix) };
236238

237239
// Update root constant in program bindings to apply model-view-projection transformation in vertex shader on GPU
238-
frame.program_bindings.Get({ Rhi::ShaderType::Vertex, "g_uniforms" })
239-
.SetRootConstant(Rhi::RootConstant(shader_uniforms));
240+
frame.uniforms_binding_ptr->SetRootConstant(Rhi::RootConstant(shader_uniforms));
240241
#else
241242
// Update vertex buffer with camera Model-View-Projection matrix applied on CPU
242243
for(size_t vertex_index = 0; vertex_index < m_proj_vertices.size(); ++vertex_index)

Apps/03-TexturedCube/TexturedCubeApp.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ void TexturedCubeApp::Init()
161161
{ { rhi::ShaderType::Pixel, "g_sampler" }, m_texture_sampler.GetResourceView() }
162162
}, frame.index);
163163
frame.program_bindings.SetName(fmt::format("Cube Bindings {}", frame.index));
164+
frame.uniforms_binding_ptr = &frame.program_bindings.Get({ rhi::ShaderType::All, "g_uniforms" });
164165

165166
// Create command list for rendering
166167
frame.render_cmd_list = render_cmd_queue.CreateRenderCommandList(frame.screen_pass);
@@ -199,10 +200,7 @@ bool TexturedCubeApp::Update()
199200
m_shader_uniforms.mvp_matrix = hlslpp::transpose(hlslpp::mul(m_shader_uniforms.model_matrix, m_camera.GetViewProjMatrix()));
200201
m_shader_uniforms.eye_position = m_camera.GetOrientation().eye;
201202

202-
const TexturedCubeFrame& frame = GetCurrentFrame();
203-
frame.program_bindings.Get({ rhi::ShaderType::All, "g_uniforms" })
204-
.SetRootConstant(rhi::RootConstant(m_shader_uniforms));
205-
203+
GetCurrentFrame().uniforms_binding_ptr->SetRootConstant(rhi::RootConstant(m_shader_uniforms));
206204
return true;
207205
}
208206

@@ -211,10 +209,9 @@ bool TexturedCubeApp::Render()
211209
if (!UserInterfaceApp::Render())
212210
return false;
213211

214-
const TexturedCubeFrame& frame = GetCurrentFrame();
215-
216212
// Issue commands for cube rendering
217213
META_DEBUG_GROUP_VAR(s_debug_group, "Cube Rendering");
214+
const TexturedCubeFrame& frame = GetCurrentFrame();
218215
frame.render_cmd_list.ResetWithState(m_render_state, &s_debug_group);
219216
frame.render_cmd_list.SetViewState(GetViewState());
220217
frame.render_cmd_list.SetProgramBindings(frame.program_bindings);

Apps/03-TexturedCube/TexturedCubeApp.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,10 @@ namespace rhi = Methane::Graphics::Rhi;
4141

4242
struct TexturedCubeFrame final : Graphics::AppFrame
4343
{
44-
rhi::ProgramBindings program_bindings;
45-
rhi::RenderCommandList render_cmd_list;
46-
rhi::CommandListSet execute_cmd_list_set;
44+
rhi::ProgramBindings program_bindings;
45+
rhi::IProgramArgumentBinding* uniforms_binding_ptr = nullptr;
46+
rhi::RenderCommandList render_cmd_list;
47+
rhi::CommandListSet execute_cmd_list_set;
4748

4849
using gfx::AppFrame::AppFrame;
4950
};

Apps/04-ShadowCube/ShadowCubeApp.cpp

Lines changed: 51 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,16 @@ void ShadowCubeApp::Init()
227227
// ========= Shadow Pass Resources =========
228228

229229
// Shadow-pass resource bindings for cube rendering
230-
frame.shadow_pass.cube_program_bindings = shadow_state_settings.program.CreateBindings({ }, frame.index);
231-
frame.shadow_pass.cube_program_bindings.SetName(fmt::format("Cube Shadow-Pass Bindings {}", frame.index));
230+
ShadowCubeFrame::PassResources::ProgramBindings& shadow_cube_binds = frame.shadow_pass.cube_bindings;
231+
shadow_cube_binds.program_bindings = shadow_state_settings.program.CreateBindings({ }, frame.index);
232+
shadow_cube_binds.program_bindings.SetName(fmt::format("Cube Shadow-Pass Bindings {}", frame.index));
233+
shadow_cube_binds.mesh_uniforms_binding_ptr = &shadow_cube_binds.program_bindings.Get({ rhi::ShaderType::Vertex, "g_mesh_uniforms" });
232234

233235
// Shadow-pass resource bindings for floor rendering
234-
frame.shadow_pass.floor_program_bindings = shadow_state_settings.program.CreateBindings({}, frame.index);
235-
frame.shadow_pass.floor_program_bindings.SetName(fmt::format("Floor Shadow-Pass Bindings {}", frame.index));
236+
ShadowCubeFrame::PassResources::ProgramBindings& shadow_floor_binds = frame.shadow_pass.floor_bindings;
237+
shadow_floor_binds.program_bindings = shadow_state_settings.program.CreateBindings({}, frame.index);
238+
shadow_floor_binds.program_bindings.SetName(fmt::format("Floor Shadow-Pass Bindings {}", frame.index));
239+
shadow_floor_binds.mesh_uniforms_binding_ptr = &shadow_cube_binds.program_bindings.Get({ rhi::ShaderType::Vertex, "g_mesh_uniforms" });
236240

237241
// Create depth texture for shadow map rendering
238242
frame.shadow_pass.rt_texture = render_context.CreateTexture(shadow_texture_settings);
@@ -251,20 +255,26 @@ void ShadowCubeApp::Init()
251255
// ========= Final Pass Resources =========
252256

253257
// Final-pass resource bindings for cube rendering
254-
frame.final_pass.cube_program_bindings = final_state_settings.program.CreateBindings({
258+
ShadowCubeFrame::PassResources::ProgramBindings& final_cube_binds = frame.final_pass.cube_bindings;
259+
final_cube_binds.program_bindings = final_state_settings.program.CreateBindings({
255260
{ { rhi::ShaderType::Pixel, "g_constants" }, rhi::RootConstant(g_scene_constants) },
256261
{ { rhi::ShaderType::Pixel, "g_shadow_map" }, frame.shadow_pass.rt_texture.GetResourceView() },
257262
{ { rhi::ShaderType::Pixel, "g_shadow_sampler" }, m_shadow_sampler.GetResourceView() },
258263
{ { rhi::ShaderType::Pixel, "g_texture" }, m_cube_buffers_ptr->GetTexture().GetResourceView() },
259264
{ { rhi::ShaderType::Pixel, "g_texture_sampler"}, m_texture_sampler.GetResourceView() },
260265
}, frame.index);
261-
frame.final_pass.cube_program_bindings.SetName(fmt::format("Cube Final-Pass Bindings {}", frame.index));
266+
final_cube_binds.program_bindings.SetName(fmt::format("Cube Final-Pass Bindings {}", frame.index));
267+
final_cube_binds.scene_uniforms_binding_ptr = &final_cube_binds.program_bindings.Get({ rhi::ShaderType::Pixel, "g_scene_uniforms" });
268+
final_cube_binds.mesh_uniforms_binding_ptr = &final_cube_binds.program_bindings.Get({ rhi::ShaderType::Vertex, "g_mesh_uniforms" });
262269

263270
// Final-pass resource bindings for floor rendering - patched a copy of cube bindings
264-
frame.final_pass.floor_program_bindings = rhi::ProgramBindings(frame.final_pass.cube_program_bindings, {
271+
ShadowCubeFrame::PassResources::ProgramBindings& final_floor_binds = frame.final_pass.floor_bindings;
272+
final_floor_binds.program_bindings = rhi::ProgramBindings(frame.final_pass.cube_bindings.program_bindings, {
265273
{ { rhi::ShaderType::Pixel, "g_texture" }, m_floor_buffers_ptr->GetTexture().GetResourceView() },
266274
}, frame.index);
267-
frame.final_pass.floor_program_bindings.SetName(fmt::format("Floor Final-Pass Bindings {}", frame.index));
275+
final_floor_binds.program_bindings.SetName(fmt::format("Floor Final-Pass Bindings {}", frame.index));
276+
final_floor_binds.scene_uniforms_binding_ptr = &final_floor_binds.program_bindings.Get({ rhi::ShaderType::Pixel, "g_scene_uniforms" });
277+
final_floor_binds.mesh_uniforms_binding_ptr = &final_floor_binds.program_bindings.Get({ rhi::ShaderType::Vertex, "g_mesh_uniforms" });
268278

269279
// Bind final pass RT texture and pass to the frame buffer texture and final pass.
270280
frame.final_pass.rt_texture = frame.screen_texture;
@@ -314,12 +324,11 @@ bool ShadowCubeApp::Update()
314324
if (!UserInterfaceApp::Update())
315325
return false;
316326

317-
// Update scene uniforms
318-
const rhi::RootConstant scene_uniforms_constant(
319-
hlslpp::SceneUniforms{
320-
/* eye_position */ hlslpp::float4(m_view_camera.GetOrientation().eye, 1.F),
321-
/* light_position */ hlslpp::float4(m_light_camera.GetOrientation().eye, 1.F)
322-
});
327+
const hlslpp::SceneUniforms scene_uniforms{
328+
/* eye_position */ hlslpp::float4(m_view_camera.GetOrientation().eye, 1.F),
329+
/* light_position */ hlslpp::float4(m_light_camera.GetOrientation().eye, 1.F)
330+
};
331+
const rhi::RootConstant scene_uniforms_constant(scene_uniforms);
323332

324333
// Prepare homogenous [-1,1] to texture [0,1] coordinates transformation matrix
325334
static const hlslpp::float4x4 s_homogen_to_texture_coords_matrix = hlslpp::mul(
@@ -333,38 +342,34 @@ bool ShadowCubeApp::Update()
333342
const ShadowCubeFrame& frame = GetCurrentFrame();
334343

335344
// Update Cube uniforms
336-
frame.final_pass.cube_program_bindings.Get({ rhi::ShaderType::Pixel, "g_scene_uniforms" }).SetRootConstant(scene_uniforms_constant);
337-
frame.final_pass.cube_program_bindings.Get({ rhi::ShaderType::Vertex, "g_mesh_uniforms" }).SetRootConstant(
338-
rhi::RootConstant(hlslpp::MeshUniforms{
339-
hlslpp::transpose(cube_model_matrix),
340-
hlslpp::transpose(hlslpp::mul(cube_model_matrix, m_view_camera.GetViewProjMatrix())),
341-
hlslpp::transpose(hlslpp::mul(hlslpp::mul(cube_model_matrix, m_light_camera.GetViewProjMatrix()), s_homogen_to_texture_coords_matrix))
342-
})
343-
);
344-
frame.shadow_pass.cube_program_bindings.Get({ rhi::ShaderType::Vertex, "g_mesh_uniforms" }).SetRootConstant(
345-
rhi::RootConstant(hlslpp::MeshUniforms{
346-
hlslpp::transpose(cube_model_matrix),
347-
hlslpp::transpose(hlslpp::mul(cube_model_matrix, m_light_camera.GetViewProjMatrix())),
348-
hlslpp::float4x4()
349-
})
350-
);
345+
const hlslpp::MeshUniforms final_cube_uniforms{
346+
hlslpp::transpose(cube_model_matrix),
347+
hlslpp::transpose(hlslpp::mul(cube_model_matrix, m_view_camera.GetViewProjMatrix())),
348+
hlslpp::transpose(hlslpp::mul(hlslpp::mul(cube_model_matrix, m_light_camera.GetViewProjMatrix()), s_homogen_to_texture_coords_matrix))
349+
};
350+
const hlslpp::MeshUniforms shadow_cube_uniforms{
351+
hlslpp::transpose(cube_model_matrix),
352+
hlslpp::transpose(hlslpp::mul(cube_model_matrix, m_light_camera.GetViewProjMatrix())),
353+
hlslpp::float4x4()
354+
};
355+
frame.final_pass.cube_bindings.scene_uniforms_binding_ptr->SetRootConstant(scene_uniforms_constant);
356+
frame.final_pass.cube_bindings.mesh_uniforms_binding_ptr->SetRootConstant(rhi::RootConstant(final_cube_uniforms));
357+
frame.shadow_pass.cube_bindings.mesh_uniforms_binding_ptr->SetRootConstant(rhi::RootConstant(shadow_cube_uniforms));
351358

352359
// Update Floor uniforms
353-
frame.final_pass.floor_program_bindings.Get({ rhi::ShaderType::Pixel, "g_scene_uniforms" }).SetRootConstant(scene_uniforms_constant);
354-
frame.final_pass.floor_program_bindings.Get({ rhi::ShaderType::Vertex, "g_mesh_uniforms" }).SetRootConstant(
355-
rhi::RootConstant(hlslpp::MeshUniforms{
356-
hlslpp::transpose(scale_matrix),
357-
hlslpp::transpose(hlslpp::mul(scale_matrix, m_view_camera.GetViewProjMatrix())),
358-
hlslpp::transpose(hlslpp::mul(hlslpp::mul(scale_matrix, m_light_camera.GetViewProjMatrix()), s_homogen_to_texture_coords_matrix))
359-
})
360-
);
361-
frame.shadow_pass.floor_program_bindings.Get({ rhi::ShaderType::Vertex, "g_mesh_uniforms" }).SetRootConstant(
362-
rhi::RootConstant(hlslpp::MeshUniforms{
363-
hlslpp::transpose(scale_matrix),
364-
hlslpp::transpose(hlslpp::mul(scale_matrix, m_light_camera.GetViewProjMatrix())),
365-
hlslpp::float4x4()
366-
})
367-
);
360+
const hlslpp::MeshUniforms final_floor_uniforms{
361+
hlslpp::transpose(scale_matrix),
362+
hlslpp::transpose(hlslpp::mul(scale_matrix, m_view_camera.GetViewProjMatrix())),
363+
hlslpp::transpose(hlslpp::mul(hlslpp::mul(scale_matrix, m_light_camera.GetViewProjMatrix()), s_homogen_to_texture_coords_matrix))
364+
};
365+
const hlslpp::MeshUniforms shadow_floor_uniforms{
366+
hlslpp::transpose(scale_matrix),
367+
hlslpp::transpose(hlslpp::mul(scale_matrix, m_light_camera.GetViewProjMatrix())),
368+
hlslpp::float4x4()
369+
};
370+
frame.final_pass.floor_bindings.scene_uniforms_binding_ptr->SetRootConstant(scene_uniforms_constant);
371+
frame.final_pass.floor_bindings.mesh_uniforms_binding_ptr->SetRootConstant(rhi::RootConstant(final_floor_uniforms));
372+
frame.shadow_pass.floor_bindings.mesh_uniforms_binding_ptr->SetRootConstant(rhi::RootConstant(shadow_floor_uniforms));
368373

369374
return true;
370375
}
@@ -395,8 +400,8 @@ void ShadowCubeApp::RenderScene(const RenderPassState& render_pass, const Shadow
395400
cmd_list.SetViewState(render_pass.view_state);
396401

397402
// Draw scene with cube and floor
398-
m_cube_buffers_ptr->Draw(cmd_list, render_pass_resources.cube_program_bindings);
399-
m_floor_buffers_ptr->Draw(cmd_list, render_pass_resources.floor_program_bindings);
403+
m_cube_buffers_ptr->Draw(cmd_list, render_pass_resources.cube_bindings.program_bindings);
404+
m_floor_buffers_ptr->Draw(cmd_list, render_pass_resources.floor_bindings.program_bindings);
400405

401406
if (render_pass.is_final_pass)
402407
{

Apps/04-ShadowCube/ShadowCubeApp.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,18 @@ struct ShadowCubeFrame final
4545
{
4646
struct PassResources
4747
{
48-
rhi::ProgramBindings cube_program_bindings;
49-
rhi::ProgramBindings floor_program_bindings;
48+
struct ProgramBindings
49+
{
50+
rhi::ProgramBindings program_bindings;
51+
rhi::IProgramArgumentBinding* scene_uniforms_binding_ptr = nullptr;
52+
rhi::IProgramArgumentBinding* mesh_uniforms_binding_ptr = nullptr;
53+
};
54+
5055
rhi::Texture rt_texture;
5156
rhi::RenderPass render_pass;
5257
rhi::RenderCommandList cmd_list;
58+
ProgramBindings cube_bindings;
59+
ProgramBindings floor_bindings;
5360
};
5461

5562
PassResources shadow_pass;

Modules/Data/Types/Include/Methane/Data/Chunk.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ class Chunk // NOSONAR - rule of zero is not applicable
4343
, m_data_size(static_cast<Size>(m_data_storage.size()))
4444
{ }
4545

46+
template<typename T>
47+
explicit Chunk(T& value)
48+
: m_data_ptr(GetByteAddress(value))
49+
, m_data_size(static_cast<Size>(sizeof(T)))
50+
{ }
51+
4652
template<typename T>
4753
explicit Chunk(T&& value)
4854
: m_data_storage(GetByteAddress(value), GetByteAddress(value) + sizeof(T))

0 commit comments

Comments
 (0)