refactor: move all caches to RenderResources object

This commit is contained in:
2026-06-29 04:08:57 +02:00
parent 3bc8ba02e1
commit aa5c497f29
27 changed files with 1187 additions and 692 deletions
+107 -48
View File
@@ -1,21 +1,32 @@
#include <destrum/Graphics/Pipelines/MeshPipeline.h>
#include <destrum/FS/AssetFS.h>
#include "destrum/Graphics/Frustum.h"
#include <array>
#include <cassert>
#include <stdexcept>
#include <destrum/FS/AssetFS.h>
#include <destrum/Graphics/GfxDevice.h>
#include <destrum/Graphics/RenderResources.h>
#include <destrum/Graphics/Caches/MeshCache.h>
#include <destrum/Graphics/Frustum.h>
#include "spdlog/spdlog.h"
MeshPipeline::MeshPipeline(): m_pipelineLayout{nullptr} {
}
MeshPipeline::MeshPipeline() = default;
MeshPipeline::~MeshPipeline() {
}
MeshPipeline::~MeshPipeline() = default;
void MeshPipeline::init(GfxDevice& gfxDevice, VkFormat drawImageFormat, VkFormat depthImageFormat) {
const auto& device = gfxDevice.getDevice();
const auto vertexShader = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/mesh.vert");
const auto fragShader = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/mesh.frag");
void MeshPipeline::init(
GfxDevice& gfxDevice,
RenderResources& resources,
VkFormat drawImageFormat,
VkFormat depthImageFormat)
{
const auto vertexShader =
AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/mesh.vert");
const auto fragShader =
AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/mesh.frag");
const auto bufferRange = VkPushConstantRange{
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
@@ -24,24 +35,31 @@ void MeshPipeline::init(GfxDevice& gfxDevice, VkFormat drawImageFormat, VkFormat
};
const auto pushConstantRanges = std::array{bufferRange};
const auto layouts = std::array{gfxDevice.getBindlessDescSetLayout()};
// m_pipelineLayout = vkutil::createPipelineLayout(device, layouts, pushConstantRanges);
// vkutil::addDebugLabel(device, pipelineLayout, "mesh pipeline layout");
const auto layouts = std::array{
resources.getBindlessDescSetLayout()
};
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = static_cast<uint32_t>(layouts.size());
pipelineLayoutInfo.setLayoutCount = static_cast<std::uint32_t>(layouts.size());
pipelineLayoutInfo.pSetLayouts = layouts.data();
pipelineLayoutInfo.pushConstantRangeCount = 1;
pipelineLayoutInfo.pushConstantRangeCount =
static_cast<std::uint32_t>(pushConstantRanges.size());
pipelineLayoutInfo.pPushConstantRanges = pushConstantRanges.data();
if (vkCreatePipelineLayout(gfxDevice.getDevice().device, &pipelineLayoutInfo, nullptr, &m_pipelineLayout) != VK_SUCCESS) {
throw std::runtime_error("Could not make pipleine layout");
if (vkCreatePipelineLayout(
gfxDevice.getDevice().device,
&pipelineLayoutInfo,
nullptr,
&m_pipelineLayout) != VK_SUCCESS)
{
throw std::runtime_error("Could not create mesh pipeline layout");
}
PipelineConfigInfo pipelineConfig{};
Pipeline::DefaultPipelineConfigInfo(pipelineConfig);
pipelineConfig.name = "Mesh Pipeline";
pipelineConfig.pipelineLayout = m_pipelineLayout;
@@ -59,78 +77,119 @@ void MeshPipeline::init(GfxDevice& gfxDevice, VkFormat drawImageFormat, VkFormat
);
}
void MeshPipeline::draw(VkCommandBuffer cmd,
VkExtent2D renderExtent,
const GfxDevice& gfxDevice,
const MeshCache& meshCache,
const MaterialCache& materialCache,
const Camera& camera,
const GPUBuffer& sceneDataBuffer,
const std::vector<MeshDrawCommand>& drawCommands,
const std::vector<std::size_t>& sortedDrawCommands) {
m_pipeline->bind(cmd);
gfxDevice.bindBindlessDescSet(cmd, m_pipelineLayout);
void MeshPipeline::draw(
VkCommandBuffer cmd,
VkExtent2D renderExtent,
const RenderResources& resources,
const Camera& camera,
const GPUBuffer& sceneDataBuffer,
const std::vector<MeshDrawCommand>& drawCommands,
const std::vector<std::size_t>& sortedDrawCommands)
{
if (!m_pipeline) {
return;
}
int ActualDrawCalls = 0;
const MeshCache& meshCache = resources.meshes();
m_pipeline->bind(cmd);
resources.bindBindlessDescSet(cmd, m_pipelineLayout);
const auto viewport = VkViewport{
.x = 0,
.y = 0,
.width = (float)renderExtent.width,
.height = (float)renderExtent.height,
.x = 0.f,
.y = 0.f,
.width = static_cast<float>(renderExtent.width),
.height = static_cast<float>(renderExtent.height),
.minDepth = 0.f,
.maxDepth = 1.f,
};
vkCmdSetViewport(cmd, 0, 1, &viewport);
const auto scissor = VkRect2D{
.offset = {},
.extent = renderExtent,
};
vkCmdSetScissor(cmd, 0, 1, &scissor);
vkCmdSetPolygonModeEXT(cmd, m_renderWireframe ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL);
vkCmdSetPolygonModeEXT(
cmd,
m_renderWireframe ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL
);
auto prevMeshId = NULL_MESH_ID;
MeshID prevMeshId = NULL_MESH_ID;
int actualDrawCalls = 0;
const auto frustum = edge::createFrustumFromCamera(camera);
for (const auto& dcIdx : drawCommands) {
const auto& dc = dcIdx;
const auto drawOne = [&](const MeshDrawCommand& dc) {
if (!edge::isInFrustum(frustum, dc.worldBoundingSphere)) {
continue;
return;
}
ActualDrawCalls++;
++actualDrawCalls;
const auto& mesh = meshCache.getMesh(dc.meshId);
if (dc.meshId != prevMeshId) {
prevMeshId = dc.meshId;
vkCmdBindIndexBuffer(cmd, mesh.indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32);
vkCmdBindIndexBuffer(
cmd,
mesh.indexBuffer.buffer,
0,
VK_INDEX_TYPE_UINT32
);
}
assert(dc.materialId != NULL_MATERIAL_ID);
const auto pushConstants = PushConstants{
.transform = dc.transformMatrix,
.sceneDataBuffer = sceneDataBuffer.address,
.vertexBuffer = dc.skinnedMesh != nullptr ? dc.skinnedMesh->skinnedVertexBuffer.address : mesh.vertexBuffer.address,
.vertexBuffer =
dc.skinnedMesh != nullptr
? dc.skinnedMesh->skinnedVertexBuffer.address
: mesh.vertexBuffer.address,
.materialId = dc.materialId,
.padding = 0,
};
vkCmdPushConstants(
cmd,
m_pipelineLayout,
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
0,
sizeof(PushConstants),
&pushConstants);
&pushConstants
);
vkCmdDrawIndexed(cmd, mesh.numIndices, 1, 0, 0, 0);
};
if (!sortedDrawCommands.empty()) {
for (std::size_t drawIndex : sortedDrawCommands) {
assert(drawIndex < drawCommands.size());
drawOne(drawCommands[drawIndex]);
}
} else {
for (const MeshDrawCommand& dc : drawCommands) {
drawOne(dc);
}
}
// Optional:
// spdlog::debug("Actual mesh draw calls: {}", actualDrawCalls);
}
void MeshPipeline::cleanup(VkDevice device) {
vkDestroyPipelineLayout(device, m_pipelineLayout, nullptr);
void MeshPipeline::cleanup(VkDevice device)
{
m_pipeline.reset();
}
if (m_pipelineLayout != VK_NULL_HANDLE) {
vkDestroyPipelineLayout(device, m_pipelineLayout, nullptr);
m_pipelineLayout = VK_NULL_HANDLE;
}
}