From 913b8391f82e9c1d3783c7b93cba8e8f9223d60b Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Fri, 7 Mar 2025 21:48:27 +0100 Subject: [PATCH 1/3] Fixing some semaphore things --- src/Editor/main.cpp | 32 +++---- src/Engine/Asset/FontAsset.cpp | 2 +- src/Engine/Graphics/Metal/Buffer.h | 2 - src/Engine/Graphics/RenderPass/BasePass.h | 10 +-- .../Graphics/RenderPass/DepthCullingPass.h | 4 +- .../Graphics/RenderPass/LightCullingPass.cpp | 2 - .../Graphics/RenderPass/LightCullingPass.h | 16 ++-- .../Graphics/RenderPass/RayTracingPass.cpp | 28 +++---- .../Graphics/RenderPass/RayTracingPass.h | 8 +- src/Engine/Graphics/RenderPass/UIPass.cpp | 6 +- src/Engine/Graphics/RenderPass/UIPass.h | 8 +- .../Graphics/RenderPass/VisibilityPass.h | 4 +- src/Engine/Graphics/StaticMeshVertexData.h | 12 +-- src/Engine/Graphics/VertexData.h | 16 ++-- src/Engine/Graphics/Vulkan/Command.cpp | 12 +-- src/Engine/Graphics/Vulkan/Descriptor.cpp | 83 +++++++++++++------ src/Engine/Graphics/Vulkan/Descriptor.h | 8 +- src/Engine/Graphics/Vulkan/Graphics.cpp | 10 ++- src/Engine/Graphics/Vulkan/Graphics.h | 1 + src/Engine/Graphics/Vulkan/Queue.cpp | 3 +- src/Engine/Graphics/Vulkan/Resources.cpp | 22 ++++- src/Engine/Graphics/Vulkan/Resources.h | 73 +++++++++++----- src/Engine/Graphics/Vulkan/Window.cpp | 8 ++ src/Engine/Graphics/Vulkan/Window.h | 1 + src/Engine/Scene/LightEnvironment.cpp | 4 +- 25 files changed, 236 insertions(+), 139 deletions(-) diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index 8648159..036d38f 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -112,7 +112,7 @@ int main() { // AssetImporter::importTexture(TextureImportArgs{ // .filePath = sourcePath / "import/textures/wgen.png", //}); - //AssetImporter::importMesh(MeshImportArgs{ + // AssetImporter::importMesh(MeshImportArgs{ // .filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.glb", // .importPath = "Whitechapel", //}); @@ -120,10 +120,10 @@ int main() { // .filePath = sourcePath / "import/models/box.glb", // .importPath = "", //}); - //AssetImporter::importMesh(MeshImportArgs{ - // .filePath = sourcePath / "import/models/rttest.glb", - // .importPath = "", - //}); + AssetImporter::importMesh(MeshImportArgs{ + .filePath = sourcePath / "import/models/rttest.glb", + .importPath = "", + }); //AssetImporter::importMesh(MeshImportArgs{ // .filePath = sourcePath / "import/models/town_hall.glb", // .importPath = "", @@ -137,16 +137,16 @@ int main() { .preferredFormat = Gfx::SE_FORMAT_B8G8R8A8_SRGB, }; auto window = windowManager->addWindow(graphics, mainWindowInfo); - ViewportCreateInfo sceneViewInfo = { - .dimensions = - { - .size = {1920, 1080}, - .offset = {0, 0}, - }, - .numSamples = Gfx::SE_SAMPLE_COUNT_4_BIT, - }; - OGameView sceneView = new Editor::PlayView(graphics, window, sceneViewInfo, binaryPath.generic_string()); - sceneView->setFocused(); + ViewportCreateInfo sceneViewInfo = { + .dimensions = + { + .size = {1920, 1080}, + .offset = {0, 0}, + }, + .numSamples = Gfx::SE_SAMPLE_COUNT_4_BIT, + }; + OGameView sceneView = new Editor::PlayView(graphics, window, sceneViewInfo, binaryPath.generic_string()); + sceneView->setFocused(); //OInspectorView inspectorView = new Editor::InspectorView(graphics, window, // ViewportCreateInfo{ // .dimensions = @@ -157,7 +157,7 @@ int main() { // .fieldOfView = 0, // .numSamples = Gfx::SE_SAMPLE_COUNT_1_BIT, // }); - + // window->show(); while (windowManager->isActive() && getGlobals().running) { windowManager->render(); diff --git a/src/Engine/Asset/FontAsset.cpp b/src/Engine/Asset/FontAsset.cpp index d0676c9..4d6709c 100644 --- a/src/Engine/Asset/FontAsset.cpp +++ b/src/Engine/Asset/FontAsset.cpp @@ -74,7 +74,7 @@ UVector2 FontAsset::shapeText(std::string_view view, uint32 fontSize, Arraynum_glyphs; ++i) { - assert(FT_Load_Glyph(ft_face, i, FT_LOAD_RENDER | FT_LOAD_COLOR) == 0); + assert(FT_Load_Glyph(ft_face, i, FT_LOAD_RENDER) == 0); FontAsset::Glyph& glyph = fontSizes[fontSize].glyphs[i]; glyph.size = IVector2(ft_face->glyph->bitmap.width, ft_face->glyph->bitmap.rows); glyph.bearing = IVector2(ft_face->glyph->bitmap_left, ft_face->glyph->bitmap_top); diff --git a/src/Engine/Graphics/Metal/Buffer.h b/src/Engine/Graphics/Metal/Buffer.h index 140cf0d..af23e05 100644 --- a/src/Engine/Graphics/Metal/Buffer.h +++ b/src/Engine/Graphics/Metal/Buffer.h @@ -2,8 +2,6 @@ #include "Graphics/Buffer.h" #include "Graphics/Enums.h" #include "Graphics/Initializer.h" -#include "Metal/MTLResource.hpp" -#include "Metal/MTLTypes.hpp" #include "MinimalEngine.h" #include "Resources.h" diff --git a/src/Engine/Graphics/RenderPass/BasePass.h b/src/Engine/Graphics/RenderPass/BasePass.h index 6383735..be76023 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.h +++ b/src/Engine/Graphics/RenderPass/BasePass.h @@ -28,8 +28,8 @@ class BasePass : public RenderPass { Gfx::PShaderBuffer tLightIndexList; Gfx::PTexture2D oLightGrid; Gfx::PTexture2D tLightGrid; - constexpr static std::string LIGHTINDEX_NAME = "lightIndexList"; - constexpr static std::string LIGHTGRID_NAME = "lightGrid"; + constexpr static const char* LIGHTINDEX_NAME = "lightIndexList"; + constexpr static const char* LIGHTGRID_NAME = "lightGrid"; Gfx::PDescriptorSet opaqueCulling; Gfx::PDescriptorSet transparentCulling; @@ -79,9 +79,9 @@ class BasePass : public RenderPass { float blendFactor; } skyboxData; Component::Skybox skybox; - constexpr static std::string SKYBOXDAY_NAME = "day"; - constexpr static std::string SKYBOXNIGHT_NAME = "night"; - constexpr static std::string SKYBOXSAMPLER_NAME = "sampler"; + const char* SKYBOXDAY_NAME = "day"; + const char* SKYBOXNIGHT_NAME = "night"; + const char* SKYBOXSAMPLER_NAME = "sampler"; PScene scene; }; DEFINE_REF(BasePass) diff --git a/src/Engine/Graphics/RenderPass/DepthCullingPass.h b/src/Engine/Graphics/RenderPass/DepthCullingPass.h index 289d3f7..9ac8670 100644 --- a/src/Engine/Graphics/RenderPass/DepthCullingPass.h +++ b/src/Engine/Graphics/RenderPass/DepthCullingPass.h @@ -29,9 +29,9 @@ class DepthCullingPass : public RenderPass { Array mipOffsets; Array mipDims; - constexpr static std::string DEPTHTEXTURE_NAME = "depthTexture"; + constexpr static const char* DEPTHTEXTURE_NAME = "depthTexture"; Gfx::OShaderBuffer depthMipBuffer; - constexpr static std::string DEPTHMIP_NAME = "depthMip"; + constexpr static const char* DEPTHMIP_NAME = "depthMip"; Gfx::RenderTargetAttachment depthAttachment; Gfx::RenderTargetAttachment visibilityAttachment; Gfx::ODescriptorLayout depthAttachmentLayout; diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp index 7b27539..7aeb007 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp @@ -6,8 +6,6 @@ #include "Math/Vector.h" #include "RenderGraph.h" #include "Scene/Scene.h" -#include "Graphics/Metal/Descriptor.h" -#include "Graphics/Metal/Shader.h" using namespace Seele; diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.h b/src/Engine/Graphics/RenderPass/LightCullingPass.h index 782d50a..e6a3f4d 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.h +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.h @@ -27,7 +27,7 @@ class LightCullingPass : public RenderPass { static constexpr uint32 INDEX_LIGHT_ENV = 1; Gfx::OShaderBuffer frustumBuffer; - constexpr static std::string FRUSTUMBUFFER_NAME = "frustums"; + const char* FRUSTUMBUFFER_NAME = "frustums"; Gfx::ODescriptorLayout dispatchParamsLayout; Gfx::PDescriptorSet dispatchParamsSet; Gfx::OComputeShader frustumShader; @@ -36,19 +36,19 @@ class LightCullingPass : public RenderPass { PLightEnvironment lightEnv; Gfx::PTexture2D depthAttachment; - constexpr static std::string DEPTHATTACHMENT_NAME = "depth"; + constexpr static const char* DEPTHATTACHMENT_NAME = "depth"; Gfx::OShaderBuffer oLightIndexCounter; - constexpr static std::string OLIGHTINDEXCOUNTER_NAME = "oLightIndexCounter"; + constexpr static const char* OLIGHTINDEXCOUNTER_NAME = "oLightIndexCounter"; Gfx::OShaderBuffer tLightIndexCounter; - constexpr static std::string TLIGHTINDEXCOUNTER_NAME = "tLightIndexCounter"; + constexpr static const char* TLIGHTINDEXCOUNTER_NAME = "tLightIndexCounter"; Gfx::OShaderBuffer oLightIndexList; - constexpr static std::string OLIGHTINDEXLIST_NAME = "oLightIndexList"; + constexpr static const char* OLIGHTINDEXLIST_NAME = "oLightIndexList"; Gfx::OShaderBuffer tLightIndexList; - constexpr static std::string TLIGHTINDEXLIST_NAME = "tLightIndexList"; + constexpr static const char* TLIGHTINDEXLIST_NAME = "tLightIndexList"; Gfx::OTexture2D oLightGrid; - constexpr static std::string OLIGHTGRID_NAME = "oLightGrid"; + constexpr static const char* OLIGHTGRID_NAME = "oLightGrid"; Gfx::OTexture2D tLightGrid; - constexpr static std::string TLIGHTGRID_NAME = "tLightGrid"; + constexpr static const char* TLIGHTGRID_NAME = "tLightGrid"; Gfx::PDescriptorSet cullingDescriptorSet; Gfx::ODescriptorLayout cullingDescriptorLayout; Gfx::OPipelineLayout cullingLayout; diff --git a/src/Engine/Graphics/RenderPass/RayTracingPass.cpp b/src/Engine/Graphics/RenderPass/RayTracingPass.cpp index 63b13b3..8b6bb0a 100644 --- a/src/Engine/Graphics/RenderPass/RayTracingPass.cpp +++ b/src/Engine/Graphics/RenderPass/RayTracingPass.cpp @@ -16,30 +16,30 @@ struct SampleParams { RayTracingPass::RayTracingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) { paramsLayout = graphics->createDescriptorLayout("pRayTracingParams"); - /*paramsLayout->addDescriptorBinding(Gfx::DescriptorBinding{ - .binding = 0, + paramsLayout->addDescriptorBinding(Gfx::DescriptorBinding{ + .name = TLAS_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, }); paramsLayout->addDescriptorBinding(Gfx::DescriptorBinding{ - .binding = 1, + .name = ACCUMULATOR_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE, }); paramsLayout->addDescriptorBinding(Gfx::DescriptorBinding{ - .binding = 2, + .name = TEXTURE_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE, }); paramsLayout->addDescriptorBinding(Gfx::DescriptorBinding{ - .binding = 3, + .name = INDEXBUFFER_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, }); paramsLayout->addDescriptorBinding(Gfx::DescriptorBinding{ - .binding = 4, + .name = SKYBOX_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, }); paramsLayout->addDescriptorBinding(Gfx::DescriptorBinding{ - .binding = 5, + .name = SKYSAMPLER_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER, - });*/ + }); paramsLayout->create(); pipelineLayout = graphics->createPipelineLayout("RayTracing"); pipelineLayout->addDescriptorLayout(viewParamsLayout); @@ -137,12 +137,12 @@ void RayTracingPass::render() { .bottomLevelStructures = accelerationStructures, }); Gfx::PDescriptorSet desc = paramsLayout->allocateDescriptorSet(); - /*desc->updateAccelerationStructure(0, 0, tlas); - desc->updateTexture(1, 0, radianceAccumulator); - desc->updateTexture(2, 0, texture); - desc->updateBuffer(3, 0, StaticMeshVertexData::getInstance()->getIndexBuffer()); - desc->updateTexture(4, 0, skyBox); - desc->updateSampler(5, 0, skyBoxSampler);*/ + desc->updateAccelerationStructure(TLAS_NAME, 0, tlas); + desc->updateTexture(ACCUMULATOR_NAME, 0, radianceAccumulator); + desc->updateTexture(TEXTURE_NAME, 0, texture); + desc->updateBuffer(INDEXBUFFER_NAME, 0, StaticMeshVertexData::getInstance()->getIndexBuffer()); + desc->updateTexture(SKYBOX_NAME, 0, skyBox); + desc->updateSampler(SKYSAMPLER_NAME, 0, skyBoxSampler); desc->writeChanges(); Gfx::ORenderCommand command = graphics->createRenderCommand("RayTracing"); diff --git a/src/Engine/Graphics/RenderPass/RayTracingPass.h b/src/Engine/Graphics/RenderPass/RayTracingPass.h index 67bdb9c..a22f1fb 100644 --- a/src/Engine/Graphics/RenderPass/RayTracingPass.h +++ b/src/Engine/Graphics/RenderPass/RayTracingPass.h @@ -17,15 +17,21 @@ class RayTracingPass : public RenderPass { private: Gfx::ODescriptorLayout paramsLayout; Gfx::OPipelineLayout pipelineLayout; + constexpr static const char* TLAS_NAME = "scene"; + Gfx::OTopLevelAS tlas; + constexpr static const char* ACCUMULATOR_NAME = "accumulator"; Gfx::OTexture2D radianceAccumulator; + constexpr static const char* TEXTURE_NAME = "image"; Gfx::OTexture2D texture; + constexpr static const char* SKYBOX_NAME = "skybox"; Gfx::PTextureCube skyBox; + constexpr static const char* SKYSAMPLER_NAME = "sampler"; Gfx::OSampler skyBoxSampler; + constexpr static const char* INDEXBUFFER_NAME = "indexBuffer"; Gfx::ORayGenShader rayGen; Gfx::OAnyHitShader anyhit; Gfx::OMissShader miss; Gfx::PRayTracingPipeline pipeline; - Gfx::OTopLevelAS tlas; PScene scene; }; } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/UIPass.cpp b/src/Engine/Graphics/RenderPass/UIPass.cpp index 8297a42..d019e03 100644 --- a/src/Engine/Graphics/RenderPass/UIPass.cpp +++ b/src/Engine/Graphics/RenderPass/UIPass.cpp @@ -32,7 +32,7 @@ UIPass::UIPass(Gfx::PGraphics graphics, UI::PSystem system) : RenderPass(graphic uiDescriptorLayout = graphics->createDescriptorLayout("pParams"); uiDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{ - .name = GLYPHINSTANCE_NAME, + .name = ELEMENT_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, }); uiDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{ @@ -57,6 +57,7 @@ void UIPass::beginFrame(const Component::Camera& cam) { RenderPass::beginFrame(cam); glyphs.clear(); usedTextures.clear(); + elements.clear(); for (auto& render : renderElements) { float x = render.position.x; float y = render.position.y; @@ -112,9 +113,6 @@ void UIPass::render() { command->bindPipeline(uiPipeline); command->bindDescriptor({viewParamsSet, uiDescriptorSet}); command->draw(4, elements.size(), 0, 0); - command->bindPipeline(textPipeline); - command->bindDescriptor({viewParamsSet, textDescriptorSet}); - command->draw(4, glyphs.size(), 0, 0); commands.add(std::move(command)); graphics->executeCommands(std::move(commands)); graphics->endRenderPass(); diff --git a/src/Engine/Graphics/RenderPass/UIPass.h b/src/Engine/Graphics/RenderPass/UIPass.h index ddf81f2..55a94ac 100644 --- a/src/Engine/Graphics/RenderPass/UIPass.h +++ b/src/Engine/Graphics/RenderPass/UIPass.h @@ -72,13 +72,13 @@ class UIPass : public RenderPass { Array glyphs; Array elements; Gfx::OShaderBuffer glyphInstanceBuffer; - constexpr static std::string GLYPHINSTANCE_NAME = "glyphData"; + constexpr static const char* GLYPHINSTANCE_NAME = "glyphData"; Gfx::OShaderBuffer elementBuffer; - constexpr static std::string ELEMENT_NAME = "elements"; + constexpr static const char* ELEMENT_NAME = "elements"; Gfx::OSampler glyphSampler; - constexpr static std::string GLYPHSAMPLER_NAME = "glyphSampler"; + constexpr static const char* GLYPHSAMPLER_NAME = "glyphSampler"; Array usedTextures; - constexpr static std::string TEXTURES_NAME = "textures"; + constexpr static const char* TEXTURES_NAME = "textures"; }; DEFINE_REF(UIPass); } // namespace Seele diff --git a/src/Engine/Graphics/RenderPass/VisibilityPass.h b/src/Engine/Graphics/RenderPass/VisibilityPass.h index e1457d2..69859d1 100644 --- a/src/Engine/Graphics/RenderPass/VisibilityPass.h +++ b/src/Engine/Graphics/RenderPass/VisibilityPass.h @@ -27,10 +27,10 @@ class VisibilityPass : public RenderPass { Gfx::OPipelineStatisticsQuery query; Gfx::PTimestampQuery timestamps; - constexpr static std::string VISIBILITY_NAME = "visibilityTexture"; + constexpr static const char* VISIBILITY_NAME = "visibilityTexture"; // Holds culling information for every meshlet for each instance Gfx::OShaderBuffer cullingBuffer; - constexpr static std::string CULLINGBUFFER_NAME = "cullingBuffer"; + constexpr static const char* CULLINGBUFFER_NAME = "cullingBuffer"; UVector threadGroupSize; }; DEFINE_REF(VisibilityPass) diff --git a/src/Engine/Graphics/StaticMeshVertexData.h b/src/Engine/Graphics/StaticMeshVertexData.h index edba7e7..1e50915 100644 --- a/src/Engine/Graphics/StaticMeshVertexData.h +++ b/src/Engine/Graphics/StaticMeshVertexData.h @@ -41,17 +41,17 @@ class StaticMeshVertexData : public VertexData { Gfx::OShaderBuffer positions; - constexpr static std::string POSITIONS_NAME = "positions"; + constexpr static const char* POSITIONS_NAME = "positions"; Gfx::OShaderBuffer texCoords[MAX_TEXCOORDS]; - constexpr static std::string TEXCOORDS_NAME = "texCoords"; + constexpr static const char* TEXCOORDS_NAME = "texCoords"; Gfx::OShaderBuffer normals; - constexpr static std::string NORMALS_NAME = "normals"; + constexpr static const char* NORMALS_NAME = "normals"; Gfx::OShaderBuffer tangents; - constexpr static std::string TANGENTS_NAME = "tangents"; + constexpr static const char* TANGENTS_NAME = "tangents"; Gfx::OShaderBuffer biTangents; - constexpr static std::string BITANGENTS_NAME = "biTangents"; + constexpr static const char* BITANGENTS_NAME = "biTangents"; Gfx::OShaderBuffer colors; - constexpr static std::string COLORS_NAME = "colors"; + constexpr static const char* COLORS_NAME = "colors"; Array posData; Array texData[MAX_TEXCOORDS]; Array norData; diff --git a/src/Engine/Graphics/VertexData.h b/src/Engine/Graphics/VertexData.h index a517e75..a4419bf 100644 --- a/src/Engine/Graphics/VertexData.h +++ b/src/Engine/Graphics/VertexData.h @@ -128,27 +128,27 @@ class VertexData { Gfx::ODescriptorLayout instanceDataLayout; // for mesh shading Gfx::OShaderBuffer meshletBuffer; - constexpr static std::string MESHLET_NAME = "meshlets"; + constexpr static const char* MESHLET_NAME = "meshlets"; Gfx::OShaderBuffer vertexIndicesBuffer; - constexpr static std::string VERTEXINDICES_NAME = "vertexIndices"; + constexpr static const char* VERTEXINDICES_NAME = "vertexIndices"; Gfx::OShaderBuffer primitiveIndicesBuffer; - constexpr static std::string PRIMITIVEINDICES_NAME = "primitiveIndices"; + constexpr static const char* PRIMITIVEINDICES_NAME = "primitiveIndices"; Gfx::OShaderBuffer cullingOffsetBuffer; - constexpr static std::string CULLINGOFFSETS_NAME = "cullingOffsets"; - constexpr static std::string CULLINGDATA_NAME = "cullingData"; + constexpr static const char* CULLINGOFFSETS_NAME = "cullingOffsets"; + constexpr static const char* CULLINGDATA_NAME = "cullingData"; // for legacy pipeline Gfx::OIndexBuffer indexBuffer; - constexpr static std::string INDEXBUFFER_NAME = "indexBuffer"; + constexpr static const char* INDEXBUFFER_NAME = "indexBuffer"; Array dataToBuild; // Material data Array instanceData; Gfx::OShaderBuffer instanceBuffer; - constexpr static std::string INSTANCES_NAME = "instances"; + constexpr static const char* INSTANCES_NAME = "instances"; Array instanceMeshData; Gfx::OShaderBuffer instanceMeshDataBuffer; - constexpr static std::string MESHDATA_NAME = "meshData"; + constexpr static const char* MESHDATA_NAME = "meshData"; Array rayTracingScene; diff --git a/src/Engine/Graphics/Vulkan/Command.cpp b/src/Engine/Graphics/Vulkan/Command.cpp index 1b3dbd9..dd96e4c 100644 --- a/src/Engine/Graphics/Vulkan/Command.cpp +++ b/src/Engine/Graphics/Vulkan/Command.cpp @@ -45,6 +45,7 @@ void Command::begin() { void Command::end() { VK_CHECK(vkEndCommandBuffer(handle)); + signalSemaphore->rotateSemaphore(); state = State::End; } @@ -111,15 +112,14 @@ void Command::executeCommands(Array commands) { } void Command::waitForSemaphore(VkPipelineStageFlags flags, PSemaphore semaphore) { + bindResource(semaphore->getCurrentSemaphore()); waitSemaphores.add(semaphore); waitFlags.add(flags); - // std::cout << "Cmd " << handle << " wait for " << semaphore->getHandle() << std::endl; } void Command::checkFence() { assert(state == State::Submit || !fence->isSignaled()); if (fence->isSignaled()) { - // std::cout << "Cmd " << handle << " was signaled" << std::endl; vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); fence->reset(); for (auto& command : executingComputes) { @@ -132,8 +132,8 @@ void Command::checkFence() { pool->cacheCommands(std::move(executingRenders)); for (auto& descriptor : boundResources) { descriptor->unbind(); - // std::cout << "Cmd " << handle << " unbind " << descriptor->getHandle() << std::endl; } + signalSemaphore->resolveSignal(); boundResources.clear(); graphics->getDestructionManager()->notifyCommandComplete(); state = State::Init; @@ -561,11 +561,12 @@ void CommandPool::submitCommands(PSemaphore signalSemaphore) { assert(command->state == Command::State::Begin); // Not in a renderpass command->end(); Array semaphores = {command->signalSemaphore->getHandle()}; + command->signalSemaphore->encodeSignal(); if (signalSemaphore != nullptr) { semaphores.add(signalSemaphore->getHandle()); + signalSemaphore->encodeSignal(); } queue->submitCommandBuffer(command, semaphores); - // std::cout << "Cmd " << command->getHandle() << " signalling " << command->signalSemaphore->getHandle() << std::endl; PSemaphore waitSemaphore = command->signalSemaphore; for (uint32 i = 0; i < allocatedBuffers.size(); ++i) { @@ -587,8 +588,7 @@ void CommandPool::submitCommands(PSemaphore signalSemaphore) { } void CommandPool::refreshCommands() { - for (uint32 i = 0; i < allocatedBuffers.size(); ++i) - { + for (uint32 i = 0; i < allocatedBuffers.size(); ++i) { allocatedBuffers[i]->checkFence(); } } diff --git a/src/Engine/Graphics/Vulkan/Descriptor.cpp b/src/Engine/Graphics/Vulkan/Descriptor.cpp index 25e4bae..0e2c060 100644 --- a/src/Engine/Graphics/Vulkan/Descriptor.cpp +++ b/src/Engine/Graphics/Vulkan/Descriptor.cpp @@ -53,6 +53,7 @@ void DescriptorLayout::create() { } else { mappings[gfxBinding.name] = { .binding = (uint32)bindings.size(), + .type = cast(gfxBinding.descriptorType), }; bindings.add({ .binding = (uint32)bindings.size(), @@ -205,11 +206,11 @@ void DescriptorSet::updateConstants(const std::string& name, uint32 offset, void void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PShaderBuffer shaderBuffer) { PShaderBuffer vulkanBuffer = shaderBuffer.cast(); - uint32 binding = owner->getLayout()->mappings[name].binding; + const auto& map = owner->getLayout()->mappings[name]; + uint32 binding = map.binding; if (boundResources[binding][index] == vulkanBuffer->getAlloc() || vulkanBuffer->getAlloc() == nullptr) { return; } - bufferInfos.add(VkDescriptorBufferInfo{ .buffer = vulkanBuffer->getHandle(), .offset = 0, @@ -222,7 +223,7 @@ void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PSh .dstBinding = binding, .dstArrayElement = index, .descriptorCount = 1, - .descriptorType = cast(layout->getBindings()[binding].descriptorType), + .descriptorType = map.type, .pBufferInfo = &bufferInfos.back(), }); @@ -231,7 +232,8 @@ void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PSh void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PVertexBuffer indexBuffer) { PVertexBuffer vulkanBuffer = indexBuffer.cast(); - uint32 binding = owner->getLayout()->mappings[name].binding; + const auto& map = owner->getLayout()->mappings[name]; + uint32 binding = map.binding; if (boundResources[binding][index] == vulkanBuffer->getAlloc() || vulkanBuffer->getAlloc() == nullptr) { return; } @@ -248,7 +250,7 @@ void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PVe .dstBinding = binding, .dstArrayElement = index, .descriptorCount = 1, - .descriptorType = cast(layout->getBindings()[binding].descriptorType), + .descriptorType = map.type, .pBufferInfo = &bufferInfos.back(), }); @@ -257,7 +259,8 @@ void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PVe void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PIndexBuffer indexBuffer) { PIndexBuffer vulkanBuffer = indexBuffer.cast(); - uint32 binding = owner->getLayout()->mappings[name].binding; + const auto& map = owner->getLayout()->mappings[name]; + uint32 binding = map.binding; if (boundResources[binding][index] == vulkanBuffer->getAlloc() || vulkanBuffer->getAlloc() == nullptr) { return; } @@ -274,7 +277,7 @@ void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PIn .dstBinding = binding, .dstArrayElement = index, .descriptorCount = 1, - .descriptorType = cast(layout->getBindings()[binding].descriptorType), + .descriptorType = map.type, .pBufferInfo = &bufferInfos.back(), }); @@ -283,7 +286,8 @@ void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PIn void DescriptorSet::updateSampler(const std::string& name, uint32 index, Gfx::PSampler samplerState) { PSampler vulkanSampler = samplerState.cast(); - uint32 binding = owner->getLayout()->mappings[name].binding; + const auto& map = owner->getLayout()->mappings[name]; + uint32 binding = map.binding; if (boundResources[binding][index] == vulkanSampler->getHandle()) { return; } @@ -301,7 +305,7 @@ void DescriptorSet::updateSampler(const std::string& name, uint32 index, Gfx::PS .dstBinding = binding, .dstArrayElement = index, .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER, + .descriptorType = map.type, .pImageInfo = &imageInfos.back(), }); @@ -310,7 +314,8 @@ void DescriptorSet::updateSampler(const std::string& name, uint32 index, Gfx::PS void DescriptorSet::updateTexture(const std::string& name, uint32 index, Gfx::PTexture2D texture) { TextureBase* vulkanTexture = texture.cast().getHandle(); - uint32 binding = owner->getLayout()->mappings[name].binding; + const auto& map = owner->getLayout()->mappings[name]; + uint32 binding = map.binding; if (boundResources[binding][index] == vulkanTexture->getHandle()) { return; } @@ -328,7 +333,7 @@ void DescriptorSet::updateTexture(const std::string& name, uint32 index, Gfx::PT .dstBinding = binding, .dstArrayElement = index, .descriptorCount = 1, - .descriptorType = cast(layout->getBindings()[binding].descriptorType), + .descriptorType = map.type, .pImageInfo = &imageInfos.back(), }); @@ -337,7 +342,8 @@ void DescriptorSet::updateTexture(const std::string& name, uint32 index, Gfx::PT void DescriptorSet::updateTexture(const std::string& name, uint32 index, Gfx::PTexture3D texture) { TextureBase* vulkanTexture = texture.cast().getHandle(); - uint32 binding = owner->getLayout()->mappings[name].binding; + const auto& map = owner->getLayout()->mappings[name]; + uint32 binding = map.binding; if (boundResources[binding][index] == vulkanTexture->getHandle()) { return; } @@ -355,7 +361,7 @@ void DescriptorSet::updateTexture(const std::string& name, uint32 index, Gfx::PT .dstBinding = binding, .dstArrayElement = index, .descriptorCount = 1, - .descriptorType = cast(layout->getBindings()[binding].descriptorType), + .descriptorType = map.type, .pImageInfo = &imageInfos.back(), }); @@ -364,7 +370,8 @@ void DescriptorSet::updateTexture(const std::string& name, uint32 index, Gfx::PT void DescriptorSet::updateTexture(const std::string& name, uint32 index, Gfx::PTextureCube texture) { TextureBase* vulkanTexture = texture.cast().getHandle(); - uint32 binding = owner->getLayout()->mappings[name].binding; + const auto& map = owner->getLayout()->mappings[name]; + uint32 binding = map.binding; if (boundResources[binding][index] == vulkanTexture->getHandle()) { return; } @@ -382,7 +389,7 @@ void DescriptorSet::updateTexture(const std::string& name, uint32 index, Gfx::PT .dstBinding = binding, .dstArrayElement = index, .descriptorCount = 1, - .descriptorType = cast(layout->getBindings()[binding].descriptorType), + .descriptorType = map.type, .pImageInfo = &imageInfos.back(), }); @@ -410,6 +417,42 @@ void DescriptorSet::updateAccelerationStructure(const std::string& name, uint32 } void DescriptorSet::writeChanges() { + if (constantData.size() > 0) { + if (constantsBuffer != nullptr) + { + graphics->getDestructionManager()->queueResourceForDestruction(std::move(constantsBuffer)); + } + constantsBuffer = new BufferAllocation(graphics, owner->getLayout()->getName(), + VkBufferCreateInfo{ + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .size = constantData.size(), + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + }, + VmaAllocationCreateInfo{ + .usage = VMA_MEMORY_USAGE_AUTO, + }, + Gfx::QueueType::GRAPHICS); + constantsBuffer->updateContents(0, constantData.size(), constantData.data()); + constantsBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, + Gfx::SE_ACCESS_UNIFORM_READ_BIT, Gfx::SE_PIPELINE_STAGE_ALL_COMMANDS_BIT); + bufferInfos.add(VkDescriptorBufferInfo{ + .buffer = constantsBuffer->buffer, + .offset = 0, + .range = constantsBuffer->size, + }); + writeDescriptors.add(VkWriteDescriptorSet{ + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .pNext = nullptr, + .dstSet = setHandle, + .dstBinding = 0, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .pBufferInfo = &bufferInfos.back(), + }); + } + if (writeDescriptors.size() > 0) { if (isCurrentlyBound()) { std::cout << "Descriptor currently bound, allocate a new one instead" << std::endl; @@ -420,16 +463,6 @@ void DescriptorSet::writeChanges() { imageInfos.clear(); bufferInfos.clear(); } - constantsBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{ - .sourceData = - { - .size = constantData.size(), - .data = constantData.data(), - }, - .name = owner->getLayout()->getName(), - }); - constantsBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, - Gfx::SE_ACCESS_UNIFORM_READ_BIT, Gfx::SE_PIPELINE_STAGE_ALL_COMMANDS_BIT); } PipelineLayout::PipelineLayout(PGraphics graphics, const std::string& name, Gfx::PPipelineLayout baseLayout) diff --git a/src/Engine/Graphics/Vulkan/Descriptor.h b/src/Engine/Graphics/Vulkan/Descriptor.h index 082f8e4..ec23b38 100644 --- a/src/Engine/Graphics/Vulkan/Descriptor.h +++ b/src/Engine/Graphics/Vulkan/Descriptor.h @@ -8,11 +8,11 @@ namespace Seele { namespace Vulkan { DECLARE_REF(Graphics) -struct DescriptorMapping -{ +struct DescriptorMapping { uint32 binding; uint32 constantOffset; uint32 constantSize; + VkDescriptorType type; }; class DescriptorLayout : public Gfx::DescriptorLayout { public: @@ -23,7 +23,7 @@ class DescriptorLayout : public Gfx::DescriptorLayout { private: PGraphics graphics; - uint32 constantsSize; + uint32 constantsSize = 0; VkShaderStageFlags constantsStages; Array bindings; Map mappings; @@ -73,7 +73,7 @@ class DescriptorSet : public Gfx::DescriptorSet, public CommandBoundResource { private: std::vector constantData; - Gfx::OUniformBuffer constantsBuffer; + OBufferAllocation constantsBuffer; VkShaderStageFlags constantsStageFlags; List imageInfos; List bufferInfos; diff --git a/src/Engine/Graphics/Vulkan/Graphics.cpp b/src/Engine/Graphics/Vulkan/Graphics.cpp index 2ff3536..dfcefc1 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.cpp +++ b/src/Engine/Graphics/Vulkan/Graphics.cpp @@ -142,7 +142,9 @@ Graphics::~Graphics() { void Graphics::init(GraphicsInitializer initInfo) { initInstance(initInfo); - //setupDebugCallback(); +#ifdef ENABLE_VALIDATION + setupDebugCallback(); +#endif pickPhysicalDevice(); createDevice(initInfo); VmaAllocatorCreateInfo createInfo = { @@ -197,6 +199,12 @@ void Graphics::waitDeviceIdle() { getGraphicsCommands()->refreshCommands(); } +void Graphics::executeCommands(Gfx::ORenderCommand commands) { + Array commandArray; + commandArray.add(std::move(commands)); + getGraphicsCommands()->getCommands()->executeCommands(std::move(commandArray)); +} + void Graphics::executeCommands(Array commands) { getGraphicsCommands()->getCommands()->executeCommands(std::move(commands)); } diff --git a/src/Engine/Graphics/Vulkan/Graphics.h b/src/Engine/Graphics/Vulkan/Graphics.h index d47ad24..58cb080 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.h +++ b/src/Engine/Graphics/Vulkan/Graphics.h @@ -40,6 +40,7 @@ class Graphics : public Gfx::Graphics { virtual void endRenderPass() override; virtual void waitDeviceIdle() override; + virtual void executeCommands(Gfx::ORenderCommand commands) override; virtual void executeCommands(Array commands) override; virtual void executeCommands(Gfx::OComputeCommand commands) override; virtual void executeCommands(Array commands) override; diff --git a/src/Engine/Graphics/Vulkan/Queue.cpp b/src/Engine/Graphics/Vulkan/Queue.cpp index 0f5cb4b..0517a6a 100644 --- a/src/Engine/Graphics/Vulkan/Queue.cpp +++ b/src/Engine/Graphics/Vulkan/Queue.cpp @@ -25,6 +25,8 @@ void Queue::submitCommandBuffer(PCommand command, const Array& sign VkCommandBuffer cmdHandle = command->handle; Array waitSemaphores; + // wait semaphores get bound to the cmd when they are added + // and unbound when the command completes for (PSemaphore semaphore : command->waitSemaphores) { waitSemaphores.add(semaphore->getHandle()); } @@ -40,7 +42,6 @@ void Queue::submitCommandBuffer(PCommand command, const Array& sign .signalSemaphoreCount = static_cast(signalSemaphores.size()), .pSignalSemaphores = signalSemaphores.data(), }; - VK_CHECK(vkQueueSubmit(queue, 1, &submitInfo, command->fence->getHandle())); command->fence->submit(); command->state = Command::State::Submit; diff --git a/src/Engine/Graphics/Vulkan/Resources.cpp b/src/Engine/Graphics/Vulkan/Resources.cpp index 82aaf56..7cca67d 100644 --- a/src/Engine/Graphics/Vulkan/Resources.cpp +++ b/src/Engine/Graphics/Vulkan/Resources.cpp @@ -7,7 +7,7 @@ using namespace Seele; using namespace Seele::Vulkan; -Semaphore::Semaphore(PGraphics graphics) : graphics(graphics) { +SemaphoreHandle::SemaphoreHandle(PGraphics graphics, const std::string& name) : CommandBoundResource(graphics, name) { VkSemaphoreCreateInfo info = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, .pNext = nullptr, @@ -16,8 +16,26 @@ Semaphore::Semaphore(PGraphics graphics) : graphics(graphics) { VK_CHECK(vkCreateSemaphore(graphics->getDevice(), &info, nullptr, &handle)); } +SemaphoreHandle::~SemaphoreHandle() { vkDestroySemaphore(graphics->getDevice(), handle, nullptr); } + +Semaphore::Semaphore(PGraphics graphics) : graphics(graphics) {} + Semaphore::~Semaphore() { - // graphics->getDestructionManager()->queueSemaphore(graphics->getGraphicsCommands()->getCommands(), handle); + for (auto& h : handles) { + graphics->getDestructionManager()->queueResourceForDestruction(std::move(h)); + } +} + +void Semaphore::rotateSemaphore() { + for (uint32 i = 0; i < handles.size(); ++i) { + if (handles[i]->isCurrentlyBound()) { + continue; + } + currentHandle = i; + return; + } + currentHandle = handles.size(); + handles.add(new SemaphoreHandle(graphics, "Semaphore")); } Fence::Fence(PGraphics graphics) : graphics(graphics), status(Status::Ready) { diff --git a/src/Engine/Graphics/Vulkan/Resources.h b/src/Engine/Graphics/Vulkan/Resources.h index b1ca748..8290ecc 100644 --- a/src/Engine/Graphics/Vulkan/Resources.h +++ b/src/Engine/Graphics/Vulkan/Resources.h @@ -4,21 +4,67 @@ #include #include - namespace Seele { namespace Vulkan { DECLARE_REF(DescriptorPool) DECLARE_REF(CommandPool) DECLARE_REF(Command) DECLARE_REF(Graphics) -class Semaphore { + +class CommandBoundResource { public: - Semaphore(PGraphics graphics); - virtual ~Semaphore(); + CommandBoundResource(PGraphics graphics, const std::string& name) : graphics(graphics), name(name) {} + virtual ~CommandBoundResource() { + if (isCurrentlyBound()) + abort(); + } + constexpr bool isCurrentlyBound() const { return bindCount > 0; } + constexpr void bind() { bindCount++; } + constexpr void unbind() { bindCount--; } + + protected: + PGraphics graphics; + std::string name; + uint64 bindCount = 0; +}; +DEFINE_REF(CommandBoundResource) + +class SemaphoreHandle : public CommandBoundResource { + public: + SemaphoreHandle(PGraphics graphics, const std::string& name); + virtual ~SemaphoreHandle(); + constexpr VkSemaphore getHandle() const { return handle; } private: VkSemaphore handle; +}; +DEFINE_REF(SemaphoreHandle) + +class Semaphore { + public: + Semaphore(PGraphics graphics); + virtual ~Semaphore(); + // call when you need a new semaphore + void rotateSemaphore(); + // call when the semaphore is to signal something, for example after using it in vkAcquireImage + void encodeSignal() { + if (handles.size() == 0) + return; + handles[currentHandle]->bind(); + } + // call when the semaphore has been signalled + void resolveSignal() { + if (handles.size() == 0) + return; + handles[currentHandle]->unbind(); + } + constexpr VkSemaphore getHandle() const { return handles[currentHandle]->getHandle(); } + PSemaphoreHandle getCurrentSemaphore() const { return handles[currentHandle]; } + + private: + Array handles; + uint32 currentHandle = 0; PGraphics graphics; }; DEFINE_REF(Semaphore) @@ -45,7 +91,6 @@ class Fence { VkFence fence; }; DEFINE_REF(Fence) -DECLARE_REF(CommandBoundResource) class DestructionManager { public: DestructionManager(PGraphics graphics); @@ -59,24 +104,6 @@ class DestructionManager { }; DEFINE_REF(DestructionManager) -class CommandBoundResource { - public: - CommandBoundResource(PGraphics graphics, const std::string& name) : graphics(graphics), name(name) {} - virtual ~CommandBoundResource() { - if (isCurrentlyBound()) - abort(); - } - constexpr bool isCurrentlyBound() const { return bindCount > 0; } - constexpr void bind() { bindCount++; } - constexpr void unbind() { bindCount--; } - - protected: - PGraphics graphics; - std::string name; - uint64 bindCount = 0; -}; -DEFINE_REF(CommandBoundResource) - class SamplerHandle : public CommandBoundResource { public: SamplerHandle(PGraphics graphics, VkSamplerCreateInfo createInfo); diff --git a/src/Engine/Graphics/Vulkan/Window.cpp b/src/Engine/Graphics/Vulkan/Window.cpp index 0fbdda8..a5f0e18 100644 --- a/src/Engine/Graphics/Vulkan/Window.cpp +++ b/src/Engine/Graphics/Vulkan/Window.cpp @@ -59,6 +59,7 @@ Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo) : graphics(graphics), preferences(createInfo), instance(graphics->getInstance()), swapchain(VK_NULL_HANDLE) { glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &contentScaleX, &contentScaleY); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); GLFWwindow* handle = glfwCreateWindow(createInfo.width / contentScaleX, createInfo.height / contentScaleY, createInfo.title, nullptr, nullptr); windowHandle = handle; glfwSetWindowUserPointer(handle, this); @@ -92,11 +93,16 @@ Window::~Window() { void Window::pollInput() { glfwPollEvents(); } +void Window::show() { glfwShowWindow(static_cast(windowHandle)); } + void Window::beginFrame() { imageAvailableFences[currentSemaphoreIndex]->reset(); + imageAvailableSemaphores[currentSemaphoreIndex]->resolveSignal(); + imageAvailableSemaphores[currentSemaphoreIndex]->rotateSemaphore(); VK_CHECK(vkAcquireNextImageKHR(graphics->getDevice(), swapchain, std::numeric_limits::max(), imageAvailableSemaphores[currentSemaphoreIndex]->getHandle(), imageAvailableFences[currentSemaphoreIndex]->getHandle(), ¤tImageIndex)); + imageAvailableSemaphores[currentSemaphoreIndex]->encodeSignal(); imageAvailableFences[currentSemaphoreIndex]->submit(); graphics->getGraphicsCommands()->getCommands()->waitForSemaphore(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, imageAvailableSemaphores[currentSemaphoreIndex]); @@ -111,6 +117,7 @@ void Window::endFrame() { swapChainTextures[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_PRESENT_SRC_KHR, Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, Gfx::SE_ACCESS_MEMORY_READ_BIT, Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + renderingDoneSemaphores[currentSemaphoreIndex]->rotateSemaphore(); graphics->getGraphicsCommands()->submitCommands(renderingDoneSemaphores[currentSemaphoreIndex]); VkSemaphore renderDoneHandle = renderingDoneSemaphores[currentSemaphoreIndex]->getHandle(); VkPresentInfoKHR presentInfo = { @@ -130,6 +137,7 @@ void Window::endFrame() { } else { VK_CHECK(r); } + renderingDoneSemaphores[currentSemaphoreIndex]->resolveSignal(); currentSemaphoreIndex = (currentSemaphoreIndex + 1) % Gfx::numFramesBuffered; currentFrameIndex = currentSemaphoreIndex; // graphics->waitDeviceIdle(); diff --git a/src/Engine/Graphics/Vulkan/Window.h b/src/Engine/Graphics/Vulkan/Window.h index db81e82..0e50bd2 100644 --- a/src/Engine/Graphics/Vulkan/Window.h +++ b/src/Engine/Graphics/Vulkan/Window.h @@ -12,6 +12,7 @@ class Window : public Gfx::Window { Window(PGraphics graphics, const WindowCreateInfo& createInfo); virtual ~Window(); virtual void pollInput() override; + virtual void show() override; virtual void beginFrame() override; virtual void endFrame() override; virtual Gfx::PTexture2D getBackBuffer() const override; diff --git a/src/Engine/Scene/LightEnvironment.cpp b/src/Engine/Scene/LightEnvironment.cpp index c0994cb..52409da 100644 --- a/src/Engine/Scene/LightEnvironment.cpp +++ b/src/Engine/Scene/LightEnvironment.cpp @@ -11,7 +11,7 @@ LightEnvironment::LightEnvironment(Gfx::PGraphics graphics) : graphics(graphics) }); layout->addDescriptorBinding(Gfx::DescriptorBinding{ .name = "numDirectionalLights", - .uniformLength = sizeof(uint) + .uniformLength = sizeof(uint32), }); layout->addDescriptorBinding(Gfx::DescriptorBinding{ .name = "pointLights", @@ -19,7 +19,7 @@ LightEnvironment::LightEnvironment(Gfx::PGraphics graphics) : graphics(graphics) }); layout->addDescriptorBinding(Gfx::DescriptorBinding{ .name = "numPointLights", - .uniformLength = sizeof(uint) + .uniformLength = sizeof(uint32), }); layout->create(); From 6f0e2fe7e7d1f99f04dae15ccbea218213b78f23 Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Sun, 9 Mar 2025 22:42:05 +0100 Subject: [PATCH 2/3] Fixing the maximum 2048 meshlet limit --- res/shaders/lib/Scene.slang | 7 +- src/Engine/Graphics/Enums.h | 4 +- src/Engine/Graphics/Mesh.cpp | 2 +- src/Engine/Graphics/RenderPass/BasePass.cpp | 48 ++--- src/Engine/Graphics/RenderPass/BasePass.h | 3 + .../Graphics/RenderPass/CachedDepthPass.cpp | 7 +- .../Graphics/RenderPass/DepthCullingPass.cpp | 6 +- .../Graphics/RenderPass/LightCullingPass.cpp | 28 +-- .../Graphics/RenderPass/LightCullingPass.h | 4 +- .../Graphics/RenderPass/VisibilityPass.cpp | 7 +- src/Engine/Graphics/StaticMeshVertexData.cpp | 6 +- src/Engine/Graphics/StaticMeshVertexData.h | 2 +- src/Engine/Graphics/VertexData.cpp | 186 ++++++++---------- src/Engine/Graphics/VertexData.h | 9 +- src/Engine/Graphics/Vulkan/RayTracing.cpp | 3 +- src/Engine/Graphics/slang-compile.cpp | 2 +- 16 files changed, 151 insertions(+), 173 deletions(-) diff --git a/res/shaders/lib/Scene.slang b/res/shaders/lib/Scene.slang index b18676d..9179579 100644 --- a/res/shaders/lib/Scene.slang +++ b/res/shaders/lib/Scene.slang @@ -20,9 +20,8 @@ struct MeshData uint32_t numIndices; }; -static const uint32_t MAX_VERTICES = 64; -static const uint32_t MAX_PRIMITIVES = 128; -static const uint32_t MAX_MESHLETS_PER_INSTANCE = 2048; +static const uint32_t MAX_VERTICES = 256; +static const uint32_t MAX_PRIMITIVES = 256; struct InstanceData { @@ -77,7 +76,7 @@ uint decodePrimitive(uint32_t encoded) struct MeshPayload { - uint culledMeshlets[MAX_MESHLETS_PER_INSTANCE]; + uint culledMeshlets[2048]; uint instanceId; uint meshletOffset; uint cullingOffset; diff --git a/src/Engine/Graphics/Enums.h b/src/Engine/Graphics/Enums.h index c16df4f..9c59c18 100644 --- a/src/Engine/Graphics/Enums.h +++ b/src/Engine/Graphics/Enums.h @@ -159,8 +159,8 @@ static constexpr bool useAsyncCompute = false; static constexpr bool useMeshShading = true; static constexpr uint32 numFramesBuffered = 3; -static constexpr uint32 numVerticesPerMeshlet = 64; -static constexpr uint32 numPrimitivesPerMeshlet = 126; +static constexpr uint32 numVerticesPerMeshlet = 256; +static constexpr uint32 numPrimitivesPerMeshlet = 256; double getCurrentFrameDelta(); double getCurrentFrameTime(); uint32 getCurrentFrameIndex(); diff --git a/src/Engine/Graphics/Mesh.cpp b/src/Engine/Graphics/Mesh.cpp index 7c0249e..f1d61e2 100644 --- a/src/Engine/Graphics/Mesh.cpp +++ b/src/Engine/Graphics/Mesh.cpp @@ -14,7 +14,7 @@ void Mesh::save(ArchiveBuffer& buffer) const { Serialization::save(buffer, vertexCount); Serialization::save(buffer, referencedMaterial->getFolderPath()); Serialization::save(buffer, referencedMaterial->getName()); - vertexData->serializeMesh(id, vertexCount, buffer); + vertexData->serializeMesh(id, buffer); } void Mesh::load(ArchiveBuffer& buffer) { diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index 117205d..20c9905 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -135,10 +135,10 @@ void BasePass::beginFrame(const Component::Camera& cam) { } void BasePass::render() { - /*opaqueCulling->updateBuffer(0, 0, oLightIndexList); - opaqueCulling->updateTexture(1, 0, oLightGrid); - transparentCulling->updateBuffer(0, 0, tLightIndexList); - transparentCulling->updateTexture(1, 0, tLightGrid); + opaqueCulling->updateBuffer(LIGHTINDEX_NAME, 0, oLightIndexList); + opaqueCulling->updateTexture(LIGHTGRID_NAME, 0, oLightGrid); + transparentCulling->updateBuffer(LIGHTINDEX_NAME, 0, tLightIndexList); + transparentCulling->updateTexture(LIGHTGRID_NAME, 0, tLightGrid); opaqueCulling->writeChanges(); transparentCulling->writeChanges(); @@ -153,7 +153,7 @@ void BasePass::render() { // Base Rendering for (VertexData* vertexData : VertexData::getList()) { transparentData.addAll(vertexData->getTransparentData()); - vertexData->getInstanceDataSet()->updateBuffer(6, 0, cullingBuffer); + vertexData->getInstanceDataSet()->updateBuffer(VertexData::CULLINGDATA_NAME, 0, cullingBuffer); vertexData->getInstanceDataSet()->writeChanges(); permutation.setVertexData(vertexData->getTypeName()); const auto& materials = vertexData->getMaterialData(); @@ -231,7 +231,7 @@ void BasePass::render() { Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(VertexData::DrawCallOffsets), &drawCall.offsets); if (graphics->supportMeshShading()) { - command->drawMesh(drawCall.instanceMeshData.size(), 1, 1); + //command->drawMesh(drawCall.instanceMeshData.size(), 1, 1); } else { command->bindIndexBuffer(vertexData->getIndexBuffer()); for (const auto& meshData : drawCall.instanceMeshData) { @@ -247,9 +247,8 @@ void BasePass::render() { //commands.add(waterRenderer->render(viewParamsSet)); //commands.add(terrainRenderer->render(viewParamsSet)); - */ + // Skybox - graphics->beginRenderPass(renderPass); { Gfx::ORenderCommand skyboxCommand = graphics->createRenderCommand("SkyboxRender"); skyboxCommand->setViewport(viewport); @@ -258,8 +257,6 @@ void BasePass::render() { skyboxCommand->draw(36, 1, 0, 0); graphics->executeCommands(std::move(skyboxCommand)); } - graphics->endRenderPass(); - /* // Transparent rendering { permutation.setDepthCulling(false); // ignore visibility infos for transparency @@ -348,7 +345,7 @@ void BasePass::render() { Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(VertexData::DrawCallOffsets), &t.offsets); if (graphics->supportMeshShading()) { - transparentCommand->drawMesh(1, 1, 1); + //transparentCommand->drawMesh(1, 1, 1); } else { // command->bindIndexBuffer(t.vertexData->getIndexBuffer()); // for (const auto& meshData : drawCall.instanceMeshData) { @@ -376,37 +373,40 @@ void BasePass::render() { query->endQuery(); timestamps->write(Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, "BaseEnd"); gDebugVertices.clear(); - */ } void BasePass::endFrame() {} void BasePass::publishOutputs() { - TextureCreateInfo depthBufferInfo = { + basePassDepth = graphics->createTexture2D(TextureCreateInfo{ .format = Gfx::SE_FORMAT_D32_SFLOAT, .width = viewport->getOwner()->getFramebufferWidth(), .height = viewport->getOwner()->getFramebufferHeight(), .usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - }; - basePassDepth = graphics->createTexture2D(depthBufferInfo); + }); - TextureCreateInfo msDepthInfo = { + basePassColor = graphics->createTexture2D(TextureCreateInfo{ + .format = Gfx::SE_FORMAT_R32G32B32A32_SFLOAT, + .width = viewport->getOwner()->getFramebufferWidth(), + .height = viewport->getOwner()->getFramebufferHeight(), + .usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + }); + + msBasePassDepth = graphics->createTexture2D(TextureCreateInfo{ .format = Gfx::SE_FORMAT_D32_SFLOAT, .width = viewport->getOwner()->getFramebufferWidth(), .height = viewport->getOwner()->getFramebufferHeight(), .samples = viewport->getSamples(), .usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, - }; - msBasePassDepth = graphics->createTexture2D(msDepthInfo); - - TextureCreateInfo msBaseColorInfo = { - .format = viewport->getOwner()->getSwapchainFormat(), + }); + + msBasePassColor = graphics->createTexture2D(TextureCreateInfo{ + .format = Gfx::SE_FORMAT_R32G32B32A32_SFLOAT, .width = viewport->getOwner()->getFramebufferWidth(), .height = viewport->getOwner()->getFramebufferHeight(), .samples = viewport->getSamples(), .usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, - }; - msBasePassColor = graphics->createTexture2D(msBaseColorInfo); + }); depthAttachment = Gfx::RenderTargetAttachment(basePassDepth, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, @@ -418,7 +418,7 @@ void BasePass::publishOutputs() { msDepthAttachment.clear.depthStencil.depth = 0.0f; colorAttachment = Gfx::RenderTargetAttachment(viewport, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - Gfx::SE_ATTACHMENT_LOAD_OP_DONT_CARE, Gfx::SE_ATTACHMENT_STORE_OP_DONT_CARE); + Gfx::SE_ATTACHMENT_LOAD_OP_DONT_CARE, Gfx::SE_ATTACHMENT_STORE_OP_STORE); msColorAttachment = Gfx::RenderTargetAttachment(msBasePassColor, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, diff --git a/src/Engine/Graphics/RenderPass/BasePass.h b/src/Engine/Graphics/RenderPass/BasePass.h index be76023..81507cc 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.h +++ b/src/Engine/Graphics/RenderPass/BasePass.h @@ -19,6 +19,7 @@ class BasePass : public RenderPass { virtual void createRenderPass() override; private: + // hdr Gfx::RenderTargetAttachment msColorAttachment; Gfx::RenderTargetAttachment colorAttachment; Gfx::RenderTargetAttachment msDepthAttachment; @@ -37,7 +38,9 @@ class BasePass : public RenderPass { // use a different texture here so we can do multisampling Gfx::OTexture2D msBasePassDepth; Gfx::OTexture2D basePassDepth; + // hdr Gfx::OTexture2D msBasePassColor; + Gfx::OTexture2D basePassColor; // used for transparency sorting Vector cameraPos; diff --git a/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp b/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp index 8a2212e..8b0b44a 100644 --- a/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp +++ b/src/Engine/Graphics/RenderPass/CachedDepthPass.cpp @@ -43,7 +43,7 @@ CachedDepthPass::~CachedDepthPass() {} void CachedDepthPass::beginFrame(const Component::Camera& cam) { RenderPass::beginFrame(cam); } void CachedDepthPass::render() { -/* query->beginQuery(); + query->beginQuery(); timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "CachedBegin"); graphics->beginRenderPass(renderPass); Array commands; @@ -53,7 +53,7 @@ void CachedDepthPass::render() { permutation.setDepthCulling(true); for (VertexData* vertexData : VertexData::getList()) { permutation.setVertexData(vertexData->getTypeName()); - vertexData->getInstanceDataSet()->updateBuffer(6, 0, cullingBuffer); + vertexData->getInstanceDataSet()->updateBuffer(VertexData::CULLINGDATA_NAME, 0, cullingBuffer); vertexData->getInstanceDataSet()->writeChanges(); // Create Pipeline(VertexData) @@ -134,9 +134,8 @@ void CachedDepthPass::render() { graphics->executeCommands(std::move(commands)); graphics->endRenderPass(); - graphics->waitDeviceIdle(); timestamps->write(Gfx::SE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, "CachedEnd"); - query->endQuery();*/ + query->endQuery(); } void CachedDepthPass::endFrame() {} diff --git a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp index f16f33b..0e6190d 100644 --- a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp @@ -68,7 +68,7 @@ DepthCullingPass::~DepthCullingPass() {} void DepthCullingPass::beginFrame(const Component::Camera& cam) { RenderPass::beginFrame(cam); } void DepthCullingPass::render() { - /*query->beginQuery(); + query->beginQuery(); depthAttachment.getTexture()->changeLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL, Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); @@ -125,7 +125,7 @@ void DepthCullingPass::render() { permutation.setDepthCulling(getGlobals().useDepthCulling); for (VertexData* vertexData : VertexData::getList()) { permutation.setVertexData(vertexData->getTypeName()); - vertexData->getInstanceDataSet()->updateBuffer(6, 0, cullingBuffer); + vertexData->getInstanceDataSet()->updateBuffer(VertexData::CULLINGDATA_NAME, 0, cullingBuffer); vertexData->getInstanceDataSet()->writeChanges(); // Create Pipeline(VertexData) // Descriptors: @@ -217,7 +217,7 @@ void DepthCullingPass::render() { // Sync visibility write with compute read visibilityAttachment.getTexture()->pipelineBarrier(Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, - Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);*/ + Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); } void DepthCullingPass::endFrame() {} diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp index 7aeb007..099031d 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp @@ -37,19 +37,19 @@ void LightCullingPass::beginFrame(const Component::Camera& cam) { } void LightCullingPass::render() { - /*query->beginQuery(); + query->beginQuery(); timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "LightCullBegin"); oLightGrid->pipelineBarrier(Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); tLightGrid->pipelineBarrier(Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); - cullingDescriptorSet->updateTexture(0, 0, depthAttachment); - cullingDescriptorSet->updateBuffer(1, 0, oLightIndexCounter); - cullingDescriptorSet->updateBuffer(2, 0, tLightIndexCounter); - cullingDescriptorSet->updateBuffer(3, 0, oLightIndexList); - cullingDescriptorSet->updateBuffer(4, 0, tLightIndexList); - cullingDescriptorSet->updateTexture(5, 0, oLightGrid); - cullingDescriptorSet->updateTexture(6, 0, tLightGrid); + cullingDescriptorSet->updateTexture(DEPTHATTACHMENT_NAME, 0, depthAttachment); + cullingDescriptorSet->updateBuffer(OLIGHTINDEXCOUNTER_NAME, 0, oLightIndexCounter); + cullingDescriptorSet->updateBuffer(TLIGHTINDEXCOUNTER_NAME, 0, tLightIndexCounter); + cullingDescriptorSet->updateBuffer(OLIGHTINDEXLIST_NAME, 0, oLightIndexList); + cullingDescriptorSet->updateBuffer(TLIGHTINDEXLIST_NAME, 0, tLightIndexList); + cullingDescriptorSet->updateTexture(OLIGHTGRID_NAME, 0, oLightGrid); + cullingDescriptorSet->updateTexture(TLIGHTGRID_NAME, 0, tLightGrid); cullingDescriptorSet->writeChanges(); Gfx::OComputeCommand computeCommand = graphics->createComputeCommand("CullingCommand"); if (getGlobals().useLightCulling) { @@ -58,7 +58,7 @@ void LightCullingPass::render() { computeCommand->bindPipeline(cullingPipeline); } computeCommand->bindDescriptor({viewParamsSet, dispatchParamsSet, cullingDescriptorSet, lightEnv->getDescriptorSet()}); - computeCommand->dispatch(dispatchParams.numThreadGroups.x, dispatchParams.numThreadGroups.y, dispatchParams.numThreadGroups.z); + computeCommand->dispatch(numThreadGroups.x, numThreadGroups.y, numThreadGroups.z); Array commands; commands.add(std::move(computeCommand)); // std::cout << "Execute" << std::endl; @@ -72,7 +72,7 @@ void LightCullingPass::render() { oLightGrid->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); tLightGrid->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, - Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);*/ + Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); } void LightCullingPass::endFrame() {} @@ -81,8 +81,8 @@ void LightCullingPass::publishOutputs() { setupFrustums(); uint32_t viewportWidth = viewport->getWidth(); uint32_t viewportHeight = viewport->getHeight(); - UVector4 numThreadGroups = glm::ceil(glm::vec4(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1, 0)); - UVector4 numThreads = numThreadGroups * glm::uvec4(BLOCK_SIZE, BLOCK_SIZE, 1, 0); + numThreadGroups = glm::ceil(glm::vec4(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1, 0)); + numThreads = numThreadGroups * glm::uvec4(BLOCK_SIZE, BLOCK_SIZE, 1, 0); dispatchParamsSet = dispatchParamsLayout->allocateDescriptorSet(); dispatchParamsSet->updateConstants("numThreadGroups", 0, &numThreadGroups); dispatchParamsSet->updateConstants("numThreads", 0, &numThreads); @@ -225,8 +225,8 @@ void LightCullingPass::setupFrustums() { uint32_t viewportWidth = viewport->getWidth(); uint32_t viewportHeight = viewport->getHeight(); - glm::uvec4 numThreads = glm::ceil(glm::vec4(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1, 0)); - glm::uvec4 numThreadGroups = glm::ceil(glm::vec4(numThreads.x / (float)BLOCK_SIZE, numThreads.y / (float)BLOCK_SIZE, 1, 0)); + numThreads = glm::ceil(glm::vec4(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1, 0)); + numThreadGroups = glm::ceil(glm::vec4(numThreads.x / (float)BLOCK_SIZE, numThreads.y / (float)BLOCK_SIZE, 1, 0)); RenderPass::beginFrame(Component::Camera()); diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.h b/src/Engine/Graphics/RenderPass/LightCullingPass.h index e6a3f4d..2bbc662 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.h +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.h @@ -59,7 +59,9 @@ class LightCullingPass : public RenderPass { Gfx::PComputePipeline cullingEnabledPipeline; Gfx::OPipelineStatisticsQuery query; Gfx::PTimestampQuery timestamps; - + UVector4 numThreadGroups; + UVector4 numThreads; + PScene scene; }; DEFINE_REF(LightCullingPass) diff --git a/src/Engine/Graphics/RenderPass/VisibilityPass.cpp b/src/Engine/Graphics/RenderPass/VisibilityPass.cpp index 69b2857..f26ef87 100644 --- a/src/Engine/Graphics/RenderPass/VisibilityPass.cpp +++ b/src/Engine/Graphics/RenderPass/VisibilityPass.cpp @@ -13,11 +13,12 @@ void VisibilityPass::beginFrame(const Component::Camera& cam) { } void VisibilityPass::render() { - /*cullingBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_MESH_SHADER_BIT_EXT, + cullingBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_MESH_SHADER_BIT_EXT, Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT); cullingBuffer->clear(); - cullingBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, + cullingBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, + Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); visibilityDescriptor->reset(); visibilitySet = visibilityDescriptor->allocateDescriptorSet(); @@ -38,7 +39,7 @@ void VisibilityPass::render() { query->endQuery(); cullingBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, - Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT | Gfx::SE_PIPELINE_STAGE_MESH_SHADER_BIT_EXT);*/ + Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT | Gfx::SE_PIPELINE_STAGE_MESH_SHADER_BIT_EXT); } void VisibilityPass::endFrame() {} diff --git a/src/Engine/Graphics/StaticMeshVertexData.cpp b/src/Engine/Graphics/StaticMeshVertexData.cpp index 3f37be1..3457866 100644 --- a/src/Engine/Graphics/StaticMeshVertexData.cpp +++ b/src/Engine/Graphics/StaticMeshVertexData.cpp @@ -53,12 +53,14 @@ void StaticMeshVertexData::loadColors(uint64 offset, const Array& dat dirty = true; } -void StaticMeshVertexData::serializeMesh(MeshId id, uint64 numVertices, ArchiveBuffer& buffer) { - VertexData::serializeMesh(id, numVertices, buffer); +void StaticMeshVertexData::serializeMesh(MeshId id, ArchiveBuffer& buffer) { + VertexData::serializeMesh(id, buffer); uint64 offset; + uint64 numVertices; { std::unique_lock l(vertexDataLock); offset = meshOffsets[id]; + numVertices = meshVertexCounts[id]; } Array tex[MAX_TEXCOORDS]; for (size_t i = 0; i < MAX_TEXCOORDS; ++i) { diff --git a/src/Engine/Graphics/StaticMeshVertexData.h b/src/Engine/Graphics/StaticMeshVertexData.h index 1e50915..ed59ac2 100644 --- a/src/Engine/Graphics/StaticMeshVertexData.h +++ b/src/Engine/Graphics/StaticMeshVertexData.h @@ -25,7 +25,7 @@ class StaticMeshVertexData : public VertexData { void loadTangents(uint64 offset, const Array& data); void loadBitangents(uint64 offset, const Array& data); void loadColors(uint64 offset, const Array& data); - virtual void serializeMesh(MeshId id, uint64 numVertices, ArchiveBuffer& buffer) override; + virtual void serializeMesh(MeshId id, ArchiveBuffer& buffer) override; virtual uint64 deserializeMesh(MeshId id, ArchiveBuffer& buffer) override; virtual void init(Gfx::PGraphics graphics) override; virtual void destroy() override; diff --git a/src/Engine/Graphics/VertexData.cpp b/src/Engine/Graphics/VertexData.cpp index dbc854d..fda6d04 100644 --- a/src/Engine/Graphics/VertexData.cpp +++ b/src/Engine/Graphics/VertexData.cpp @@ -39,8 +39,6 @@ void VertexData::updateMesh(uint32 meshletOffset, PMesh mesh, Component::Transfo std::unique_lock l(materialDataLock); PMaterialInstance referencedInstance = mesh->referencedMaterial->getHandle(); PMaterial mat = referencedInstance->getBaseMaterial(); - const auto& data = meshData[mesh->id]; - Matrix4 transformMatrix = transform.toMatrix() * mesh->transform; InstanceData inst = InstanceData{ .transformMatrix = transformMatrix, @@ -48,26 +46,6 @@ void VertexData::updateMesh(uint32 meshletOffset, PMesh mesh, Component::Transfo }; referencedInstance->updateDescriptor(); - if (mat->hasTransparency()) { - auto params = referencedInstance->getMaterialOffsets(); - transparentData.add(TransparentDraw{ - .matInst = referencedInstance, - .vertexData = this, - .offsets = - { - .instanceOffset = 0, - .textureOffset = params.textureOffset, - .samplerOffset = params.samplerOffset, - .floatOffset = params.floatOffset, - }, - .worldPosition = Vector(inst.transformMatrix[3]), - .instanceData = inst, - .meshData = data, - .cullingOffset = meshletOffset, - .rayTracingScene = mesh->blas, - }); - return; - } if (materialData.size() <= mat->getId()) { materialData.resize(mat->getId() + 1); } @@ -77,50 +55,33 @@ void VertexData::updateMesh(uint32 meshletOffset, PMesh mesh, Component::Transfo matData.instances.resize(referencedInstance->getId() + 1); } BatchedDrawCall& matInstanceData = matData.instances[referencedInstance->getId()]; - matInstanceData.materialInstance = referencedInstance; - matInstanceData.rayTracingData.add(mesh->blas); - matInstanceData.instanceData.add(inst); - matInstanceData.instanceMeshData.add(data); - matInstanceData.cullingOffsets.add(meshletOffset); - - /* for (size_t i = 0; i < 0; ++i) { - auto bounding = meshlets[data.meshletOffset + i].bounding; - StaticArray corners; - Vector min = bounding.min; // bounding.center - bounding.radius * Vector(1, 1, 1); - Vector max = bounding.max; // bounding.center + bounding.radius * Vector(1, 1, 1); - corners[0] = transformMatrix * Vector4(min.x, min.y, min.z, 1); - corners[1] = transformMatrix * Vector4(min.x, min.y, max.z, 1); - corners[2] = transformMatrix * Vector4(min.x, max.y, min.z, 1); - corners[3] = transformMatrix * Vector4(min.x, max.y, max.z, 1); - corners[4] = transformMatrix * Vector4(max.x, min.y, min.z, 1); - corners[5] = transformMatrix * Vector4(max.x, min.y, max.z, 1); - corners[6] = transformMatrix * Vector4(max.x, max.y, min.z, 1); - corners[7] = transformMatrix * Vector4(max.x, max.y, max.z, 1); - addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color}); - addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color}); - }*/ + for (const auto& data : meshData[mesh->id]) { + if (mat->hasTransparency()) { + auto params = referencedInstance->getMaterialOffsets(); + transparentData.add(TransparentDraw{ + .matInst = referencedInstance, + .vertexData = this, + .offsets = + { + .instanceOffset = 0, + .textureOffset = params.textureOffset, + .samplerOffset = params.samplerOffset, + .floatOffset = params.floatOffset, + }, + .worldPosition = Vector(inst.transformMatrix[3]), + .instanceData = inst, + .meshData = data, + .cullingOffset = meshletOffset, + .rayTracingScene = mesh->blas, + }); + } else { // opaque + matInstanceData.materialInstance = referencedInstance; + matInstanceData.rayTracingData.add(mesh->blas); + matInstanceData.instanceData.add(inst); + matInstanceData.instanceMeshData.add(data); + matInstanceData.cullingOffsets.add(meshletOffset); + } + } } void VertexData::createDescriptors() { @@ -177,37 +138,42 @@ void VertexData::createDescriptors() { void VertexData::loadMesh(MeshId id, Array loadedIndices, Array loadedMeshlets) { std::unique_lock l(vertexDataLock); - uint32 meshletOffset = meshlets.size(); - AABB meshAABB; - for (uint32 i = 0; i < loadedMeshlets.size(); ++i) { - Meshlet& m = loadedMeshlets[i]; - meshAABB = meshAABB.combine(m.boundingBox); - uint32 vertexOffset = vertexIndices.size(); - vertexIndices.resize(vertexOffset + m.numVertices); - std::memcpy(vertexIndices.data() + vertexOffset, m.uniqueVertices, m.numVertices * sizeof(uint32)); - uint32 primitiveOffset = primitiveIndices.size(); - primitiveIndices.resize(primitiveOffset + (m.numPrimitives * 3)); - std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8)); - meshlets.add(MeshletDescription{ - .bounding = m.boundingBox, //.toSphere(), - .vertexCount = m.numVertices, - .primitiveCount = m.numPrimitives, - .vertexOffset = vertexOffset, - .primitiveOffset = primitiveOffset, - .color = Vector((float)rand() / RAND_MAX, (float)rand() / RAND_MAX, (float)rand() / RAND_MAX), - .indicesOffset = (uint32)meshOffsets[id], + uint32 numMeshData = (loadedMeshlets.size() + 2047) / 2048; // todo: magic number + for (uint32 n = 0; n < numMeshData; ++n) { + uint32 meshletsToProcess = std::min(loadedMeshlets.size() - n * 2048, 2048); + uint32 meshletOffset = meshlets.size(); + AABB meshAABB; + for (uint32 i = 0; i < meshletsToProcess; ++i) { + Meshlet& m = loadedMeshlets[n * 2048 + i]; + //... + meshAABB = meshAABB.combine(m.boundingBox); + uint32 vertexOffset = vertexIndices.size(); + vertexIndices.resize(vertexOffset + m.numVertices); + std::memcpy(vertexIndices.data() + vertexOffset, m.uniqueVertices, m.numVertices * sizeof(uint32)); + uint32 primitiveOffset = primitiveIndices.size(); + primitiveIndices.resize(primitiveOffset + (m.numPrimitives * 3)); + std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8)); + meshlets.add(MeshletDescription{ + .bounding = m.boundingBox, //.toSphere(), + .vertexCount = m.numVertices, + .primitiveCount = m.numPrimitives, + .vertexOffset = vertexOffset, + .primitiveOffset = primitiveOffset, + .color = Vector((float)rand() / RAND_MAX, (float)rand() / RAND_MAX, (float)rand() / RAND_MAX), + .indicesOffset = (uint32)meshOffsets[id], + }); + } + meshData[id].add(MeshData{ + .bounding = meshAABB, //.toSphere(), + .numMeshlets = (uint32)meshletsToProcess, + .meshletOffset = meshletOffset, }); } - meshData[id] = MeshData{ - .bounding = meshAABB, //.toSphere(), - .numMeshlets = (uint32)loadedMeshlets.size(), - .meshletOffset = meshletOffset, - .firstIndex = (uint32)indices.size(), - .numIndices = (uint32)loadedIndices.size(), - }; - + // todo: in case of a index split for 16 bit, do something here + meshData[id][0].firstIndex = (uint32)indices.size(); + meshData[id][0].numIndices = (uint32)loadedIndices.size(); indices.resize(indices.size() + loadedIndices.size()); - std::memcpy(indices.data() + meshData[id].firstIndex, loadedIndices.data(), loadedIndices.size() * sizeof(uint32)); + std::memcpy(indices.data() + meshData[id][0].firstIndex, loadedIndices.data(), loadedIndices.size() * sizeof(uint32)); } void VertexData::commitMeshes() { @@ -268,22 +234,24 @@ MeshId VertexData::allocateVertexData(uint64 numVertices) { return res; } -void VertexData::serializeMesh(MeshId id, uint64, ArchiveBuffer& buffer) { +void VertexData::serializeMesh(MeshId id, ArchiveBuffer& buffer) { std::unique_lock l(vertexDataLock); Array out; - MeshData data = meshData[id]; - for (size_t i = 0; i < data.numMeshlets; ++i) { - MeshletDescription& desc = meshlets[i + data.meshletOffset]; - Meshlet m; - std::memcpy(m.uniqueVertices, &vertexIndices[desc.vertexOffset], desc.vertexCount * sizeof(uint32)); - std::memcpy(m.primitiveLayout, &primitiveIndices[desc.primitiveOffset], desc.primitiveCount * 3 * sizeof(uint8)); - m.numPrimitives = desc.primitiveCount; - m.numVertices = desc.vertexCount; - m.boundingBox = desc.bounding; - out.add(std::move(m)); + for (uint32 n = 0; n < meshData[id].size(); ++n) { + MeshData data = meshData[id][n]; + for (size_t i = 0; i < data.numMeshlets; ++i) { + MeshletDescription& desc = meshlets[i + data.meshletOffset]; + Meshlet m; + std::memcpy(m.uniqueVertices, &vertexIndices[desc.vertexOffset], desc.vertexCount * sizeof(uint32)); + std::memcpy(m.primitiveLayout, &primitiveIndices[desc.primitiveOffset], desc.primitiveCount * 3 * sizeof(uint8)); + m.numPrimitives = desc.primitiveCount; + m.numVertices = desc.vertexCount; + m.boundingBox = desc.bounding; + out.add(std::move(m)); + } } - Array ind(data.numIndices); - std::memcpy(ind.data(), &indices[data.firstIndex], data.numIndices * sizeof(uint32)); + Array ind(meshData[id][0].numIndices); + std::memcpy(ind.data(), &indices[meshData[id][0].firstIndex], meshData[id][0].numIndices * sizeof(uint32)); Serialization::save(buffer, out); Serialization::save(buffer, ind); } @@ -383,7 +351,9 @@ void VertexData::destroy() { uint32 VertexData::addCullingMapping(MeshId id) { uint32 result = meshletCount; - meshletCount += getMeshData(id).numMeshlets; + for (const auto& md : getMeshData(id)) { + meshletCount += md.numMeshlets; + } return result; } diff --git a/src/Engine/Graphics/VertexData.h b/src/Engine/Graphics/VertexData.h index a4419bf..139fa50 100644 --- a/src/Engine/Graphics/VertexData.h +++ b/src/Engine/Graphics/VertexData.h @@ -62,7 +62,7 @@ class VertexData { MeshId allocateVertexData(uint64 numVertices); uint64 getMeshOffset(MeshId id) const { return meshOffsets[id]; } uint64 getMeshVertexCount(MeshId id) { return meshVertexCounts[id]; } - virtual void serializeMesh(MeshId id, uint64 numVertices, ArchiveBuffer& buffer); + virtual void serializeMesh(MeshId id, ArchiveBuffer& buffer); virtual uint64 deserializeMesh(MeshId id, ArchiveBuffer& buffer); virtual void bindBuffers(Gfx::PRenderCommand command) = 0; virtual Gfx::PDescriptorLayout getVertexDataLayout() = 0; @@ -76,7 +76,7 @@ class VertexData { const Array& getMaterialData() const { return materialData; } const Array& getTransparentData() const { return transparentData; } const Array& getRayTracingData() const { return rayTracingScene; } - const MeshData& getMeshData(MeshId id) const { return meshData[id]; } + const Array& getMeshData(MeshId id) const { return meshData[id]; } void registerBottomLevelAccelerationStructure(Gfx::PBottomLevelAS blas) { dataToBuild.add(blas); } @@ -89,6 +89,7 @@ class VertexData { uint32 addCullingMapping(MeshId id); static uint64 getMeshletCount() { return meshletCount; } + constexpr static const char* CULLINGDATA_NAME = "cullingData"; protected: virtual void resizeBuffers() = 0; @@ -113,7 +114,8 @@ class VertexData { Array transparentData; std::mutex vertexDataLock; - Array meshData; + // each mesh id can have multiple meshdata, in case it needs to be split for having too many meshlets + Array> meshData; Array meshOffsets; Array meshVertexCounts; @@ -135,7 +137,6 @@ class VertexData { constexpr static const char* PRIMITIVEINDICES_NAME = "primitiveIndices"; Gfx::OShaderBuffer cullingOffsetBuffer; constexpr static const char* CULLINGOFFSETS_NAME = "cullingOffsets"; - constexpr static const char* CULLINGDATA_NAME = "cullingData"; // for legacy pipeline Gfx::OIndexBuffer indexBuffer; diff --git a/src/Engine/Graphics/Vulkan/RayTracing.cpp b/src/Engine/Graphics/Vulkan/RayTracing.cpp index e9370e7..1b4fb4e 100644 --- a/src/Engine/Graphics/Vulkan/RayTracing.cpp +++ b/src/Engine/Graphics/Vulkan/RayTracing.cpp @@ -22,7 +22,8 @@ BottomLevelAS::BottomLevelAS(PGraphics graphics, const Gfx::BottomLevelASCreateI 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, }; VertexData* vertexData = createInfo.mesh->vertexData; - MeshData meshData = vertexData->getMeshData(createInfo.mesh->id); + //todo: indices might be split as well + MeshData meshData = vertexData->getMeshData(createInfo.mesh->id)[0]; vertexOffset = vertexData->getMeshOffset(createInfo.mesh->id) * sizeof(Vector); vertexCount = vertexData->getMeshVertexCount(createInfo.mesh->id); indexOffset = meshData.firstIndex * sizeof(uint32); diff --git a/src/Engine/Graphics/slang-compile.cpp b/src/Engine/Graphics/slang-compile.cpp index fb689d3..55d8494 100644 --- a/src/Engine/Graphics/slang-compile.cpp +++ b/src/Engine/Graphics/slang-compile.cpp @@ -55,7 +55,7 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg .value = { .kind = slang::CompilerOptionValueKind::Int, - .intValue0 = SLANG_DEBUG_INFO_LEVEL_NONE, + .intValue0 = SLANG_DEBUG_INFO_LEVEL_STANDARD, }, }, { From a957b0561593df6d4bd9eb5a7179c2b466552b0d Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Mon, 10 Mar 2025 18:35:35 +0100 Subject: [PATCH 3/3] adding basic tone mapping --- res/shaders/DepthCullingTask.slang | 4 +- res/shaders/FullscreenQuad.slang | 15 +++ res/shaders/LegacyPass.slang | 2 +- res/shaders/ToneMapping.slang | 117 ++++++++++++++++++ src/Benchmark/main.cpp | 1 - src/Editor/Asset/TextureLoader.cpp | 2 +- src/Editor/main.cpp | 9 +- src/Engine/Graphics/Initializer.h | 1 - src/Engine/Graphics/RenderPass/BasePass.cpp | 24 ++-- src/Engine/Graphics/RenderPass/CMakeLists.txt | 3 + .../Graphics/RenderPass/TerrainRenderer.cpp | 2 +- .../Graphics/RenderPass/ToneMappingPass.cpp | 112 +++++++++++++++++ .../Graphics/RenderPass/ToneMappingPass.h | 33 +++++ .../Graphics/RenderPass/WaterRenderer.cpp | 2 +- src/Engine/Graphics/RenderTarget.h | 3 +- src/Engine/Graphics/VertexData.cpp | 13 +- src/Engine/Graphics/Vulkan/RenderPass.cpp | 2 +- src/Engine/Graphics/Window.cpp | 2 +- src/Engine/Graphics/Window.h | 2 - src/Engine/Window/GameView.cpp | 2 + 20 files changed, 314 insertions(+), 37 deletions(-) create mode 100644 res/shaders/FullscreenQuad.slang create mode 100644 res/shaders/ToneMapping.slang create mode 100644 src/Engine/Graphics/RenderPass/ToneMappingPass.cpp create mode 100644 src/Engine/Graphics/RenderPass/ToneMappingPass.h diff --git a/res/shaders/DepthCullingTask.slang b/res/shaders/DepthCullingTask.slang index e98a2ac..1269b05 100644 --- a/res/shaders/DepthCullingTask.slang +++ b/res/shaders/DepthCullingTask.slang @@ -123,11 +123,11 @@ void taskMain( if(!culling.wasVisible()) { // if the meshlet is outside of the frustum, we skip it since we cant do depth culling anyways - if(meshlet.bounding.insideFrustum(viewFrustum)) + //if(meshlet.bounding.insideFrustum(viewFrustum)) { #ifdef DEPTH_CULLING // if the meshlet bounding box is behind the cached depth buffer, we skip - if(isBoxVisible(meshlet.bounding)) + //if(isBoxVisible(meshlet.bounding)) #endif { uint index; diff --git a/res/shaders/FullscreenQuad.slang b/res/shaders/FullscreenQuad.slang new file mode 100644 index 0000000..ada8674 --- /dev/null +++ b/res/shaders/FullscreenQuad.slang @@ -0,0 +1,15 @@ +struct QuadOutput +{ + float2 uv : UV; + float4 position : SV_Position; +} + +[shader("vertex")] +QuadOutput quadMain(uint vertexIndex : SV_VertexID) +{ + QuadOutput result; + result.uv = float2((vertexIndex << 1) & 2, vertexIndex & 2); + result.position = float4(result.uv * 2.0f + -1.0f, 0.0f, 1.0f); + result.uv.y = 1 - result.uv.y; + return result; +} \ No newline at end of file diff --git a/res/shaders/LegacyPass.slang b/res/shaders/LegacyPass.slang index 5038305..7bbe099 100644 --- a/res/shaders/LegacyPass.slang +++ b/res/shaders/LegacyPass.slang @@ -10,5 +10,5 @@ FragmentParameter vertexMain( ){ InstanceData inst = pScene.instances[input.instanceId]; VertexAttributes attr = pVertexData.getAttributes(input.vertexId); - return attr.getParameter(inst.transformMatrix); + return attr.getParameter(inst.transformMatrix, inst.inverseTransformMatrix); } \ No newline at end of file diff --git a/res/shaders/ToneMapping.slang b/res/shaders/ToneMapping.slang new file mode 100644 index 0000000..242be48 --- /dev/null +++ b/res/shaders/ToneMapping.slang @@ -0,0 +1,117 @@ +// MIT License +// +// Copyright (c) 2024 Missing Deadlines (Benjamin Wrensch) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// All values used to derive this implementation are sourced from Troy�s initial AgX implementation/OCIO config file available here: +// https://github.com/sobotka/AgX + +struct Parameters +{ + float4 offset = float4(0.0); + float4 slope = float4(1.0); + float4 power = float4(1.0); + float sat = 1.0; + Texture2D hdrInputTexture; + SamplerState hdrSampler; +}; +ParameterBlock pParams; + +// AgX +// -> + +// Mean error^2: 3.6705141e-06 +float3 agxDefaultContrastApprox(float3 x) { + float3 x2 = x * x; + float3 x4 = x2 * x2; + + return + 15.5 * x4 * x2 + - 40.14 * x4 * x + + 31.96 * x4 + - 6.868 * x2 * x + + 0.4298 * x2 + + 0.1191 * x + - 0.00232; +} + +float3 agx(float3 val) { + const float3x3 agx_mat = transpose(float3x3( + 0.842479062253094, 0.0423282422610123, 0.0423756549057051, + 0.0784335999999992, 0.878468636469772, 0.0784336, + 0.0792237451477643, 0.0791661274605434, 0.879142973793104)); + + const float min_ev = -12.47393f; + const float max_ev = 4.026069f; + + // Input transform + val = mul(agx_mat, val); + + // Log2 space encoding + val = clamp(log2(val), min_ev, max_ev); + val = (val - min_ev) / (max_ev - min_ev); + + // Apply sigmoid function approximation + val = agxDefaultContrastApprox(val); + + return val; +} + +float3 agxEotf(float3 val) { + const float3x3 agx_mat_inv = transpose(float3x3( + 1.19687900512017, -0.0528968517574562, -0.0529716355144438, + -0.0980208811401368, 1.15190312990417, -0.0980434501171241, + -0.0990297440797205, -0.0989611768448433, 1.15107367264116)); + + // Undo input transform + val = mul(agx_mat_inv, val); + + // sRGB IEC 61966-2-1 2.2 Exponent Reference EOTF Display + //val = pow(val, float3(2.2)); + + return val; +} + +float3 agxLook(float3 val) { + const float3 lw = float3(0.2126, 0.7152, 0.0722); + float luma = dot(val, lw); + + // Default + float3 offset = pParams.offset.xyz; + float3 slope = pParams.slope.xyz; + float3 power = pParams.power.xyz; + float sat = pParams.sat; + + // ASC CDL + val = pow(val * slope + offset, power); + return luma + sat * (val - luma); +} + +[shader("pixel")] +float4 toneMapping(float2 uv : UV) : SV_Target +{ + float3 hdrValue = pParams.hdrInputTexture.Sample(pParams.hdrSampler, uv).rgb; + //float3 value = agx(hdrValue); + //value = agxLook(value); + //value = agxEotf(value); + + float3 value = hdrValue / (hdrValue + float3(10)); + + return float4(value, 1); +} \ No newline at end of file diff --git a/src/Benchmark/main.cpp b/src/Benchmark/main.cpp index 172af20..695e3d8 100644 --- a/src/Benchmark/main.cpp +++ b/src/Benchmark/main.cpp @@ -56,7 +56,6 @@ int main(int argc, char** argv) { .size = {1920, 1080}, .offset = {0, 0}, }, - .numSamples = Gfx::SE_SAMPLE_COUNT_4_BIT, }; OGameView sceneView = new PlayView(graphics, window, sceneViewInfo, binaryPath.generic_string(), useDepthCulling); sceneView->setFocused(); diff --git a/src/Editor/Asset/TextureLoader.cpp b/src/Editor/Asset/TextureLoader.cpp index 8330c32..bf24c20 100644 --- a/src/Editor/Asset/TextureLoader.cpp +++ b/src/Editor/Asset/TextureLoader.cpp @@ -60,7 +60,7 @@ void TextureLoader::import(TextureImportArgs args, PTextureAsset textureAsset) { int totalWidth = 0, totalHeight = 0, n = 0; unsigned char* data = stbi_load(args.filePath.string().c_str(), &totalWidth, &totalHeight, &n, 4); ktxTexture2* kTexture = nullptr; - VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; + VkFormat format = VK_FORMAT_R8G8B8A8_SRGB; ktxTextureCreateInfo createInfo = { .vkFormat = (uint32)format, .baseDepth = 1, diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index 036d38f..5f0053f 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -112,10 +112,10 @@ int main() { // AssetImporter::importTexture(TextureImportArgs{ // .filePath = sourcePath / "import/textures/wgen.png", //}); - // AssetImporter::importMesh(MeshImportArgs{ - // .filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.glb", - // .importPath = "Whitechapel", - //}); + AssetImporter::importMesh(MeshImportArgs{ + .filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.glb", + .importPath = "Whitechapel", + }); //AssetImporter::importMesh(MeshImportArgs{ // .filePath = sourcePath / "import/models/box.glb", // .importPath = "", @@ -143,7 +143,6 @@ int main() { .size = {1920, 1080}, .offset = {0, 0}, }, - .numSamples = Gfx::SE_SAMPLE_COUNT_4_BIT, }; OGameView sceneView = new Editor::PlayView(graphics, window, sceneViewInfo, binaryPath.generic_string()); sceneView->setFocused(); diff --git a/src/Engine/Graphics/Initializer.h b/src/Engine/Graphics/Initializer.h index 7ab9916..4889cb8 100644 --- a/src/Engine/Graphics/Initializer.h +++ b/src/Engine/Graphics/Initializer.h @@ -35,7 +35,6 @@ struct WindowCreateInfo { struct ViewportCreateInfo { URect dimensions; float fieldOfView = glm::radians(70.0f); - Gfx::SeSampleCountFlags numSamples; }; // doesnt own the data, only proxy it struct DataSource { diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index 20c9905..bf215e2 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -189,7 +189,7 @@ void BasePass::render() { .pipelineLayout = collection->pipelineLayout, .multisampleState = { - .samples = viewport->getSamples(), + .samples = msColorAttachment.getNumSamples(), }, .rasterizationState = { @@ -210,7 +210,7 @@ void BasePass::render() { .pipelineLayout = collection->pipelineLayout, .multisampleState = { - .samples = viewport->getSamples(), + .samples = msColorAttachment.getNumSamples(), }, .rasterizationState = { @@ -231,7 +231,7 @@ void BasePass::render() { Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(VertexData::DrawCallOffsets), &drawCall.offsets); if (graphics->supportMeshShading()) { - //command->drawMesh(drawCall.instanceMeshData.size(), 1, 1); + command->drawMesh(drawCall.instanceMeshData.size(), 1, 1); } else { command->bindIndexBuffer(vertexData->getIndexBuffer()); for (const auto& meshData : drawCall.instanceMeshData) { @@ -287,7 +287,7 @@ void BasePass::render() { .pipelineLayout = collection->pipelineLayout, .multisampleState = { - .samples = viewport->getSamples(), + .samples = msColorAttachment.getNumSamples(), }, .rasterizationState = { @@ -314,7 +314,7 @@ void BasePass::render() { .pipelineLayout = collection->pipelineLayout, .multisampleState = { - .samples = viewport->getSamples(), + .samples = msColorAttachment.getNumSamples(), }, .rasterizationState = { @@ -345,7 +345,7 @@ void BasePass::render() { Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(VertexData::DrawCallOffsets), &t.offsets); if (graphics->supportMeshShading()) { - //transparentCommand->drawMesh(1, 1, 1); + transparentCommand->drawMesh(1, 1, 1); } else { // command->bindIndexBuffer(t.vertexData->getIndexBuffer()); // for (const auto& meshData : drawCall.instanceMeshData) { @@ -396,7 +396,7 @@ void BasePass::publishOutputs() { .format = Gfx::SE_FORMAT_D32_SFLOAT, .width = viewport->getOwner()->getFramebufferWidth(), .height = viewport->getOwner()->getFramebufferHeight(), - .samples = viewport->getSamples(), + .samples = Gfx::SE_SAMPLE_COUNT_4_BIT, .usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, }); @@ -404,7 +404,7 @@ void BasePass::publishOutputs() { .format = Gfx::SE_FORMAT_R32G32B32A32_SFLOAT, .width = viewport->getOwner()->getFramebufferWidth(), .height = viewport->getOwner()->getFramebufferHeight(), - .samples = viewport->getSamples(), + .samples = Gfx::SE_SAMPLE_COUNT_4_BIT, // todo: configure .usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, }); @@ -417,7 +417,7 @@ void BasePass::publishOutputs() { Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_DONT_CARE); msDepthAttachment.clear.depthStencil.depth = 0.0f; - colorAttachment = Gfx::RenderTargetAttachment(viewport, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + colorAttachment = Gfx::RenderTargetAttachment(basePassColor, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, Gfx::SE_ATTACHMENT_LOAD_OP_DONT_CARE, Gfx::SE_ATTACHMENT_STORE_OP_STORE); msColorAttachment = @@ -437,7 +437,7 @@ void BasePass::publishOutputs() { } void BasePass::createRenderPass() { - RenderPass::beginFrame(Component::Camera()); + //RenderPass::beginFrame(Component::Camera()); //terrainRenderer = new TerrainRenderer(graphics, scene, viewParamsLayout, viewParamsSet); cullingBuffer = resources->requestBuffer("CULLINGBUFFER"); timestamps = resources->requestTimestampQuery("TIMESTAMPS"); @@ -538,7 +538,7 @@ void BasePass::createRenderPass() { .pipelineLayout = debugPipelineLayout, .multisampleState = { - .samples = viewport->getSamples(), + .samples = msColorAttachment.getNumSamples(), }, .rasterizationState = { @@ -612,7 +612,7 @@ void BasePass::createRenderPass() { .pipelineLayout = pipelineLayout, .multisampleState = { - .samples = viewport->getSamples(), + .samples = msColorAttachment.getNumSamples(), }, .rasterizationState = { diff --git a/src/Engine/Graphics/RenderPass/CMakeLists.txt b/src/Engine/Graphics/RenderPass/CMakeLists.txt index 06165ce..7102259 100644 --- a/src/Engine/Graphics/RenderPass/CMakeLists.txt +++ b/src/Engine/Graphics/RenderPass/CMakeLists.txt @@ -17,6 +17,8 @@ target_sources(Engine RenderPass.cpp TerrainRenderer.h TerrainRenderer.cpp + ToneMappingPass.h + ToneMappingPass.cpp UIPass.h UIPass.cpp VisibilityPass.h @@ -31,6 +33,7 @@ target_sources(Engine CachedDepthPass.h DepthCullingPass.h LightCullingPass.h + ToneMappingPass.h RayTracingPass.h RenderGraph.h RenderGraphResources.h diff --git a/src/Engine/Graphics/RenderPass/TerrainRenderer.cpp b/src/Engine/Graphics/RenderPass/TerrainRenderer.cpp index d5cc386..045a2b4 100644 --- a/src/Engine/Graphics/RenderPass/TerrainRenderer.cpp +++ b/src/Engine/Graphics/RenderPass/TerrainRenderer.cpp @@ -297,7 +297,7 @@ void TerrainRenderer::setViewport(Gfx::PViewport _viewport, Gfx::PRenderPass ren .pipelineLayout = meshUpdater.pipelineLayout, .multisampleState = { - .samples = viewport->getSamples(), + .samples = Gfx::SE_SAMPLE_COUNT_1_BIT, }, .rasterizationState = { diff --git a/src/Engine/Graphics/RenderPass/ToneMappingPass.cpp b/src/Engine/Graphics/RenderPass/ToneMappingPass.cpp new file mode 100644 index 0000000..6ba084b --- /dev/null +++ b/src/Engine/Graphics/RenderPass/ToneMappingPass.cpp @@ -0,0 +1,112 @@ +#include "ToneMappingPass.h" + +using namespace Seele; + +ToneMappingPass::ToneMappingPass(Gfx::PGraphics graphics) : RenderPass(graphics) { + layout = graphics->createDescriptorLayout("ToneMappingDescriptor"); + layout->addDescriptorBinding(Gfx::DescriptorBinding{ + .name = "offset", + .uniformLength = sizeof(Vector4), + }); + layout->addDescriptorBinding(Gfx::DescriptorBinding{ + .name = "slope", + .uniformLength = sizeof(Vector4), + }); + layout->addDescriptorBinding(Gfx::DescriptorBinding{ + .name = "power", + .uniformLength = sizeof(Vector4), + }); + layout->addDescriptorBinding(Gfx::DescriptorBinding{ + .name = "sat", + .uniformLength = sizeof(float), + }); + layout->addDescriptorBinding(Gfx::DescriptorBinding{ + .name = "hdrInputTexture", + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + }); + layout->addDescriptorBinding(Gfx::DescriptorBinding{ + .name = "hdrSampler", + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER, + }); + layout->create(); + pipelineLayout = graphics->createPipelineLayout("ToneMappingLayout"); + pipelineLayout->addDescriptorLayout(layout); + graphics->beginShaderCompilation(ShaderCompilationInfo{ + .name = "ToneMapping", + .modules = {"FullScreenQuad", "ToneMapping"}, + .entryPoints = {{"quadMain", "FullScreenQuad"}, {"toneMapping", "ToneMapping"}}, + .rootSignature = pipelineLayout, + }); + pipelineLayout->create(); + vert = graphics->createVertexShader({0}); + frag = graphics->createFragmentShader({1}); + sampler = graphics->createSampler({}); +} + +ToneMappingPass::~ToneMappingPass() {} + +void ToneMappingPass::beginFrame(const Component::Camera& cam) { RenderPass::beginFrame(cam); } + +void ToneMappingPass::render() { + hdrInputTexture.getTexture()->changeLayout(Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, + Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + layout->reset(); + set = layout->allocateDescriptorSet(); + set->updateTexture("hdrInputTexture", 0, hdrInputTexture.getTexture()); + set->updateSampler("hdrSampler", 0, sampler); + set->writeChanges(); + graphics->beginRenderPass(renderPass); + Gfx::ORenderCommand command = graphics->createRenderCommand("ToneMapping"); + command->setViewport(viewport); + command->bindPipeline(pipeline); + command->bindDescriptor({set}); + command->draw(3, 1, 0, 0); + graphics->executeCommands(std::move(command)); + graphics->endRenderPass(); +} + +void ToneMappingPass::endFrame() {} + +void ToneMappingPass::publishOutputs() { + colorAttachment = Gfx::RenderTargetAttachment(viewport, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + Gfx::SE_ATTACHMENT_LOAD_OP_DONT_CARE, Gfx::SE_ATTACHMENT_STORE_OP_STORE); + resources->registerRenderPassOutput("TONEMAPPING_COLOR", colorAttachment); +} + +void ToneMappingPass::createRenderPass() { + hdrInputTexture = resources->requestRenderTarget("BASEPASS_COLOR"); + Gfx::RenderTargetLayout targetLayout = Gfx::RenderTargetLayout{ + .colorAttachments = {colorAttachment}, + }; + Array dependency = { + { + .srcSubpass = ~0U, + .dstSubpass = 0, + .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + .dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + }, + { + .srcSubpass = 0, + .dstSubpass = ~0U, + .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + .dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + }, + }; + renderPass = graphics->createRenderPass(targetLayout, dependency, viewport, "ToneMappingPass"); + pipeline = graphics->createGraphicsPipeline(Gfx::LegacyPipelineCreateInfo{ + .vertexShader = vert, + .fragmentShader = frag, + .renderPass = renderPass, + .pipelineLayout = pipelineLayout, + .colorBlend = + { + .attachmentCount = 1, + }, + }); +} diff --git a/src/Engine/Graphics/RenderPass/ToneMappingPass.h b/src/Engine/Graphics/RenderPass/ToneMappingPass.h new file mode 100644 index 0000000..6a41dd6 --- /dev/null +++ b/src/Engine/Graphics/RenderPass/ToneMappingPass.h @@ -0,0 +1,33 @@ +#pragma once +#include "RenderPass.h" +#include "Graphics/Shader.h" + +namespace Seele +{ +class ToneMappingPass : public RenderPass { + public: + ToneMappingPass(Gfx::PGraphics graphics); + ToneMappingPass(ToneMappingPass&&) = default; + ToneMappingPass& operator=(ToneMappingPass&&) = default; + virtual ~ToneMappingPass(); + virtual void beginFrame(const Component::Camera& cam) override; + virtual void render() override; + virtual void endFrame() override; + virtual void publishOutputs() override; + virtual void createRenderPass() override; + + private: + // non-hdr swapchain output + Gfx::RenderTargetAttachment colorAttachment; + + Gfx::RenderTargetAttachment hdrInputTexture; + Gfx::OSampler sampler; + + Gfx::ODescriptorLayout layout; + Gfx::PDescriptorSet set; + Gfx::OPipelineLayout pipelineLayout; + Gfx::OVertexShader vert; + Gfx::OFragmentShader frag; + Gfx::PGraphicsPipeline pipeline; +}; +} \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/WaterRenderer.cpp b/src/Engine/Graphics/RenderPass/WaterRenderer.cpp index 58c4c5a..785b0a2 100644 --- a/src/Engine/Graphics/RenderPass/WaterRenderer.cpp +++ b/src/Engine/Graphics/RenderPass/WaterRenderer.cpp @@ -458,7 +458,7 @@ void WaterRenderer::setViewport(Gfx::PViewport _viewport, Gfx::PRenderPass rende .pipelineLayout = waterLayout, .multisampleState = { - .samples = viewport->getSamples(), + .samples = Gfx::SE_SAMPLE_COUNT_4_BIT, }, .rasterizationState = { diff --git a/src/Engine/Graphics/RenderTarget.h b/src/Engine/Graphics/RenderTarget.h index 6468c1e..6aed4b4 100644 --- a/src/Engine/Graphics/RenderTarget.h +++ b/src/Engine/Graphics/RenderTarget.h @@ -35,7 +35,8 @@ class RenderTargetAttachment { } SeSampleCountFlags getNumSamples() const { if (viewport != nullptr) { - return viewport->getSamples(); + // viewport backbuffers are not multisampled themselves + return Gfx::SE_SAMPLE_COUNT_1_BIT; } return texture->getNumSamples(); } diff --git a/src/Engine/Graphics/VertexData.cpp b/src/Engine/Graphics/VertexData.cpp index fda6d04..fa4e401 100644 --- a/src/Engine/Graphics/VertexData.cpp +++ b/src/Engine/Graphics/VertexData.cpp @@ -55,6 +55,7 @@ void VertexData::updateMesh(uint32 meshletOffset, PMesh mesh, Component::Transfo matData.instances.resize(referencedInstance->getId() + 1); } BatchedDrawCall& matInstanceData = matData.instances[referencedInstance->getId()]; + matInstanceData.materialInstance = referencedInstance; for (const auto& data : meshData[mesh->id]) { if (mat->hasTransparency()) { auto params = referencedInstance->getMaterialOffsets(); @@ -75,7 +76,6 @@ void VertexData::updateMesh(uint32 meshletOffset, PMesh mesh, Component::Transfo .rayTracingScene = mesh->blas, }); } else { // opaque - matInstanceData.materialInstance = referencedInstance; matInstanceData.rayTracingData.add(mesh->blas); matInstanceData.instanceData.add(inst); matInstanceData.instanceMeshData.add(data); @@ -138,13 +138,12 @@ void VertexData::createDescriptors() { void VertexData::loadMesh(MeshId id, Array loadedIndices, Array loadedMeshlets) { std::unique_lock l(vertexDataLock); - uint32 numMeshData = (loadedMeshlets.size() + 2047) / 2048; // todo: magic number - for (uint32 n = 0; n < numMeshData; ++n) { - uint32 meshletsToProcess = std::min(loadedMeshlets.size() - n * 2048, 2048); + for (auto&& chunk : loadedMeshlets | std::views::chunk(2048)) { uint32 meshletOffset = meshlets.size(); AABB meshAABB; - for (uint32 i = 0; i < meshletsToProcess; ++i) { - Meshlet& m = loadedMeshlets[n * 2048 + i]; + uint32 numMeshlets = 0; + for (auto&& m : chunk) { + numMeshlets++; //... meshAABB = meshAABB.combine(m.boundingBox); uint32 vertexOffset = vertexIndices.size(); @@ -165,7 +164,7 @@ void VertexData::loadMesh(MeshId id, Array loadedIndices, Array } meshData[id].add(MeshData{ .bounding = meshAABB, //.toSphere(), - .numMeshlets = (uint32)meshletsToProcess, + .numMeshlets = numMeshlets, .meshletOffset = meshletOffset, }); } diff --git a/src/Engine/Graphics/Vulkan/RenderPass.cpp b/src/Engine/Graphics/Vulkan/RenderPass.cpp index f135df6..613ddcf 100644 --- a/src/Engine/Graphics/Vulkan/RenderPass.cpp +++ b/src/Engine/Graphics/Vulkan/RenderPass.cpp @@ -172,7 +172,7 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::RenderTargetLayout _layout, Arra .colorAttachmentCount = (uint32)colorRefs.size(), .pColorAttachments = colorRefs.data(), .pResolveAttachments = resolveRefs.size() > 0 ? resolveRefs.data() : nullptr, - .pDepthStencilAttachment = &depthRef, + .pDepthStencilAttachment = layout.depthAttachment.getTexture() != nullptr ? &depthRef : nullptr, }; Array dep; for (const auto& d : dependencies) { diff --git a/src/Engine/Graphics/Window.cpp b/src/Engine/Graphics/Window.cpp index 960e4db..70bd098 100644 --- a/src/Engine/Graphics/Window.cpp +++ b/src/Engine/Graphics/Window.cpp @@ -10,7 +10,7 @@ Window::~Window() {} Viewport::Viewport(PWindow owner, const ViewportCreateInfo& viewportInfo) : sizeX(std::min(owner->getFramebufferWidth(), viewportInfo.dimensions.size.x)), sizeY(std::min(owner->getFramebufferHeight(), viewportInfo.dimensions.size.y)), offsetX(viewportInfo.dimensions.offset.x), - offsetY(viewportInfo.dimensions.offset.y), fieldOfView(viewportInfo.fieldOfView), samples(viewportInfo.numSamples), owner(owner) {} + offsetY(viewportInfo.dimensions.offset.y), fieldOfView(viewportInfo.fieldOfView), owner(owner) {} Viewport::~Viewport() {} diff --git a/src/Engine/Graphics/Window.h b/src/Engine/Graphics/Window.h index 87eeecb..11dfded 100644 --- a/src/Engine/Graphics/Window.h +++ b/src/Engine/Graphics/Window.h @@ -52,7 +52,6 @@ class Viewport { constexpr uint32 getOffsetY() const { return offsetY; } constexpr float getContentScaleX() const { return owner->getContentScaleX(); } constexpr float getContentScaleY() const { return owner->getContentScaleY(); } - constexpr Gfx::SeSampleCountFlags getSamples() const { return samples; } Matrix4 getProjectionMatrix() const; protected: @@ -61,7 +60,6 @@ class Viewport { uint32 offsetX; uint32 offsetY; float fieldOfView; - Gfx::SeSampleCountFlags samples; PWindow owner; }; DEFINE_REF(Viewport) diff --git a/src/Engine/Window/GameView.cpp b/src/Engine/Window/GameView.cpp index 8fae9fb..2b6582b 100644 --- a/src/Engine/Window/GameView.cpp +++ b/src/Engine/Window/GameView.cpp @@ -11,6 +11,7 @@ #include "Graphics/RenderPass/RayTracingPass.h" #include "Graphics/RenderPass/RenderGraphResources.h" #include "Graphics/RenderPass/VisibilityPass.h" +#include "Graphics/RenderPass/ToneMappingPass.h" #include "System/CameraUpdater.h" #include "System/LightGather.h" #include "System/MeshUpdater.h" @@ -26,6 +27,7 @@ GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate renderGraph.addPass(new VisibilityPass(graphics)); renderGraph.addPass(new LightCullingPass(graphics, scene)); renderGraph.addPass(new BasePass(graphics, scene)); + renderGraph.addPass(new ToneMappingPass(graphics)); renderGraph.setViewport(viewport); renderGraph.createRenderPass(); if (graphics->supportRayTracing()) {