From e97beda2bc1262958a33c85555184ef6060965ce Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Fri, 5 Sep 2025 07:10:27 +0200 Subject: [PATCH] Fixing command resource binding --- res/shaders/EnvironmentMapping.slang | 2 +- src/Editor/Asset/EnvironmentLoader.cpp | 1 + src/Editor/main.cpp | 4 +- src/Engine/Graphics/Descriptor.h | 9 +++- src/Engine/Graphics/Metal/Buffer.mm | 2 +- src/Engine/Graphics/Metal/Command.mm | 16 +++---- src/Engine/Graphics/Metal/Descriptor.h | 1 - src/Engine/Graphics/Metal/Descriptor.mm | 3 +- src/Engine/Graphics/Metal/RenderPass.mm | 8 ++-- src/Engine/Graphics/Metal/Resources.h | 17 +++++-- src/Engine/Graphics/Metal/Texture.mm | 15 ++++-- src/Engine/Graphics/RenderPass/ShadowPass.cpp | 48 ++++++++----------- src/Engine/Platform/Mac/GameInterface.cpp | 4 +- 13 files changed, 73 insertions(+), 57 deletions(-) diff --git a/res/shaders/EnvironmentMapping.slang b/res/shaders/EnvironmentMapping.slang index 0a942a0..38a6774 100644 --- a/res/shaders/EnvironmentMapping.slang +++ b/res/shaders/EnvironmentMapping.slang @@ -253,7 +253,7 @@ float2 integrateBRDF(float nDotV, float roughness) { } [shader("pixel")] -float2 precomputeBRDF(float2 texCoords) : SV_Target +float2 precomputeBRDF(float2 texCoords : UV) : SV_Target { return integrateBRDF(texCoords.x, texCoords.y); } \ No newline at end of file diff --git a/src/Editor/Asset/EnvironmentLoader.cpp b/src/Editor/Asset/EnvironmentLoader.cpp index db57097..0780bce 100644 --- a/src/Editor/Asset/EnvironmentLoader.cpp +++ b/src/Editor/Asset/EnvironmentLoader.cpp @@ -95,6 +95,7 @@ EnvironmentLoader::EnvironmentLoader(Gfx::PGraphics graphics) : graphics(graphic {"precomputeBRDF", "EnvironmentMapping"}, }, .rootSignature = cubePipelineLayout, + .dumpIntermediate = true, }); cubePipelineLayout->create(); diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index 523d479..d7634d0 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -24,8 +24,8 @@ static Gfx::OGraphics graphics; int main() { std::string gameName = "MeshShadingDemo"; - std::filesystem::path outputPath = fmt::format("/home/dynamitos/{0}Game/", gameName); - std::filesystem::path sourcePath = fmt::format("/home/dynamitos/{0}/", gameName); + std::filesystem::path outputPath = fmt::format("/Users/dynamitos/{0}Game/", gameName); + std::filesystem::path sourcePath = fmt::format("/Users/dynamitos/{0}/", gameName); #ifdef WIN32 std::string libraryEnding = "dll"; #elif __APPLE__ diff --git a/src/Engine/Graphics/Descriptor.h b/src/Engine/Graphics/Descriptor.h index 2011420..38b0ea3 100644 --- a/src/Engine/Graphics/Descriptor.h +++ b/src/Engine/Graphics/Descriptor.h @@ -62,7 +62,7 @@ class DescriptorSet { virtual void updateConstants(const std::string& name, uint32 offset, void* data) = 0; virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PShaderBuffer shaderBuffer) = 0; virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PVertexBuffer vertexBuffer) = 0; - virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PIndexBuffer indexBuffer) = 0;\ + virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PIndexBuffer indexBuffer) = 0; virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PUniformBuffer uniformBuffer) = 0; virtual void updateSampler(const std::string& name, uint32 index, Gfx::PSampler samplerState) = 0; virtual void updateTexture(const std::string& name, uint32 index, Gfx::PTextureView texture) = 0; @@ -93,6 +93,13 @@ class PipelineLayout { constexpr std::string getName() const { return name; }; constexpr bool hasPushConstants() const { return !pushConstants.empty(); } constexpr uint64 getPushConstantsSize() const { return pushConstants[0].size; } + constexpr const std::string& getPushConstantName(uint64 offset) { + for (uint32 i = 0; i < pushConstants.size(); ++i) { + if (offset == pushConstants[i].offset) + return pushConstants[i].name; + } + throw std::logic_error("unknown push constant offset"); + } protected: uint32 layoutHash = 0; diff --git a/src/Engine/Graphics/Metal/Buffer.mm b/src/Engine/Graphics/Metal/Buffer.mm index 71307a9..0a13413 100644 --- a/src/Engine/Graphics/Metal/Buffer.mm +++ b/src/Engine/Graphics/Metal/Buffer.mm @@ -12,7 +12,7 @@ using namespace Seele; using namespace Seele::Metal; BufferAllocation::BufferAllocation(PGraphics graphics, const std::string& name, uint64 size, MTL::ResourceOptions options) - : CommandBoundResource(graphics) { + : CommandBoundResource(graphics, name) { buffer = graphics->getDevice()->newBuffer(size, options); buffer->setLabel(NS::String::string(name.c_str(), NS::ASCIIStringEncoding)); } diff --git a/src/Engine/Graphics/Metal/Command.mm b/src/Engine/Graphics/Metal/Command.mm index fb92928..b33055f 100644 --- a/src/Engine/Graphics/Metal/Command.mm +++ b/src/Engine/Graphics/Metal/Command.mm @@ -147,7 +147,7 @@ void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) { createEncoder(boundPipeline->vertexFunction, boundPipeline->vertexSets); createEncoder(boundPipeline->fragmentFunction, boundPipeline->fragmentSets); if(setHandle->argumentBuffer == nullptr) { - setHandle->argumentBuffer = new BufferAllocation(setHandle->graphics, "ArgumentBuffer", setHandle->encoder->encodedLength()); + setHandle->argumentBuffer = new BufferAllocation(metalSet->graphics, "ArgumentBuffer", setHandle->encoder->encodedLength()); setHandle->encoder->setArgumentBuffer(setHandle->argumentBuffer->buffer, 0); } setHandle->argumentBuffer->bind(); @@ -198,18 +198,18 @@ void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer gfxIndexBuffer) { } void RenderCommand::pushConstants(Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) { - uint pushIndex = boundPipeline->getPipelineLayout()->findParameter("pOffsets"); + uint pushIndex = boundPipeline->getPipelineLayout()->findParameter(boundPipeline->getPipelineLayout()->getPushConstantName(offset)); if (stage & Gfx::SE_SHADER_STAGE_VERTEX_BIT) { - encoder->setVertexBytes(data, size, pushIndex); // TODO: hardcoded + encoder->setVertexBytes(data, size, pushIndex); } if (stage & Gfx::SE_SHADER_STAGE_FRAGMENT_BIT) { - encoder->setFragmentBytes(data, size, pushIndex); // TODO: hardcoded + encoder->setFragmentBytes(data, size, pushIndex); } if (stage & Gfx::SE_SHADER_STAGE_TASK_BIT_EXT) { - encoder->setObjectBytes(data, size, pushIndex); // TODO: hardcoded + encoder->setObjectBytes(data, size, pushIndex); } if (stage & Gfx::SE_SHADER_STAGE_MESH_BIT_EXT) { - encoder->setMeshBytes(data, size, pushIndex); // TODO: hardcoded + encoder->setMeshBytes(data, size, pushIndex); } } @@ -271,7 +271,7 @@ void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) { }; createEncoder(boundPipeline->computeFunction); if(setHandle->argumentBuffer == nullptr) { - setHandle->argumentBuffer = new BufferAllocation(setHandle->graphics, "ArgumentBuffer", setHandle->encoder->encodedLength()); + setHandle->argumentBuffer = new BufferAllocation(metalSet->graphics, "ArgumentBuffer", setHandle->encoder->encodedLength()); setHandle->encoder->setArgumentBuffer(setHandle->argumentBuffer->buffer, 0); } setHandle->argumentBuffer->bind(); @@ -366,6 +366,7 @@ void CommandQueue::submitCommands(PEvent signalSemaphore) { for (auto it = pendingCommands.begin(); it != pendingCommands.end(); it++) { if ((*it)->getHandle() == cmdBuffer) { auto& cmd = *it; + std::cout << "Command completed" << std::endl; cmd->reset(); readyCommands.add(std::move(*it)); pendingCommands.erase(it); @@ -375,7 +376,6 @@ void CommandQueue::submitCommands(PEvent signalSemaphore) { })); PEvent prevCmdEvent = activeCommand->getCompletedEvent(); activeCommand->end(signalSemaphore); - activeCommand->waitDeviceIdle(); pendingCommands.add(std::move(activeCommand)); if (!readyCommands.empty()) { activeCommand = std::move(readyCommands.front()); diff --git a/src/Engine/Graphics/Metal/Descriptor.h b/src/Engine/Graphics/Metal/Descriptor.h index 797c36d..950d4d3 100644 --- a/src/Engine/Graphics/Metal/Descriptor.h +++ b/src/Engine/Graphics/Metal/Descriptor.h @@ -58,7 +58,6 @@ public: void updateTexture(const std::string& name, uint32 index, Gfx::PTextureView texture); void updateAccelerationStructure(const std::string& name, uint32 index, Gfx::PTopLevelAS as); - PGraphics graphics; PDescriptorPool owner; OBufferAllocation argumentBuffer = nullptr; MTL::ArgumentEncoder* encoder = nullptr; diff --git a/src/Engine/Graphics/Metal/Descriptor.mm b/src/Engine/Graphics/Metal/Descriptor.mm index 650061a..044092b 100644 --- a/src/Engine/Graphics/Metal/Descriptor.mm +++ b/src/Engine/Graphics/Metal/Descriptor.mm @@ -59,7 +59,7 @@ void DescriptorLayout::create() { MTL::ArgumentEncoder* DescriptorLayout::createEncoder() { return graphics->getDevice()->newArgumentEncoder(arguments); } DescriptorSetHandle::DescriptorSetHandle(PGraphics graphics, PDescriptorPool owner, const std::string& name) - : CommandBoundResource(graphics), owner(owner) + : CommandBoundResource(graphics, name), owner(owner) { } @@ -143,6 +143,7 @@ void DescriptorSetHandle::updateTexture(const std::string& name, uint32 index, G .access = owner->getLayout()->variableMapping[name].access, }); boundResources.add(tex); + boundResources.add(tex->getSource()); } void DescriptorSetHandle::updateAccelerationStructure(const std::string& , uint32 , Gfx::PTopLevelAS ){} diff --git a/src/Engine/Graphics/Metal/RenderPass.mm b/src/Engine/Graphics/Metal/RenderPass.mm index dc82cb0..1caac2d 100644 --- a/src/Engine/Graphics/Metal/RenderPass.mm +++ b/src/Engine/Graphics/Metal/RenderPass.mm @@ -56,17 +56,17 @@ void RenderPass::updateRenderPass() { for (size_t i = 0; i < layout.colorAttachments.size(); ++i) { const auto& color = layout.colorAttachments[i]; auto desc = renderPass->colorAttachments()->object(i); - desc->setTexture(color.getTextureView().cast()->getImage()); + desc->setTexture(color.getTextureView().cast()->getHandle()); if (!layout.resolveAttachments.empty()) { const auto& resolve = layout.resolveAttachments[i]; - desc->setResolveTexture(resolve.getTextureView().cast()->getImage()); + desc->setResolveTexture(resolve.getTextureView().cast()->getHandle()); } } if (layout.depthAttachment.getTextureView() != nullptr) { auto depth = renderPass->depthAttachment(); - depth->setTexture(layout.depthAttachment.getTextureView().cast()->getImage()); + depth->setTexture(layout.depthAttachment.getTextureView().cast()->getHandle()); if (layout.depthResolveAttachment.getTextureView() != nullptr) { - depth->setResolveTexture(layout.depthResolveAttachment.getTextureView().cast()->getImage()); + depth->setResolveTexture(layout.depthResolveAttachment.getTextureView().cast()->getHandle()); } } } diff --git a/src/Engine/Graphics/Metal/Resources.h b/src/Engine/Graphics/Metal/Resources.h index 7d8b6d6..543ac7d 100644 --- a/src/Engine/Graphics/Metal/Resources.h +++ b/src/Engine/Graphics/Metal/Resources.h @@ -5,6 +5,7 @@ #include #include #include +#include namespace Seele { namespace Metal { @@ -25,18 +26,26 @@ class DestructionManager { DEFINE_REF(DestructionManager) class CommandBoundResource { - public: - CommandBoundResource(PGraphics graphics) : graphics(graphics) {} +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--; } + void bind() { bindCount++; + std::cout << "Bind " << bindCount << " " << name << std::endl; + } + void unbind() { bindCount--; + std::cout << "Unbind " << bindCount << " " << name << std::endl; + } + const std::string& getName() const { + return name; + } protected: PGraphics graphics; + std::string name; uint64 bindCount = 0; }; DEFINE_REF(CommandBoundResource) diff --git a/src/Engine/Graphics/Metal/Texture.mm b/src/Engine/Graphics/Metal/Texture.mm index 2015d3c..25ecea2 100644 --- a/src/Engine/Graphics/Metal/Texture.mm +++ b/src/Engine/Graphics/Metal/Texture.mm @@ -13,7 +13,7 @@ using namespace Seele; using namespace Seele::Metal; TextureView::TextureView(PGraphics graphics, PTextureHandle source, uint32 width, uint32 height, uint32 numLayers, uint32 numMipLevels, MTL::Texture* view) - : CommandBoundResource(graphics), width(width), height(height), numLayers(numLayers), numMipLevels(numMipLevels), source(source), view(view) {} + : CommandBoundResource(graphics, source->getName()), width(width), height(height), numLayers(numLayers), numMipLevels(numMipLevels), source(source), view(view) {} TextureView::~TextureView() {} @@ -43,15 +43,22 @@ void TextureView::changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags Gfx::OTextureView TextureHandle::createTextureView(uint32 baseMipLevel, uint32 viewLevelCount, uint32 baseArrayLayer, uint32 viewLayerCount) { - MTL::Texture* viewTexture = - texture->newTextureView(cast(format), type, NS::Range(baseMipLevel, viewLevelCount), NS::Range(baseArrayLayer, viewLayerCount)); + MTL::Texture* viewTexture; + if(viewLevelCount > 1) + { + viewTexture = texture->newTextureView(cast(format), type, NS::Range(baseMipLevel, viewLevelCount), NS::Range(baseArrayLayer, viewLayerCount)); + } + else + { + viewTexture = texture->newTextureView(cast(format)); + } uint32 viewWidth = width * std::pow(0.5, baseMipLevel); uint32 viewHeight = height * std::pow(0.5, baseMipLevel); return new TextureView(graphics, this, viewWidth, viewHeight, viewLayerCount, viewLevelCount, viewTexture); } TextureHandle::TextureHandle(PGraphics graphics, MTL::TextureType type, const TextureCreateInfo& createInfo, MTL::Texture* existingImage) - : CommandBoundResource(graphics), texture(existingImage), type(type), width(createInfo.width), height(createInfo.height), + : CommandBoundResource(graphics, createInfo.name), texture(existingImage), type(type), width(createInfo.width), height(createInfo.height), depth(createInfo.depth), arrayCount(createInfo.elements), mipLevels(1), samples(createInfo.samples), format(createInfo.format), usage(createInfo.usage), layout(Gfx::SE_IMAGE_LAYOUT_UNDEFINED), ownsImage(existingImage == nullptr) { if (createInfo.useMip) { diff --git a/src/Engine/Graphics/RenderPass/ShadowPass.cpp b/src/Engine/Graphics/RenderPass/ShadowPass.cpp index f6faa95..d299c43 100644 --- a/src/Engine/Graphics/RenderPass/ShadowPass.cpp +++ b/src/Engine/Graphics/RenderPass/ShadowPass.cpp @@ -78,14 +78,8 @@ void ShadowPass::beginFrame(const Component::Camera& camera, const Component::Tr float splitDist = cascadeSplits[i]; Array frustumCorners = { - Vector(-1.0f, 1.0f, 1.0f), - Vector(1.0f, 1.0f, 1.0f), - Vector(1.0f, -1.0f, 1.0f), - Vector(-1.0f, -1.0f, 1.0f), - Vector(-1.0f, 1.0f, 0.0f), - Vector(1.0f, 1.0f, 0.0f), - Vector(1.0f, -1.0f, 0.0f), - Vector(-1.0f, -1.0f, 0.0f), + Vector(-1.0f, 1.0f, 1.0f), Vector(1.0f, 1.0f, 1.0f), Vector(1.0f, -1.0f, 1.0f), Vector(-1.0f, -1.0f, 1.0f), + Vector(-1.0f, 1.0f, 0.0f), Vector(1.0f, 1.0f, 0.0f), Vector(1.0f, -1.0f, 0.0f), Vector(-1.0f, -1.0f, 0.0f), }; for (auto& c : frustumCorners) { @@ -127,7 +121,7 @@ void ShadowPass::beginFrame(const Component::Camera& camera, const Component::Tr viewParams.viewProjectionMatrix = viewProjectionMatrix; viewParams.inverseViewProjectionMatrix = glm::inverse(viewProjectionMatrix); viewParams.cameraPosition_WS = Vector4(cameraPos, 1); - viewParams.cameraForward_WS = Vector4(frustumCenter - cameraPos, 0); + viewParams.cameraForward_WS = Vector4(frustumCenter - cameraPos, 0); viewParams.screenDimensions = Vector2(maxExtents.x - minExtents.x, maxExtents.y - minExtents.y); viewParams.invScreenDimensions = 1.0f / viewParams.screenDimensions; cascades[i].viewParams.add(createViewParamsSet()); @@ -262,11 +256,11 @@ void ShadowPass::endFrame() {} void ShadowPass::publishOutputs() { cascadeSplitsBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{.sourceData = - { - .size = sizeof(float) * NUM_CASCADES, - .data = nullptr, - }, - .name = "CascadeSplits"}); + { + .size = sizeof(float) * NUM_CASCADES, + .data = nullptr, + }, + .name = "CascadeSplits"}); shadowViewport = graphics->createViewport(nullptr, ViewportCreateInfo{.dimensions = { .size = {SHADOW_MAP_SIZE, SHADOW_MAP_SIZE}, @@ -287,13 +281,12 @@ void ShadowPass::publishOutputs() { .usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_SAMPLED_BIT, .name = "ShadowMapCascade", }); - cascades[s].lightSpaceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ - .sourceData = { - .size = sizeof(Matrix4), - .data = nullptr, - }, - .name = "LightSpaceBuffer" - }); + cascades[s].lightSpaceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{.sourceData = + { + .size = sizeof(Matrix4), + .data = nullptr, + }, + .name = "LightSpaceBuffer"}); cascades[s].views.clear(); for (uint32 j = 0; j < cascades[s].shadowMaps->getNumLayers(); ++j) { cascades[s].views.add(cascades[s].shadowMaps->createTextureView(0, 1, j, 1)); @@ -302,13 +295,12 @@ void ShadowPass::publishOutputs() { resources->registerTextureOutput(fmt::format("SHADOWMAP_TEXTURE{0}", s), Gfx::PTexture2DArray(cascades[s].shadowMaps)); resources->registerBufferOutput(fmt::format("SHADOWMAP_LIGHTSPACE{0}", s), cascades[s].lightSpaceBuffer); } - cascadeSplitsBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{ - .sourceData = { - .size = sizeof(float) * NUM_CASCADES, - .data = nullptr, - }, - .name = "CASCADE_SPLITS" - }); + cascadeSplitsBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{.sourceData = + { + .size = sizeof(float) * NUM_CASCADES, + .data = nullptr, + }, + .name = "CASCADE_SPLITS"}); resources->registerUniformOutput("SHADOWMAP_CASCADESPLITS", cascadeSplitsBuffer); viewport = shadowViewport; } diff --git a/src/Engine/Platform/Mac/GameInterface.cpp b/src/Engine/Platform/Mac/GameInterface.cpp index 161e494..0e08f9f 100644 --- a/src/Engine/Platform/Mac/GameInterface.cpp +++ b/src/Engine/Platform/Mac/GameInterface.cpp @@ -15,9 +15,9 @@ void GameInterface::reload() { destroyInstance(game); dlclose(lib); } - std::filesystem::copy(soPath.parent_path().parent_path() / "res" / "shaders", "shaders/game", std::filesystem::copy_options::overwrite_existing); + //std::filesystem::copy(soPath.parent_path().parent_path() / "res" / "shaders", "shaders/game", std::filesystem::copy_options::overwrite_existing); lib = dlopen(soPath.c_str(), RTLD_NOW); createInstance = (decltype(createInstance))dlsym(lib, "createInstance"); destroyInstance = (decltype(destroyInstance))dlsym(lib, "destroyInstance"); game = createInstance(); -} \ No newline at end of file +}