diff --git a/aster/include/aster/core/buffer.h b/aster/include/aster/core/buffer.h index 18f1a51..cd398c3 100644 --- a/aster/include/aster/core/buffer.h +++ b/aster/include/aster/core/buffer.h @@ -30,6 +30,7 @@ struct Buffer vk::Buffer m_Buffer = nullptr; VmaAllocation m_Allocation = nullptr; u8 *m_Mapped = nullptr; ///< If the buffer is host visible, it should be (and stay) mapped. + uptr m_DeviceAddr = 0; usize m_Size = 0; Flags m_Flags = {}; @@ -54,7 +55,7 @@ struct Buffer /// If Buffer Device Address is enabled, /// Get a pointer. - uptr GetDeviceAddress(Device const *device) const; + [[nodiscard]] uptr GetDeviceAddress() const; // Constructors diff --git a/aster/include/aster/systems/commit_manager.h b/aster/include/aster/systems/commit_manager.h index b0afaca..5c2eeb8 100644 --- a/aster/include/aster/systems/commit_manager.h +++ b/aster/include/aster/systems/commit_manager.h @@ -16,187 +16,191 @@ #include "aster/core/buffer.h" #include "aster/core/image_view.h" #include "aster/core/sampler.h" + #include "resource.h" namespace systems { class RenderingDevice; -class CommitManager +namespace _internal { - template - struct HandleMapper +template +struct HandleMapper +{ + using Type = T; + using Handle = Ref; + using Resource = ResId; + + struct Entry : eastl::intrusive_hash_node_key { - using Type = T; - using Handle = Ref; - using Resource = ResId; + std::atomic m_CommitCount; - struct Entry : eastl::intrusive_hash_node_key + void + AddRef() { - std::atomic m_CommitCount; - - void - AddRef() - { - auto const rc = ++m_CommitCount; - assert(rc > 0); - } - - void - Release() - { - auto const rc = --m_CommitCount; - assert(rc < MaxValue); - } - - u32 - IsReferenced() const - { - return m_CommitCount; - } - - bool - operator==(Entry const &other) const - { - return this->mKey == other.mKey; - } - - Entry * - Next() - { - return reinterpret_cast(this->mpNext); - } - - void - SetNext(Entry &entry) - { - this->mpNext = &entry; - } - - struct Hash - { - usize - operator()(Handle const &e) - { - return eastl::hash()(e.get()); - } - }; - }; - - eastl::vector m_Data; - FreeList m_FreeList; - eastl::intrusive_hash_map m_InUse; - std::array, 4> m_ToDelete; - u8 m_ToDeleteIndex = 0; - - explicit HandleMapper(u32 const maxCount) - : m_Data{maxCount} - { - // Setup freelist - for (auto it = m_Data.rbegin(); it != m_Data.rend(); ++it) - { - m_FreeList.Push(*it); - } - } - - ~HandleMapper() - { - for (auto &toDelete : m_ToDelete) - { - ClearEntries(toDelete); - } - } - - PIN_MEMORY(HandleMapper); - - /// Returns a commit, and a bool signifying if it is a new commit. - std::tuple - Create(Handle const &object) - { - // Get-from freelist - assert(!m_FreeList.Empty()); - - auto it = m_InUse.find(object); - if (it != m_InUse.end()) - { - it->AddRef(); - auto i = GetIndex(*it); - return {Resource{i}, false}; - } - - Entry &data = m_FreeList.Pop(); - - data.mKey = object; - data.m_CommitCount = 0; - - m_InUse.insert(data); - - auto i = GetIndex(data); - - return {Resource{i}, true}; - } - - Handle - GetHandle(Resource const &res) - { - return m_Data[res.m_Index].mKey; + auto const rc = ++m_CommitCount; + assert(rc > 0); } void - AddRef(Resource const &commit) + Release() { - m_Data.at(commit.m_Index).AddRef(); + auto const rc = --m_CommitCount; + assert(rc < MaxValue); } - void - Release(Resource const &commit) - { - auto &entry = m_Data.at(commit.m_Index); - entry.Release(); - if (!entry.IsReferenced()) - { - QueueDelete(entry); - } - } - - /** - * Sweeps through the delete queue. - * All freed items are cleared. (With a 3 frame delay) - */ - void - Update() - { - m_ToDeleteIndex = (m_ToDeleteIndex + 1) % m_ToDelete.size(); - auto &list = m_ToDelete[m_ToDeleteIndex]; - ClearEntries(list); - } - - private: u32 - GetIndex(Entry const &entry) + IsReferenced() const { - return static_cast(&entry - m_Data.begin()); + return m_CommitCount; + } + + bool + operator==(Entry const &other) const + { + return this->mKey == other.mKey; + } + + Entry * + Next() + { + return reinterpret_cast(this->mpNext); } void - QueueDelete(Entry &entry) + SetNext(Entry &entry) { - m_InUse.remove(entry); - m_ToDelete[m_ToDeleteIndex].Push(entry); + this->mpNext = &entry; } - void - ClearEntries(FreeList &entries) + struct Hash { - while (!entries.Empty()) + usize + operator()(Handle const &e) { - Entry &entry = entries.Pop(); - entry.mKey.reset(); - entry.m_CommitCount = 0; + return eastl::hash()(e.get()); } - } + }; }; + eastl::vector m_Data; + FreeList m_FreeList; + eastl::intrusive_hash_map m_InUse; + std::array, 4> m_ToDelete; + u8 m_ToDeleteIndex = 0; + + explicit HandleMapper(u32 const maxCount) + : m_Data{maxCount} + { + // Setup freelist + for (auto it = m_Data.rbegin(); it != m_Data.rend(); ++it) + { + m_FreeList.Push(*it); + } + } + + ~HandleMapper() + { + for (auto &toDelete : m_ToDelete) + { + ClearEntries(toDelete); + } + } + + PIN_MEMORY(HandleMapper); + + /// Returns a commit, and a bool signifying if it is a new commit. + std::tuple + Create(Handle const &object) + { + // Get-from freelist + assert(!m_FreeList.Empty()); + + auto it = m_InUse.find(object); + if (it != m_InUse.end()) + { + it->AddRef(); + auto i = GetIndex(*it); + return {Resource{i}, false}; + } + + Entry &data = m_FreeList.Pop(); + + data.mKey = object; + data.m_CommitCount = 0; + + m_InUse.insert(data); + + auto i = GetIndex(data); + + return {Resource{i}, true}; + } + + Handle + GetHandle(Resource const &res) + { + return m_Data[res.m_Index].mKey; + } + + void + AddRef(Resource const &commit) + { + m_Data.at(commit.m_Index).AddRef(); + } + + void + Release(Resource const &commit) + { + auto &entry = m_Data.at(commit.m_Index); + entry.Release(); + if (!entry.IsReferenced()) + { + QueueDelete(entry); + } + } + + /** + * Sweeps through the delete queue. + * All freed items are cleared. (With a 3 frame delay) + */ + void + Update() + { + m_ToDeleteIndex = (m_ToDeleteIndex + 1) % m_ToDelete.size(); + auto &list = m_ToDelete[m_ToDeleteIndex]; + ClearEntries(list); + } + + private: + u32 + GetIndex(Entry const &entry) + { + return static_cast(&entry - m_Data.begin()); + } + + void + QueueDelete(Entry &entry) + { + m_InUse.remove(entry); + m_ToDelete[m_ToDeleteIndex].Push(entry); + } + + void + ClearEntries(FreeList &entries) + { + while (!entries.Empty()) + { + Entry &entry = entries.Pop(); + entry.mKey.reset(); + entry.m_CommitCount = 0; + } + } +}; +} // namespace _internal + +class CommitManager +{ union WriteInfo { vk::DescriptorBufferInfo uBufferInfo; vk::DescriptorImageInfo uImageInfo; @@ -221,8 +225,10 @@ class CommitManager PIN_MEMORY(CommitManager); // Commit Buffer + private: ResId CommitBuffer(Ref const &buffer); + public: // Commit Storage Images ResId CommitStorageImage(concepts::ViewRefTo auto const &image) @@ -302,9 +308,9 @@ class CommitManager constexpr static u8 IMAGE_BINDING_INDEX = 0x1; constexpr static u8 STORAGE_IMAGE_BINDING_INDEX = 0x2; - HandleMapper m_Buffers; - HandleMapper m_Images; - HandleMapper m_StorageImages; + _internal::HandleMapper m_Buffers; + _internal::HandleMapper m_Images; + _internal::HandleMapper m_StorageImages; Ref m_DefaultSampler; diff --git a/aster/src/aster/core/buffer.cpp b/aster/src/aster/core/buffer.cpp index e80446d..a08d6af 100644 --- a/aster/src/aster/core/buffer.cpp +++ b/aster/src/aster/core/buffer.cpp @@ -16,7 +16,7 @@ Buffer::Buffer(Device const *device, usize const size, vk::BufferUsageFlags cons vk::BufferCreateInfo bufferCreateInfo = { .size = size, - .usage = bufferUsage, + .usage = bufferUsage | vk::BufferUsageFlagBits::eShaderDeviceAddress, .sharingMode = vk::SharingMode::eExclusive, }; VmaAllocationCreateInfo const allocationCreateInfo = { @@ -56,6 +56,9 @@ Buffer::Buffer(Device const *device, usize const size, vk::BufferUsageFlags cons if (bufferUsage & vk::BufferUsageFlagBits::eStorageBuffer) m_Flags |= FlagBits::eStorage; + vk::BufferDeviceAddressInfo const addressInfo = {.buffer = m_Buffer}; + m_DeviceAddr = m_Device->m_Device.getBufferAddress(&addressInfo); + device->SetName(m_Buffer, name); } @@ -64,6 +67,7 @@ Buffer::Buffer(Buffer &&other) noexcept , m_Buffer{Take(other.m_Buffer)} , m_Allocation{Take(other.m_Allocation)} , m_Mapped{Take(other.m_Mapped)} + , m_DeviceAddr{Take(other.m_DeviceAddr)} , m_Size{Take(other.m_Size)} { } @@ -78,6 +82,7 @@ Buffer::operator=(Buffer &&other) noexcept swap(m_Buffer, other.m_Buffer); swap(m_Allocation, other.m_Allocation); swap(m_Mapped, other.m_Mapped); + swap(m_DeviceAddr, other.m_DeviceAddr); swap(m_Size, other.m_Size); return *this; } @@ -92,10 +97,9 @@ Buffer::~Buffer() } uptr -Buffer::GetDeviceAddress(Device const *device) const +Buffer::GetDeviceAddress() const { - vk::BufferDeviceAddressInfo const addressInfo = {.buffer = m_Buffer}; - return device->m_Device.getBufferAddress(&addressInfo); + return m_DeviceAddr; } void diff --git a/samples/02_box/CMakeLists.txt b/samples/02_box/CMakeLists.txt index a554695..4ddc6ed 100644 --- a/samples/02_box/CMakeLists.txt +++ b/samples/02_box/CMakeLists.txt @@ -5,11 +5,7 @@ cmake_minimum_required(VERSION 3.13) #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fsanitize=address") add_executable(box "box.cpp" "stb_image.h") -add_shader(box "shader/box.vert.glsl") -add_shader(box "shader/box.frag.glsl") -add_shader(box "shader/box.vs.hlsl") -add_shader(box "shader/box.ps.hlsl") -add_shader(box "shader/triangle.slang") +add_shader(box "shader/box.slang") add_resource_dir(box "shader/") target_link_libraries(box PRIVATE aster_core) diff --git a/samples/02_box/box.cpp b/samples/02_box/box.cpp index d6fa76c..97d9c46 100644 --- a/samples/02_box/box.cpp +++ b/samples/02_box/box.cpp @@ -23,7 +23,7 @@ constexpr auto VERTEX_SHADER_FILE = "shader/box.vs.hlsl.spv"; constexpr auto FRAGMENT_SHADER_FILE = "shader/box.ps.hlsl.spv"; -constexpr auto SHADER_FILE = "triangle"; +constexpr auto SHADER_FILE = "box"; struct ImageFile { @@ -328,11 +328,10 @@ main(int, char **) initDepthImages(extent); }; - // TODO: Move to 64bit handles. struct PCB { - systems::ResId m_VertexBuffer; - systems::ResId m_Camera; + uptr m_VertexBuffer; + uptr m_Camera; systems::ResId m_Texture; }; static_assert(sizeof(PCB) == 24); @@ -340,8 +339,8 @@ main(int, char **) auto &commitManager = systems::CommitManager::Instance(); PCB pcb = { - .m_VertexBuffer = commitManager.CommitBuffer(vbo), - .m_Camera = commitManager.CommitBuffer(ubo), + .m_VertexBuffer = vbo->GetDeviceAddress(), + .m_Camera = ubo->GetDeviceAddress(), .m_Texture = commitManager.CommitTexture(crate), }; diff --git a/samples/02_box/shader/bindless.hlsli b/samples/02_box/shader/bindless.hlsli deleted file mode 100644 index db1cc68..0000000 --- a/samples/02_box/shader/bindless.hlsli +++ /dev/null @@ -1,31 +0,0 @@ - - -struct VertexData -{ - float4 Position; - float2 TexCoord0; - float2 _pad0; -}; - -struct CameraData -{ - float4x4 Model; - float4x4 View; - float4x4 Projection; -}; - -struct Handle -{ - uint value; - - uint GetIndex() - { - return value & 0x0FFFFFFF; - } -}; - -[[vk::binding(0, 0)]] StructuredBuffer VertexDataBuffer[]; -[[vk::binding(0, 0)]] StructuredBuffer CameraDataBuffer[]; - -[[vk::binding(1, 0)]] Texture2D Textures[]; -[[vk::binding(1, 0)]] SamplerState Samplers[]; diff --git a/samples/02_box/shader/box.frag.glsl b/samples/02_box/shader/box.frag.glsl deleted file mode 100644 index 76dbfaf..0000000 --- a/samples/02_box/shader/box.frag.glsl +++ /dev/null @@ -1,11 +0,0 @@ -#version 450 -#pragma shader_stage(fragment) - -layout (location = 0) in vec2 inUV; -layout (location = 0) out vec4 outColor; - -layout(binding = 1) uniform sampler2D tex; - -void main() { - outColor = vec4(texture(tex, inUV).rgb, 1.0f); -} \ No newline at end of file diff --git a/samples/02_box/shader/box.ps.hlsl b/samples/02_box/shader/box.ps.hlsl deleted file mode 100644 index 262dfbb..0000000 --- a/samples/02_box/shader/box.ps.hlsl +++ /dev/null @@ -1,27 +0,0 @@ -#include "bindless.hlsli" - -struct FS_Input { - float2 UV0 : TEXCOORD0; -}; - -struct FS_Output -{ - float4 ColorTarget : SV_Target0; -}; - -struct PCB -{ - Handle CameraBuffer; - Handle VertexBuffer; - Handle Texture; -}; - -[[vk::push_constant]] PCB Block; - -FS_Output main(FS_Input StageInput) { - FS_Output output; - - output.ColorTarget = float4(Textures[Block.Texture.GetIndex()].Sample(Samplers[Block.Texture.GetIndex()], StageInput.UV0).rgb, 1.0); - - return output; -} \ No newline at end of file diff --git a/samples/02_box/shader/triangle.slang b/samples/02_box/shader/box.slang similarity index 72% rename from samples/02_box/shader/triangle.slang rename to samples/02_box/shader/box.slang index 1f45865..ff62baf 100644 --- a/samples/02_box/shader/triangle.slang +++ b/samples/02_box/shader/box.slang @@ -15,9 +15,9 @@ struct CameraData }; struct PCB { - DescriptorHandle> vertexBuffer; - DescriptorHandle> cameraBuffer; - DescriptorHandle texture; + VertexData* vertexBuffer; + CameraData* cameraBuffer; + Sampler2D.Handle texture; }; [vk::push_constant] @@ -43,7 +43,7 @@ func vsmain(VSIn input) -> VSOut { VertexData vd = pcb.vertexBuffer[input.vertexIndex]; - output.position = mul(mul(mul(float4(vd.position.xyz, 1.0f), pcb.cameraBuffer[0].model), pcb.cameraBuffer[0].view), pcb.cameraBuffer[0].projection); + output.position = mul(mul(mul(float4(vd.position.xyz, 1.0f), pcb.cameraBuffer->model), pcb.cameraBuffer->view), pcb.cameraBuffer->projection); output.texCoord0 = vd.texCoord0; return output; @@ -52,7 +52,6 @@ func vsmain(VSIn input) -> VSOut { [shader("fragment")] func fsmain(VSOut input) -> FSOut { FSOut outp; - outp.Color = pcb.vertexBuffer[0].position.rgba; outp.Color = float4(pcb.texture.Sample(input.texCoord0).rgb, 1.0); return outp; } \ No newline at end of file diff --git a/samples/02_box/shader/box.vert.glsl b/samples/02_box/shader/box.vert.glsl deleted file mode 100644 index 76c8f66..0000000 --- a/samples/02_box/shader/box.vert.glsl +++ /dev/null @@ -1,19 +0,0 @@ -#version 450 -#pragma shader_stage(vertex) - -layout(location=0) in vec4 position; -layout(location=1) in vec2 uv0; - -layout(location=0) out vec2 outUV; - -layout(binding=0) uniform Camera { - mat4 model; - mat4 view; - mat4 proj; -} ubo; - -void main() { - outUV = uv0; - gl_Position = ubo.proj * ubo.view * ubo.model * vec4(position.xyz, 1.0f); - // outColor = vec3(0.5f, 0.3f, 0.1f); -} \ No newline at end of file diff --git a/samples/02_box/shader/box.vs.hlsl b/samples/02_box/shader/box.vs.hlsl deleted file mode 100644 index c1c168e..0000000 --- a/samples/02_box/shader/box.vs.hlsl +++ /dev/null @@ -1,35 +0,0 @@ -#include "bindless.hlsli" - -struct VS_Input -{ - uint VertexIndex : SV_VertexID; -}; - -struct VS_Output -{ - float2 UV0 : TEXCOORD0; - float4 VertexPosition : SV_Position; -}; - -struct PCB -{ - Handle CameraBuffer; - Handle VertexBuffer; - Handle Texture; -}; - -[[vk::push_constant]] PCB Block; - -VS_Output main(VS_Input StageInput) { - VS_Output output; - - CameraData Camera = CameraDataBuffer[Block.CameraBuffer.GetIndex()][0]; - - output.UV0 = VertexDataBuffer[Block.VertexBuffer.GetIndex()][StageInput.VertexIndex].TexCoord0; - - float4 position = VertexDataBuffer[Block.VertexBuffer.GetIndex()][StageInput.VertexIndex].Position; - - output.VertexPosition = mul(Camera.Projection, mul(Camera.View, mul(Camera.Model, position))); - - return output; -} \ No newline at end of file diff --git a/samples/03_model_render/asset_loader.cpp b/samples/03_model_render/asset_loader.cpp index e174d2d..11f110c 100644 --- a/samples/03_model_render/asset_loader.cpp +++ b/samples/03_model_render/asset_loader.cpp @@ -474,7 +474,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name) eastl::hash_map> textureHandleMap; eastl::vector materials; - systems::ResId materialsHandle = systems::ResId::Null(); + Ref materialsBuffer; if (!model.materials.empty()) { @@ -515,8 +515,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name) } usize materialsByteSize = materials.size() * sizeof materials[0]; - auto materialsBuffer = m_Device->CreateStorageBuffer(materialsByteSize, name); - materialsHandle = m_Device->m_CommitManager->CommitBuffer(materialsBuffer); + materialsBuffer = m_Device->CreateStorageBuffer(materialsByteSize, name); context.UploadBuffer(materialsBuffer, materials); } @@ -803,7 +802,6 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name) auto nodeBuffer = m_Device->CreateStorageBuffer(nodes.GetGlobalTransformByteSize()); nodeBuffer->Write(0, nodes.GetGlobalTransformByteSize(), nodes.GetGlobalTransformPtr()); - systems::ResId nodeHandle = m_Device->m_CommitManager->CommitBuffer(nodeBuffer); #pragma region Staging / Transfer / Uploads systems::ResId positionBufferHandle = systems::ResId::Null(); @@ -811,11 +809,9 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name) Ref indexBuffer; auto positionBuffer = m_Device->CreateStorageBuffer(vertexPositions.size() * sizeof vertexPositions[0]); - positionBufferHandle = m_Device->m_CommitManager->CommitBuffer(positionBuffer); context.UploadBuffer(positionBuffer, vertexPositions); auto vertexDataBuffer = m_Device->CreateStorageBuffer(vertexData.size() * sizeof vertexData[0]); - vertexDataHandle = m_Device->m_CommitManager->CommitBuffer(vertexDataBuffer); context.UploadBuffer(vertexDataBuffer, vertexData); // TODO: Index buffer needs to be separated. @@ -834,11 +830,14 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name) m_Device->WaitOn(rcpt); Model::ModelHandles handles = { - .m_VertexPositionHandle = positionBufferHandle, - .m_VertexDataHandle = vertexDataHandle, - .m_MaterialsHandle = materialsHandle, - .m_NodeHandle = nodeHandle, + .m_VertexPositionHandle = positionBuffer, + .m_VertexDataHandle = vertexDataBuffer, + .m_MaterialsHandle = materialsBuffer, + .m_NodeHandle = nodeBuffer, }; + Model::ModelHandlesData handlesData = handles; + auto handlesBuffer = m_Device->CreateStorageBuffer(sizeof handlesData, "Materials"); + handlesBuffer->Write(0, sizeof handlesData, &handlesData); eastl::vector> textureHandles; textureHandles.reserve(textureHandleMap.size()); @@ -849,17 +848,19 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name) } return Model{ - textureHandles, std::move(nodes), nodeBuffer, handles, indexBuffer, meshPrimitives, + textureHandles, std::move(nodes), nodeBuffer, handles, handlesBuffer, indexBuffer, meshPrimitives, }; } Model::Model(eastl::vector> &textureHandles, Nodes &&nodes, Ref nodeBuffer, - ModelHandles &handles, Ref indexBuffer, eastl::vector const &meshPrimitives) + ModelHandles &handles, Ref modelHandlesBuffer, Ref indexBuffer, + eastl::vector const &meshPrimitives) : m_TextureHandles(std::move(textureHandles)) , m_Nodes(std::move(nodes)) , m_Handles(std::move(handles)) , m_NodeBuffer(std::move(nodeBuffer)) , m_IndexBuffer(std::move(indexBuffer)) + , m_ModelHandlesBuffer(std::move(modelHandlesBuffer)) , m_MeshPrimitives(meshPrimitives) { } diff --git a/samples/03_model_render/asset_loader.h b/samples/03_model_render/asset_loader.h index ed0cd23..6878290 100644 --- a/samples/03_model_render/asset_loader.h +++ b/samples/03_model_render/asset_loader.h @@ -74,16 +74,35 @@ struct Model eastl::vector> m_TextureHandles; Nodes m_Nodes; + struct ModelHandlesData + { + uptr m_VertexPositionHandle; + uptr m_VertexDataHandle; + uptr m_MaterialsHandle; + uptr m_NodeHandle; + }; + struct ModelHandles { - systems::ResId m_VertexPositionHandle; - systems::ResId m_VertexDataHandle; - systems::ResId m_MaterialsHandle; - systems::ResId m_NodeHandle; + Ref m_VertexPositionHandle; + Ref m_VertexDataHandle; + Ref m_MaterialsHandle; + Ref m_NodeHandle; + + operator ModelHandlesData() const + { + return { + .m_VertexPositionHandle = m_VertexPositionHandle->GetDeviceAddress(), + .m_VertexDataHandle = m_VertexDataHandle->GetDeviceAddress(), + .m_MaterialsHandle = m_MaterialsHandle->GetDeviceAddress(), + .m_NodeHandle = m_NodeHandle->GetDeviceAddress(), + }; + } } m_Handles; Ref m_NodeBuffer; Ref m_IndexBuffer; + Ref m_ModelHandlesBuffer; eastl::vector m_MeshPrimitives; [[nodiscard]] mat4 const &GetModelTransform() const; @@ -91,7 +110,8 @@ struct Model void Update(); Model(eastl::vector> &textureHandles, Nodes &&nodes, Ref nodeBuffer, - ModelHandles &handles, Ref indexBuffer, eastl::vector const &meshPrimitives); + ModelHandles &handles, Ref modelHandlesBuffer, Ref indexBuffer, + eastl::vector const &meshPrimitives); ~Model() = default; Model(Model &&other) noexcept = default; diff --git a/samples/03_model_render/light_manager.cpp b/samples/03_model_render/light_manager.cpp index 7ec49da..8fc6a6d 100644 --- a/samples/03_model_render/light_manager.cpp +++ b/samples/03_model_render/light_manager.cpp @@ -59,35 +59,11 @@ LightManager::LightManager(systems::RenderingDevice &device) : m_Device{&device} , m_DirectionalLightCount{} , m_PointLightCount{} - , m_MetaInfo{.m_LightBuffer = systems::NullId()} + , m_MetaInfo{} , m_GpuBufferCapacity_{0} { } -LightManager::LightManager(LightManager &&other) noexcept - : m_Device{Take(other.m_Device)} - , m_Lights(std::move(other.m_Lights)) - , m_DirectionalLightCount(other.m_DirectionalLightCount) - , m_PointLightCount(other.m_PointLightCount) - , m_MetaInfo(std::move(other.m_MetaInfo)) - , m_GpuBufferCapacity_(other.m_GpuBufferCapacity_) -{ -} - -LightManager & -LightManager::operator=(LightManager &&other) noexcept -{ - if (this == &other) - return *this; - m_Device = Take(other.m_Device); - m_Lights = std::move(other.m_Lights); - m_DirectionalLightCount = other.m_DirectionalLightCount; - m_PointLightCount = other.m_PointLightCount; - m_MetaInfo = std::move(other.m_MetaInfo); - m_GpuBufferCapacity_ = other.m_GpuBufferCapacity_; - return *this; -} - LightHandle LightManager::AddDirectional(vec3 const &direction, vec3 const &color, f32 intensity) { @@ -208,15 +184,14 @@ LightManager::Update() u16 const requiredBufferCapacity = eastl::min(static_cast(m_Lights.capacity()), MAX_LIGHTS); if ((m_GpuBufferCapacity_ & CAPACITY_MASK) < requiredBufferCapacity) { - auto newBuffer = m_Device->CreateStorageBuffer(requiredBufferCapacity * sizeof m_Lights[0], "Light Buffer"); + m_LightBuffer = m_Device->CreateStorageBuffer(requiredBufferCapacity * sizeof m_Lights[0], "Light Buffer"); m_GpuBufferCapacity_ = requiredBufferCapacity | UPDATE_REQUIRED_BIT; - m_MetaInfo.m_LightBuffer = m_Device->m_CommitManager->CommitBuffer(newBuffer); + m_MetaInfo.m_LightBuffer = m_LightBuffer->GetDeviceAddress(); } if (m_GpuBufferCapacity_ & UPDATE_REQUIRED_BIT) { - auto const ref = m_Device->m_CommitManager->FetchHandle(m_MetaInfo.m_LightBuffer); - ref->Write(0, m_Lights.size() * sizeof m_Lights[0], m_Lights.data()); + m_LightBuffer->Write(0, m_Lights.size() * sizeof m_Lights[0], m_Lights.data()); } } diff --git a/samples/03_model_render/light_manager.h b/samples/03_model_render/light_manager.h index cd38abf..1b05bd8 100644 --- a/samples/03_model_render/light_manager.h +++ b/samples/03_model_render/light_manager.h @@ -82,15 +82,16 @@ struct LightManager // We can use that with Offset = 0, and point light at further offsets. // This way we don't need to move point lights often. - systems::ResId m_LightBuffer; // 04 04 - u16 m_PointLightMaxCount; // 02 06 - u16 m_PointLightOffset; // 02 08 - u16 m_DirectionalLightMaxCount; // 02 10 - u16 m_UnusedPadding0 = 0; // 02 12 + uptr m_LightBuffer; // 08 08 + u16 m_PointLightMaxCount; // 02 10 + u16 m_PointLightOffset; // 02 12 + u16 m_DirectionalLightMaxCount; // 02 14 + u16 m_UnusedPadding0 = 0; // 02 16 }; systems::RenderingDevice *m_Device; eastl::vector m_Lights; + Ref m_LightBuffer; // We don't need a Directional Light free list. We will just brute force iterate. u16 m_DirectionalLightCount; @@ -113,9 +114,9 @@ struct LightManager ~LightManager() = default; - LightManager(systems::RenderingDevice &device); - LightManager(LightManager &&other) noexcept; - LightManager &operator=(LightManager &&other) noexcept; + explicit LightManager(systems::RenderingDevice &device); + LightManager(LightManager &&other) noexcept = default; + LightManager &operator=(LightManager &&other) noexcept = default; DISALLOW_COPY_AND_ASSIGN(LightManager); }; \ No newline at end of file diff --git a/samples/03_model_render/model_render.cpp b/samples/03_model_render/model_render.cpp index 1cdb46d..410d7b4 100644 --- a/samples/03_model_render/model_render.cpp +++ b/samples/03_model_render/model_render.cpp @@ -138,7 +138,12 @@ main(int, char **) Window window = {"ModelRender (Aster)", {INIT_WIDTH, INIT_HEIGHT}}; Features enabledDeviceFeatures = { - .m_Vulkan10Features = {.samplerAnisotropy = true, .shaderInt16 = true}, + .m_Vulkan10Features = + { + .samplerAnisotropy = true, + .shaderInt64 = true, + .shaderInt16 = true, + }, .m_Vulkan12Features = { .descriptorIndexing = true, @@ -185,12 +190,12 @@ main(int, char **) Pipeline pipeline; if (auto result = device.CreateGraphicsPipeline(pipeline, { - .m_Shaders = {{ - .m_ShaderFile = MODEL_SHADER_FILE, - .m_EntryPoints = {"vsmain", "fsmain"}, - }}, - .m_Name = "Primary", - })) + .m_Shaders = {{ + .m_ShaderFile = MODEL_SHADER_FILE, + .m_EntryPoints = {"vsmain", "fsmain"}, + }}, + .m_Name = "Primary", + })) { ERROR("Could not create model pipeline. Cause: {}", result.What()) THEN_ABORT(result.Value()); } @@ -226,10 +231,8 @@ main(int, char **) static_cast(swapchainSize.m_Height)}; auto cameraBuffer = device.CreateStorageBuffer(sizeof cameraController.m_Camera, "Camera Info"); - auto cameraBufferId = device.m_CommitManager->CommitBuffer(cameraBuffer); auto lightManagerBuffer = device.CreateStorageBuffer(sizeof environment + sizeof lightManager.m_MetaInfo, "Light Info"); - auto lightsBufferId = device.m_CommitManager->CommitBuffer(lightManagerBuffer); lightManagerBuffer->Write(0, sizeof environment, &environment); lightManagerBuffer->Write(sizeof environment, sizeof lightManager.m_MetaInfo, &lightManager.m_MetaInfo); @@ -544,12 +547,21 @@ main(int, char **) } u32 pcbOffset = 0; - context.PushConstantBlock(model.m_Handles); - pcbOffset += sizeof model.m_Handles; - context.PushConstantBlock(pcbOffset, cameraBufferId); - pcbOffset += sizeof cameraBufferId; - context.PushConstantBlock(pcbOffset, lightsBufferId); - pcbOffset += sizeof lightsBufferId; + { + auto modelHandlesAddr = model.m_ModelHandlesBuffer->GetDeviceAddress(); + context.PushConstantBlock(pcbOffset, modelHandlesAddr); + pcbOffset += sizeof modelHandlesAddr; + } + { + auto cameraBufferAddr = cameraBuffer->GetDeviceAddress(); + context.PushConstantBlock(pcbOffset, cameraBufferAddr); + pcbOffset += sizeof cameraBufferAddr; + } + { + auto lightsBufferAddr = lightManagerBuffer->GetDeviceAddress(); + context.PushConstantBlock(pcbOffset, lightsBufferAddr); + pcbOffset += sizeof lightsBufferAddr; + } context.PushConstantBlock(pcbOffset, flags); pcbOffset += sizeof flags; diff --git a/samples/03_model_render/shader/background.slang b/samples/03_model_render/shader/background.slang index fd20eaf..5ec9d93 100644 --- a/samples/03_model_render/shader/background.slang +++ b/samples/03_model_render/shader/background.slang @@ -25,8 +25,8 @@ VS_Output vsmain( VS_Output stageOutput; stageOutput.vertexPosition = float4(trianglePoints[vertexId], 1.0f); - float4 clipSpace = mul(float4(trianglePoints[vertexId], 1.0f), pcb.camera[0].invProj); - float4 worldSpace = mul(clipSpace / clipSpace.wwww, pcb.camera[0].invView); + float4 clipSpace = mul(float4(trianglePoints[vertexId], 1.0f), pcb.camera->invProj); + float4 worldSpace = mul(clipSpace / clipSpace.wwww, pcb.camera->invView); stageOutput.worldPosition = worldSpace.xyz; return stageOutput; @@ -35,22 +35,22 @@ VS_Output vsmain( [shader("fragment")] float4 fsmain(float3 worldPosition: World_Position) : SV_Target0 { - float3 direction = normalize(worldPosition - pcb.camera[0].position.xyz); + float3 direction = normalize(worldPosition - pcb.camera->position.xyz); #ifndef _DEBUG - float4 color = pcb.lights[0].environment.Sample(direction); + float4 color = pcb.lights->environment.Sample(direction); #else float4 color; if (pcb.showDiffuse) { - color = pcb.lights[0].diffuseIrradiance.Sample(direction); + color = pcb.lights->diffuseIrradiance.Sample(direction); } else if (pcb.showPrefilter) { - color = pcb.lights[0].prefilter.Sample(direction); + color = pcb.lights->prefilter.Sample(direction); } else { - color = pcb.lights[0].environment.Sample(direction); + color = pcb.lights->environment.Sample(direction); } #endif return float4(Uncharted2Tonemap(color.rgb), color.a); diff --git a/samples/03_model_render/shader/common_structs.slang b/samples/03_model_render/shader/common_structs.slang index 084c951..fb39132 100644 --- a/samples/03_model_render/shader/common_structs.slang +++ b/samples/03_model_render/shader/common_structs.slang @@ -70,11 +70,19 @@ struct Lighting SamplerCube.Handle diffuseIrradiance; // 16 SamplerCube.Handle prefilter; // 24 Sampler2D.Handle brdfLUT; // 32 - ByteAddressBuffer.Handle lights; // 40 + void* lightData; // 40 Indexer pointLightIndexer; // 44 Indexer dirLightIndexer; // 48 }; +struct ModelHandles +{ + float4 *vertexBuffer; // 8 + VertexData* vertexData; // 16 + MaterialData* materialBuffer; // 24 + TransformData* nodeBuffer; // 32 +}; + struct Block { static const uint USE_DIFFUSE_BIT = 1; @@ -82,12 +90,9 @@ struct Block static const uint SHOW_DIFFUSE_BIT = 4; static const uint SHOW_PREFILTER_BIT = 8; - StructuredBuffer.Handle vertexBuffer; // 8 - StructuredBuffer.Handle vertexData; // 16 - StructuredBuffer.Handle materialBuffer; // 24 - StructuredBuffer.Handle nodeBuffer; // 32 - StructuredBuffer.Handle camera; // 40 - StructuredBuffer.Handle lights; // 48 + ModelHandles *modelHandles; + CameraData* camera; // 40 + Lighting* lights; // 48 uint debugFlags; // 52 diff --git a/samples/03_model_render/shader/model.slang b/samples/03_model_render/shader/model.slang index 968a624..7a05b50 100644 --- a/samples/03_model_render/shader/model.slang +++ b/samples/03_model_render/shader/model.slang @@ -2,14 +2,6 @@ import bindless; import ibl_common; import common_structs; -struct ModelHandles -{ - StructuredBuffer.Handle vertexBuffer; // 8 - StructuredBuffer.Handle vertexData; // 16 - StructuredBuffer.Handle materialBuffer; // 24 - StructuredBuffer.Handle nodeBuffer; // 32 -}; - [vk::push_constant] uniform Block pcb; @@ -29,32 +21,32 @@ struct VS_Output float2 GetUV(uint vertexId) { - return pcb.vertexData[vertexId].uv0.xy; + return pcb.modelHandles->vertexData[vertexId].uv0.xy; } float4 GetPosition(uint vertexId) { - return float4(pcb.vertexBuffer[vertexId].xyz, 1.0f); + return float4(pcb.modelHandles->vertexBuffer[vertexId].xyz, 1.0f); } float4 GetNormal(uint vertexId) { - return pcb.vertexData[vertexId].normal; + return pcb.modelHandles->vertexData[vertexId].normal; } float4 GetColor(uint vertexId) { - return pcb.vertexData[vertexId].color0; + return pcb.modelHandles->vertexData[vertexId].color0; } float4x4 GetNodeTransform(uint nodeIdx) { - return pcb.nodeBuffer[nodeIdx].transform; + return pcb.modelHandles->nodeBuffer[nodeIdx].transform; } float4x4 GetNormalTransform(uint nodeIdx) { - return pcb.nodeBuffer[nodeIdx].normalTransform; + return pcb.modelHandles->nodeBuffer[nodeIdx].normalTransform; } [shader("vertex")] @@ -63,9 +55,9 @@ VS_Output vsmain(VS_Input stageInput) VS_Output stageOutput; float4 worldPosition = mul(GetPosition(stageInput.vertexId), GetNodeTransform(pcb.nodeIdx)); - float4 clipSpace = mul(worldPosition, pcb.camera[0].view); + float4 clipSpace = mul(worldPosition, pcb.camera->view); - stageOutput.vertexPosition = mul(clipSpace, pcb.camera[0].proj); + stageOutput.vertexPosition = mul(clipSpace, pcb.camera->proj); stageOutput.worldPosition = worldPosition; stageOutput.uv0 = GetUV(stageInput.vertexId); stageOutput.vertexColor = GetColor(stageInput.vertexId); @@ -76,23 +68,23 @@ VS_Output vsmain(VS_Input stageInput) float4 GetAlbedo(float2 uv, float4 color) { - float4 albedoFactor = pcb.materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].albedoFactor; - var albedoTex = pcb.materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].albedoTex; + float4 albedoFactor = pcb.modelHandles->materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].albedoFactor; + var albedoTex = pcb.modelHandles->materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].albedoTex; return albedoFactor * color * (IsValid(albedoTex) ? albedoTex.Sample(uv) : 1.0f.xxxx); } float GetOcclusion(float2 uv) { - var occlusionTex = pcb.materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].occlusionTex; + var occlusionTex = pcb.modelHandles->materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].occlusionTex; return IsValid(occlusionTex) ? occlusionTex.Sample(uv).r : 1.0f; } float3 GetEmissive(float2 uv) { - float3 emissionFactor = pcb.materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].emissionFactor.rgb; - var emissionTex = pcb.materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].emissionTex; + float3 emissionFactor = pcb.modelHandles->materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].emissionFactor.rgb; + var emissionTex = pcb.modelHandles->materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].emissionTex; return emissionFactor * (IsValid(emissionTex) ? emissionTex.Sample(uv).rgb : 1.0f.xxx); } @@ -101,7 +93,7 @@ float3 GetNormal(float3 position, float3 normal, float2 uv) { float3 N = normalize(normal); - var normalTex = pcb.materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].normalTex; + var normalTex = pcb.modelHandles->materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].normalTex; if (!IsValid(normalTex)) { return N; @@ -123,16 +115,16 @@ float3 GetNormal(float3 position, float3 normal, float2 uv) float2 GetMetalRough(float2 uv) { - var material = pcb.materialBuffer[NonUniformResourceIndex(pcb.materialIdx)]; + var material = pcb.modelHandles->materialBuffer[NonUniformResourceIndex(pcb.materialIdx)]; float2 metalRough = float2(material.metalFactor, material.roughFactor); - var metalRoughTex = pcb.materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].metalRoughTex; + var metalRoughTex = pcb.modelHandles->materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].metalRoughTex; return metalRough * (IsValid(metalRoughTex) ? metalRoughTex.Sample(uv).bg : 1.0f.xx); // Metal is B, Rough is G. } float3 SampleIrradiance(float3 direction) { - var diffuseIrradiance = pcb.lights[0].diffuseIrradiance; + var diffuseIrradiance = pcb.lights->diffuseIrradiance; if (IsValid(diffuseIrradiance)) { return diffuseIrradiance.Sample(direction).rgb; @@ -142,7 +134,7 @@ float3 SampleIrradiance(float3 direction) float3 SamplePrefiltered(float3 direction, float roughness) { - var prefilter = pcb.lights[0].prefilter; + var prefilter = pcb.lights->prefilter; if (!IsValid(prefilter)) return 0.0f.xxx; @@ -154,7 +146,7 @@ float3 SamplePrefiltered(float3 direction, float roughness) float2 SampleBrdfLut(float nDotV, float roughness) { - var brdfLut = pcb.lights[0].brdfLUT; + var brdfLut = pcb.lights->brdfLUT; if (IsValid(brdfLut)) { return brdfLut.Sample(float2(nDotV, roughness)); @@ -206,16 +198,16 @@ float3 GetPBRContrib(float3 Albedo, float3 LightColor, float3 ViewDir, float3 No float3 GetPointLightInfluence(float3 Albedo, float2 MetalRough, float3 Position, float3 Normal) { - var lightData = pcb.lights[0]; - var pointLightBuffer = (StructuredBuffer.Handle)lightData.lights; + Lighting* lightData = pcb.lights; + PointLight* pointLightBuffer = (PointLight*)lightData->lightData; - if (!IsValid(pointLightBuffer)) + if (!pointLightBuffer) return 0.0f.xxx; uint offset = lightData.pointLightIndexer.offset; uint count = lightData.pointLightIndexer.count; - float3 ViewDir = normalize(pcb.camera[0].position.xyz - Position); + float3 ViewDir = normalize(pcb.camera->position.xyz - Position); float Metallic = MetalRough.r; float Roughness = MetalRough.g; @@ -256,15 +248,15 @@ float3 GetPointLightInfluence(float3 Albedo, float2 MetalRough, float3 Position, float3 GetDirectionalLightInfluence(float3 Albedo, float2 MetalRough, float3 Position, float3 Normal) { - var lightData = pcb.lights[0]; - var dirLightBuffer = (StructuredBuffer.Handle)lightData.lights; + Lighting* lightData = pcb.lights; + var dirLightBuffer = (DirectionalLight*)lightData.lightData; - if (!IsValid(dirLightBuffer)) + if (!dirLightBuffer) return 0.0f.xxx; uint count = lightData.dirLightIndexer.count; - float3 ViewDir = normalize(pcb.camera[0].position.xyz - Position); + float3 ViewDir = normalize(pcb.camera->position.xyz - Position); float Metallic = MetalRough.r; float Roughness = MetalRough.g; @@ -299,7 +291,7 @@ float3 GetDirectionalLightInfluence(float3 Albedo, float2 MetalRough, float3 Pos float3 GetAmbientInfluence(float3 Albedo, float2 MetalRough, float3 Position, float3 Normal, float Occlusion) { - float3 ViewDir = normalize(pcb.camera[0].position.xyz - Position); + float3 ViewDir = normalize(pcb.camera->position.xyz - Position); float CosineFactor = max(dot(Normal, ViewDir), 0.0f); // Normal instead of Halfway since there's no halfway in ambient. float Metal = MetalRough.r;