Move all buffers to DeviceAddress.

This commit is contained in:
Anish Bhobe 2025-06-01 19:17:21 +02:00
parent 19e3222460
commit 38b697f202
19 changed files with 147 additions and 263 deletions

View File

@ -30,6 +30,7 @@ struct Buffer
vk::Buffer m_Buffer = nullptr; vk::Buffer m_Buffer = nullptr;
VmaAllocation m_Allocation = nullptr; VmaAllocation m_Allocation = nullptr;
u8 *m_Mapped = nullptr; ///< If the buffer is host visible, it should be (and stay) mapped. u8 *m_Mapped = nullptr; ///< If the buffer is host visible, it should be (and stay) mapped.
uptr m_DeviceAddr = 0;
usize m_Size = 0; usize m_Size = 0;
Flags m_Flags = {}; Flags m_Flags = {};
@ -54,7 +55,7 @@ struct Buffer
/// If Buffer Device Address is enabled, /// If Buffer Device Address is enabled,
/// Get a pointer. /// Get a pointer.
uptr GetDeviceAddress(Device const *device) const; [[nodiscard]] uptr GetDeviceAddress() const;
// Constructors // Constructors

View File

@ -221,8 +221,10 @@ class CommitManager
PIN_MEMORY(CommitManager); PIN_MEMORY(CommitManager);
// Commit Buffer // Commit Buffer
private:
ResId<Buffer> CommitBuffer(Ref<Buffer> const &buffer); ResId<Buffer> CommitBuffer(Ref<Buffer> const &buffer);
public:
// Commit Storage Images // Commit Storage Images
ResId<StorageImageView> ResId<StorageImageView>
CommitStorageImage(concepts::ViewRefTo<StorageImage> auto const &image) CommitStorageImage(concepts::ViewRefTo<StorageImage> auto const &image)

View File

@ -16,7 +16,7 @@ Buffer::Buffer(Device const *device, usize const size, vk::BufferUsageFlags cons
vk::BufferCreateInfo bufferCreateInfo = { vk::BufferCreateInfo bufferCreateInfo = {
.size = size, .size = size,
.usage = bufferUsage, .usage = bufferUsage | vk::BufferUsageFlagBits::eShaderDeviceAddress,
.sharingMode = vk::SharingMode::eExclusive, .sharingMode = vk::SharingMode::eExclusive,
}; };
VmaAllocationCreateInfo const allocationCreateInfo = { VmaAllocationCreateInfo const allocationCreateInfo = {
@ -56,6 +56,9 @@ Buffer::Buffer(Device const *device, usize const size, vk::BufferUsageFlags cons
if (bufferUsage & vk::BufferUsageFlagBits::eStorageBuffer) if (bufferUsage & vk::BufferUsageFlagBits::eStorageBuffer)
m_Flags |= FlagBits::eStorage; m_Flags |= FlagBits::eStorage;
vk::BufferDeviceAddressInfo const addressInfo = {.buffer = m_Buffer};
m_DeviceAddr = m_Device->m_Device.getBufferAddress(&addressInfo);
device->SetName(m_Buffer, name); device->SetName(m_Buffer, name);
} }
@ -64,6 +67,7 @@ Buffer::Buffer(Buffer &&other) noexcept
, m_Buffer{Take(other.m_Buffer)} , m_Buffer{Take(other.m_Buffer)}
, m_Allocation{Take(other.m_Allocation)} , m_Allocation{Take(other.m_Allocation)}
, m_Mapped{Take(other.m_Mapped)} , m_Mapped{Take(other.m_Mapped)}
, m_DeviceAddr{Take(other.m_DeviceAddr)}
, m_Size{Take(other.m_Size)} , m_Size{Take(other.m_Size)}
{ {
} }
@ -78,6 +82,7 @@ Buffer::operator=(Buffer &&other) noexcept
swap(m_Buffer, other.m_Buffer); swap(m_Buffer, other.m_Buffer);
swap(m_Allocation, other.m_Allocation); swap(m_Allocation, other.m_Allocation);
swap(m_Mapped, other.m_Mapped); swap(m_Mapped, other.m_Mapped);
swap(m_DeviceAddr, other.m_DeviceAddr);
swap(m_Size, other.m_Size); swap(m_Size, other.m_Size);
return *this; return *this;
} }
@ -92,10 +97,9 @@ Buffer::~Buffer()
} }
uptr uptr
Buffer::GetDeviceAddress(Device const *device) const Buffer::GetDeviceAddress() const
{ {
vk::BufferDeviceAddressInfo const addressInfo = {.buffer = m_Buffer}; return m_DeviceAddr;
return device->m_Device.getBufferAddress(&addressInfo);
} }
void void

View File

@ -5,11 +5,7 @@ cmake_minimum_required(VERSION 3.13)
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fsanitize=address") #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fsanitize=address")
add_executable(box "box.cpp" "stb_image.h") add_executable(box "box.cpp" "stb_image.h")
add_shader(box "shader/box.vert.glsl") add_shader(box "shader/box.slang")
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_resource_dir(box "shader/") add_resource_dir(box "shader/")
target_link_libraries(box PRIVATE aster_core) target_link_libraries(box PRIVATE aster_core)

View File

@ -23,7 +23,7 @@
constexpr auto VERTEX_SHADER_FILE = "shader/box.vs.hlsl.spv"; constexpr auto VERTEX_SHADER_FILE = "shader/box.vs.hlsl.spv";
constexpr auto FRAGMENT_SHADER_FILE = "shader/box.ps.hlsl.spv"; constexpr auto FRAGMENT_SHADER_FILE = "shader/box.ps.hlsl.spv";
constexpr auto SHADER_FILE = "triangle"; constexpr auto SHADER_FILE = "box";
struct ImageFile struct ImageFile
{ {
@ -328,11 +328,10 @@ main(int, char **)
initDepthImages(extent); initDepthImages(extent);
}; };
// TODO: Move to 64bit handles.
struct PCB struct PCB
{ {
systems::ResId<Buffer> m_VertexBuffer; uptr m_VertexBuffer;
systems::ResId<Buffer> m_Camera; uptr m_Camera;
systems::ResId<TextureView> m_Texture; systems::ResId<TextureView> m_Texture;
}; };
static_assert(sizeof(PCB) == 24); static_assert(sizeof(PCB) == 24);
@ -340,8 +339,8 @@ main(int, char **)
auto &commitManager = systems::CommitManager::Instance(); auto &commitManager = systems::CommitManager::Instance();
PCB pcb = { PCB pcb = {
.m_VertexBuffer = commitManager.CommitBuffer(vbo), .m_VertexBuffer = vbo->GetDeviceAddress(),
.m_Camera = commitManager.CommitBuffer(ubo), .m_Camera = ubo->GetDeviceAddress(),
.m_Texture = commitManager.CommitTexture(crate), .m_Texture = commitManager.CommitTexture(crate),
}; };

View File

@ -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<VertexData> VertexDataBuffer[];
[[vk::binding(0, 0)]] StructuredBuffer<CameraData> CameraDataBuffer[];
[[vk::binding(1, 0)]] Texture2D<float4> Textures[];
[[vk::binding(1, 0)]] SamplerState Samplers[];

View File

@ -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);
}

View File

@ -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;
}

View File

@ -15,9 +15,9 @@ struct CameraData
}; };
struct PCB { struct PCB {
DescriptorHandle<StructuredBuffer<VertexData>> vertexBuffer; VertexData* vertexBuffer;
DescriptorHandle<StructuredBuffer<CameraData>> cameraBuffer; CameraData* cameraBuffer;
DescriptorHandle<Sampler2D> texture; Sampler2D.Handle texture;
}; };
[vk::push_constant] [vk::push_constant]
@ -43,7 +43,7 @@ func vsmain(VSIn input) -> VSOut {
VertexData vd = pcb.vertexBuffer[input.vertexIndex]; 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; output.texCoord0 = vd.texCoord0;
return output; return output;
@ -52,7 +52,6 @@ func vsmain(VSIn input) -> VSOut {
[shader("fragment")] [shader("fragment")]
func fsmain(VSOut input) -> FSOut { func fsmain(VSOut input) -> FSOut {
FSOut outp; FSOut outp;
outp.Color = pcb.vertexBuffer[0].position.rgba;
outp.Color = float4(pcb.texture.Sample(input.texCoord0).rgb, 1.0); outp.Color = float4(pcb.texture.Sample(input.texCoord0).rgb, 1.0);
return outp; return outp;
} }

View File

@ -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);
}

View File

@ -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;
}

View File

@ -474,7 +474,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
eastl::hash_map<i32, systems::ResId<TextureView>> textureHandleMap; eastl::hash_map<i32, systems::ResId<TextureView>> textureHandleMap;
eastl::vector<Material> materials; eastl::vector<Material> materials;
systems::ResId<Buffer> materialsHandle = systems::ResId<Buffer>::Null(); Ref<Buffer> materialsBuffer;
if (!model.materials.empty()) if (!model.materials.empty())
{ {
@ -515,8 +515,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
} }
usize materialsByteSize = materials.size() * sizeof materials[0]; usize materialsByteSize = materials.size() * sizeof materials[0];
auto materialsBuffer = m_Device->CreateStorageBuffer(materialsByteSize, name); materialsBuffer = m_Device->CreateStorageBuffer(materialsByteSize, name);
materialsHandle = m_Device->m_CommitManager->CommitBuffer(materialsBuffer);
context.UploadBuffer(materialsBuffer, materials); context.UploadBuffer(materialsBuffer, materials);
} }
@ -803,7 +802,6 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
auto nodeBuffer = m_Device->CreateStorageBuffer(nodes.GetGlobalTransformByteSize()); auto nodeBuffer = m_Device->CreateStorageBuffer(nodes.GetGlobalTransformByteSize());
nodeBuffer->Write(0, nodes.GetGlobalTransformByteSize(), nodes.GetGlobalTransformPtr()); nodeBuffer->Write(0, nodes.GetGlobalTransformByteSize(), nodes.GetGlobalTransformPtr());
systems::ResId<Buffer> nodeHandle = m_Device->m_CommitManager->CommitBuffer(nodeBuffer);
#pragma region Staging / Transfer / Uploads #pragma region Staging / Transfer / Uploads
systems::ResId<Buffer> positionBufferHandle = systems::ResId<Buffer>::Null(); systems::ResId<Buffer> positionBufferHandle = systems::ResId<Buffer>::Null();
@ -811,11 +809,9 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
Ref<IndexBuffer> indexBuffer; Ref<IndexBuffer> indexBuffer;
auto positionBuffer = m_Device->CreateStorageBuffer(vertexPositions.size() * sizeof vertexPositions[0]); auto positionBuffer = m_Device->CreateStorageBuffer(vertexPositions.size() * sizeof vertexPositions[0]);
positionBufferHandle = m_Device->m_CommitManager->CommitBuffer(positionBuffer);
context.UploadBuffer(positionBuffer, vertexPositions); context.UploadBuffer(positionBuffer, vertexPositions);
auto vertexDataBuffer = m_Device->CreateStorageBuffer(vertexData.size() * sizeof vertexData[0]); auto vertexDataBuffer = m_Device->CreateStorageBuffer(vertexData.size() * sizeof vertexData[0]);
vertexDataHandle = m_Device->m_CommitManager->CommitBuffer(vertexDataBuffer);
context.UploadBuffer(vertexDataBuffer, vertexData); context.UploadBuffer(vertexDataBuffer, vertexData);
// TODO: Index buffer needs to be separated. // TODO: Index buffer needs to be separated.
@ -834,11 +830,14 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
m_Device->WaitOn(rcpt); m_Device->WaitOn(rcpt);
Model::ModelHandles handles = { Model::ModelHandles handles = {
.m_VertexPositionHandle = positionBufferHandle, .m_VertexPositionHandle = positionBuffer,
.m_VertexDataHandle = vertexDataHandle, .m_VertexDataHandle = vertexDataBuffer,
.m_MaterialsHandle = materialsHandle, .m_MaterialsHandle = materialsBuffer,
.m_NodeHandle = nodeHandle, .m_NodeHandle = nodeBuffer,
}; };
Model::ModelHandlesData handlesData = handles;
auto handlesBuffer = m_Device->CreateStorageBuffer(sizeof handlesData, "Materials");
handlesBuffer->Write(0, sizeof handlesData, &handlesData);
eastl::vector<systems::ResId<TextureView>> textureHandles; eastl::vector<systems::ResId<TextureView>> textureHandles;
textureHandles.reserve(textureHandleMap.size()); textureHandles.reserve(textureHandleMap.size());
@ -849,17 +848,19 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
} }
return Model{ return Model{
textureHandles, std::move(nodes), nodeBuffer, handles, indexBuffer, meshPrimitives, textureHandles, std::move(nodes), nodeBuffer, handles, handlesBuffer, indexBuffer, meshPrimitives,
}; };
} }
Model::Model(eastl::vector<systems::ResId<TextureView>> &textureHandles, Nodes &&nodes, Ref<Buffer> nodeBuffer, Model::Model(eastl::vector<systems::ResId<TextureView>> &textureHandles, Nodes &&nodes, Ref<Buffer> nodeBuffer,
ModelHandles &handles, Ref<IndexBuffer> indexBuffer, eastl::vector<MeshPrimitive> const &meshPrimitives) ModelHandles &handles, Ref<Buffer> modelHandlesBuffer, Ref<IndexBuffer> indexBuffer,
eastl::vector<MeshPrimitive> const &meshPrimitives)
: m_TextureHandles(std::move(textureHandles)) : m_TextureHandles(std::move(textureHandles))
, m_Nodes(std::move(nodes)) , m_Nodes(std::move(nodes))
, m_Handles(std::move(handles)) , m_Handles(std::move(handles))
, m_NodeBuffer(std::move(nodeBuffer)) , m_NodeBuffer(std::move(nodeBuffer))
, m_IndexBuffer(std::move(indexBuffer)) , m_IndexBuffer(std::move(indexBuffer))
, m_ModelHandlesBuffer(std::move(modelHandlesBuffer))
, m_MeshPrimitives(meshPrimitives) , m_MeshPrimitives(meshPrimitives)
{ {
} }

View File

@ -74,16 +74,35 @@ struct Model
eastl::vector<systems::ResId<TextureView>> m_TextureHandles; eastl::vector<systems::ResId<TextureView>> m_TextureHandles;
Nodes m_Nodes; Nodes m_Nodes;
struct ModelHandlesData
{
uptr m_VertexPositionHandle;
uptr m_VertexDataHandle;
uptr m_MaterialsHandle;
uptr m_NodeHandle;
};
struct ModelHandles struct ModelHandles
{ {
systems::ResId<Buffer> m_VertexPositionHandle; Ref<Buffer> m_VertexPositionHandle;
systems::ResId<Buffer> m_VertexDataHandle; Ref<Buffer> m_VertexDataHandle;
systems::ResId<Buffer> m_MaterialsHandle; Ref<Buffer> m_MaterialsHandle;
systems::ResId<Buffer> m_NodeHandle; Ref<Buffer> 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; } m_Handles;
Ref<Buffer> m_NodeBuffer; Ref<Buffer> m_NodeBuffer;
Ref<IndexBuffer> m_IndexBuffer; Ref<IndexBuffer> m_IndexBuffer;
Ref<Buffer> m_ModelHandlesBuffer;
eastl::vector<MeshPrimitive> m_MeshPrimitives; eastl::vector<MeshPrimitive> m_MeshPrimitives;
[[nodiscard]] mat4 const &GetModelTransform() const; [[nodiscard]] mat4 const &GetModelTransform() const;
@ -91,7 +110,8 @@ struct Model
void Update(); void Update();
Model(eastl::vector<systems::ResId<TextureView>> &textureHandles, Nodes &&nodes, Ref<Buffer> nodeBuffer, Model(eastl::vector<systems::ResId<TextureView>> &textureHandles, Nodes &&nodes, Ref<Buffer> nodeBuffer,
ModelHandles &handles, Ref<IndexBuffer> indexBuffer, eastl::vector<MeshPrimitive> const &meshPrimitives); ModelHandles &handles, Ref<Buffer> modelHandlesBuffer, Ref<IndexBuffer> indexBuffer,
eastl::vector<MeshPrimitive> const &meshPrimitives);
~Model() = default; ~Model() = default;
Model(Model &&other) noexcept = default; Model(Model &&other) noexcept = default;

View File

@ -59,35 +59,11 @@ LightManager::LightManager(systems::RenderingDevice &device)
: m_Device{&device} : m_Device{&device}
, m_DirectionalLightCount{} , m_DirectionalLightCount{}
, m_PointLightCount{} , m_PointLightCount{}
, m_MetaInfo{.m_LightBuffer = systems::NullId()} , m_MetaInfo{}
, m_GpuBufferCapacity_{0} , 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 LightHandle
LightManager::AddDirectional(vec3 const &direction, vec3 const &color, f32 intensity) LightManager::AddDirectional(vec3 const &direction, vec3 const &color, f32 intensity)
{ {
@ -208,15 +184,14 @@ LightManager::Update()
u16 const requiredBufferCapacity = eastl::min(static_cast<u16>(m_Lights.capacity()), MAX_LIGHTS); u16 const requiredBufferCapacity = eastl::min(static_cast<u16>(m_Lights.capacity()), MAX_LIGHTS);
if ((m_GpuBufferCapacity_ & CAPACITY_MASK) < requiredBufferCapacity) 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_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) if (m_GpuBufferCapacity_ & UPDATE_REQUIRED_BIT)
{ {
auto const ref = m_Device->m_CommitManager->FetchHandle(m_MetaInfo.m_LightBuffer); m_LightBuffer->Write(0, m_Lights.size() * sizeof m_Lights[0], m_Lights.data());
ref->Write(0, m_Lights.size() * sizeof m_Lights[0], m_Lights.data());
} }
} }

View File

@ -82,15 +82,16 @@ struct LightManager
// We can use that with Offset = 0, and point light at further offsets. // We can use that with Offset = 0, and point light at further offsets.
// This way we don't need to move point lights often. // This way we don't need to move point lights often.
systems::ResId<Buffer> m_LightBuffer; // 04 04 uptr m_LightBuffer; // 08 08
u16 m_PointLightMaxCount; // 02 06 u16 m_PointLightMaxCount; // 02 10
u16 m_PointLightOffset; // 02 08 u16 m_PointLightOffset; // 02 12
u16 m_DirectionalLightMaxCount; // 02 10 u16 m_DirectionalLightMaxCount; // 02 14
u16 m_UnusedPadding0 = 0; // 02 12 u16 m_UnusedPadding0 = 0; // 02 16
}; };
systems::RenderingDevice *m_Device; systems::RenderingDevice *m_Device;
eastl::vector<Light> m_Lights; eastl::vector<Light> m_Lights;
Ref<Buffer> m_LightBuffer;
// We don't need a Directional Light free list. We will just brute force iterate. // We don't need a Directional Light free list. We will just brute force iterate.
u16 m_DirectionalLightCount; u16 m_DirectionalLightCount;
@ -113,9 +114,9 @@ struct LightManager
~LightManager() = default; ~LightManager() = default;
LightManager(systems::RenderingDevice &device); explicit LightManager(systems::RenderingDevice &device);
LightManager(LightManager &&other) noexcept; LightManager(LightManager &&other) noexcept = default;
LightManager &operator=(LightManager &&other) noexcept; LightManager &operator=(LightManager &&other) noexcept = default;
DISALLOW_COPY_AND_ASSIGN(LightManager); DISALLOW_COPY_AND_ASSIGN(LightManager);
}; };

View File

@ -138,7 +138,12 @@ main(int, char **)
Window window = {"ModelRender (Aster)", {INIT_WIDTH, INIT_HEIGHT}}; Window window = {"ModelRender (Aster)", {INIT_WIDTH, INIT_HEIGHT}};
Features enabledDeviceFeatures = { Features enabledDeviceFeatures = {
.m_Vulkan10Features = {.samplerAnisotropy = true, .shaderInt16 = true}, .m_Vulkan10Features =
{
.samplerAnisotropy = true,
.shaderInt64 = true,
.shaderInt16 = true,
},
.m_Vulkan12Features = .m_Vulkan12Features =
{ {
.descriptorIndexing = true, .descriptorIndexing = true,
@ -226,10 +231,8 @@ main(int, char **)
static_cast<f32>(swapchainSize.m_Height)}; static_cast<f32>(swapchainSize.m_Height)};
auto cameraBuffer = device.CreateStorageBuffer(sizeof cameraController.m_Camera, "Camera Info"); auto cameraBuffer = device.CreateStorageBuffer(sizeof cameraController.m_Camera, "Camera Info");
auto cameraBufferId = device.m_CommitManager->CommitBuffer(cameraBuffer);
auto lightManagerBuffer = auto lightManagerBuffer =
device.CreateStorageBuffer(sizeof environment + sizeof lightManager.m_MetaInfo, "Light Info"); 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(0, sizeof environment, &environment);
lightManagerBuffer->Write(sizeof environment, sizeof lightManager.m_MetaInfo, &lightManager.m_MetaInfo); lightManagerBuffer->Write(sizeof environment, sizeof lightManager.m_MetaInfo, &lightManager.m_MetaInfo);
@ -544,12 +547,21 @@ main(int, char **)
} }
u32 pcbOffset = 0; u32 pcbOffset = 0;
context.PushConstantBlock(model.m_Handles); {
pcbOffset += sizeof model.m_Handles; auto modelHandlesAddr = model.m_ModelHandlesBuffer->GetDeviceAddress();
context.PushConstantBlock(pcbOffset, cameraBufferId); context.PushConstantBlock(pcbOffset, modelHandlesAddr);
pcbOffset += sizeof cameraBufferId; pcbOffset += sizeof modelHandlesAddr;
context.PushConstantBlock(pcbOffset, lightsBufferId); }
pcbOffset += sizeof lightsBufferId; {
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); context.PushConstantBlock(pcbOffset, flags);
pcbOffset += sizeof flags; pcbOffset += sizeof flags;

View File

@ -25,8 +25,8 @@ VS_Output vsmain(
VS_Output stageOutput; VS_Output stageOutput;
stageOutput.vertexPosition = float4(trianglePoints[vertexId], 1.0f); stageOutput.vertexPosition = float4(trianglePoints[vertexId], 1.0f);
float4 clipSpace = mul(float4(trianglePoints[vertexId], 1.0f), pcb.camera[0].invProj); float4 clipSpace = mul(float4(trianglePoints[vertexId], 1.0f), pcb.camera->invProj);
float4 worldSpace = mul(clipSpace / clipSpace.wwww, pcb.camera[0].invView); float4 worldSpace = mul(clipSpace / clipSpace.wwww, pcb.camera->invView);
stageOutput.worldPosition = worldSpace.xyz; stageOutput.worldPosition = worldSpace.xyz;
return stageOutput; return stageOutput;
@ -35,22 +35,22 @@ VS_Output vsmain(
[shader("fragment")] [shader("fragment")]
float4 fsmain(float3 worldPosition: World_Position) : SV_Target0 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 #ifndef _DEBUG
float4 color = pcb.lights[0].environment.Sample(direction); float4 color = pcb.lights->environment.Sample(direction);
#else #else
float4 color; float4 color;
if (pcb.showDiffuse) if (pcb.showDiffuse)
{ {
color = pcb.lights[0].diffuseIrradiance.Sample(direction); color = pcb.lights->diffuseIrradiance.Sample(direction);
} }
else if (pcb.showPrefilter) else if (pcb.showPrefilter)
{ {
color = pcb.lights[0].prefilter.Sample(direction); color = pcb.lights->prefilter.Sample(direction);
} }
else else
{ {
color = pcb.lights[0].environment.Sample(direction); color = pcb.lights->environment.Sample(direction);
} }
#endif #endif
return float4(Uncharted2Tonemap(color.rgb), color.a); return float4(Uncharted2Tonemap(color.rgb), color.a);

View File

@ -70,11 +70,19 @@ struct Lighting
SamplerCube.Handle diffuseIrradiance; // 16 SamplerCube.Handle diffuseIrradiance; // 16
SamplerCube.Handle prefilter; // 24 SamplerCube.Handle prefilter; // 24
Sampler2D<float2>.Handle brdfLUT; // 32 Sampler2D<float2>.Handle brdfLUT; // 32
ByteAddressBuffer.Handle lights; // 40 void* lightData; // 40
Indexer pointLightIndexer; // 44 Indexer pointLightIndexer; // 44
Indexer dirLightIndexer; // 48 Indexer dirLightIndexer; // 48
}; };
struct ModelHandles
{
float4 *vertexBuffer; // 8
VertexData* vertexData; // 16
MaterialData* materialBuffer; // 24
TransformData* nodeBuffer; // 32
};
struct Block struct Block
{ {
static const uint USE_DIFFUSE_BIT = 1; static const uint USE_DIFFUSE_BIT = 1;
@ -82,12 +90,9 @@ struct Block
static const uint SHOW_DIFFUSE_BIT = 4; static const uint SHOW_DIFFUSE_BIT = 4;
static const uint SHOW_PREFILTER_BIT = 8; static const uint SHOW_PREFILTER_BIT = 8;
StructuredBuffer<float4>.Handle vertexBuffer; // 8 ModelHandles *modelHandles;
StructuredBuffer<VertexData>.Handle vertexData; // 16 CameraData* camera; // 40
StructuredBuffer<MaterialData>.Handle materialBuffer; // 24 Lighting* lights; // 48
StructuredBuffer<TransformData>.Handle nodeBuffer; // 32
StructuredBuffer<CameraData>.Handle camera; // 40
StructuredBuffer<Lighting>.Handle lights; // 48
uint debugFlags; // 52 uint debugFlags; // 52

View File

@ -2,14 +2,6 @@ import bindless;
import ibl_common; import ibl_common;
import common_structs; import common_structs;
struct ModelHandles
{
StructuredBuffer<float4>.Handle vertexBuffer; // 8
StructuredBuffer<VertexData>.Handle vertexData; // 16
StructuredBuffer<MaterialData>.Handle materialBuffer; // 24
StructuredBuffer<TransformData>.Handle nodeBuffer; // 32
};
[vk::push_constant] [vk::push_constant]
uniform Block pcb; uniform Block pcb;
@ -29,32 +21,32 @@ struct VS_Output
float2 GetUV(uint vertexId) float2 GetUV(uint vertexId)
{ {
return pcb.vertexData[vertexId].uv0.xy; return pcb.modelHandles->vertexData[vertexId].uv0.xy;
} }
float4 GetPosition(uint vertexId) 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) float4 GetNormal(uint vertexId)
{ {
return pcb.vertexData[vertexId].normal; return pcb.modelHandles->vertexData[vertexId].normal;
} }
float4 GetColor(uint vertexId) float4 GetColor(uint vertexId)
{ {
return pcb.vertexData[vertexId].color0; return pcb.modelHandles->vertexData[vertexId].color0;
} }
float4x4 GetNodeTransform(uint nodeIdx) float4x4 GetNodeTransform(uint nodeIdx)
{ {
return pcb.nodeBuffer[nodeIdx].transform; return pcb.modelHandles->nodeBuffer[nodeIdx].transform;
} }
float4x4 GetNormalTransform(uint nodeIdx) float4x4 GetNormalTransform(uint nodeIdx)
{ {
return pcb.nodeBuffer[nodeIdx].normalTransform; return pcb.modelHandles->nodeBuffer[nodeIdx].normalTransform;
} }
[shader("vertex")] [shader("vertex")]
@ -63,9 +55,9 @@ VS_Output vsmain(VS_Input stageInput)
VS_Output stageOutput; VS_Output stageOutput;
float4 worldPosition = mul(GetPosition(stageInput.vertexId), GetNodeTransform(pcb.nodeIdx)); 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.worldPosition = worldPosition;
stageOutput.uv0 = GetUV(stageInput.vertexId); stageOutput.uv0 = GetUV(stageInput.vertexId);
stageOutput.vertexColor = GetColor(stageInput.vertexId); stageOutput.vertexColor = GetColor(stageInput.vertexId);
@ -76,23 +68,23 @@ VS_Output vsmain(VS_Input stageInput)
float4 GetAlbedo(float2 uv, float4 color) float4 GetAlbedo(float2 uv, float4 color)
{ {
float4 albedoFactor = pcb.materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].albedoFactor; float4 albedoFactor = pcb.modelHandles->materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].albedoFactor;
var albedoTex = pcb.materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].albedoTex; var albedoTex = pcb.modelHandles->materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].albedoTex;
return albedoFactor * color * (IsValid(albedoTex) ? albedoTex.Sample(uv) : 1.0f.xxxx); return albedoFactor * color * (IsValid(albedoTex) ? albedoTex.Sample(uv) : 1.0f.xxxx);
} }
float GetOcclusion(float2 uv) 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; return IsValid(occlusionTex) ? occlusionTex.Sample(uv).r : 1.0f;
} }
float3 GetEmissive(float2 uv) float3 GetEmissive(float2 uv)
{ {
float3 emissionFactor = pcb.materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].emissionFactor.rgb; float3 emissionFactor = pcb.modelHandles->materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].emissionFactor.rgb;
var emissionTex = pcb.materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].emissionTex; var emissionTex = pcb.modelHandles->materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].emissionTex;
return emissionFactor * (IsValid(emissionTex) ? emissionTex.Sample(uv).rgb : 1.0f.xxx); 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); float3 N = normalize(normal);
var normalTex = pcb.materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].normalTex; var normalTex = pcb.modelHandles->materialBuffer[NonUniformResourceIndex(pcb.materialIdx)].normalTex;
if (!IsValid(normalTex)) if (!IsValid(normalTex))
{ {
return N; return N;
@ -123,16 +115,16 @@ float3 GetNormal(float3 position, float3 normal, float2 uv)
float2 GetMetalRough(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); 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. return metalRough * (IsValid(metalRoughTex) ? metalRoughTex.Sample(uv).bg : 1.0f.xx); // Metal is B, Rough is G.
} }
float3 SampleIrradiance(float3 direction) float3 SampleIrradiance(float3 direction)
{ {
var diffuseIrradiance = pcb.lights[0].diffuseIrradiance; var diffuseIrradiance = pcb.lights->diffuseIrradiance;
if (IsValid(diffuseIrradiance)) if (IsValid(diffuseIrradiance))
{ {
return diffuseIrradiance.Sample(direction).rgb; return diffuseIrradiance.Sample(direction).rgb;
@ -142,7 +134,7 @@ float3 SampleIrradiance(float3 direction)
float3 SamplePrefiltered(float3 direction, float roughness) float3 SamplePrefiltered(float3 direction, float roughness)
{ {
var prefilter = pcb.lights[0].prefilter; var prefilter = pcb.lights->prefilter;
if (!IsValid(prefilter)) if (!IsValid(prefilter))
return 0.0f.xxx; return 0.0f.xxx;
@ -154,7 +146,7 @@ float3 SamplePrefiltered(float3 direction, float roughness)
float2 SampleBrdfLut(float nDotV, float roughness) float2 SampleBrdfLut(float nDotV, float roughness)
{ {
var brdfLut = pcb.lights[0].brdfLUT; var brdfLut = pcb.lights->brdfLUT;
if (IsValid(brdfLut)) if (IsValid(brdfLut))
{ {
return brdfLut.Sample(float2(nDotV, roughness)); 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) float3 GetPointLightInfluence(float3 Albedo, float2 MetalRough, float3 Position, float3 Normal)
{ {
var lightData = pcb.lights[0]; Lighting* lightData = pcb.lights;
var pointLightBuffer = (StructuredBuffer<PointLight>.Handle)lightData.lights; PointLight* pointLightBuffer = (PointLight*)lightData->lightData;
if (!IsValid(pointLightBuffer)) if (!pointLightBuffer)
return 0.0f.xxx; return 0.0f.xxx;
uint offset = lightData.pointLightIndexer.offset; uint offset = lightData.pointLightIndexer.offset;
uint count = lightData.pointLightIndexer.count; 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 Metallic = MetalRough.r;
float Roughness = MetalRough.g; 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) float3 GetDirectionalLightInfluence(float3 Albedo, float2 MetalRough, float3 Position, float3 Normal)
{ {
var lightData = pcb.lights[0]; Lighting* lightData = pcb.lights;
var dirLightBuffer = (StructuredBuffer<DirectionalLight>.Handle)lightData.lights; var dirLightBuffer = (DirectionalLight*)lightData.lightData;
if (!IsValid(dirLightBuffer)) if (!dirLightBuffer)
return 0.0f.xxx; return 0.0f.xxx;
uint count = lightData.dirLightIndexer.count; 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 Metallic = MetalRough.r;
float Roughness = MetalRough.g; 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 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 CosineFactor = max(dot(Normal, ViewDir), 0.0f); // Normal instead of Halfway since there's no halfway in ambient.
float Metal = MetalRough.r; float Metal = MetalRough.r;