Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Axiom/Renderer/RenderScene.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct VisibleSubmission {
uint32_t SubmissionIndex{0};
MeshHandle MeshHandle{};
float SortDepth{0.0f};
uint64_t SortKey{0};
};

struct VisibleSubmissionList {
Expand Down
7 changes: 6 additions & 1 deletion AxiomInternal/AxiomRHI/Vulkan/VulkanDescriptors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@

void DescriptorLayoutBuilder::AddBinding(uint32_t Binding,
VkDescriptorType Type) {
AddBinding(Binding, Type, 1);
}

void DescriptorLayoutBuilder::AddBinding(uint32_t Binding, VkDescriptorType Type,
uint32_t DescriptorCount) {
VkDescriptorSetLayoutBinding NewBind{};
NewBind.binding = Binding;
NewBind.descriptorType = Type;
NewBind.descriptorCount = 1;
NewBind.descriptorCount = DescriptorCount;

Bindings.push_back(NewBind);
}
Expand Down
2 changes: 2 additions & 0 deletions AxiomInternal/AxiomRHI/Vulkan/VulkanDescriptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ struct DescriptorLayoutBuilder {
std::vector<VkDescriptorSetLayoutBinding> Bindings;

void AddBinding(uint32_t Binding, VkDescriptorType Type);
void AddBinding(uint32_t Binding, VkDescriptorType Type,
uint32_t DescriptorCount);
void Clear();
VkDescriptorSetLayout Build(VkDevice Device, VkShaderStageFlags ShaderStages,
void *pNext = VK_NULL_HANDLE,
Expand Down
1 change: 1 addition & 0 deletions AxiomInternal/AxiomRHI/Vulkan/VulkanDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ void VulkanDevice::Init(VulkanContext &Context) {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES};
Features12.bufferDeviceAddress = true;
Features12.descriptorIndexing = true;
Features12.shaderSampledImageArrayNonUniformIndexing = true;

vkb::PhysicalDeviceSelector Selector{Context.BootstrapInstance};
Selector.set_minimum_version(1, 3)
Expand Down
74 changes: 51 additions & 23 deletions AxiomInternal/AxiomRHI/Vulkan/VulkanMaterialResources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,35 @@
#include <cassert>

namespace Axiom {
namespace {
constexpr uint32_t MaxGraphicsMaterialTextures = 1024;
}

void VulkanMaterialResources::Init(const CreateInfo &CreateInfo) {
m_Device = CreateInfo.Device;
m_DescriptorAllocator = CreateInfo.DescriptorAllocator;
m_MaterialDescriptorSetLayout = CreateInfo.MaterialDescriptorSetLayout;
m_TextureSampler = CreateInfo.TextureSampler;
m_CreateTextureImage = CreateInfo.CreateTextureImage;
m_BindlessMaterialDescriptorSet =
m_DescriptorAllocator->Allocate(m_Device, m_MaterialDescriptorSetLayout);

VkDescriptorImageInfo GraphicsTextureSamplerInfo{};
GraphicsTextureSamplerInfo.sampler = m_TextureSampler;
const VkWriteDescriptorSet SamplerWrite = VkInit::WriteDescriptorSet(
VK_DESCRIPTOR_TYPE_SAMPLER, m_BindlessMaterialDescriptorSet,
&GraphicsTextureSamplerInfo, 2);
vkUpdateDescriptorSets(m_Device, 1, &SamplerWrite, 0, VK_NULL_HANDLE);
}

void VulkanMaterialResources::Shutdown() {
m_MaterialsByHandle.clear();
m_MaterialImageViews.clear();
m_MaterialDescriptorSets.clear();
m_FallbackTexture = {};
m_BindlessMaterialDescriptorSet = VK_NULL_HANDLE;
m_NextMaterialHandleValue = 1;
m_NextTextureIndex = 1;
#if !defined(NDEBUG)
m_DebugGraphicsMaterialDescriptorUpdates = 0;
#endif
Expand Down Expand Up @@ -50,6 +65,10 @@ void VulkanMaterialResources::InitFallbackTexture() {
}

m_FallbackTexture = m_CreateTextureImage(CheckerTexture);
for (uint32_t TextureIndex = 0; TextureIndex < MaxGraphicsMaterialTextures;
++TextureIndex) {
WriteTextureDescriptor(TextureIndex, m_FallbackTexture.ImageView);
}
}

MaterialHandle
Expand Down Expand Up @@ -111,8 +130,8 @@ VulkanMaterialResources::ResolveMaterialTextureView(const MaterialInstance *Mate
return TextureImage.ImageView;
}

VkDescriptorSet
VulkanMaterialResources::ResolveMaterialDescriptorSet(const MaterialInstance *Material) {
uint32_t VulkanMaterialResources::ResolveMaterialTextureIndex(
const MaterialInstance *Material) {
const MaterialInstance *MaterialKey = Material;
const uint64_t MaterialRevision = Material ? Material->Revision : 0;
const TextureSourceData *TextureSource =
Expand All @@ -131,14 +150,19 @@ VulkanMaterialResources::ResolveMaterialDescriptorSet(const MaterialInstance *Ma
if (It != m_MaterialDescriptorSets.end() &&
It->second.Revision == MaterialRevision &&
It->second.TextureView == TextureView) {
return It->second.DescriptorSet;
return It->second.TextureIndex;
}

MaterialDescriptorCacheEntry *Entry = nullptr;
if (It == m_MaterialDescriptorSets.end()) {
MaterialDescriptorCacheEntry NewEntry{};
NewEntry.DescriptorSet = m_DescriptorAllocator->Allocate(
m_Device, m_MaterialDescriptorSetLayout);
NewEntry.DescriptorSet = m_BindlessMaterialDescriptorSet;
NewEntry.TextureIndex = MaterialKey == nullptr ? 0 : m_NextTextureIndex++;
assert(NewEntry.TextureIndex < MaxGraphicsMaterialTextures &&
"Vulkan graphics material texture table exhausted");
if (NewEntry.TextureIndex >= MaxGraphicsMaterialTextures) {
NewEntry.TextureIndex = 0;
}
auto [InsertedIt, Inserted] =
m_MaterialDescriptorSets.emplace(MaterialKey, NewEntry);
(void)Inserted;
Expand All @@ -147,30 +171,34 @@ VulkanMaterialResources::ResolveMaterialDescriptorSet(const MaterialInstance *Ma
Entry = &It->second;
}

VkDescriptorImageInfo GraphicsTextureImageInfo{};
GraphicsTextureImageInfo.imageView = TextureView;
GraphicsTextureImageInfo.imageLayout =
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkDescriptorImageInfo GraphicsTextureSamplerInfo{};
GraphicsTextureSamplerInfo.sampler = m_TextureSampler;

const std::array<VkWriteDescriptorSet, 2> GraphicsMaterialWrites = {
VkInit::WriteDescriptorSet(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
Entry->DescriptorSet, &GraphicsTextureImageInfo,
1),
VkInit::WriteDescriptorSet(VK_DESCRIPTOR_TYPE_SAMPLER,
Entry->DescriptorSet,
&GraphicsTextureSamplerInfo, 2)};
vkUpdateDescriptorSets(m_Device,
static_cast<uint32_t>(GraphicsMaterialWrites.size()),
GraphicsMaterialWrites.data(), 0, VK_NULL_HANDLE);
WriteTextureDescriptor(Entry->TextureIndex, TextureView);
Entry->TextureView = TextureView;
Entry->TextureSource = TextureSource;
Entry->Revision = MaterialRevision;
#if !defined(NDEBUG)
++m_DebugGraphicsMaterialDescriptorUpdates;
#endif
return Entry->DescriptorSet;
return Entry->TextureIndex;
}

VkDescriptorSet
VulkanMaterialResources::ResolveMaterialDescriptorSet(
const MaterialInstance *Material) {
(void)ResolveMaterialTextureIndex(Material);
return m_BindlessMaterialDescriptorSet;
}

void VulkanMaterialResources::WriteTextureDescriptor(uint32_t TextureIndex,
VkImageView TextureView) {
VkDescriptorImageInfo GraphicsTextureImageInfo{};
GraphicsTextureImageInfo.imageView = TextureView;
GraphicsTextureImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;

VkWriteDescriptorSet Write = VkInit::WriteDescriptorSet(
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, m_BindlessMaterialDescriptorSet,
&GraphicsTextureImageInfo, 1);
Write.dstArrayElement = TextureIndex;
vkUpdateDescriptorSets(m_Device, 1, &Write, 0, VK_NULL_HANDLE);
}

#if !defined(NDEBUG)
Expand Down
6 changes: 6 additions & 0 deletions AxiomInternal/AxiomRHI/Vulkan/VulkanMaterialResources.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class VulkanMaterialResources {
void UpdateMaterialHandle(MaterialHandle Handle, const MaterialInstance &Material);
const MaterialInstance *ResolveMaterialHandle(MaterialHandle Handle) const;
VkImageView ResolveMaterialTextureView(const MaterialInstance *Material);
uint32_t ResolveMaterialTextureIndex(const MaterialInstance *Material);
VkDescriptorSet ResolveMaterialDescriptorSet(const MaterialInstance *Material);
VkImageView GetFallbackTextureView() const { return m_FallbackTexture.ImageView; }
#if !defined(NDEBUG)
Expand All @@ -42,20 +43,25 @@ class VulkanMaterialResources {
VkImageView TextureView{VK_NULL_HANDLE};
const TextureSourceData *TextureSource{nullptr};
uint64_t Revision{0};
uint32_t TextureIndex{0};
};

void WriteTextureDescriptor(uint32_t TextureIndex, VkImageView TextureView);

VkDevice m_Device{VK_NULL_HANDLE};
DescriptorAllocator *m_DescriptorAllocator{nullptr};
VkDescriptorSetLayout m_MaterialDescriptorSetLayout{VK_NULL_HANDLE};
VkSampler m_TextureSampler{VK_NULL_HANDLE};
std::function<AllocatedImage(const TextureSourceData &)> m_CreateTextureImage;
AllocatedImage m_FallbackTexture;
VkDescriptorSet m_BindlessMaterialDescriptorSet{VK_NULL_HANDLE};
std::unordered_map<MaterialHandle, std::unique_ptr<MaterialInstance>,
MaterialHandleHash>
m_MaterialsByHandle;
std::unordered_map<const MaterialInstance *, VkImageView> m_MaterialImageViews;
std::unordered_map<const MaterialInstance *, MaterialDescriptorCacheEntry>
m_MaterialDescriptorSets;
uint32_t m_NextTextureIndex{1};
uint32_t m_NextMaterialHandleValue{1};
#if !defined(NDEBUG)
uint32_t m_DebugGraphicsMaterialDescriptorUpdates{0};
Expand Down
3 changes: 3 additions & 0 deletions AxiomInternal/AxiomRHI/Vulkan/VulkanMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ class VulkanMesh final : public Mesh {
AllocatedBuffer VertexBuffer;
AllocatedBuffer IndexBuffer;
AllocatedBuffer ProjectedVertexBuffer;
VkDeviceSize PooledVertexOffset{0};
VkDeviceSize PooledIndexOffset{0};
int32_t PooledVertexBase{0};
VkDescriptorSet DescriptorSet{VK_NULL_HANDLE};
glm::vec3 BoundsMin{0.0f};
glm::vec3 BoundsMax{0.0f};
Expand Down
16 changes: 16 additions & 0 deletions AxiomInternal/AxiomRHI/Vulkan/VulkanRendererTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include "AxiomRHI/Vulkan/VulkanTypes.h"

#include <cstddef>

#include <glm/ext/vector_uint4.hpp>
#include <glm/mat4x4.hpp>
#include <glm/vec2.hpp>
Expand Down Expand Up @@ -44,6 +46,16 @@ struct MeshGraphicsPushConstants {
glm::vec4 BaseColorFactor{1.0f};
float Metallic{0.0f};
float Roughness{0.5f};
glm::vec2 Padding{0.0f};
glm::uvec4 DrawOptions{0xffffffffu, 0u, 0u, 0u};
};
static_assert(offsetof(MeshGraphicsPushConstants, DrawOptions) == 96);
static_assert(sizeof(MeshGraphicsPushConstants) == 112);

struct MeshGraphicsObjectData {
glm::mat4 Model{1.0f};
glm::vec4 BaseColorFactor{1.0f};
glm::vec4 MaterialParams{0.0f};
};

struct HzbReducePushConstants {
Expand All @@ -58,7 +70,11 @@ struct ProjectedMeshVertexGpu {

struct MeshFrameResources {
AllocatedBuffer CameraBuffer;
AllocatedBuffer OpaqueObjectBuffer;
AllocatedBuffer OpaqueIndirectBuffer;
AllocatedBuffer HzbReadbackBuffer;
size_t OpaqueObjectCapacity{0};
size_t OpaqueIndirectCapacity{0};
VkDescriptorSet DepthFrameDescriptorSet{VK_NULL_HANDLE};
VkDescriptorSet GraphicsFrameDescriptorSet{VK_NULL_HANDLE};
VkDescriptorSet ComputeFrameDescriptorSet{VK_NULL_HANDLE};
Expand Down
73 changes: 71 additions & 2 deletions AxiomInternal/AxiomRHI/Vulkan/VulkanResourceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

namespace Axiom {
namespace {
constexpr uint32_t MaxGraphicsMaterialTextures = 1024;

uint32_t ComputeHzbMipCount(VkExtent2D BaseExtent) {
uint32_t Width = BaseExtent.width;
uint32_t Height = BaseExtent.height;
Expand Down Expand Up @@ -80,6 +82,8 @@ void VulkanResourceManager::Shutdown() {
Frame.TimestampQueryPool = VK_NULL_HANDLE;
}
VkBufferUtil::DestroyBuffer(m_Device->Allocator, Frame.CameraBuffer);
VkBufferUtil::DestroyBuffer(m_Device->Allocator, Frame.OpaqueObjectBuffer);
VkBufferUtil::DestroyBuffer(m_Device->Allocator, Frame.OpaqueIndirectBuffer);
VkBufferUtil::DestroyBuffer(m_Device->Allocator, Frame.HzbReadbackBuffer);
}

Expand Down Expand Up @@ -298,7 +302,7 @@ void VulkanResourceManager::InitDescriptors() {
std::vector<DescriptorAllocator::PoolSizeRatio> Sizes = {
{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 4.0f},
{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 6.0f},
{VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 2.0f},
{VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 20.0f},
{VK_DESCRIPTOR_TYPE_SAMPLER, 2.0f},
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4.0f},
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2.0f}};
Expand All @@ -320,13 +324,15 @@ void VulkanResourceManager::InitDescriptors() {
{
DescriptorLayoutBuilder Builder;
Builder.AddBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
Builder.AddBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
m_MeshGraphicsFrameDescriptorLayout =
Builder.Build(m_Device->Device,
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
}
{
DescriptorLayoutBuilder Builder;
Builder.AddBinding(1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
Builder.AddBinding(1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
MaxGraphicsMaterialTextures);
Builder.AddBinding(2, VK_DESCRIPTOR_TYPE_SAMPLER);
m_MeshGraphicsMaterialDescriptorLayout =
Builder.Build(m_Device->Device,
Expand Down Expand Up @@ -439,6 +445,18 @@ void VulkanResourceManager::InitMeshFrameResources() {
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_MAPPED_BIT);
Frame.OpaqueObjectBuffer = VkBufferUtil::CreateBuffer(
m_Device->Allocator, sizeof(MeshGraphicsObjectData),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_MAPPED_BIT);
Frame.OpaqueIndirectBuffer = VkBufferUtil::CreateBuffer(
m_Device->Allocator, sizeof(VkDrawIndexedIndirectCommand),
VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_MAPPED_BIT);
Frame.OpaqueObjectCapacity = 1;
Frame.OpaqueIndirectCapacity = 1;
Frame.HzbReadbackBuffer = VkBufferUtil::CreateBuffer(
m_Device->Allocator, static_cast<size_t>(m_HzbReadbackBufferSize),
VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_TO_CPU,
Expand All @@ -459,7 +477,58 @@ void VulkanResourceManager::InitMeshFrameResources() {
.queryCount = TimestampQueryCount};
VK_CHECK(vkCreateQueryPool(m_Device->Device, &QueryPoolInfo, VK_NULL_HANDLE,
&Frame.TimestampQueryPool));
UpdateGraphicsFrameDescriptor(Frame);
}
}

void VulkanResourceManager::EnsureOpaqueIndirectCapacity(
MeshFrameResources &Frame, size_t DrawCapacity) {
const size_t WantedCapacity = std::max<size_t>(1, DrawCapacity);
if (Frame.OpaqueObjectCapacity >= WantedCapacity &&
Frame.OpaqueIndirectCapacity >= WantedCapacity) {
return;
}

size_t NewCapacity =
std::max(Frame.OpaqueObjectCapacity, Frame.OpaqueIndirectCapacity);
NewCapacity = std::max<size_t>(1, NewCapacity);
while (NewCapacity < WantedCapacity) {
NewCapacity *= 2;
}

VkBufferUtil::DestroyBuffer(m_Device->Allocator, Frame.OpaqueObjectBuffer);
VkBufferUtil::DestroyBuffer(m_Device->Allocator, Frame.OpaqueIndirectBuffer);
Frame.OpaqueObjectBuffer = VkBufferUtil::CreateBuffer(
m_Device->Allocator, NewCapacity * sizeof(MeshGraphicsObjectData),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_MAPPED_BIT);
Frame.OpaqueIndirectBuffer = VkBufferUtil::CreateBuffer(
m_Device->Allocator, NewCapacity * sizeof(VkDrawIndexedIndirectCommand),
VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_MAPPED_BIT);
Frame.OpaqueObjectCapacity = NewCapacity;
Frame.OpaqueIndirectCapacity = NewCapacity;
UpdateGraphicsFrameDescriptor(Frame);
}

void VulkanResourceManager::UpdateGraphicsFrameDescriptor(
const MeshFrameResources &Frame) const {
VkDescriptorBufferInfo CameraBufferInfo =
VkInit::BufferInfo(Frame.CameraBuffer.Buffer, 0, Frame.CameraBuffer.Size);
VkDescriptorBufferInfo ObjectBufferInfo =
VkInit::BufferInfo(Frame.OpaqueObjectBuffer.Buffer, 0,
Frame.OpaqueObjectBuffer.Size);
const std::array<VkWriteDescriptorSet, 2> Writes = {
VkInit::WriteDescriptorBuffer(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
Frame.GraphicsFrameDescriptorSet,
&CameraBufferInfo, 0),
VkInit::WriteDescriptorBuffer(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
Frame.GraphicsFrameDescriptorSet,
&ObjectBufferInfo, 1)};
vkUpdateDescriptorSets(m_Device->Device, static_cast<uint32_t>(Writes.size()),
Writes.data(), 0, VK_NULL_HANDLE);
}

AllocatedImage
Expand Down
3 changes: 3 additions & 0 deletions AxiomInternal/AxiomRHI/Vulkan/VulkanResourceManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ class VulkanResourceManager {
MeshFrameResources &GetMeshFrame(uint64_t FrameNumber) {
return m_MeshFrames[FrameNumber % FRAME_OVERLAP];
}
void EnsureOpaqueIndirectCapacity(MeshFrameResources &Frame,
size_t DrawCapacity);

std::array<OffscreenCaptureFrame, FRAME_OVERLAP> &GetOffscreenCaptureFrames() {
return m_OffscreenCaptureFrames;
Expand All @@ -129,6 +131,7 @@ class VulkanResourceManager {
void InitHzbResources();
void InitDescriptors();
void InitMeshFrameResources();
void UpdateGraphicsFrameDescriptor(const MeshFrameResources &Frame) const;
AllocatedImage CreateTextureImage(const TextureSourceData &TextureData,
bool TrackForShutdown);
AllocatedImage CreateTextureImage(const HDRTextureSourceData &TextureData,
Expand Down
Loading
Loading