From 46134bec05ca09fd81259b1de3c943db44beaa08 Mon Sep 17 00:00:00 2001 From: CrabeExtra Date: Tue, 22 Sep 2026 19:14:00 +0330 Subject: [PATCH] cross HLSL and C++ wrapper/typedef for BDA --- include/nbl/builtin/hlsl/bda/ptr.hlsl | 87 +++++++++++++++++++++++++++ include/nbl/video/IGPUBuffer.h | 52 ++++++++++++++++ src/nbl/builtin/CMakeLists.txt | 1 + 3 files changed, 140 insertions(+) create mode 100644 include/nbl/builtin/hlsl/bda/ptr.hlsl diff --git a/include/nbl/builtin/hlsl/bda/ptr.hlsl b/include/nbl/builtin/hlsl/bda/ptr.hlsl new file mode 100644 index 0000000000..c410cc91bf --- /dev/null +++ b/include/nbl/builtin/hlsl/bda/ptr.hlsl @@ -0,0 +1,87 @@ +// Copyright (C) 2018-2026 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_BDA_PTR_HLSL_INCLUDED_ +#define _NBL_BUILTIN_HLSL_BDA_PTR_HLSL_INCLUDED_ + +#include "nbl/builtin/hlsl/cpp_compat/matrix.hlsl" +#include "nbl/builtin/hlsl/type_traits.hlsl" + +#ifndef __HLSL_VERSION +#include +#include +#endif + +namespace nbl +{ +namespace hlsl +{ +namespace bda +{ + +namespace impl +{ +// no `const` pointee: DXC silently drops stores through `vk::BufferPointer` +template +struct pointee +{ + using type = T; +}; +template +struct pointee {}; +} + +#ifdef __HLSL_VERSION +// https://github.com/microsoft/hlsl-specs/blob/main/proposals/0010-vk-buffer-ref.md#buffer-pointers-and-aliasing +template::value> +using ptr = vk::BufferPointer::type,Alignment>; +#else +template::value> +struct ptr +{ + using pointee_t = typename impl::pointee::type; + + uint64_t address; + + ptr() = default; + constexpr explicit ptr(const uint64_t _address) : address(_address) + { + // https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#VUID-RuntimeSpirv-PhysicalStorageBuffer64-06315 + assert(Alignment==0u || (_address%Alignment)==0ull); + } + + constexpr explicit operator uint64_t() const {return address;} + + // integers scroll by `sizeof(T)*arg`, byte offsets go through `offsetBytes` + template + constexpr ptr operator+(const I elements) const {return ptr(address+static_cast(elements)*sizeof(T));} + template + constexpr ptr operator-(const I elements) const {return ptr(address-static_cast(elements)*sizeof(T));} + template + constexpr ptr& operator+=(const I elements) {return *this = *this+elements;} + template + constexpr ptr& operator-=(const I elements) {return *this = *this-elements;} + + template + constexpr ptr offsetBytes(const I bytes) const {return ptr(address+static_cast(bytes));} +}; +static_assert(sizeof(ptr)==sizeof(uint64_t) && alignof(ptr)==alignof(uint64_t) && std::is_trivially_copyable_v >); +#endif + +} + +#ifdef __HLSL_VERSION +namespace impl +{ +template +struct static_cast_helper,void> +{ + static uint64_t cast(vk::BufferPointer p) {return (uint64_t)p;} +}; +} +#endif + +} +} + +#endif diff --git a/include/nbl/video/IGPUBuffer.h b/include/nbl/video/IGPUBuffer.h index 73f640a937..8d8c46e921 100644 --- a/include/nbl/video/IGPUBuffer.h +++ b/include/nbl/video/IGPUBuffer.h @@ -11,6 +11,8 @@ #include "nbl/video/decl/IBackendObject.h" #include "nbl/video/IDeviceMemoryBacked.h" +#include "nbl/builtin/hlsl/bda/ptr.hlsl" + namespace nbl::video { @@ -49,5 +51,55 @@ class IGPUBuffer : public asset::IBuffer, public IDeviceMemoryBacked } // end namespace nbl::video +namespace nbl::hlsl::impl +{ + +template requires std::is_base_of_v +struct static_cast_helper,BufferT*,void> +{ + static inline bda::ptr cast(const BufferT* buffer) + { + if (!buffer) + return bda::ptr(0ull); + assert(buffer->getDeviceAddress()!=0ull); + return bda::ptr(buffer->getDeviceAddress()); + } +}; + +template requires std::is_base_of_v +struct static_cast_helper,core::smart_refctd_ptr,void> +{ + static inline bda::ptr cast(const core::smart_refctd_ptr& buffer) + { + return _static_cast>(buffer.get()); + } +}; + +template requires std::is_base_of_v +struct static_cast_helper,asset::SBufferBinding,void> +{ + static inline bda::ptr cast(const asset::SBufferBinding& binding) + { + if (!binding.buffer) + return bda::ptr(0ull); + assert(binding.isValid()); + return _static_cast>(binding.buffer.get()).offsetBytes(binding.offset); + } +}; + +template requires std::is_base_of_v +struct static_cast_helper,asset::SBufferRange,void> +{ + static inline bda::ptr cast(const asset::SBufferRange& range) + { + if (!range.buffer) + return bda::ptr(0ull); + assert(range.isValid()); + return _static_cast>(range.buffer.get()).offsetBytes(range.offset); + } +}; + +} + #endif diff --git a/src/nbl/builtin/CMakeLists.txt b/src/nbl/builtin/CMakeLists.txt index 8701aaee9b..cbdcbbb8e4 100644 --- a/src/nbl/builtin/CMakeLists.txt +++ b/src/nbl/builtin/CMakeLists.txt @@ -25,6 +25,7 @@ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "glsl/barycentric/utils.glsl") #bda LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bda/__ref.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bda/__ptr.hlsl") +LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bda/ptr.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bda/struct_declare.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bda/bda_accessor.hlsl") LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/bda/legacy_bda_accessor.hlsl")