Skip to content

Commit

Permalink
Use automatic root constant buffer bindings instead of manually creat…
Browse files Browse the repository at this point in the history
…ed uniform buffers
  • Loading branch information
egorodet committed Jan 2, 2025
1 parent dd6ddbc commit 3f777d5
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 99 deletions.
67 changes: 32 additions & 35 deletions App/AsteroidsApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ static const std::map<pin::Keyboard::State, AsteroidsAppAction> g_asteroids_acti
{ { pin::Keyboard::Key::Num9 }, AsteroidsAppAction::SetComplexity9 },
};

static const float g_scene_scale = 15.F;
static const hlslpp::SceneConstants g_scene_constants{
{ 1.F, 1.F, 1.F, 1.F }, // - light_color
3.0F, // - light_power
0.05F, // - light_ambient_factor
30.F // - light_specular_factor
};

void AsteroidsFrame::ReleaseScreenPassAttachmentTextures()
{
META_FUNCTION_TASK();
Expand Down Expand Up @@ -150,7 +158,7 @@ AsteroidsApp::AsteroidsApp()
, m_asteroids_array_settings( // Asteroids array settings:
{ // ================
m_view_camera, // - view_camera
m_scene_scale, // - scale
g_scene_scale, // - scale
GetMutableParameters().instances_count, // - instance_count
GetMutableParameters().unique_mesh_count, // - unique_mesh_count
4U, // - subdivisions_count
Expand Down Expand Up @@ -272,7 +280,7 @@ void AsteroidsApp::Init()
gfx::SkyBox::Settings
{
m_view_camera,
m_scene_scale * 100.F,
g_scene_scale * 100.F,
{ gfx::SkyBox::Option::DepthEnabled, gfx::SkyBox::Option::DepthReversed }
});

Expand All @@ -284,7 +292,7 @@ void AsteroidsApp::Init()
m_light_camera,
"Planet/Mars.jpg", // texture_path
hlslpp::float3(0.F, 0.F, 0.F), // position
m_scene_scale * 3.F, // scale
g_scene_scale * 3.F, // scale
0.1F, // spin_velocity_rps
true, // depth_reversed
{ gfx::ImageOption::Mipmapped, // image_options
Expand All @@ -299,15 +307,14 @@ void AsteroidsApp::Init()
: std::make_unique<AsteroidsArray>(render_cmd_queue, m_asteroids_render_pattern, m_asteroids_array_settings);

const auto constants_data_size = static_cast<Data::Size>(sizeof(hlslpp::SceneConstants));
const auto scene_uniforms_data_size = static_cast<Data::Size>(sizeof(hlslpp::SceneUniforms));
const Data::Size asteroid_uniforms_data_size = m_asteroids_array_ptr->GetUniformsBufferSize();

// Create constants buffer for frame rendering
m_const_buffer = context.CreateBuffer(rhi::BufferSettings::ForConstantBuffer(constants_data_size));
m_const_buffer.SetName("Constants Buffer");
m_const_buffer.SetData(render_cmd_queue, {
reinterpret_cast<Data::ConstRawPtr>(&m_scene_constants),
sizeof(m_scene_constants)
reinterpret_cast<Data::ConstRawPtr>(&g_scene_constants),
sizeof(g_scene_constants)
});

// ========= Per-Frame Data =========
Expand Down Expand Up @@ -335,18 +342,6 @@ void AsteroidsApp::Init()
// Rendering command lists sequence
frame.execute_cmd_list_set = CreateExecuteCommandListSet(frame);

// Create uniforms buffer with volatile parameters for the whole scene rendering
frame.scene_uniforms_buffer = context.CreateBuffer(rhi::BufferSettings::ForConstantBuffer(scene_uniforms_data_size, false, true));
frame.scene_uniforms_buffer.SetName(fmt::format("Scene Uniforms Buffer {}", frame.index));

// Create uniforms buffer for Sky-Box rendering
frame.sky_box.uniforms_buffer = context.CreateBuffer(rhi::BufferSettings::ForConstantBuffer(gfx::SkyBox::GetUniformsSize(), false, true));
frame.sky_box.uniforms_buffer.SetName(fmt::format("Sky-box Uniforms Buffer {}", frame.index));

// Create uniforms buffer for Planet rendering
frame.planet.uniforms_buffer = context.CreateBuffer(rhi::BufferSettings::ForConstantBuffer(sizeof(hlslpp::PlanetUniforms), false, true));
frame.planet.uniforms_buffer.SetName(fmt::format("Planet Uniforms Buffer {}", frame.index));

// Create uniforms buffer for Asteroids array rendering
frame.asteroids.uniforms_buffer = context.CreateBuffer(rhi::BufferSettings::ForConstantBuffer(asteroid_uniforms_data_size, true, true));
frame.asteroids.uniforms_buffer.SetName(fmt::format("Asteroids Array Uniforms Buffer {}", frame.index));
Expand All @@ -356,15 +351,13 @@ void AsteroidsApp::Init()
frame.sky_box.program_bindings.SetName(fmt::format("Space Sky-Box Bindings {}", frame.index));

// Resource bindings for Planet rendering
frame.planet.program_bindings = m_planet_ptr->CreateProgramBindings(m_const_buffer, frame.planet.uniforms_buffer, frame.index);
std::tie(frame.planet.program_bindings, frame.planet.uniforms_argument_binding_ptr) = m_planet_ptr->CreateProgramBindings(m_const_buffer, frame.index);
frame.planet.program_bindings.SetName(fmt::format("Planet Bindings {}", frame.index));


// Resource bindings for Asteroids rendering
frame.asteroids.program_bindings_per_instance = m_asteroids_array_ptr->CreateProgramBindings(m_const_buffer,
frame.scene_uniforms_buffer,
frame.asteroids.uniforms_buffer,
frame.index);
frame.asteroids = m_asteroids_array_ptr->CreateProgramBindings(m_const_buffer,
frame.asteroids.uniforms_buffer,
frame.index);
}

// Update initial resource states before asteroids drawing without applying barriers on GPU (automatic state propagation from Common state works),
Expand All @@ -386,14 +379,13 @@ bool AsteroidsApp::Resize(const gfx::FrameSize& frame_size, bool is_minimized)
// Update frame buffer and depth textures in initial & final render passes
for (const AsteroidsFrame& frame : GetFrames())
{
rhi::RenderPassSettings asteroids_pass_settings{
frame.asteroids_pass.Update(rhi::RenderPassSettings{
{
rhi::TextureView(frame.screen_texture.GetInterface()),
rhi::TextureView(GetDepthTexture().GetInterface())
},
frame_size
};
frame.asteroids_pass.Update(asteroids_pass_settings);
});
}

m_view_camera.Resize(frame_size);
Expand All @@ -412,9 +404,15 @@ bool AsteroidsApp::Update()
const AsteroidsFrame& frame = GetCurrentFrame();

// Update scene uniforms
m_scene_uniforms.view_proj_matrix = hlslpp::transpose(m_view_camera.GetViewProjMatrix());
m_scene_uniforms.eye_position = m_view_camera.GetOrientation().eye;
m_scene_uniforms.light_position = m_light_camera.GetOrientation().eye;
hlslpp::SceneUniforms scene_uniforms{ };
scene_uniforms.view_proj_matrix = hlslpp::transpose(m_view_camera.GetViewProjMatrix());
scene_uniforms.eye_position = m_view_camera.GetOrientation().eye;
scene_uniforms.light_position = m_light_camera.GetOrientation().eye;

// NOTE: It's enough to set root constant only for the first asteroid bindings,
// since scene uniforms argument is declared as FRAME_CONSTANT, so all asteroids
// use the same argument buffer range for all instances.
frame.asteroids.scene_uniforms_binding_ptrs[0]->SetRootConstant(rhi::RootConstant(scene_uniforms));

m_sky_box.Update(*frame.sky_box.uniforms_argument_binding_ptr);
return true;
Expand All @@ -423,7 +421,8 @@ bool AsteroidsApp::Update()
bool AsteroidsApp::Animate(double elapsed_seconds, double delta_seconds) const
{
META_FUNCTION_TASK();
bool update_result = m_planet_ptr->Update(elapsed_seconds, delta_seconds);
const AsteroidsFrame& frame = GetCurrentFrame();
bool update_result = m_planet_ptr->Update(elapsed_seconds, delta_seconds, *frame.planet.uniforms_argument_binding_ptr);
update_result |= m_asteroids_array_ptr->Update(elapsed_seconds, delta_seconds);
return update_result;
}
Expand All @@ -437,8 +436,6 @@ bool AsteroidsApp::Render()

// Upload uniform buffers to GPU
const AsteroidsFrame& frame = GetCurrentFrame();
rhi::CommandQueue render_cmd_queue = GetRenderContext().GetRenderCommandKit().GetQueue();
frame.scene_uniforms_buffer.SetData(render_cmd_queue, m_scene_uniforms_subresource);

// Asteroids rendering in parallel or in main thread
if (m_is_parallel_rendering_enabled)
Expand All @@ -453,14 +450,14 @@ bool AsteroidsApp::Render()
}

// Draw planet and sky-box after asteroids to minimize pixel overdraw
m_planet_ptr->Draw(frame.final_cmd_list, frame.planet, GetViewState());
m_planet_ptr->Draw(frame.final_cmd_list, frame.planet.program_bindings, GetViewState());
m_sky_box.Draw(frame.final_cmd_list, frame.sky_box.program_bindings, GetViewState());

RenderOverlay(frame.final_cmd_list);
frame.final_cmd_list.Commit();

// Execute rendering commands and present frame to screen
render_cmd_queue.Execute(frame.execute_cmd_list_set);
GetRenderContext().GetRenderCommandKit().GetQueue().Execute(frame.execute_cmd_list_set);
GetRenderContext().Present();

return true;
Expand Down
34 changes: 12 additions & 22 deletions App/AsteroidsApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,22 @@ namespace pin = Platform::Input;

struct AsteroidsFrame final : gfx::AppFrame
{
struct MeshBufferBindings : gfx::MeshBufferBindings
struct Bindings
{
rhi::ProgramBindings program_bindings;
rhi::IProgramArgumentBinding* uniforms_argument_binding_ptr;
};

rhi::RenderPass asteroids_pass;
rhi::ParallelRenderCommandList parallel_cmd_list;
rhi::RenderCommandList serial_cmd_list;
rhi::RenderCommandList final_cmd_list;
rhi::CommandListSet execute_cmd_list_set;
rhi::Buffer scene_uniforms_buffer;
MeshBufferBindings sky_box;
MeshBufferBindings planet;
gfx::InstancedMeshBufferBindings asteroids;
using AsteroidMeshBufferBindings = AsteroidsArray::AsteroidMeshBufferBindings;

rhi::RenderPass asteroids_pass;
rhi::ParallelRenderCommandList parallel_cmd_list;
rhi::RenderCommandList serial_cmd_list;
rhi::RenderCommandList final_cmd_list;
rhi::CommandListSet execute_cmd_list_set;
Bindings sky_box;
Bindings planet;
AsteroidMeshBufferBindings asteroids;

using gfx::AppFrame::AppFrame;

Expand Down Expand Up @@ -102,21 +104,9 @@ class AsteroidsApp final

gfx::ActionCamera m_view_camera;
gfx::ActionCamera m_light_camera;
const float m_scene_scale = 15.F;
const hlslpp::SceneConstants m_scene_constants{
{ 1.F, 1.F, 1.F, 1.F }, // - light_color
3.0F, // - light_power
0.05F, // - light_ambient_factor
30.F // - light_specular_factor
};
AsteroidsArray::Settings m_asteroids_array_settings;
uint32_t m_asteroids_complexity = 0U;
bool m_is_parallel_rendering_enabled = true;
hlslpp::SceneUniforms m_scene_uniforms{ };
rhi::SubResource m_scene_uniforms_subresource{
reinterpret_cast<Data::ConstRawPtr>(&m_scene_uniforms), sizeof(hlslpp::SceneUniforms)
};

rhi::RenderPattern m_asteroids_render_pattern;
rhi::Buffer m_const_buffer;
gfx::SkyBox m_sky_box;
Expand Down
33 changes: 21 additions & 12 deletions Modules/Simulation/AsteroidsArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ AsteroidsArray::AsteroidsArray(const rhi::CommandQueue& render_cmd_queue,
},
rhi::Program::ArgumentAccessors
{
META_PROGRAM_ARG_ROOT_BUFFER_FRAME_CONSTANT(rhi::ShaderType::All, "g_scene_uniforms"),
META_PROGRAM_ARG_BUFFER_ADDRESS_MUTABLE(rhi::ShaderType::All, "g_mesh_uniforms")
},
render_pattern.GetAttachmentFormats()
Expand Down Expand Up @@ -302,36 +303,42 @@ AsteroidsArray::AsteroidsArray(const rhi::CommandQueue& render_cmd_queue,
Update(0.0, 0.0);
}

std::vector<rhi::ProgramBindings> AsteroidsArray::CreateProgramBindings(const rhi::Buffer& constants_buffer,
const rhi::Buffer& scene_uniforms_buffer,
const rhi::Buffer& asteroids_uniforms_buffer,
Data::Index frame_index) const
AsteroidsArray::AsteroidMeshBufferBindings AsteroidsArray::CreateProgramBindings(
const rhi::Buffer& constants_buffer,
const rhi::Buffer& asteroids_uniforms_buffer,
Data::Index frame_index) const
{
META_FUNCTION_TASK();
META_SCOPE_TIMER("AsteroidsArray::CreateProgramBindings");

std::vector<rhi::ProgramBindings> program_bindings_array;
AsteroidMeshBufferBindings asteroid_mesh_buffer_bindings;
asteroid_mesh_buffer_bindings.uniforms_buffer = asteroids_uniforms_buffer;
if (m_settings.instance_count == 0)
return program_bindings_array;
return asteroid_mesh_buffer_bindings;

std::vector<rhi::ProgramBindings>& program_bindings_array = asteroid_mesh_buffer_bindings.program_bindings_per_instance;
std::vector<rhi::IProgramArgumentBinding*>& scene_uniforms_binding_ptrs = asteroid_mesh_buffer_bindings.scene_uniforms_binding_ptrs;

const Data::Size uniform_data_size = MeshBuffers::GetUniformSize();
const rhi::ResourceViews face_texture_locations = m_settings.textures_array_enabled
? rhi::CreateResourceViews(m_unique_textures)
: rhi::CreateResourceViews(GetInstanceTexture());

program_bindings_array.resize(m_settings.instance_count);
scene_uniforms_binding_ptrs.resize(m_settings.instance_count, nullptr);

program_bindings_array[0] = m_render_state.GetProgram().CreateBindings({
{ { rhi::ShaderType::All, "g_mesh_uniforms" }, asteroids_uniforms_buffer.GetBufferView(GetUniformsBufferOffset(0), uniform_data_size) },
{ { rhi::ShaderType::All, "g_scene_uniforms" }, scene_uniforms_buffer.GetResourceView() },
{ { rhi::ShaderType::Pixel, "g_constants" }, constants_buffer.GetResourceView() },
{ { rhi::ShaderType::Pixel, "g_face_textures" }, face_texture_locations },
{ { rhi::ShaderType::Pixel, "g_texture_sampler"}, m_texture_sampler.GetResourceView() },
}, frame_index);
program_bindings_array[0].SetName(fmt::format("Asteroids[0] Bindings {}", frame_index));
scene_uniforms_binding_ptrs[0] = &program_bindings_array[0].Get({ rhi::ShaderType::All, "g_scene_uniforms" });

tf::Taskflow task_flow;
task_flow.for_each_index(1U, m_settings.instance_count, 1U,
[this, &program_bindings_array, &asteroids_uniforms_buffer, uniform_data_size, frame_index](const uint32_t asteroid_index)
[this, &program_bindings_array, &scene_uniforms_binding_ptrs, &asteroids_uniforms_buffer, uniform_data_size, frame_index](const uint32_t asteroid_index)
{
META_UNUSED(uniform_data_size); // workaround for Clang error unused-lambda-capture uniform_data_size (false positive)
const Data::Size asteroid_uniform_offset = GetUniformsBufferOffset(asteroid_index);
Expand All @@ -345,13 +352,15 @@ std::vector<rhi::ProgramBindings> AsteroidsArray::CreateProgramBindings(const rh
{ { rhi::ShaderType::Pixel, "g_face_textures" }, GetInstanceTexture(asteroid_index).GetResourceView() }
);
}
program_bindings_array[asteroid_index] = rhi::ProgramBindings(program_bindings_array[0], set_resource_view_by_argument, frame_index);
program_bindings_array[asteroid_index].SetName(fmt::format("Asteroids[{}] Bindings {}", asteroid_index, frame_index));
rhi::ProgramBindings& asteroid_program_bindings = program_bindings_array[asteroid_index];
asteroid_program_bindings = rhi::ProgramBindings(program_bindings_array[0], set_resource_view_by_argument, frame_index);
asteroid_program_bindings.SetName(fmt::format("Asteroids[{}] Bindings {}", asteroid_index, frame_index));
scene_uniforms_binding_ptrs[asteroid_index] = &asteroid_program_bindings.Get({ rhi::ShaderType::All, "g_scene_uniforms" });
}
);
GetContext().GetParallelExecutor().run(task_flow).get();

return program_bindings_array;
return asteroid_mesh_buffer_bindings;
}

bool AsteroidsArray::Update(double elapsed_seconds, double /*delta_seconds*/)
Expand Down
12 changes: 8 additions & 4 deletions Modules/Simulation/AsteroidsArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ class AsteroidsArray final
Parameters parameters;
};

struct AsteroidMeshBufferBindings : gfx::InstancedMeshBufferBindings
{
std::vector<rhi::IProgramArgumentBinding*> scene_uniforms_binding_ptrs;
};

AsteroidsArray(const rhi::CommandQueue& render_cmd_queue,
const rhi::RenderPattern& render_pattern,
const Settings& settings);
Expand All @@ -128,10 +133,9 @@ class AsteroidsArray final
[[nodiscard]] const Ptr<ContentState>& GetState() const { return m_content_state_ptr; }
using BaseBuffers::GetUniformsBufferSize;

std::vector<rhi::ProgramBindings> CreateProgramBindings(const rhi::Buffer& constants_buffer,
const rhi::Buffer& scene_uniforms_buffer,
const rhi::Buffer& asteroids_uniforms_buffer,
Data::Index frame_index) const;
AsteroidMeshBufferBindings CreateProgramBindings(const rhi::Buffer& constants_buffer,
const rhi::Buffer& asteroids_uniforms_buffer,
Data::Index frame_index) const;

bool Update(double elapsed_seconds, double delta_seconds);

Expand Down
Loading

0 comments on commit 3f777d5

Please sign in to comment.