Skip to content

Vulkan raygen entrypoint parameter support#676

Open
skallweitNV wants to merge 6 commits intomainfrom
dev/skallweit/vulkan-raygen
Open

Vulkan raygen entrypoint parameter support#676
skallweitNV wants to merge 6 commits intomainfrom
dev/skallweit/vulkan-raygen

Conversation

@skallweitNV
Copy link
Collaborator

@skallweitNV skallweitNV commented Feb 24, 2026

  • Minor cleanup in D3D12 backend
  • Add support for passing entrypoint parameters to raygen shaders in Vulkan

Summary by CodeRabbit

  • New Features
    • Per-entry-point ray-tracing parameters and dynamic shader-record sizing so each ray-generation entry can carry its own parameters.
  • Bug Fixes
    • Bounds validation for ray-generation indices to prevent out-of-range dispatches.
    • Use of per-pipeline shader-table data for correct SBT construction.
  • Tests
    • Several ray-tracing tests no longer skip Vulkan and will run on Vulkan devices.

@skallweitNV skallweitNV requested a review from a team as a code owner February 24, 2026 15:58
@skallweitNV skallweitNV requested review from bmillsNV and removed request for a team February 24, 2026 15:58
@coderabbitai
Copy link

coderabbitai bot commented Feb 24, 2026

📝 Walkthrough

Walkthrough

Refactors ray-tracing shader table handling to store per-pipeline PipelineData (per-entry raygen info and sizes), updates D3D12/Vulkan command paths to use that data (with bounds checks and early returns), adds vkCmdUpdateBuffer to device procs, and enables Vulkan ray-tracing tests by removing Vulkan-only skips.

Changes

Cohort / File(s) Summary
Build / tests
CMakeLists.txt, tests/test-ray-tracing-raygen-entrypoint.cpp, tests/test-ray-tracing-shader-table-multi-pipeline.cpp
Reorders and reinstates ray-tracing tests; removes Vulkan-specific skips so tests run on Vulkan.
D3D12 ray-tracing
src/d3d12/d3d12-command.cpp, src/d3d12/d3d12-shader-table.cpp
Use per-pipeline PipelineData for SBT offsets/strides; add shaderTable null-check and rayGen index bounds checks; move PipelineData init after buffer creation.
Vulkan API surface
src/vulkan/vk-api.h
Add vkCmdUpdateBuffer to device-level proc list.
Vulkan command recording
src/vulkan/vk-command.cpp
Add m_shaderTablePipelineData member; use per-pipeline PipelineData for SBT addresses/strides; copy per-raygen params via vkCmdUpdateBuffer and insert memory barrier; add rayGen bounds check.
Vulkan shader-table core
src/vulkan/vk-shader-table.h, src/vulkan/vk-shader-table.cpp
Replace per-table fields with PipelineData and RaygenInfo; implement getPipelineData(...); compute per-entry offsets/sizes/strides and store per-pipeline metadata.
Vulkan shader-object / layout
src/vulkan/vk-shader-object-layout.h, src/vulkan/vk-shader-object-layout.cpp, src/vulkan/vk-shader-object.h, src/vulkan/vk-shader-object.cpp
Add EntryPointInfo.paramsSize; add per-entry EntryPointData storage and entryPointData arrays; change bindAsEntryPoint signature to accept entryPointIndex; store raygen ordinary data into per-entry buffers instead of push constants.

Sequence Diagram

sequenceDiagram
    actor App as Application
    participant CR as CommandRecorder
    participant ST as ShaderTable
    participant CB as CommandBuffer
    participant GPU as GPU_Driver

    App->>CR: Prepare DispatchRays (rayGen index + params)
    CR->>ST: getPipelineData(rayTracingPipeline)
    ST-->>CR: PipelineData (buffer, raygenInfos, offsets/strides)
    CR->>CR: Lookup raygenInfo by index
    alt params present
        CR->>CB: vkCmdUpdateBuffer(copy entryPointData -> SBT)
        CB->>GPU: barrier / buffer visibility
    end
    CR->>CB: Configure SBT addresses & strides from PipelineData
    App->>CB: vkCmdTraceRaysKHR (dispatch)
    CB->>GPU: Execute ray tracing
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Shader table improvements #675: Implements a similar shader-table refactor to per-pipeline PipelineData and updates command paths to use getPipelineData.

Suggested reviewers

  • bmillsNV
  • ccummingsNV

Poem

🐰 I hopped through pipelines, offsets in paw,
Stored raygen bits where each entry saw.
vkCmdUpdateBuffer carried the tune,
Now SBTs sing and rays trace by noon. 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.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 directly reflects the main objective: adding Vulkan raygen entrypoint parameter support, which is confirmed by the extensive changes across Vulkan backend files.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev/skallweit/vulkan-raygen

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
CMakeLists.txt (1)

697-722: ⚠️ Potential issue | 🔴 Critical

Add src/debug-layer/debug-pipeline.cpp to CMakeLists.txt.

The file src/debug-layer/debug-pipeline.cpp exists in the repository but is missing from the CMakeLists.txt target_sources block for the debug-layer component. This will prevent it from being compiled and linked into the library. Add it to the appropriate location in the debug-layer section of CMakeLists.txt.

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

In `@CMakeLists.txt` around lines 697 - 722, The file
src/debug-layer/debug-pipeline.cpp is present in the repo but not listed in the
debug-layer target_sources block, so it never gets compiled; locate the
debug-layer target_sources section in CMakeLists.txt (the block that adds
sources for the debug-layer component) and add
src/debug-layer/debug-pipeline.cpp to that list so the debug-layer object is
built and linked into the library.
🤖 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/d3d12/d3d12-command.cpp`:
- Around line 1107-1117: The code assumes
ShaderTableImpl::getPipelineData(m_rayTracingPipeline) always returns a valid
ShaderTableImpl::PipelineData and dereferences shaderTablePipelineData->buffer;
add a null check after calling
m_shaderTable->getPipelineData(m_rayTracingPipeline) and if it returns nullptr,
early-return (or set an error/abort path) to avoid dereferencing a null pointer.
Specifically, locate the block that assigns shaderTablePipelineData and
shaderTableAddr and guard usage of shaderTablePipelineData (and its buffer)
before computing m_rayGenTableAddr, m_rayGenRecordStride, and populating
m_dispatchRaysDesc so the function safely exits when PipelineData is missing.

In `@src/vulkan/vk-command.cpp`:
- Around line 1098-1115: The code assumes
m_shaderTable->getPipelineData(m_rayTracingPipeline) always returns non-null and
immediately dereferences m_shaderTablePipelineData->buffer; guard against
nullptr by checking the result of getPipelineData() (e.g.,
m_shaderTablePipelineData) and early-return or handle the error path if it's
null before accessing members like buffer, raygenTableSize, missRecordStride,
hitGroupRecordStride, and callableRecordStride; ensure any cleanup/logging is
performed and that m_shaderTablePipelineData is assigned only after the
null-check.
- Around line 1130-1169: The call to m_api.vkCmdUpdateBuffer must be guarded for
Vulkan constraints: validate that dstOffset (raygenInfo.sbtOffset) and copySize
(min(entryPointData.size, raygenInfo.paramsSize)) are non-zero, multiples of 4,
and that copySize <= 65536; if any check fails, do not call
m_api.vkCmdUpdateBuffer directly—either adjust/round the copy or use a fallback
(e.g., a staging buffer + vkCmdCopyBuffer or skip the update) so you avoid
violating vkCmdUpdateBuffer requirements; add these checks just before the
vkCmdUpdateBuffer call and handle the invalid-case path accordingly.

In `@src/vulkan/vk-shader-object-layout.cpp`:
- Around line 929-970: info.paramsSize is taken from
entryPointLayout->getTotalOrdinaryDataSize() before unwrapping
ConstantBuffer/PushConstant for raygen, which yields 0; for raygen compute
paramsSize by summing the inner element type ordinary data sizes from the
unwrapped ranges: iterate entryPointTypeLayout->getSubObjectRangeCount(), for
each range whose getBindingRangeType(...) is slang::BindingType::ConstantBuffer
or PushConstant get the wrapperLayout via getBindingRangeLeafTypeLayout(...),
get elementVarLayout = wrapperLayout->getElementVarLayout(), then add
elementVarLayout->getTypeLayout()->getTotalOrdinaryDataSize() into a paramsSize
accumulator; set info.paramsSize = that accumulated value for the raygen branch
(or compute and assign before storing info) so subsequent SBT parameter handling
uses the unwrapped size; keep non-raygen behavior using
entryPointLayout->getTotalOrdinaryDataSize().

In `@src/vulkan/vk-shader-object-layout.h`:
- Around line 405-408: Rename the member variable paramsSize to follow the m_
prefix convention (m_paramsSize) and update all references to it throughout the
codebase; change the declaration "size_t paramsSize = 0;" to "size_t
m_paramsSize = 0;" and modify any constructors, initializers, member accesses,
assignments, and usages (e.g., in methods of the same class/struct, functions
referencing this field, tests, and serialization/deserialization code) to use
m_paramsSize instead of paramsSize to keep naming consistent with the project's
member-variable convention.

In `@src/vulkan/vk-shader-object.h`:
- Around line 96-103: Rename the struct members to follow the m_ prefix and
camelCase and fix the typo: in struct EntryPointData change data -> m_data and
size -> m_size (also update the comment to "Size of the data in bytes"); update
all call sites that reference EntryPointData::data and ::size to use m_data and
m_size; likewise rename any class/struct members entryPointData and
entryPointCount to m_entryPointData and m_entryPointCount (references around the
EntryPointData usage at the later block that currently uses
entryPointData/entryPointCount must be updated to the new names); ensure
compilation by updating any variable initializers, constructors, or accessors
that touch these symbols.

In `@src/vulkan/vk-shader-table.h`:
- Line 48: Change the non-failing signature of getPipelineData to return a
Result and take an out-parameter for the PipelineData pointer so failures can be
propagated; i.e. replace PipelineData* getPipelineData(RayTracingPipelineImpl*
pipeline) with a Result getPipelineData(RayTracingPipelineImpl* pipeline,
PipelineData** outPipelineData), update the implementation to write the created
PipelineData to *outPipelineData and propagate any errors using
SLANG_RETURN_ON_FAIL where buffer or resource creation can fail, and update all
call sites to handle the Result and use the out-parameter accordingly.
- Around line 12-41: Rename the struct member fields to use the m_ prefix and
camelCase and update all call sites: in RaygenInfo change entryPointIndex,
sbtOffset, paramsSize, recordOffset, recordSize to m_entryPointIndex,
m_sbtOffset, m_paramsSize, m_recordOffset, m_recordSize; in PipelineData change
buffer, raygenInfos, raygenTableSize, missTableSize, hitTableSize,
callableTableSize, missRecordStride, hitGroupRecordStride, callableRecordStride
to m_buffer, m_raygenInfos, m_raygenTableSize, m_missTableSize, m_hitTableSize,
m_callableTableSize, m_missRecordStride, m_hitGroupRecordStride,
m_callableRecordStride; update all uses and initializers accordingly (search for
RaygenInfo:: and PipelineData:: usages and adjust in vk-shader-table.cpp,
vk-command.cpp and any other callers).

---

Outside diff comments:
In `@CMakeLists.txt`:
- Around line 697-722: The file src/debug-layer/debug-pipeline.cpp is present in
the repo but not listed in the debug-layer target_sources block, so it never
gets compiled; locate the debug-layer target_sources section in CMakeLists.txt
(the block that adds sources for the debug-layer component) and add
src/debug-layer/debug-pipeline.cpp to that list so the debug-layer object is
built and linked into the library.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 02d255f and 8243b05.

📒 Files selected for processing (13)
  • CMakeLists.txt
  • src/d3d12/d3d12-command.cpp
  • src/d3d12/d3d12-shader-table.cpp
  • src/vulkan/vk-api.h
  • src/vulkan/vk-command.cpp
  • src/vulkan/vk-shader-object-layout.cpp
  • src/vulkan/vk-shader-object-layout.h
  • src/vulkan/vk-shader-object.cpp
  • src/vulkan/vk-shader-object.h
  • src/vulkan/vk-shader-table.cpp
  • src/vulkan/vk-shader-table.h
  • tests/test-ray-tracing-raygen-entrypoint.cpp
  • tests/test-ray-tracing-shader-table-multi-pipeline.cpp
💤 Files with no reviewable changes (2)
  • tests/test-ray-tracing-raygen-entrypoint.cpp
  • tests/test-ray-tracing-shader-table-multi-pipeline.cpp

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
src/vulkan/vk-command.cpp (1)

1135-1174: ⚠️ Potential issue | 🟠 Major

Guard vkCmdUpdateBuffer against Vulkan size/offset constraints.

vkCmdUpdateBuffer requires dstOffset and dataSize to be multiples of 4 and dataSize ≤ 65536. Add validation (or fallback to a staging copy) to avoid validation errors or undefined behavior.

🛠️ Suggested guard
 VkDeviceSize dstOffset = raygenInfo.sbtOffset;
 VkDeviceSize copySize = std::min(entryPointData.size, raygenInfo.paramsSize);
+if ((dstOffset % 4) != 0 || (copySize % 4) != 0 || copySize > 65536)
+{
+    // TODO: Use a staging buffer + vkCmdCopyBuffer for large/unaligned payloads.
+    SLANG_RHI_ASSERT_FAILURE("vkCmdUpdateBuffer size/offset constraints violated");
+    return;
+}
 m_api.vkCmdUpdateBuffer(
Vulkan vkCmdUpdateBuffer valid usage requirements dstOffset dataSize multiple of 4 65536 limit
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/vulkan/vk-command.cpp` around lines 1135 - 1174, The vkCmdUpdateBuffer
call must respect Vulkan constraints (dstOffset and dataSize multiples of 4 and
dataSize ≤ 65536), so add a guard around m_api.vkCmdUpdateBuffer: compute
dstOffset and copySize (from raygenInfo.sbtOffset and
std::min(entryPointData.size, raygenInfo.paramsSize)) and if dstOffset % 4 == 0
&& copySize % 4 == 0 && copySize <= 65536 call m_api.vkCmdUpdateBuffer as
before; otherwise create a host-visible staging buffer, map and memcpy
entryPointData.data into it, issue vkCmdCopyBuffer from the staging buffer to
m_shaderTablePipelineData->buffer->m_buffer.m_buffer at dstOffset, and use the
same pipeline barrier; update/clean up staging resources accordingly and
reference symbols: vkCmdUpdateBuffer, m_api.vkCmdUpdateBuffer, dstOffset,
copySize, entryPointData, raygenInfo, and m_shaderTablePipelineData->buffer to
locate the changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/vulkan/vk-command.cpp`:
- Around line 1135-1174: The vkCmdUpdateBuffer call must respect Vulkan
constraints (dstOffset and dataSize multiples of 4 and dataSize ≤ 65536), so add
a guard around m_api.vkCmdUpdateBuffer: compute dstOffset and copySize (from
raygenInfo.sbtOffset and std::min(entryPointData.size, raygenInfo.paramsSize))
and if dstOffset % 4 == 0 && copySize % 4 == 0 && copySize <= 65536 call
m_api.vkCmdUpdateBuffer as before; otherwise create a host-visible staging
buffer, map and memcpy entryPointData.data into it, issue vkCmdCopyBuffer from
the staging buffer to m_shaderTablePipelineData->buffer->m_buffer.m_buffer at
dstOffset, and use the same pipeline barrier; update/clean up staging resources
accordingly and reference symbols: vkCmdUpdateBuffer, m_api.vkCmdUpdateBuffer,
dstOffset, copySize, entryPointData, raygenInfo, and
m_shaderTablePipelineData->buffer to locate the changes.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8243b05 and 1a59d98.

📒 Files selected for processing (2)
  • src/d3d12/d3d12-command.cpp
  • src/vulkan/vk-command.cpp
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/d3d12/d3d12-command.cpp

@skallweitNV skallweitNV force-pushed the dev/skallweit/vulkan-raygen branch from 1a59d98 to 91e516b Compare February 24, 2026 17:37
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (5)
src/vulkan/vk-shader-object.h (1)

96-128: ⚠️ Potential issue | 🟡 Minor

Naming convention violations and typo in EntryPointData (unchanged from previous review).

EntryPointData members data and size, and the BindingDataImpl members entryPointData and entryPointCount, still lack the required m_ prefix. Line 101 also retains the "bytess" typo. As per coding guidelines, member variables should start with m_ prefix and be in camelCase.

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

In `@src/vulkan/vk-shader-object.h` around lines 96 - 128, Rename struct and class
members to follow the m_ prefix and camelCase convention: in EntryPointData
rename data -> m_data and size -> m_size (also fix the comment typo "bytess" ->
"bytes"), and in BindingDataImpl (or the owning class) rename entryPointData ->
m_entryPointData and entryPointCount -> m_entryPointCount; update all
references/usages (constructors, initializers, accessors) to use the new names
to keep the API consistent.
src/vulkan/vk-shader-table.h (2)

12-41: ⚠️ Potential issue | 🟡 Minor

RaygenInfo and PipelineData member variables still lack m_ prefix.

All fields in both structs (entryPointIndex, sbtOffset, paramsSize, recordOffset, recordSize, buffer, raygenInfos, raygenTableSize, etc.) should use the m_ prefix per the project naming convention. As per coding guidelines, member variables should start with m_ prefix and be in camelCase.

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

In `@src/vulkan/vk-shader-table.h` around lines 12 - 41, Update the member field
names in struct RaygenInfo and struct PipelineData to follow the project naming
convention by adding the m_ prefix and using camelCase: rename
RaygenInfo::entryPointIndex, sbtOffset, paramsSize, recordOffset, recordSize to
m_entryPointIndex, m_sbtOffset, m_paramsSize, m_recordOffset, m_recordSize; and
rename PipelineData::buffer, raygenInfos, raygenTableSize, missTableSize,
hitTableSize, callableTableSize, missRecordStride, hitGroupRecordStride,
callableRecordStride to m_buffer, m_raygenInfos, m_raygenTableSize,
m_missTableSize, m_hitTableSize, m_callableTableSize, m_missRecordStride,
m_hitGroupRecordStride, m_callableRecordStride; then update all uses/references
of these symbols throughout the codebase (constructors, accessors, member
initializers, and any external files) to the new names.

48-48: 🛠️ Refactor suggestion | 🟠 Major

getPipelineData should return Result with an out-parameter.

The implementation can fail (buffer creation failure), but the current signature returns a raw nullable pointer. Per coding guidelines, functions that can fail should return a Result type and output values via pointer parameters.

🔧 Suggested signature change
-    PipelineData* getPipelineData(RayTracingPipelineImpl* pipeline);
+    Result getPipelineData(RayTracingPipelineImpl* pipeline, PipelineData** outPipelineData);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/vulkan/vk-shader-table.h` at line 48, Change the
getPipelineData(RayTracingPipelineImpl* pipeline) API to return a Result and
provide the PipelineData via an out-parameter (e.g., Result
getPipelineData(RayTracingPipelineImpl* pipeline, PipelineData** outData) or
Result getPipelineData(RayTracingPipelineImpl* pipeline, PipelineData*&
outData)); update the declaration and the implementation in vk-shader-table to
allocate/populate the PipelineData into the out parameter and return an error
Result when buffer creation or any other failure occurs instead of returning
nullptr; ensure all callers are updated to check the returned Result and use the
out parameter on success.
src/vulkan/vk-shader-object-layout.cpp (1)

935-963: ⚠️ Potential issue | 🟠 Major

paramsSize will be 0 for raygen entry points with uniform parameters.

entryPointLayout->getTotalOrdinaryDataSize() returns m_totalOrdinaryDataSize, which was set in setElementTypeLayout via _unwrapParameterGroups(entryPointLayout->getTypeLayout(), ...). For a Vulkan raygen entry point, Slang's getTypeLayout() returns a struct whose uniform params are wrapped inside ConstantBuffer<T> (or PushConstant) sub-objects. _unwrapParameterGroups only unwraps when the top-level type is a parameter group — it does not dive into sub-object ranges. So struct->getSize() == 0, meaning m_totalOrdinaryDataSize == 0 and paramsSize == 0. The raygen-specific loop (lines 950–963) correctly unwraps for descriptor registration but never updates paramsSize, so the SBT record size stays handleSize and the parameter copy path in cmdDispatchRays is never triggered.

To fix, compute paramsSize from the element type inside the unwrapped wrapper, as suggested previously.

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

In `@src/vulkan/vk-shader-object-layout.cpp` around lines 935 - 963, The
paramsSize remains zero for raygen entry points because
entryPointLayout->getTotalOrdinaryDataSize() is computed from the top-level type
(a struct) while the actual uniform params live inside
ConstantBuffer/PushConstant sub-objects; update the ray-generation branch (where
slangEntryPointLayout->getStage() == SLANG_STAGE_RAY_GENERATION) to compute and
assign info.paramsSize from the unwrapped element type layout instead of relying
on entryPointLayout->getTotalOrdinaryDataSize(): inside the loop that inspects
sub-object ranges (using entryPointTypeLayout, bindingRangeIndex, wrapperLayout,
elementVarLayout) obtain the inner element type layout
(elementVarLayout->getTypeLayout()), compute its ordinary data size (equivalent
to what getTotalOrdinaryDataSize would return for that element type) and
add/assign that to info.paramsSize so the SBT record size reflects the wrapped
uniform parameter size and the cmdDispatchRays copy path will be taken.
src/vulkan/vk-command.cpp (1)

1149-1157: ⚠️ Potential issue | 🟠 Major

vkCmdUpdateBuffer invoked without validating alignment and size constraints.

The Vulkan spec requires:

  • dstOffset must be a multiple of 4
  • dataSize must be a multiple of 4
  • dataSize ≤ 65536 bytes

copySize = std::min(entryPointData.size, raygenInfo.paramsSize) is used directly with no alignment padding or upper-bound guard. If a parameter struct is not naturally 4-byte-aligned in size (e.g., paramsSize = 5), or if it exceeds 65536 bytes, this call will trigger Vulkan validation errors or undefined behaviour.

For the size-limit case, a fallback to a staging buffer + vkCmdCopyBuffer is needed.

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

In `@src/vulkan/vk-command.cpp` around lines 1149 - 1157, vkCmdUpdateBuffer is
being called with dstOffset and copySize without enforcing Vulkan's alignment
and size constraints; ensure dstOffset (raygenInfo.sbtOffset) and dataSize
(copySize computed from entryPointData.size and raygenInfo.paramsSize) are
rounded up to a 4-byte multiple and that dataSize <= 65536. Modify the code
around copySize and the vkCmdUpdateBuffer invocation to: compute an alignedSize
= align_up(std::min(entryPointData.size, raygenInfo.paramsSize), 4), clamp to
65536, and if the needed size exceeds 65536 or the source buffer cannot provide
aligned data, copy the full parameter payload into a temporary 4-byte-aligned
staging buffer and perform a vkCmdCopyBuffer to
m_shaderTablePipelineData->buffer->m_buffer.m_buffer via m_cmdBuffer instead of
calling m_api.vkCmdUpdateBuffer; otherwise call m_api.vkCmdUpdateBuffer with
dstOffset aligned and the alignedSize.
🧹 Nitpick comments (2)
src/d3d12/d3d12-command.cpp (1)

1120-1120: Dead write: RayGenerationShaderRecord.StartAddress is unconditionally overridden before use.

Line 1120 sets StartAddress = shaderTableAddr (the raw buffer base), but cmdDispatchRays overwrites it with the correct per-entry address before calling DispatchRays. The assignment here is never observed by the GPU.

♻️ Proposed cleanup
-        m_dispatchRaysDesc.RayGenerationShaderRecord.StartAddress = shaderTableAddr;
         m_dispatchRaysDesc.RayGenerationShaderRecord.SizeInBytes = shaderTablePipelineData->rayGenRecordStride;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/d3d12/d3d12-command.cpp` at line 1120, Dead write: remove the
unconditional assignment to
m_dispatchRaysDesc.RayGenerationShaderRecord.StartAddress = shaderTableAddr
since cmdDispatchRays overwrites the start address per-entry before calling
DispatchRays; locate the assignment by the symbol m_dispatchRaysDesc and the
field RayGenerationShaderRecord.StartAddress and either delete that line or
guard it so it is only set when a true base address is required (ensure
cmdDispatchRays still computes and writes the correct per-entry address before
DispatchRays).
src/vulkan/vk-shader-table.cpp (1)

17-32: Remove unused layout parameter from findEntryPointIndexByName.

The RootShaderObjectLayoutImpl* layout parameter is never referenced in the function body — only programLayout and name are used. The parameter can be dropped, and call sites updated accordingly.

♻️ Proposed simplification
-static uint32_t findEntryPointIndexByName(
-    RootShaderObjectLayoutImpl* layout,
-    slang::ProgramLayout* programLayout,
-    const std::string& name
-)
+static uint32_t findEntryPointIndexByName(
+    slang::ProgramLayout* programLayout,
+    const std::string& name
+)

Update the call site:

-uint32_t entryPointIndex = findEntryPointIndexByName(rootLayout, programLayout, entryPointName);
+uint32_t entryPointIndex = findEntryPointIndexByName(programLayout, entryPointName);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/vulkan/vk-shader-table.cpp` around lines 17 - 32, The function
findEntryPointIndexByName currently declares an unused parameter
RootShaderObjectLayoutImpl* layout; remove that parameter from the function
signature and definition so it becomes
findEntryPointIndexByName(slang::ProgramLayout* programLayout, const
std::string& name), then update every call site to pass only programLayout and
name (drop the layout argument). Also update any forward declarations,
prototypes, or header entries for findEntryPointIndexByName to match the new
signature and rebuild to catch remaining references.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/vulkan/vk-command.cpp`:
- Around line 1149-1157: vkCmdUpdateBuffer is being called with dstOffset and
copySize without enforcing Vulkan's alignment and size constraints; ensure
dstOffset (raygenInfo.sbtOffset) and dataSize (copySize computed from
entryPointData.size and raygenInfo.paramsSize) are rounded up to a 4-byte
multiple and that dataSize <= 65536. Modify the code around copySize and the
vkCmdUpdateBuffer invocation to: compute an alignedSize =
align_up(std::min(entryPointData.size, raygenInfo.paramsSize), 4), clamp to
65536, and if the needed size exceeds 65536 or the source buffer cannot provide
aligned data, copy the full parameter payload into a temporary 4-byte-aligned
staging buffer and perform a vkCmdCopyBuffer to
m_shaderTablePipelineData->buffer->m_buffer.m_buffer via m_cmdBuffer instead of
calling m_api.vkCmdUpdateBuffer; otherwise call m_api.vkCmdUpdateBuffer with
dstOffset aligned and the alignedSize.

In `@src/vulkan/vk-shader-object-layout.cpp`:
- Around line 935-963: The paramsSize remains zero for raygen entry points
because entryPointLayout->getTotalOrdinaryDataSize() is computed from the
top-level type (a struct) while the actual uniform params live inside
ConstantBuffer/PushConstant sub-objects; update the ray-generation branch (where
slangEntryPointLayout->getStage() == SLANG_STAGE_RAY_GENERATION) to compute and
assign info.paramsSize from the unwrapped element type layout instead of relying
on entryPointLayout->getTotalOrdinaryDataSize(): inside the loop that inspects
sub-object ranges (using entryPointTypeLayout, bindingRangeIndex, wrapperLayout,
elementVarLayout) obtain the inner element type layout
(elementVarLayout->getTypeLayout()), compute its ordinary data size (equivalent
to what getTotalOrdinaryDataSize would return for that element type) and
add/assign that to info.paramsSize so the SBT record size reflects the wrapped
uniform parameter size and the cmdDispatchRays copy path will be taken.

In `@src/vulkan/vk-shader-object.h`:
- Around line 96-128: Rename struct and class members to follow the m_ prefix
and camelCase convention: in EntryPointData rename data -> m_data and size ->
m_size (also fix the comment typo "bytess" -> "bytes"), and in BindingDataImpl
(or the owning class) rename entryPointData -> m_entryPointData and
entryPointCount -> m_entryPointCount; update all references/usages
(constructors, initializers, accessors) to use the new names to keep the API
consistent.

In `@src/vulkan/vk-shader-table.h`:
- Around line 12-41: Update the member field names in struct RaygenInfo and
struct PipelineData to follow the project naming convention by adding the m_
prefix and using camelCase: rename RaygenInfo::entryPointIndex, sbtOffset,
paramsSize, recordOffset, recordSize to m_entryPointIndex, m_sbtOffset,
m_paramsSize, m_recordOffset, m_recordSize; and rename PipelineData::buffer,
raygenInfos, raygenTableSize, missTableSize, hitTableSize, callableTableSize,
missRecordStride, hitGroupRecordStride, callableRecordStride to m_buffer,
m_raygenInfos, m_raygenTableSize, m_missTableSize, m_hitTableSize,
m_callableTableSize, m_missRecordStride, m_hitGroupRecordStride,
m_callableRecordStride; then update all uses/references of these symbols
throughout the codebase (constructors, accessors, member initializers, and any
external files) to the new names.
- Line 48: Change the getPipelineData(RayTracingPipelineImpl* pipeline) API to
return a Result and provide the PipelineData via an out-parameter (e.g., Result
getPipelineData(RayTracingPipelineImpl* pipeline, PipelineData** outData) or
Result getPipelineData(RayTracingPipelineImpl* pipeline, PipelineData*&
outData)); update the declaration and the implementation in vk-shader-table to
allocate/populate the PipelineData into the out parameter and return an error
Result when buffer creation or any other failure occurs instead of returning
nullptr; ensure all callers are updated to check the returned Result and use the
out parameter on success.

---

Nitpick comments:
In `@src/d3d12/d3d12-command.cpp`:
- Line 1120: Dead write: remove the unconditional assignment to
m_dispatchRaysDesc.RayGenerationShaderRecord.StartAddress = shaderTableAddr
since cmdDispatchRays overwrites the start address per-entry before calling
DispatchRays; locate the assignment by the symbol m_dispatchRaysDesc and the
field RayGenerationShaderRecord.StartAddress and either delete that line or
guard it so it is only set when a true base address is required (ensure
cmdDispatchRays still computes and writes the correct per-entry address before
DispatchRays).

In `@src/vulkan/vk-shader-table.cpp`:
- Around line 17-32: The function findEntryPointIndexByName currently declares
an unused parameter RootShaderObjectLayoutImpl* layout; remove that parameter
from the function signature and definition so it becomes
findEntryPointIndexByName(slang::ProgramLayout* programLayout, const
std::string& name), then update every call site to pass only programLayout and
name (drop the layout argument). Also update any forward declarations,
prototypes, or header entries for findEntryPointIndexByName to match the new
signature and rebuild to catch remaining references.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a59d98 and 91e516b.

📒 Files selected for processing (13)
  • CMakeLists.txt
  • src/d3d12/d3d12-command.cpp
  • src/d3d12/d3d12-shader-table.cpp
  • src/vulkan/vk-api.h
  • src/vulkan/vk-command.cpp
  • src/vulkan/vk-shader-object-layout.cpp
  • src/vulkan/vk-shader-object-layout.h
  • src/vulkan/vk-shader-object.cpp
  • src/vulkan/vk-shader-object.h
  • src/vulkan/vk-shader-table.cpp
  • src/vulkan/vk-shader-table.h
  • tests/test-ray-tracing-raygen-entrypoint.cpp
  • tests/test-ray-tracing-shader-table-multi-pipeline.cpp
💤 Files with no reviewable changes (2)
  • tests/test-ray-tracing-raygen-entrypoint.cpp
  • tests/test-ray-tracing-shader-table-multi-pipeline.cpp
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/d3d12/d3d12-shader-table.cpp
  • CMakeLists.txt
  • src/vulkan/vk-shader-object.cpp
  • src/vulkan/vk-api.h
  • src/vulkan/vk-shader-object-layout.h

@skallweitNV skallweitNV requested a review from csyonghe February 24, 2026 17:53
@skallweitNV
Copy link
Collaborator Author

@csyonghe can you take a look at the changes in the vk shader object and layout changes?

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