Skip to content

Dev bindgroup set - #26

Merged
mucbuc merged 31 commits into
masterfrom
dev_bindgroup_set
Apr 10, 2026
Merged

Dev bindgroup set#26
mucbuc merged 31 commits into
masterfrom
dev_bindgroup_set

Conversation

@mucbuc

@mucbuc mucbuc commented Apr 10, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

Release Notes

  • New Features
    • Introduced bindgroup_set type for managing multiple bindgroups with a fluent add_bindgroup API
    • Extended compute and render operations to support bindgroup_set alongside individual bindgroup usage

@coderabbitai

coderabbitai Bot commented Apr 10, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

A new bindgroup_set class was introduced to aggregate multiple bind groups by group index, alongside corresponding implementations. The compute_wrapper and render_wrapper classes were extended with overloaded methods accepting bindgroup_set, and some return types were changed from bool to void. The build configuration was updated to include the new source files.

Changes

Cohort / File(s) Summary
Build Configuration
CMakeLists.txt
Added two new source files (src/bindgroup_set.cpp, src/bindgroup_set_impl.hpp) to build target sources.
bindgroup_set Implementation
src/bindgroup_set.cpp, src/bindgroup_set_impl.hpp
New bindgroup_set class with a default constructor and fluent add_bindgroup() method; underlying pimpl stores bindgroups in a std::map<unsigned, bindgroup_wrapper>.
Public API Headers
src/dawn_wrapper.hpp
Added bindgroup_set struct declaration; updated compute_wrapper return type (boolvoid) and added bindgroup_set overload; added bindgroup_set render overload to render_wrapper; adjusted PIMPL friend declarations.
Compute Wrapper Updates
src/compute_wrapper.cpp, src/compute_wrapper_impl.hpp
Changed compute(bindgroup_wrapper, ...) return type to void; added new compute(bindgroup_set, ...) overload that iterates and binds each bindgroup at its specified index before dispatching.
Render Wrapper Updates
src/render_wrapper.cpp, src/render_wrapper_impl.hpp
Added new render(bindgroup_set, ...) overload that iterates through the bindgroup collection, binds each at its index, and issues a fixed indexed draw; removed get_bindGroupLayout() accessor from pimpl.

Sequence Diagram

sequenceDiagram
    participant App as Application
    participant CW as compute_wrapper
    participant CPI as compute_wrapper::pimpl
    participant BGS as bindgroup_set
    participant Pass as ComputePass

    App->>CW: compute(bindgroup_set, width, height, encoder)
    CW->>CPI: compute(set, width, height, encoder)
    CPI->>BGS: access m_pimpl->m_bindgroups
    loop for each (group_index, bindgroup_wrapper)
        CPI->>Pass: SetBindGroup(group_index, bindgroup)
    end
    CPI->>Pass: Dispatch(width, height, 1)
    CPI->>Pass: End()
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly Related PRs

  • Dev bindgroup set #22: Modifies compute and render wrapper APIs around bind-group handling with similar pimpl implementation changes.
  • Codereview #13: Edits src/compute_wrapper.cpp alongside this PR, touching the same wrapper class and file.

Poem

🐰 A bindgroup set now hops to life,
Collecting groups, no more the strife!
Compute and render, they now embrace,
The many bindgroups, each in place!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Dev bindgroup set' accurately describes the main change—adding a new bindgroup_set type with supporting implementation across multiple files to enable managing multiple bind groups.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev_bindgroup_set

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/bindgroup_set_impl.hpp`:
- Around line 24-27: The class currently keeps m_bindgroups private with no
accessor, preventing consumers (e.g., compute(bindgroup_set, ...) and
render(bindgroup_set, ...)) from reading stored bind groups; add a const
accessor on the bindgroup_set_impl class such as const std::map<unsigned,
bindgroup_wrapper>& bindgroups() const (or an equivalent read-only view/iterator
interface) so callers can iterate/lookup bind groups without mutating them;
update call sites to use bindgroups() where they need to bind or inspect
entries.

In `@src/compute_wrapper_impl.hpp`:
- Around line 39-44: The compute(bindgroup_set set, unsigned width, unsigned
height, encoder_wrapper encoder) function currently returns immediately;
implement the dispatch path by creating a compute pass from the provided
encoder_wrapper (e.g., begin/create a compute pass via encoder), bind the
provided bindgroup_set to that pass (use bindgroup_set's method that attaches
its groups to a pass), call the dispatch call with the given width and height to
issue workgroups, end/close the compute pass on the encoder, and return true on
success (return false only on failure). Ensure you reference and use the
existing symbols compute, bindgroup_set, and encoder_wrapper when locating and
wiring up the pass creation, binding, dispatchWorkgroups, and pass finish/close
steps.

In `@src/dawn_wrapper.hpp`:
- Around line 90-95: The default constructor for bindgroup_set leaves the PIMPL
pointer (m_pimpl) null while add_bindgroup(bindgroup_wrapper bg, unsigned group)
dereferences it; initialize m_pimpl in the default constructor or remove the
public default ctor. Modify the bindgroup_set() constructor to allocate and set
up the PIMPL used by DAWN_WRAPPER_PIMPL_DEC (so add_bindgroup can safely use
m_pimpl), or make the default ctor private/deleted and provide a
factory/explicit constructor that initializes the PIMPL; ensure add_bindgroup
assumes a valid m_pimpl only after these changes.

In `@src/render_wrapper_impl.hpp`:
- Around line 53-57: The public render(bindgroup_set set, encoder_wrapper
encoder) is currently a no-op; implement it to execute the render path by
starting a render pass with the provided encoder, binding the pipeline and the
provided bindgroup_set, issuing the appropriate draw/dispatch calls, ending the
pass, submitting the encoder/command buffer, and presenting the output. Locate
the render function named render(bindgroup_set set, encoder_wrapper encoder) in
render_wrapper_impl.hpp and forward or reuse the existing internal render logic
(the pipeline setup, bind group bindings, draw calls, command submission and
present steps) so that providing a bindgroup_set actually performs rendering
rather than returning immediately. Ensure proper use of the encoder_wrapper API
to begin/end the pass and to submit/present.

In `@test/build_and_run`:
- Around line 5-6: The build step was left without its configure step: re-enable
the configuration command (restore the "cmake -B build" line) before the "cmake
--build build -j 8" invocation so the build/ directory is created and CI no
longer fails; ensure the script runs the configure step (cmake -B build) and
only then runs the build step (cmake --build build -j 8).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e0856a60-9f2d-41de-a156-8d5908e33d9d

📥 Commits

Reviewing files that changed from the base of the PR and between 5565b8a and 0d51e10.

📒 Files selected for processing (9)
  • CMakeLists.txt
  • src/bindgroup_set.cpp
  • src/bindgroup_set_impl.hpp
  • src/compute_wrapper.cpp
  • src/compute_wrapper_impl.hpp
  • src/dawn_wrapper.hpp
  • src/render_wrapper.cpp
  • src/render_wrapper_impl.hpp
  • test/build_and_run

Comment thread src/bindgroup_set_impl.hpp Outdated
Comment thread src/compute_wrapper_impl.hpp Outdated
Comment thread src/dawn_wrapper.hpp
Comment thread src/render_wrapper_impl.hpp
Comment thread test/build_and_run Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/render_wrapper_impl.hpp (1)

54-78: Extract common render-pass body to avoid overload drift.

This overload duplicates pass setup/draw/submit/present logic already present in other render(...) overloads. A shared helper would reduce maintenance risk.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/render_wrapper_impl.hpp` around lines 54 - 78, The render(bindgroup_set,
encoder_wrapper) overload duplicates the render-pass setup, draw and
submit/present sequence; extract that common sequence into a shared private
helper (e.g., a method like execute_render_pass_or_finish(RenderPassEncoder&
pass, const bindgroup_set& set, encoder_wrapper& encoder) or
renderPassBody(const bindgroup_set& set, dawn::RenderPassEncoder& pass,
encoder_wrapper& encoder)) that does ASSERT(m_bindGroupLayout), calls
dawn_utils::begin_render_pass/getCurrentTextureView as needed,
SetPipeline(get_pipeline()), iterates set.m_pimpl->m_bindgroups to call
make_bindgroup(m_device), sets vertex/index buffers, calls DrawIndexed and End,
then does encoder.submit_command_buffer() and m_surface.present() guarded by the
__EMSCRIPTEN__ macro; replace the duplicated body in this render(...) and the
other render(...) overloads to a single call to that helper so behavior and
assertions remain identical.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/render_wrapper_impl.hpp`:
- Around line 54-67: The render(bindgroup_set set, encoder_wrapper encoder)
function dereferences set.m_pimpl without validating it which can crash for
default/invalid bindgroup_set; before using set.m_pimpl (and before iterating
set.m_pimpl->m_bindgroups) add a guard (e.g. ASSERT or if-check) to ensure
set.m_pimpl is non-null and return/handle the error early if it is null,
mirroring the safety used for bindgroup_wrapper, so subsequent calls like
make_bindgroup(m_device) and access to m_bindgroups are only performed when
set.m_pimpl is valid.

---

Nitpick comments:
In `@src/render_wrapper_impl.hpp`:
- Around line 54-78: The render(bindgroup_set, encoder_wrapper) overload
duplicates the render-pass setup, draw and submit/present sequence; extract that
common sequence into a shared private helper (e.g., a method like
execute_render_pass_or_finish(RenderPassEncoder& pass, const bindgroup_set& set,
encoder_wrapper& encoder) or renderPassBody(const bindgroup_set& set,
dawn::RenderPassEncoder& pass, encoder_wrapper& encoder)) that does
ASSERT(m_bindGroupLayout), calls
dawn_utils::begin_render_pass/getCurrentTextureView as needed,
SetPipeline(get_pipeline()), iterates set.m_pimpl->m_bindgroups to call
make_bindgroup(m_device), sets vertex/index buffers, calls DrawIndexed and End,
then does encoder.submit_command_buffer() and m_surface.present() guarded by the
__EMSCRIPTEN__ macro; replace the duplicated body in this render(...) and the
other render(...) overloads to a single call to that helper so behavior and
assertions remain identical.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 998e00b7-189f-49c1-9dde-0ac3795113c8

📥 Commits

Reviewing files that changed from the base of the PR and between 0d51e10 and 4c78336.

📒 Files selected for processing (5)
  • src/bindgroup_set_impl.hpp
  • src/compute_wrapper.cpp
  • src/compute_wrapper_impl.hpp
  • src/dawn_wrapper.hpp
  • src/render_wrapper_impl.hpp
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/bindgroup_set_impl.hpp
  • src/compute_wrapper_impl.hpp
  • src/dawn_wrapper.hpp
  • src/compute_wrapper.cpp

Comment on lines +54 to +67
void render(bindgroup_set set, encoder_wrapper encoder)
{
ASSERT(m_bindGroupLayout);

auto textureView = getCurrentTextureView();
ASSERT(textureView);

auto pass = dawn_utils::begin_render_pass(encoder.m_pimpl->m_encoder, textureView);
pass.SetPipeline(get_pipeline());

for (auto entry : set.m_pimpl->m_bindgroups)
{
pass.SetBindGroup(entry.first, entry.second.m_pimpl->make_bindgroup(m_device));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Guard bindgroup_set validity before dereferencing m_pimpl.

Line 64 dereferences set.m_pimpl without validation. Unlike the bindgroup_wrapper path (Line 83), this can crash on invalid/default bindgroup_set.

🛠️ Proposed fix
 void render(bindgroup_set set, encoder_wrapper encoder)
 {
     ASSERT(m_bindGroupLayout);
+    ASSERT(set.is_valid());
     
     auto textureView = getCurrentTextureView();
     ASSERT(textureView);

     auto pass = dawn_utils::begin_render_pass(encoder.m_pimpl->m_encoder, textureView);
     pass.SetPipeline(get_pipeline());
    
-    for (auto entry : set.m_pimpl->m_bindgroups)
+    for (const auto& entry : set.m_pimpl->m_bindgroups)
     {
+        ASSERT(entry.second.is_valid());
         pass.SetBindGroup(entry.first, entry.second.m_pimpl->make_bindgroup(m_device));
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
void render(bindgroup_set set, encoder_wrapper encoder)
{
ASSERT(m_bindGroupLayout);
auto textureView = getCurrentTextureView();
ASSERT(textureView);
auto pass = dawn_utils::begin_render_pass(encoder.m_pimpl->m_encoder, textureView);
pass.SetPipeline(get_pipeline());
for (auto entry : set.m_pimpl->m_bindgroups)
{
pass.SetBindGroup(entry.first, entry.second.m_pimpl->make_bindgroup(m_device));
}
void render(bindgroup_set set, encoder_wrapper encoder)
{
ASSERT(m_bindGroupLayout);
ASSERT(set.is_valid());
auto textureView = getCurrentTextureView();
ASSERT(textureView);
auto pass = dawn_utils::begin_render_pass(encoder.m_pimpl->m_encoder, textureView);
pass.SetPipeline(get_pipeline());
for (const auto& entry : set.m_pimpl->m_bindgroups)
{
ASSERT(entry.second.is_valid());
pass.SetBindGroup(entry.first, entry.second.m_pimpl->make_bindgroup(m_device));
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/render_wrapper_impl.hpp` around lines 54 - 67, The render(bindgroup_set
set, encoder_wrapper encoder) function dereferences set.m_pimpl without
validating it which can crash for default/invalid bindgroup_set; before using
set.m_pimpl (and before iterating set.m_pimpl->m_bindgroups) add a guard (e.g.
ASSERT or if-check) to ensure set.m_pimpl is non-null and return/handle the
error early if it is null, mirroring the safety used for bindgroup_wrapper, so
subsequent calls like make_bindgroup(m_device) and access to m_bindgroups are
only performed when set.m_pimpl is valid.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/compute_wrapper_impl.hpp (1)

40-57: Implementation looks correct; consider using const reference in range-for.

The bindgroup_set overload properly iterates the bind groups and sets each at its designated group index. One minor optimization: auto entry copies each map entry. Since bindgroup_wrapper likely contains a shared_ptr, the copy is cheap, but using const auto& is idiomatic and avoids any unnecessary overhead.

♻️ Suggested change
-        for (auto entry : set.m_pimpl->m_bindgroups)
+        for (const auto& entry : set.m_pimpl->m_bindgroups)
         {
             ASSERT(entry.second.m_pimpl);
             computePass.SetBindGroup(entry.first, entry.second.m_pimpl->make_bindgroup(m_device));
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/compute_wrapper_impl.hpp` around lines 40 - 57, In compute(bindgroup_set
set, unsigned width, unsigned height, encoder_wrapper encoder) the range-for
loop copies each map entry; change the loop header over
set.m_pimpl->m_bindgroups to use a const reference (e.g., const auto&) so
entries are not copied unnecessarily, keeping the rest of the body
(ASSERT(entry.second.m_pimpl); computePass.SetBindGroup(...)) unchanged.
src/bindgroup_set.cpp (1)

1-3: Unused includes can be removed.

<iostream> and <map> are included but not used in this translation unit. The <map> is used in bindgroup_set_impl.hpp and <memory> is needed for std::make_shared, but <iostream> appears entirely unused.

🧹 Proposed cleanup
-#include <iostream>
-#include <map>
 `#include` <memory>
 
 `#include` "bindgroup_set_impl.hpp"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/bindgroup_set.cpp` around lines 1 - 3, Remove the unused includes from
this translation unit: delete `#include` <iostream> and `#include` <map> from
src/bindgroup_set.cpp, leaving `#include` <memory> (needed for std::make_shared)
and any required project headers (e.g., bindgroup_set_impl.hpp) in place; ensure
any <map> usage remains in bindgroup_set_impl.hpp so the map include stays where
it's actually needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/bindgroup_set.cpp`:
- Around line 1-3: Remove the unused includes from this translation unit: delete
`#include` <iostream> and `#include` <map> from src/bindgroup_set.cpp, leaving
`#include` <memory> (needed for std::make_shared) and any required project headers
(e.g., bindgroup_set_impl.hpp) in place; ensure any <map> usage remains in
bindgroup_set_impl.hpp so the map include stays where it's actually needed.

In `@src/compute_wrapper_impl.hpp`:
- Around line 40-57: In compute(bindgroup_set set, unsigned width, unsigned
height, encoder_wrapper encoder) the range-for loop copies each map entry;
change the loop header over set.m_pimpl->m_bindgroups to use a const reference
(e.g., const auto&) so entries are not copied unnecessarily, keeping the rest of
the body (ASSERT(entry.second.m_pimpl); computePass.SetBindGroup(...))
unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 42a086d0-c9c5-4525-8636-3b7edee0f4af

📥 Commits

Reviewing files that changed from the base of the PR and between 4c78336 and e42939c.

📒 Files selected for processing (5)
  • src/bindgroup_set.cpp
  • src/bindgroup_set_impl.hpp
  • src/compute_wrapper_impl.hpp
  • src/dawn_wrapper.hpp
  • src/render_wrapper_impl.hpp
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/bindgroup_set_impl.hpp
  • src/render_wrapper_impl.hpp
  • src/dawn_wrapper.hpp

@mucbuc
mucbuc merged commit 0faa739 into master Apr 10, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant