diff --git a/slangpy/__init__.py b/slangpy/__init__.py index 475ef000e..533570ae3 100644 --- a/slangpy/__init__.py +++ b/slangpy/__init__.py @@ -35,6 +35,9 @@ # Bring all shared types into the top level namespace from .types import * +# Portable NumPy layouts for GPU-side slang-rhi records +from . import gpu_structs + # Bring tested experimental types into top level namespace from .experimental.gridarg import grid diff --git a/slangpy/gpu_structs.py b/slangpy/gpu_structs.py new file mode 100644 index 000000000..384a0ec13 --- /dev/null +++ b/slangpy/gpu_structs.py @@ -0,0 +1,211 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +"""NumPy layouts and field encodings for portable slang-rhi GPU records.""" + +from __future__ import annotations + +from typing import Any + +import numpy as np +import numpy.typing as npt + + +# Values used to encode fields in triangle_cluster_args_dtype. These mirror +# slang-rhi-device.h and are intentionally scoped to GPU record construction. +CLUSTER_FLAG_NONE = 0 +CLUSTER_FLAG_ALLOW_DISABLE_OMMS = 1 << 0 + +CLUSTER_INDEX_FORMAT_UINT8 = 1 +CLUSTER_INDEX_FORMAT_UINT16 = 2 +CLUSTER_INDEX_FORMAT_UINT32 = 4 + +CLUSTER_GEOMETRY_FLAG_NONE = 0 +CLUSTER_GEOMETRY_FLAG_CULL_DISABLE = 1 << 29 +CLUSTER_GEOMETRY_FLAG_NO_DUPLICATE_ANY_HIT_INVOCATION = 1 << 30 +CLUSTER_GEOMETRY_FLAG_OPAQUE = 1 << 31 + + +def _structured_dtype( + names: list[str], + formats: list[str], + offsets: list[int], + itemsize: int, +) -> np.dtype[Any]: + return np.dtype( + { + "names": names, + "formats": formats, + "offsets": offsets, + "itemsize": itemsize, + } + ) + + +indirect_draw_arguments_dtype = _structured_dtype( + [ + "vertex_count_per_instance", + "instance_count", + "start_vertex_location", + "start_instance_location", + ], + [" npt.NDArray[np.uint32]: + array = np.asarray(value) + if not np.issubdtype(array.dtype, np.integer): + raise TypeError(f"{name} must contain integers") + if np.any(array < 0) or np.any(array > maximum): + raise ValueError(f"{name} must be in the range [0, {maximum}]") + return array.astype(np.uint32, copy=False) + + +def pack_triangle_cluster_args_fields( + triangle_count: npt.ArrayLike, + vertex_count: npt.ArrayLike, + position_truncate_bit_count: npt.ArrayLike = 0, + index_format: npt.ArrayLike = 0, + opacity_micromap_index_format: npt.ArrayLike = 0, +) -> npt.NDArray[np.uint32]: + """ + Pack the bitfields stored in ``triangle_cluster_args_dtype``. + + Arguments may be integer scalars or broadcast-compatible integer arrays. + Cluster triangle and vertex counts are limited to the portable slang-rhi + maximum of 256. + """ + + triangles = _checked_uint_field(triangle_count, "triangle_count", 256) + vertices = _checked_uint_field(vertex_count, "vertex_count", 256) + truncate = _checked_uint_field(position_truncate_bit_count, "position_truncate_bit_count", 0x3F) + indices = _checked_uint_field(index_format, "index_format", 0xF) + omm_indices = _checked_uint_field( + opacity_micromap_index_format, + "opacity_micromap_index_format", + 0xF, + ) + return ( + triangles + | (vertices << np.uint32(9)) + | (truncate << np.uint32(18)) + | (indices << np.uint32(24)) + | (omm_indices << np.uint32(28)) + ) + + +__all__ = [ + "aabb_dtype", + "cluster_args_dtype", + "CLUSTER_FLAG_ALLOW_DISABLE_OMMS", + "CLUSTER_FLAG_NONE", + "CLUSTER_GEOMETRY_FLAG_CULL_DISABLE", + "CLUSTER_GEOMETRY_FLAG_NO_DUPLICATE_ANY_HIT_INVOCATION", + "CLUSTER_GEOMETRY_FLAG_NONE", + "CLUSTER_GEOMETRY_FLAG_OPAQUE", + "CLUSTER_INDEX_FORMAT_UINT16", + "CLUSTER_INDEX_FORMAT_UINT32", + "CLUSTER_INDEX_FORMAT_UINT8", + "indirect_dispatch_arguments_dtype", + "indirect_draw_arguments_dtype", + "indirect_draw_indexed_arguments_dtype", + "instantiate_template_args_dtype", + "micromap_triangle_desc_dtype", + "pack_triangle_cluster_args_fields", + "triangle_cluster_args_dtype", +] diff --git a/slangpy/tests/device/test_cluster_acceleration_structure.py b/slangpy/tests/device/test_cluster_acceleration_structure.py new file mode 100644 index 000000000..e8860fddb --- /dev/null +++ b/slangpy/tests/device/test_cluster_acceleration_structure.py @@ -0,0 +1,400 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +import numpy as np +import pytest + +import slangpy as spy +from slangpy.testing import helpers + + +def _align_up(value: int, alignment: int) -> int: + return (value + alignment - 1) & ~(alignment - 1) + + +def _create_accel_input_buffer(device: spy.Device, data: np.ndarray) -> spy.Buffer: + return device.create_buffer( + data=data.view(np.uint8), + usage=( + spy.BufferUsage.acceleration_structure_build_input + | spy.BufferUsage.copy_source + | spy.BufferUsage.copy_destination + ), + default_state=spy.ResourceState.acceleration_structure_build_output, + ) + + +def _create_uav_buffer(device: spy.Device, size: int) -> spy.Buffer: + return device.create_buffer( + size=size, + usage=( + spy.BufferUsage.unordered_access + | spy.BufferUsage.copy_source + | spy.BufferUsage.copy_destination + ), + default_state=spy.ResourceState.unordered_access, + ) + + +def _create_handles_buffer(device: spy.Device, count: int) -> spy.Buffer: + size = _align_up( + count * spy.CLUSTER_DEFAULT_HANDLE_STRIDE, + spy.CLUSTER_OUTPUT_ALIGNMENT, + ) + return device.create_buffer( + size=size, + usage=( + spy.BufferUsage.unordered_access + | spy.BufferUsage.acceleration_structure + | spy.BufferUsage.copy_source + | spy.BufferUsage.copy_destination + ), + default_state=spy.ResourceState.unordered_access, + ) + + +def _execute_implicit_cluster_operation( + device: spy.Device, + desc: spy.ClusterOperationDesc, + result_size: int, + scratch_size: int, + handle_count: int, +) -> tuple[spy.Buffer, spy.Buffer]: + arg_count_buffer = _create_accel_input_buffer( + device, + np.array([handle_count], dtype=np.uint32), + ) + scratch_buffer = _create_uav_buffer(device, scratch_size) + addresses_buffer = _create_handles_buffer(device, handle_count) + result_buffer = device.create_buffer( + size=result_size, + usage=spy.BufferUsage.acceleration_structure, + ) + + desc.arg_count_buffer = arg_count_buffer + desc.scratch_buffer = scratch_buffer + desc.addresses_buffer = addresses_buffer + desc.result_buffer = result_buffer + + command_encoder = device.create_command_encoder() + command_encoder.execute_cluster_operation(desc) + device.submit_command_buffer(command_encoder.finish()) + device.wait_for_idle() + return result_buffer, addresses_buffer + + +def test_cluster_argument_records() -> None: + triangle_args = np.zeros(1, dtype=spy.gpu_structs.triangle_cluster_args_dtype) + triangle_args["cluster_id"] = 7 + triangle_args["packed_counts_and_formats"] = spy.gpu_structs.pack_triangle_cluster_args_fields( + triangle_count=1, + vertex_count=3, + index_format=spy.gpu_structs.CLUSTER_INDEX_FORMAT_UINT32, + ) + assert triangle_args["cluster_id"][0] == 7 + assert triangle_args.nbytes == 72 + + template_args = np.zeros(1, dtype=spy.gpu_structs.instantiate_template_args_dtype) + assert template_args.nbytes == 32 + + cluster_args = np.zeros(1, dtype=spy.gpu_structs.cluster_args_dtype) + cluster_args["cluster_handles_stride"] = spy.CLUSTER_DEFAULT_HANDLE_STRIDE + assert cluster_args["cluster_handles_stride"][0] == spy.CLUSTER_DEFAULT_HANDLE_STRIDE + assert cluster_args.nbytes == 16 + + handle = spy.AccelerationStructureHandle(123) + assert handle.value == 123 + + +@pytest.mark.parametrize("device_type", helpers.DEFAULT_DEVICE_TYPES) +def test_cluster_explicit_destination(device_type: spy.DeviceType) -> None: + device = helpers.get_device(type=device_type) + if not device.has_feature(spy.Feature.cluster_acceleration_structure): + pytest.skip("Cluster acceleration structures are not supported on this device") + + vertices = np.array( + [[0.0, 0.0, 1.0], [1.0, 0.0, 1.0], [0.0, 1.0, 1.0]], + dtype=np.float32, + ) + indices = np.array([0, 1, 2], dtype=np.uint32) + vertex_buffer = _create_accel_input_buffer(device, vertices) + index_buffer = _create_accel_input_buffer(device, indices) + triangle_args_data = np.zeros(1, dtype=spy.gpu_structs.triangle_cluster_args_dtype) + triangle_args_data["packed_counts_and_formats"] = ( + spy.gpu_structs.pack_triangle_cluster_args_fields( + triangle_count=1, + vertex_count=3, + index_format=spy.gpu_structs.CLUSTER_INDEX_FORMAT_UINT32, + ) + ) + triangle_args_data["vertex_buffer_stride"] = vertices.strides[0] + triangle_args_data["index_buffer"] = index_buffer.device_address + triangle_args_data["vertex_buffer"] = vertex_buffer.device_address + args_buffer = _create_accel_input_buffer(device, triangle_args_data) + arg_count_buffer = _create_accel_input_buffer( + device, + np.array([1], dtype=np.uint32), + ) + + params_values = { + "type": spy.ClusterOperationType.clas_from_triangles, + "max_arg_count": 1, + "clas": { + "max_unique_geometry_count": 1, + "max_triangle_count": 1, + "max_vertex_count": 3, + "max_total_triangle_count": 1, + "max_total_vertex_count": 3, + }, + } + operation_sizes = device.get_cluster_operation_sizes(spy.ClusterOperationParams(params_values)) + scratch_buffer = _create_uav_buffer(device, operation_sizes.scratch_size) + per_clas_sizes = _create_uav_buffer(device, np.dtype(np.uint32).itemsize) + + get_sizes_desc = spy.ClusterOperationDesc( + { + "params": { + **params_values, + "mode": spy.ClusterOperationMode.get_sizes, + }, + "arg_count_buffer": arg_count_buffer, + "args_buffer": args_buffer, + "args_buffer_stride": triangle_args_data.nbytes, + "scratch_buffer": scratch_buffer, + "sizes_buffer": per_clas_sizes, + } + ) + command_encoder = device.create_command_encoder() + command_encoder.execute_cluster_operation(get_sizes_desc) + device.submit_command_buffer(command_encoder.finish()) + device.wait_for_idle() + + clas_size = int(per_clas_sizes.to_numpy().view(np.uint32)[0]) + assert clas_size > 0 + arena = device.create_buffer( + size=_align_up(clas_size, spy.CLUSTER_OUTPUT_ALIGNMENT), + usage=spy.BufferUsage.acceleration_structure, + ) + destination = np.array([arena.device_address], dtype=np.uint64) + destination_buffer = device.create_buffer( + data=destination, + usage=( + spy.BufferUsage.unordered_access + | spy.BufferUsage.acceleration_structure + | spy.BufferUsage.copy_source + | spy.BufferUsage.copy_destination + ), + default_state=spy.ResourceState.unordered_access, + ) + explicit_desc = spy.ClusterOperationDesc( + { + "params": { + **params_values, + "mode": spy.ClusterOperationMode.explicit_destinations, + }, + "arg_count_buffer": arg_count_buffer, + "args_buffer": args_buffer, + "args_buffer_stride": triangle_args_data.nbytes, + "scratch_buffer": scratch_buffer, + "addresses_buffer": destination_buffer, + } + ) + command_encoder = device.create_command_encoder() + command_encoder.execute_cluster_operation(explicit_desc) + device.submit_command_buffer(command_encoder.finish()) + device.wait_for_idle() + + cluster_handle = int(destination_buffer.to_numpy().view(np.uint64)[0]) + assert cluster_handle == arena.device_address + + +@pytest.mark.parametrize("device_type", helpers.DEFAULT_DEVICE_TYPES) +def test_cluster_acceleration_structure_trace(device_type: spy.DeviceType) -> None: + device = helpers.get_device(type=device_type) + if not device.has_feature(spy.Feature.cluster_acceleration_structure): + pytest.skip("Cluster acceleration structures are not supported on this device") + + vertices = np.array( + [ + [0.0, 0.0, 1.0], + [1.0, 0.0, 1.0], + [0.0, 1.0, 1.0], + ], + dtype=np.float32, + ) + indices = np.array([0, 1, 2], dtype=np.uint32) + vertex_buffer = _create_accel_input_buffer(device, vertices) + index_buffer = _create_accel_input_buffer(device, indices) + + triangle_args_stride = spy.gpu_structs.triangle_cluster_args_dtype.itemsize + triangle_args_buffer = device.create_buffer( + size=triangle_args_stride, + struct_size=triangle_args_stride, + usage=( + spy.BufferUsage.unordered_access + | spy.BufferUsage.acceleration_structure_build_input + | spy.BufferUsage.copy_source + | spy.BufferUsage.copy_destination + ), + default_state=spy.ResourceState.unordered_access, + ) + write_args_program = device.load_program( + "test_cluster_acceleration_structure.slang", + ["write_triangle_args"], + ) + write_args_kernel = device.create_compute_kernel(write_args_program) + write_args_kernel.dispatch( + thread_count=[1, 1, 1], + vars={ + "triangle_args": triangle_args_buffer, + "index_buffer_address": index_buffer.device_address, + "vertex_buffer_address": vertex_buffer.device_address, + "vertex_buffer_stride": vertices.strides[0], + }, + ) + device.wait_for_idle() + + clas_params = spy.ClusterOperationParams( + { + "type": spy.ClusterOperationType.clas_from_triangles, + "max_arg_count": 1, + "clas": { + "max_unique_geometry_count": 1, + "max_triangle_count": 1, + "max_vertex_count": 3, + "max_total_triangle_count": 1, + "max_total_vertex_count": 3, + }, + } + ) + clas_sizes = device.get_cluster_operation_sizes(clas_params) + assert clas_sizes.result_size > 0 + assert clas_sizes.scratch_size > 0 + + clas_desc = spy.ClusterOperationDesc( + { + "params": clas_params, + "args_buffer": triangle_args_buffer, + "args_buffer_stride": triangle_args_stride, + } + ) + clas_result_buffer, clas_handles_buffer = _execute_implicit_cluster_operation( + device, + clas_desc, + clas_sizes.result_size, + clas_sizes.scratch_size, + 1, + ) + clas_handle = int(clas_handles_buffer.to_numpy().view(np.uint64)[0]) + assert clas_handle != 0 + + cluster_args_data = np.zeros(1, dtype=spy.gpu_structs.cluster_args_dtype) + cluster_args_data["cluster_handles_count"] = 1 + cluster_args_data["cluster_handles_stride"] = spy.CLUSTER_DEFAULT_HANDLE_STRIDE + cluster_args_data["cluster_handles_buffer"] = clas_handles_buffer.device_address + cluster_args_buffer = _create_accel_input_buffer(device, cluster_args_data) + + blas_params = spy.ClusterOperationParams( + { + "type": spy.ClusterOperationType.blas_from_clas, + "max_arg_count": 1, + "blas": { + "max_clas_count": 1, + "max_total_clas_count": 1, + }, + } + ) + blas_sizes = device.get_cluster_operation_sizes(blas_params) + assert blas_sizes.result_size > 0 + assert blas_sizes.scratch_size > 0 + + blas_desc = spy.ClusterOperationDesc( + { + "params": blas_params, + "args_buffer": cluster_args_buffer, + "args_buffer_stride": cluster_args_data.nbytes, + } + ) + blas_result_buffer, blas_handles_buffer = _execute_implicit_cluster_operation( + device, + blas_desc, + blas_sizes.result_size, + blas_sizes.scratch_size, + 1, + ) + blas_handle = int(blas_handles_buffer.to_numpy().view(np.uint64)[0]) + assert blas_handle != 0 + + instance_list = device.create_acceleration_structure_instance_list(1) + instance_list.write( + 0, + { + "transform": spy.float3x4([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0]), + "instance_id": 0, + "instance_mask": 0xFF, + "instance_contribution_to_hit_group_index": 0, + "flags": spy.AccelerationStructureInstanceFlags.none, + "acceleration_structure": spy.AccelerationStructureHandle(blas_handle), + }, + ) + tlas_build_desc = spy.AccelerationStructureBuildDesc( + {"inputs": [instance_list.build_input_instances()]} + ) + tlas_sizes = device.get_acceleration_structure_sizes(tlas_build_desc) + tlas = device.create_acceleration_structure( + kind=spy.AccelerationStructureKind.top_level, + size=tlas_sizes.acceleration_structure_size, + label="cluster_tlas", + ) + tlas_scratch = _create_uav_buffer(device, tlas_sizes.scratch_size) + command_encoder = device.create_command_encoder() + command_encoder.build_acceleration_structure( + tlas_build_desc, + tlas, + None, + tlas_scratch, + ) + device.submit_command_buffer(command_encoder.finish()) + device.wait_for_idle() + + program = device.load_program( + "test_cluster_acceleration_structure.slang", + ["ray_gen", "miss", "closest_hit"], + ) + pipeline = device.create_ray_tracing_pipeline( + program=program, + hit_groups=[ + spy.HitGroupDesc( + hit_group_name="hit_group", + closest_hit_entry_point="closest_hit", + ) + ], + max_recursion=1, + max_ray_payload_size=4, + flags=spy.RayTracingPipelineFlags.enable_clusters, + ) + shader_table = device.create_shader_table( + program=program, + ray_gen_entry_points=["ray_gen"], + miss_entry_points=["miss"], + hit_group_names=["hit_group"], + ) + trace_result = device.create_buffer( + data=np.zeros(1, dtype=np.uint32), + usage=spy.BufferUsage.unordered_access | spy.BufferUsage.copy_source, + ) + + command_encoder = device.create_command_encoder() + with command_encoder.begin_ray_tracing_pass() as pass_encoder: + shader_object = pass_encoder.bind_pipeline(pipeline, shader_table) + cursor = spy.ShaderCursor(shader_object) + cursor.result_buffer = trace_result + cursor.scene_bvh = tlas + pass_encoder.dispatch_rays(0, [1, 1, 1]) + device.submit_command_buffer(command_encoder.finish()) + device.wait_for_idle() + + assert trace_result.to_numpy().view(np.uint32)[0] == 2 + + # Keep buffers that back cluster handles alive through the ray tracing dispatch. + assert clas_result_buffer.size > 0 + assert blas_result_buffer.size > 0 diff --git a/slangpy/tests/device/test_cluster_acceleration_structure.slang b/slangpy/tests/device/test_cluster_acceleration_structure.slang new file mode 100644 index 000000000..d83fbc491 --- /dev/null +++ b/slangpy/tests/device/test_cluster_acceleration_structure.slang @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +import sgl.device.rhi; + +RWStructuredBuffer triangle_args; +uniform uint64_t index_buffer_address; +uniform uint64_t vertex_buffer_address; +uniform uint vertex_buffer_stride; + +[shader("compute")] +[numthreads(1, 1, 1)] +void write_triangle_args(uint3 tid : SV_DispatchThreadID) +{ + // Explicit initialization works around default initialization issues for structures with bit fields. + rhi::TriangleClusterArgs args; + args.clusterId = 0; + args.clusterFlags = rhi::kClusterFlagNone; + args.triangleCount = 1; + args.vertexCount = 3; + args.positionTruncateBitCount = 0; + args.indexFormat = rhi::kClusterIndexFormat32bit; + args.opacityMicromapIndexFormat = 0; + args.baseGeometryIndexAndFlags = 0; + args.indexBufferStride = uint16_t(0); + args.vertexBufferStride = uint16_t(vertex_buffer_stride); + args.geometryIndexAndFlagsBufferStride = uint16_t(0); + args.opacityMicromapIndexBufferStride = uint16_t(0); + args.indexBuffer = index_buffer_address; + args.vertexBuffer = vertex_buffer_address; + args.geometryIndexAndFlagsBuffer = 0; + args.opacityMicromapArray = 0; + args.opacityMicromapIndexBuffer = 0; + args.instantiationBoundingBoxLimit = 0; + triangle_args[tid.x] = args; +} + +[raypayload] +struct Payload +{ + uint result : read(caller) : write(caller, closesthit, miss); +}; + +uniform RWStructuredBuffer result_buffer; +uniform RaytracingAccelerationStructure scene_bvh; + +[shader("raygeneration")] +void ray_gen() +{ + RayDesc ray; + ray.Origin = float3(0.25, 0.25, 0.0); + ray.Direction = float3(0.0, 0.0, 1.0); + ray.TMin = 0.001; + ray.TMax = 100.0; + + Payload payload = {0}; + TraceRay(scene_bvh, RAY_FLAG_NONE, 0xff, 0, 0, 0, ray, payload); + result_buffer[0] = payload.result; +} + +[shader("miss")] +void miss(inout Payload payload) +{ + payload.result = 1; +} + +[shader("closesthit")] +void closest_hit(inout Payload payload, BuiltInTriangleIntersectionAttributes attributes) +{ + payload.result = 2; +} diff --git a/slangpy/tests/device/test_opacity_micromap.py b/slangpy/tests/device/test_opacity_micromap.py index bfb90e28f..0d2de42d6 100644 --- a/slangpy/tests/device/test_opacity_micromap.py +++ b/slangpy/tests/device/test_opacity_micromap.py @@ -25,14 +25,7 @@ def test_opacity_micromap_trace(device_type: spy.DeviceType) -> None: label="opacity_data", ) - triangle_desc_dtype = np.dtype( - [ - ("data_offset", np.uint32), - ("subdivision_level", np.uint16), - ("format", np.uint16), - ] - ) - triangle_descs = np.zeros(32, dtype=triangle_desc_dtype) + triangle_descs = np.zeros(32, dtype=spy.gpu_structs.micromap_triangle_desc_dtype) triangle_descs[0] = (0, 0, spy.OpacityMicromapFormat.two_state.value) triangle_descs[1] = (1, 0, spy.OpacityMicromapFormat.two_state.value) triangle_descs[2] = (2, 1, spy.OpacityMicromapFormat.two_state.value) diff --git a/src/sgl/device/command.cpp b/src/sgl/device/command.cpp index 76c062684..fe2fa857a 100644 --- a/src/sgl/device/command.cpp +++ b/src/sgl/device/command.cpp @@ -811,6 +811,25 @@ void CommandEncoder::query_acceleration_structure_properties( ); } +void CommandEncoder::execute_cluster_operation(const ClusterOperationDesc& desc) +{ + SGL_CHECK(m_open, "Command encoder is finished"); + + rhi::ClusterOperationDesc rhi_desc{ + .params = detail::to_rhi(desc.params), + .argCountBuffer = detail::to_rhi(desc.arg_count_buffer), + .argsBuffer = detail::to_rhi(desc.args_buffer), + .argsBufferStride = desc.args_buffer_stride, + .scratchBuffer = detail::to_rhi(desc.scratch_buffer), + .addressesBuffer = detail::to_rhi(desc.addresses_buffer), + .addressesBufferStride = desc.addresses_buffer_stride, + .resultBuffer = detail::to_rhi(desc.result_buffer), + .sizesBuffer = detail::to_rhi(desc.sizes_buffer), + .sizesBufferStride = desc.sizes_buffer_stride, + }; + m_rhi_command_encoder->executeClusterOperation(rhi_desc); +} + void CommandEncoder::convert_coop_vec_matrices( Buffer* dst, std::span dst_descs, diff --git a/src/sgl/device/command.h b/src/sgl/device/command.h index ee4d106e3..789950603 100644 --- a/src/sgl/device/command.h +++ b/src/sgl/device/command.h @@ -376,6 +376,9 @@ class SGL_API CommandEncoder : public DeviceChild { std::span queries ); + /// Execute an indirect cluster acceleration structure operation. + void execute_cluster_operation(const ClusterOperationDesc& desc); + void convert_coop_vec_matrices( Buffer* dst, std::span dst_descs, diff --git a/src/sgl/device/device.cpp b/src/sgl/device/device.cpp index 4bd54479e..86655fb60 100644 --- a/src/sgl/device/device.cpp +++ b/src/sgl/device/device.cpp @@ -662,6 +662,16 @@ ref Device::create_micromap(MicromapDesc desc) return make_ref(ref(this), std::move(desc)); } +ClusterOperationSizes Device::get_cluster_operation_sizes(const ClusterOperationParams& params) +{ + rhi::ClusterOperationSizes rhi_sizes; + SLANG_RHI_CALL(m_rhi_device->getClusterOperationSizes(detail::to_rhi(params), &rhi_sizes), this); + return { + .result_size = rhi_sizes.resultSize, + .scratch_size = rhi_sizes.scratchSize, + }; +} + ref Device::create_shader_table(ShaderTableDesc desc) { return make_ref(ref(this), std::move(desc)); @@ -1684,6 +1694,11 @@ ref create_micromap(MicromapDesc desc) return current_device()->create_micromap(std::move(desc)); } +ClusterOperationSizes get_cluster_operation_sizes(const ClusterOperationParams& params) +{ + return current_device()->get_cluster_operation_sizes(params); +} + ref create_shader_table(ShaderTableDesc desc) { return current_device()->create_shader_table(std::move(desc)); diff --git a/src/sgl/device/device.h b/src/sgl/device/device.h index 4b5017325..599d6b501 100644 --- a/src/sgl/device/device.h +++ b/src/sgl/device/device.h @@ -525,6 +525,9 @@ class SGL_API Device : public Object { /// Create a new micromap. ref create_micromap(MicromapDesc desc); + /// Query the device for buffer sizes required for a cluster operation. + ClusterOperationSizes get_cluster_operation_sizes(const ClusterOperationParams& params); + /// Create a new shader table. ref create_shader_table(ShaderTableDesc desc); @@ -1147,6 +1150,9 @@ SGL_API MicromapSizes get_micromap_sizes(const MicromapBuildDesc& desc); /// Create a new micromap on the current device. SGL_API ref create_micromap(MicromapDesc desc); +/// Query the current device for buffer sizes required for a cluster operation. +SGL_API ClusterOperationSizes get_cluster_operation_sizes(const ClusterOperationParams& params); + /// Create a new shader table. SGL_API ref create_shader_table(ShaderTableDesc desc); diff --git a/src/sgl/device/raytracing.cpp b/src/sgl/device/raytracing.cpp index b0dde4fa1..3aa6a86c4 100644 --- a/src/sgl/device/raytracing.cpp +++ b/src/sgl/device/raytracing.cpp @@ -37,6 +37,34 @@ MicromapBuildDescConverter::MicromapBuildDescConverter(const MicromapBuildDesc& }; } +rhi::ClusterOperationParams detail::to_rhi(const ClusterOperationParams& params) +{ + return { + .maxArgCount = params.max_arg_count, + .type = static_cast(params.type), + .mode = static_cast(params.mode), + .flags = static_cast(params.flags), + .move{ + .type = static_cast(params.move.type), + .maxSize = params.move.max_size, + }, + .clas{ + .vertexFormat = static_cast(params.clas.vertex_format), + .maxGeometryIndex = params.clas.max_geometry_index, + .maxUniqueGeometryCount = params.clas.max_unique_geometry_count, + .maxTriangleCount = params.clas.max_triangle_count, + .maxVertexCount = params.clas.max_vertex_count, + .maxTotalTriangleCount = params.clas.max_total_triangle_count, + .maxTotalVertexCount = params.clas.max_total_vertex_count, + .minPositionTruncateBitCount = params.clas.min_position_truncate_bit_count, + }, + .blas{ + .maxClasCount = params.blas.max_clas_count, + .maxTotalClasCount = params.blas.max_total_clas_count, + }, + }; +} + AccelerationStructureBuildDescConverter::AccelerationStructureBuildDescConverter( const AccelerationStructureBuildDesc& desc ) diff --git a/src/sgl/device/raytracing.h b/src/sgl/device/raytracing.h index 2a969df45..644cb6685 100644 --- a/src/sgl/device/raytracing.h +++ b/src/sgl/device/raytracing.h @@ -524,6 +524,142 @@ struct ShaderTableDesc { std::vector callable_entry_points; }; +// ---------------------------------------------------------------------------- +// Cluster acceleration structures +// ---------------------------------------------------------------------------- + +enum class ClusterOperationType : uint32_t { + move_objects = static_cast(rhi::ClusterOperationType::MoveObjects), + clas_from_triangles = static_cast(rhi::ClusterOperationType::CLASFromTriangles), + blas_from_clas = static_cast(rhi::ClusterOperationType::BLASFromCLAS), + templates_from_triangles = static_cast(rhi::ClusterOperationType::TemplatesFromTriangles), + clas_from_templates = static_cast(rhi::ClusterOperationType::CLASFromTemplates), +}; +SGL_ENUM_INFO( + ClusterOperationType, + { + {ClusterOperationType::move_objects, "move_objects"}, + {ClusterOperationType::clas_from_triangles, "clas_from_triangles"}, + {ClusterOperationType::blas_from_clas, "blas_from_clas"}, + {ClusterOperationType::templates_from_triangles, "templates_from_triangles"}, + {ClusterOperationType::clas_from_templates, "clas_from_templates"}, + } +); +SGL_ENUM_REGISTER(ClusterOperationType); + +enum class ClusterOperationMode : uint32_t { + implicit_destinations = static_cast(rhi::ClusterOperationMode::ImplicitDestinations), + explicit_destinations = static_cast(rhi::ClusterOperationMode::ExplicitDestinations), + get_sizes = static_cast(rhi::ClusterOperationMode::GetSizes), +}; +SGL_ENUM_INFO( + ClusterOperationMode, + { + {ClusterOperationMode::implicit_destinations, "implicit_destinations"}, + {ClusterOperationMode::explicit_destinations, "explicit_destinations"}, + {ClusterOperationMode::get_sizes, "get_sizes"}, + } +); +SGL_ENUM_REGISTER(ClusterOperationMode); + +enum class ClusterOperationFlags : uint32_t { + none = static_cast(rhi::ClusterOperationFlags::None), + fast_trace = static_cast(rhi::ClusterOperationFlags::FastTrace), + fast_build = static_cast(rhi::ClusterOperationFlags::FastBuild), + no_overlap = static_cast(rhi::ClusterOperationFlags::NoOverlap), + allow_omm = static_cast(rhi::ClusterOperationFlags::AllowOMM), +}; +SGL_ENUM_CLASS_OPERATORS(ClusterOperationFlags); +SGL_ENUM_FLAGS_INFO( + ClusterOperationFlags, + { + {ClusterOperationFlags::none, "none"}, + {ClusterOperationFlags::fast_trace, "fast_trace"}, + {ClusterOperationFlags::fast_build, "fast_build"}, + {ClusterOperationFlags::no_overlap, "no_overlap"}, + {ClusterOperationFlags::allow_omm, "allow_omm"}, + } +); +SGL_ENUM_REGISTER(ClusterOperationFlags); + +enum class ClusterOperationMoveType : uint32_t { + bottom_level = static_cast(rhi::ClusterOperationMoveType::BottomLevel), + cluster_level = static_cast(rhi::ClusterOperationMoveType::ClusterLevel), + template_ = static_cast(rhi::ClusterOperationMoveType::Template), +}; +SGL_ENUM_INFO( + ClusterOperationMoveType, + { + {ClusterOperationMoveType::bottom_level, "bottom_level"}, + {ClusterOperationMoveType::cluster_level, "cluster_level"}, + {ClusterOperationMoveType::template_, "template"}, + } +); +SGL_ENUM_REGISTER(ClusterOperationMoveType); + +struct ClusterOperationMoveParams { + ClusterOperationMoveType type{ClusterOperationMoveType::bottom_level}; + uint32_t max_size{0}; +}; + +struct ClusterOperationClasBuildParams { + Format vertex_format{Format::rgb32_float}; + uint32_t max_geometry_index{0}; + uint32_t max_unique_geometry_count{1}; + uint32_t max_triangle_count{0}; + uint32_t max_vertex_count{0}; + uint32_t max_total_triangle_count{0}; + uint32_t max_total_vertex_count{0}; + uint32_t min_position_truncate_bit_count{0}; +}; + +struct ClusterOperationBlasBuildParams { + uint32_t max_clas_count{0}; + uint32_t max_total_clas_count{0}; +}; + +struct ClusterOperationParams { + uint32_t max_arg_count{0}; + ClusterOperationType type{ClusterOperationType::clas_from_triangles}; + ClusterOperationMode mode{ClusterOperationMode::implicit_destinations}; + ClusterOperationFlags flags{ClusterOperationFlags::none}; + ClusterOperationMoveParams move; + ClusterOperationClasBuildParams clas; + ClusterOperationBlasBuildParams blas; +}; + +namespace detail { + SGL_API rhi::ClusterOperationParams to_rhi(const ClusterOperationParams& params); +} + +struct ClusterOperationDesc { + ClusterOperationParams params; + BufferOffsetPair arg_count_buffer; + BufferOffsetPair args_buffer; + uint64_t args_buffer_stride{0}; + BufferOffsetPair scratch_buffer; + BufferOffsetPair addresses_buffer; + size_t addresses_buffer_stride{rhi::kClusterDefaultHandleStride}; + BufferOffsetPair result_buffer; + BufferOffsetPair sizes_buffer; + size_t sizes_buffer_stride{sizeof(uint32_t)}; +}; + +struct ClusterOperationSizes { + DeviceSize result_size{0}; + DeviceSize scratch_size{0}; +}; + +static constexpr uint32_t CLUSTER_MAX_TRIANGLE_COUNT = rhi::kClusterMaxTriangleCount; +static constexpr uint32_t CLUSTER_MAX_VERTEX_COUNT = rhi::kClusterMaxVertexCount; +static constexpr uint32_t CLUSTER_MAX_GEOMETRY_INDEX = rhi::kClusterMaxGeometryIndex; +static constexpr uint32_t CLUSTER_DEFAULT_HANDLE_STRIDE = rhi::kClusterDefaultHandleStride; +static constexpr uint32_t CLUSTER_OUTPUT_ALIGNMENT = rhi::kClusterOutputAlignment; + +// ---------------------------------------------------------------------------- +// ShaderTable +// ---------------------------------------------------------------------------- + class SGL_API ShaderTable : public DeviceChild { SGL_OBJECT(ShaderTable) public: diff --git a/src/sgl/device/types.h b/src/sgl/device/types.h index 6ab287a6f..04d1ce14c 100644 --- a/src/sgl/device/types.h +++ b/src/sgl/device/types.h @@ -864,6 +864,7 @@ enum class RayTracingPipelineFlags : uint8_t { skip_procedurals = static_cast(rhi::RayTracingPipelineFlags::SkipProcedurals), enable_spheres = static_cast(rhi::RayTracingPipelineFlags::EnableSpheres), enable_linear_swept_spheres = static_cast(rhi::RayTracingPipelineFlags::EnableLinearSweptSpheres), + enable_clusters = static_cast(rhi::RayTracingPipelineFlags::EnableClusters), enable_opacity_micromaps = static_cast(rhi::RayTracingPipelineFlags::EnableOpacityMicromaps), }; @@ -876,6 +877,7 @@ SGL_ENUM_FLAGS_INFO( {RayTracingPipelineFlags::skip_procedurals, "skip_procedurals"}, {RayTracingPipelineFlags::enable_spheres, "enable_spheres"}, {RayTracingPipelineFlags::enable_linear_swept_spheres, "enable_linear_swept_spheres"}, + {RayTracingPipelineFlags::enable_clusters, "enable_clusters"}, {RayTracingPipelineFlags::enable_opacity_micromaps, "enable_opacity_micromaps"}, } ); diff --git a/src/slangpy_ext/device/command.cpp b/src/slangpy_ext/device/command.cpp index 42e28fa51..a23c558cc 100644 --- a/src/slangpy_ext/device/command.cpp +++ b/src/slangpy_ext/device/command.cpp @@ -512,6 +512,12 @@ SGL_PY_EXPORT(device_command) "queries"_a, D(CommandEncoder, query_acceleration_structure_properties) ) + .def( + "execute_cluster_operation", + &CommandEncoder::execute_cluster_operation, + "desc"_a, + D(CommandEncoder, execute_cluster_operation) + ) .def( "convert_coop_vec_matrices", &CommandEncoder::convert_coop_vec_matrices, diff --git a/src/slangpy_ext/device/device.cpp b/src/slangpy_ext/device/device.cpp index f058d1499..f06e53769 100644 --- a/src/slangpy_ext/device/device.cpp +++ b/src/slangpy_ext/device/device.cpp @@ -974,6 +974,12 @@ SGL_PY_EXPORT(device_device) D(Device, create_micromap) ); device.def("create_micromap", &Device::create_micromap, "desc"_a, D(Device, create_micromap)); + device.def( + "get_cluster_operation_sizes", + &Device::get_cluster_operation_sizes, + "params"_a, + D(Device, get_cluster_operation_sizes) + ); device.def( "create_shader_table", [](Device* self, @@ -1609,6 +1615,7 @@ SGL_PY_EXPORT(device_device) D(create_micromap) ); m.def("create_micromap", nb::overload_cast(&create_micromap), "desc"_a, D(create_micromap)); + m.def("get_cluster_operation_sizes", &get_cluster_operation_sizes, "params"_a, D(get_cluster_operation_sizes)); m.def( "create_shader_table", [](ref program, diff --git a/src/slangpy_ext/device/raytracing.cpp b/src/slangpy_ext/device/raytracing.cpp index e5ea86ac3..500a37a62 100644 --- a/src/slangpy_ext/device/raytracing.cpp +++ b/src/slangpy_ext/device/raytracing.cpp @@ -131,6 +131,50 @@ SGL_DICT_TO_DESC_FIELD(size, DeviceSize) SGL_DICT_TO_DESC_FIELD(label, std::string) SGL_DICT_TO_DESC_END() +SGL_DICT_TO_DESC_BEGIN(ClusterOperationMoveParams) +SGL_DICT_TO_DESC_FIELD(type, ClusterOperationMoveType) +SGL_DICT_TO_DESC_FIELD(max_size, uint32_t) +SGL_DICT_TO_DESC_END() + +SGL_DICT_TO_DESC_BEGIN(ClusterOperationClasBuildParams) +SGL_DICT_TO_DESC_FIELD(vertex_format, Format) +SGL_DICT_TO_DESC_FIELD(max_geometry_index, uint32_t) +SGL_DICT_TO_DESC_FIELD(max_unique_geometry_count, uint32_t) +SGL_DICT_TO_DESC_FIELD(max_triangle_count, uint32_t) +SGL_DICT_TO_DESC_FIELD(max_vertex_count, uint32_t) +SGL_DICT_TO_DESC_FIELD(max_total_triangle_count, uint32_t) +SGL_DICT_TO_DESC_FIELD(max_total_vertex_count, uint32_t) +SGL_DICT_TO_DESC_FIELD(min_position_truncate_bit_count, uint32_t) +SGL_DICT_TO_DESC_END() + +SGL_DICT_TO_DESC_BEGIN(ClusterOperationBlasBuildParams) +SGL_DICT_TO_DESC_FIELD(max_clas_count, uint32_t) +SGL_DICT_TO_DESC_FIELD(max_total_clas_count, uint32_t) +SGL_DICT_TO_DESC_END() + +SGL_DICT_TO_DESC_BEGIN(ClusterOperationParams) +SGL_DICT_TO_DESC_FIELD(max_arg_count, uint32_t) +SGL_DICT_TO_DESC_FIELD(type, ClusterOperationType) +SGL_DICT_TO_DESC_FIELD(mode, ClusterOperationMode) +SGL_DICT_TO_DESC_FIELD(flags, ClusterOperationFlags) +SGL_DICT_TO_DESC_FIELD(move, ClusterOperationMoveParams) +SGL_DICT_TO_DESC_FIELD(clas, ClusterOperationClasBuildParams) +SGL_DICT_TO_DESC_FIELD(blas, ClusterOperationBlasBuildParams) +SGL_DICT_TO_DESC_END() + +SGL_DICT_TO_DESC_BEGIN(ClusterOperationDesc) +SGL_DICT_TO_DESC_FIELD(params, ClusterOperationParams) +SGL_DICT_TO_DESC_FIELD(arg_count_buffer, BufferOffsetPair) +SGL_DICT_TO_DESC_FIELD(args_buffer, BufferOffsetPair) +SGL_DICT_TO_DESC_FIELD(args_buffer_stride, uint64_t) +SGL_DICT_TO_DESC_FIELD(scratch_buffer, BufferOffsetPair) +SGL_DICT_TO_DESC_FIELD(addresses_buffer, BufferOffsetPair) +SGL_DICT_TO_DESC_FIELD(addresses_buffer_stride, size_t) +SGL_DICT_TO_DESC_FIELD(result_buffer, BufferOffsetPair) +SGL_DICT_TO_DESC_FIELD(sizes_buffer, BufferOffsetPair) +SGL_DICT_TO_DESC_FIELD(sizes_buffer_stride, size_t) +SGL_DICT_TO_DESC_END() + SGL_DICT_TO_DESC_BEGIN(ShaderTableDesc) SGL_DICT_TO_DESC_FIELD(program, ref) SGL_DICT_TO_DESC_FIELD_LIST(ray_gen_entry_points, std::string) @@ -146,7 +190,17 @@ SGL_PY_EXPORT(device_raytracing) using namespace sgl; nb::class_(m, "AccelerationStructureHandle", "Acceleration structure handle.") - .def(nb::init<>()); + .def(nb::init<>()) + .def( + "__init__", + [](AccelerationStructureHandle* self, uint64_t value) + { + new (self) AccelerationStructureHandle{value}; + }, + "value"_a + ) + .def_rw("value", &AccelerationStructureHandle::value); + nb::implicitly_convertible(); nb::sgl_enum_flags(m, "AccelerationStructureGeometryFlags"); nb::sgl_enum_flags(m, "AccelerationStructureInstanceFlags"); @@ -620,6 +674,165 @@ SGL_PY_EXPORT(device_raytracing) D(AccelerationStructureInstanceList, build_input_instances) ); + nb::sgl_enum(m, "ClusterOperationType"); + nb::sgl_enum(m, "ClusterOperationMode"); + nb::sgl_enum_flags(m, "ClusterOperationFlags"); + nb::sgl_enum(m, "ClusterOperationMoveType"); + + nb::class_(m, "ClusterOperationMoveParams", D(ClusterOperationMoveParams)) + .def(nb::init<>()) + .def( + "__init__", + [](ClusterOperationMoveParams* self, nb::dict dict) + { + new (self) ClusterOperationMoveParams(dict_to_ClusterOperationMoveParams(dict)); + } + ) + .def_rw("type", &ClusterOperationMoveParams::type, D(ClusterOperationMoveParams, type)) + .def_rw("max_size", &ClusterOperationMoveParams::max_size, D(ClusterOperationMoveParams, max_size)); + nb::implicitly_convertible(); + + nb::class_( + m, + "ClusterOperationClasBuildParams", + D(ClusterOperationClasBuildParams) + ) + .def(nb::init<>()) + .def( + "__init__", + [](ClusterOperationClasBuildParams* self, nb::dict dict) + { + new (self) ClusterOperationClasBuildParams(dict_to_ClusterOperationClasBuildParams(dict)); + } + ) + .def_rw( + "vertex_format", + &ClusterOperationClasBuildParams::vertex_format, + D(ClusterOperationClasBuildParams, vertex_format) + ) + .def_rw( + "max_geometry_index", + &ClusterOperationClasBuildParams::max_geometry_index, + D(ClusterOperationClasBuildParams, max_geometry_index) + ) + .def_rw( + "max_unique_geometry_count", + &ClusterOperationClasBuildParams::max_unique_geometry_count, + D(ClusterOperationClasBuildParams, max_unique_geometry_count) + ) + .def_rw( + "max_triangle_count", + &ClusterOperationClasBuildParams::max_triangle_count, + D(ClusterOperationClasBuildParams, max_triangle_count) + ) + .def_rw( + "max_vertex_count", + &ClusterOperationClasBuildParams::max_vertex_count, + D(ClusterOperationClasBuildParams, max_vertex_count) + ) + .def_rw( + "max_total_triangle_count", + &ClusterOperationClasBuildParams::max_total_triangle_count, + D(ClusterOperationClasBuildParams, max_total_triangle_count) + ) + .def_rw( + "max_total_vertex_count", + &ClusterOperationClasBuildParams::max_total_vertex_count, + D(ClusterOperationClasBuildParams, max_total_vertex_count) + ) + .def_rw( + "min_position_truncate_bit_count", + &ClusterOperationClasBuildParams::min_position_truncate_bit_count, + D(ClusterOperationClasBuildParams, min_position_truncate_bit_count) + ); + nb::implicitly_convertible(); + + nb::class_( + m, + "ClusterOperationBlasBuildParams", + D(ClusterOperationBlasBuildParams) + ) + .def(nb::init<>()) + .def( + "__init__", + [](ClusterOperationBlasBuildParams* self, nb::dict dict) + { + new (self) ClusterOperationBlasBuildParams(dict_to_ClusterOperationBlasBuildParams(dict)); + } + ) + .def_rw( + "max_clas_count", + &ClusterOperationBlasBuildParams::max_clas_count, + D(ClusterOperationBlasBuildParams, max_clas_count) + ) + .def_rw( + "max_total_clas_count", + &ClusterOperationBlasBuildParams::max_total_clas_count, + D(ClusterOperationBlasBuildParams, max_total_clas_count) + ); + nb::implicitly_convertible(); + + nb::class_(m, "ClusterOperationParams", D(ClusterOperationParams)) + .def(nb::init<>()) + .def( + "__init__", + [](ClusterOperationParams* self, nb::dict dict) + { + new (self) ClusterOperationParams(dict_to_ClusterOperationParams(dict)); + } + ) + .def_rw("max_arg_count", &ClusterOperationParams::max_arg_count, D(ClusterOperationParams, max_arg_count)) + .def_rw("type", &ClusterOperationParams::type, D(ClusterOperationParams, type)) + .def_rw("mode", &ClusterOperationParams::mode, D(ClusterOperationParams, mode)) + .def_rw("flags", &ClusterOperationParams::flags, D(ClusterOperationParams, flags)) + .def_rw("move", &ClusterOperationParams::move, D(ClusterOperationParams, move)) + .def_rw("clas", &ClusterOperationParams::clas, D(ClusterOperationParams, clas)) + .def_rw("blas", &ClusterOperationParams::blas, D(ClusterOperationParams, blas)); + nb::implicitly_convertible(); + + nb::class_(m, "ClusterOperationDesc", D(ClusterOperationDesc)) + .def(nb::init<>()) + .def( + "__init__", + [](ClusterOperationDesc* self, nb::dict dict) + { + new (self) ClusterOperationDesc(dict_to_ClusterOperationDesc(dict)); + } + ) + .def_rw("params", &ClusterOperationDesc::params, D(ClusterOperationDesc, params)) + .def_rw("arg_count_buffer", &ClusterOperationDesc::arg_count_buffer, D(ClusterOperationDesc, arg_count_buffer)) + .def_rw("args_buffer", &ClusterOperationDesc::args_buffer, D(ClusterOperationDesc, args_buffer)) + .def_rw( + "args_buffer_stride", + &ClusterOperationDesc::args_buffer_stride, + D(ClusterOperationDesc, args_buffer_stride) + ) + .def_rw("scratch_buffer", &ClusterOperationDesc::scratch_buffer, D(ClusterOperationDesc, scratch_buffer)) + .def_rw("addresses_buffer", &ClusterOperationDesc::addresses_buffer, D(ClusterOperationDesc, addresses_buffer)) + .def_rw( + "addresses_buffer_stride", + &ClusterOperationDesc::addresses_buffer_stride, + D(ClusterOperationDesc, addresses_buffer_stride) + ) + .def_rw("result_buffer", &ClusterOperationDesc::result_buffer, D(ClusterOperationDesc, result_buffer)) + .def_rw("sizes_buffer", &ClusterOperationDesc::sizes_buffer, D(ClusterOperationDesc, sizes_buffer)) + .def_rw( + "sizes_buffer_stride", + &ClusterOperationDesc::sizes_buffer_stride, + D(ClusterOperationDesc, sizes_buffer_stride) + ); + nb::implicitly_convertible(); + + nb::class_(m, "ClusterOperationSizes", D(ClusterOperationSizes)) + .def_ro("result_size", &ClusterOperationSizes::result_size, D(ClusterOperationSizes, result_size)) + .def_ro("scratch_size", &ClusterOperationSizes::scratch_size, D(ClusterOperationSizes, scratch_size)); + + m.attr("CLUSTER_MAX_TRIANGLE_COUNT") = CLUSTER_MAX_TRIANGLE_COUNT; + m.attr("CLUSTER_MAX_VERTEX_COUNT") = CLUSTER_MAX_VERTEX_COUNT; + m.attr("CLUSTER_MAX_GEOMETRY_INDEX") = CLUSTER_MAX_GEOMETRY_INDEX; + m.attr("CLUSTER_DEFAULT_HANDLE_STRIDE") = CLUSTER_DEFAULT_HANDLE_STRIDE; + m.attr("CLUSTER_OUTPUT_ALIGNMENT") = CLUSTER_OUTPUT_ALIGNMENT; + nb::class_(m, "ShaderTableDesc", D(ShaderTableDesc)) .def(nb::init<>()) .def( diff --git a/src/slangpy_ext/py_doc.h b/src/slangpy_ext/py_doc.h index 062b6b378..a637acc7f 100644 --- a/src/slangpy_ext/py_doc.h +++ b/src/slangpy_ext/py_doc.h @@ -1701,6 +1701,128 @@ static const char *__doc_sgl_CallbackList_snapshot = R"doc()doc"; static const char *__doc_sgl_CallbackList_unregister_callback = R"doc()doc"; +static const char *__doc_sgl_ClusterOperationBlasBuildParams = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationBlasBuildParams_max_clas_count = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationBlasBuildParams_max_total_clas_count = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationClasBuildParams = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationClasBuildParams_max_geometry_index = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationClasBuildParams_max_total_triangle_count = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationClasBuildParams_max_total_vertex_count = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationClasBuildParams_max_triangle_count = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationClasBuildParams_max_unique_geometry_count = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationClasBuildParams_max_vertex_count = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationClasBuildParams_min_position_truncate_bit_count = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationClasBuildParams_vertex_format = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationDesc = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationDesc_addresses_buffer = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationDesc_addresses_buffer_stride = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationDesc_arg_count_buffer = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationDesc_args_buffer = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationDesc_args_buffer_stride = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationDesc_params = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationDesc_result_buffer = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationDesc_scratch_buffer = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationDesc_sizes_buffer = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationDesc_sizes_buffer_stride = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationFlags = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationFlags_allow_omm = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationFlags_fast_build = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationFlags_fast_trace = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationFlags_info = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationFlags_no_overlap = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationFlags_none = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationMode = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationMode_explicit_destinations = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationMode_get_sizes = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationMode_implicit_destinations = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationMode_info = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationMoveParams = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationMoveParams_max_size = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationMoveParams_type = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationMoveType = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationMoveType_bottom_level = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationMoveType_cluster_level = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationMoveType_info = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationMoveType_template = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationParams = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationParams_blas = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationParams_clas = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationParams_flags = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationParams_max_arg_count = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationParams_mode = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationParams_move = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationParams_type = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationSizes = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationSizes_result_size = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationSizes_scratch_size = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationType = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationType_blas_from_clas = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationType_clas_from_templates = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationType_clas_from_triangles = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationType_info = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationType_move_objects = R"doc()doc"; + +static const char *__doc_sgl_ClusterOperationType_templates_from_triangles = R"doc()doc"; + static const char *__doc_sgl_ColorTargetDesc = R"doc()doc"; static const char *__doc_sgl_ColorTargetDesc_alpha = R"doc()doc"; @@ -1961,6 +2083,8 @@ is heap allocated and retained until the command buffer releases it, resulting in objects captured by the lambda are kept alive for the duration of the command buffer.)doc"; +static const char *__doc_sgl_CommandEncoder_execute_cluster_operation = R"doc(Execute an indirect cluster acceleration structure operation.)doc"; + static const char *__doc_sgl_CommandEncoder_finish = R"doc()doc"; static const char *__doc_sgl_CommandEncoder_generate_mips = R"doc()doc"; @@ -3531,6 +3655,8 @@ Parameter ``desc``: Returns: Acceleration structure sizes.)doc"; +static const char *__doc_sgl_Device_get_cluster_operation_sizes = R"doc(Query the device for buffer sizes required for a cluster operation.)doc"; + static const char *__doc_sgl_Device_get_coop_vec_matrix_size = R"doc(Get the size of a cooperative vector matrix in bytes.)doc"; static const char *__doc_sgl_Device_get_created_devices = R"doc(Lists all created devices)doc"; @@ -6033,14 +6159,6 @@ static const char *__doc_sgl_MicromapSizes_micromap_size = R"doc()doc"; static const char *__doc_sgl_MicromapSizes_scratch_size = R"doc()doc"; -static const char *__doc_sgl_MicromapTriangleDesc = R"doc()doc"; - -static const char *__doc_sgl_MicromapTriangleDesc_data_offset = R"doc()doc"; - -static const char *__doc_sgl_MicromapTriangleDesc_format = R"doc()doc"; - -static const char *__doc_sgl_MicromapTriangleDesc_subdivision_level = R"doc()doc"; - static const char *__doc_sgl_MicromapType = R"doc()doc"; static const char *__doc_sgl_MicromapType_info = R"doc()doc"; @@ -7693,6 +7811,8 @@ static const char *__doc_sgl_RayTracingPipelineDesc_program = R"doc()doc"; static const char *__doc_sgl_RayTracingPipelineFlags = R"doc()doc"; +static const char *__doc_sgl_RayTracingPipelineFlags_enable_clusters = R"doc()doc"; + static const char *__doc_sgl_RayTracingPipelineFlags_enable_linear_swept_spheres = R"doc()doc"; static const char *__doc_sgl_RayTracingPipelineFlags_enable_opacity_micromaps = R"doc()doc"; @@ -10457,7 +10577,7 @@ static const char *__doc_sgl_breakable_ref_operator_bool = R"doc()doc"; static const char *__doc_sgl_breakable_ref_operator_mul = R"doc()doc"; -static const char *__doc_sgl_breakable_ref_operator_sgl_ref = R"doc()doc"; +static const char *__doc_sgl_breakable_ref_operator_ref = R"doc()doc"; static const char *__doc_sgl_breakable_ref_operator_sub = R"doc()doc"; @@ -11058,6 +11178,8 @@ static const char *__doc_sgl_detail_to_rhi = R"doc()doc"; static const char *__doc_sgl_detail_to_rhi_2 = R"doc()doc"; +static const char *__doc_sgl_detail_to_rhi_3 = R"doc()doc"; + static const char *__doc_sgl_detail_to_rhi_cooperative_vector_component_type = R"doc()doc"; static const char *__doc_sgl_detail_type_name = @@ -11258,6 +11380,14 @@ static const char *__doc_sgl_find_enum_info_adl_90 = R"doc()doc"; static const char *__doc_sgl_find_enum_info_adl_91 = R"doc()doc"; +static const char *__doc_sgl_find_enum_info_adl_92 = R"doc()doc"; + +static const char *__doc_sgl_find_enum_info_adl_93 = R"doc()doc"; + +static const char *__doc_sgl_find_enum_info_adl_94 = R"doc()doc"; + +static const char *__doc_sgl_find_enum_info_adl_95 = R"doc()doc"; + static const char *__doc_sgl_flags_to_string_list = R"doc(Convert an flags enum value to a list of strings.)doc"; static const char *__doc_sgl_flip_bit = R"doc()doc"; @@ -11288,6 +11418,8 @@ static const char *__doc_sgl_flip_bit_13 = R"doc()doc"; static const char *__doc_sgl_flip_bit_14 = R"doc()doc"; +static const char *__doc_sgl_flip_bit_15 = R"doc()doc"; + static const char *__doc_sgl_format_to_bc_format = R"doc(Convert RHI Format to BCFormat (returns nullopt if not a BC format).)doc"; static const char *__doc_sgl_func_BaseModule = R"doc(Base class for functional slangpy module.)doc"; @@ -11492,6 +11624,10 @@ Parameter ``desc``: Returns: Acceleration structure sizes.)doc"; +static const char *__doc_sgl_get_cluster_operation_sizes = +R"doc(Query the current device for buffer sizes required for a cluster +operation.)doc"; + static const char *__doc_sgl_get_coop_vec_matrix_size = R"doc(Get the size of a cooperative vector matrix in bytes.)doc"; static const char *__doc_sgl_get_cuda_current_context_native_handles = @@ -11581,6 +11717,8 @@ static const char *__doc_sgl_is_set_13 = R"doc()doc"; static const char *__doc_sgl_is_set_14 = R"doc()doc"; +static const char *__doc_sgl_is_set_15 = R"doc()doc"; + static const char *__doc_sgl_layout_from_rhilayout = R"doc()doc"; static const char *__doc_sgl_lerp = R"doc(Linearly interpolate between a and b.)doc"; @@ -12693,6 +12831,8 @@ static const char *__doc_sgl_operator_band_13 = R"doc()doc"; static const char *__doc_sgl_operator_band_14 = R"doc()doc"; +static const char *__doc_sgl_operator_band_15 = R"doc()doc"; + static const char *__doc_sgl_operator_bnot = R"doc()doc"; static const char *__doc_sgl_operator_bnot_2 = R"doc()doc"; @@ -12721,6 +12861,8 @@ static const char *__doc_sgl_operator_bnot_13 = R"doc()doc"; static const char *__doc_sgl_operator_bnot_14 = R"doc()doc"; +static const char *__doc_sgl_operator_bnot_15 = R"doc()doc"; + static const char *__doc_sgl_operator_bor = R"doc()doc"; static const char *__doc_sgl_operator_bor_2 = R"doc()doc"; @@ -12749,6 +12891,8 @@ static const char *__doc_sgl_operator_bor_13 = R"doc()doc"; static const char *__doc_sgl_operator_bor_14 = R"doc()doc"; +static const char *__doc_sgl_operator_bor_15 = R"doc()doc"; + static const char *__doc_sgl_operator_iand = R"doc()doc"; static const char *__doc_sgl_operator_iand_2 = R"doc()doc"; @@ -12777,6 +12921,8 @@ static const char *__doc_sgl_operator_iand_13 = R"doc()doc"; static const char *__doc_sgl_operator_iand_14 = R"doc()doc"; +static const char *__doc_sgl_operator_iand_15 = R"doc()doc"; + static const char *__doc_sgl_operator_ior = R"doc()doc"; static const char *__doc_sgl_operator_ior_2 = R"doc()doc"; @@ -12805,6 +12951,8 @@ static const char *__doc_sgl_operator_ior_13 = R"doc()doc"; static const char *__doc_sgl_operator_ior_14 = R"doc()doc"; +static const char *__doc_sgl_operator_ior_15 = R"doc()doc"; + static const char *__doc_sgl_platform_FileDialogFilter = R"doc()doc"; static const char *__doc_sgl_platform_FileDialogFilter_FileDialogFilter = R"doc()doc"; diff --git a/tools/postprocess_stub.py b/tools/postprocess_stub.py index 4fcefcde3..edb02b37e 100644 --- a/tools/postprocess_stub.py +++ b/tools/postprocess_stub.py @@ -27,6 +27,11 @@ "AspectBlendDesc": True, "BufferDesc": True, "BufferOffsetPair": True, + "ClusterOperationBlasBuildParams": True, + "ClusterOperationClasBuildParams": True, + "ClusterOperationDesc": True, + "ClusterOperationMoveParams": True, + "ClusterOperationParams": True, "ColorTargetDesc": True, "ComputePipelineDesc": True, "CoopVecMatrixDesc": True,