From 2a7643ddf37304b8bc1eed485d4938184856b684 Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Wed, 10 Apr 2024 09:58:39 +0200 Subject: [PATCH] Basic sync primitives --- .vscode/settings.json | 2 + src/Engine/Graphics/Metal/CMakeLists.txt | 1 + src/Engine/Graphics/Metal/Command.h | 15 +- src/Engine/Graphics/Metal/Command.mm | 216 +++++++++++------------ src/Engine/Graphics/Metal/Graphics.h | 6 +- src/Engine/Graphics/Metal/Graphics.mm | 21 ++- src/Engine/Graphics/Metal/RenderPass.mm | 1 - src/Engine/Graphics/Metal/Resources.h | 31 +++- src/Engine/Graphics/Metal/Resources.mm | 13 ++ src/Engine/Graphics/Metal/Window.mm | 3 +- 10 files changed, 182 insertions(+), 127 deletions(-) create mode 100644 src/Engine/Graphics/Metal/Resources.mm diff --git a/.vscode/settings.json b/.vscode/settings.json index 9fdc4f6..615e47b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -158,4 +158,6 @@ "**/external": true, "**/res": true, }, + "editor.tabSize": 2, + "editor.detectIndentation": false, } \ No newline at end of file diff --git a/src/Engine/Graphics/Metal/CMakeLists.txt b/src/Engine/Graphics/Metal/CMakeLists.txt index 68703af..7e00d7e 100644 --- a/src/Engine/Graphics/Metal/CMakeLists.txt +++ b/src/Engine/Graphics/Metal/CMakeLists.txt @@ -10,6 +10,7 @@ target_sources(Engine RenderPass.h RenderPass.mm Resources.h + Resources.mm Texture.h Texture.mm Window.h diff --git a/src/Engine/Graphics/Metal/Command.h b/src/Engine/Graphics/Metal/Command.h index e37736a..4788f67 100644 --- a/src/Engine/Graphics/Metal/Command.h +++ b/src/Engine/Graphics/Metal/Command.h @@ -1,6 +1,7 @@ #pragma once #include "Graphics/Command.h" #include "Metal/MTLComputeCommandEncoder.hpp" +#include "Metal/MTLDrawable.hpp" #include "Metal/MTLRenderCommandEncoder.hpp" #include "MinimalEngine.h" #include "RenderPass.h" @@ -19,15 +20,22 @@ public: ~Command(); void beginRenderPass(PRenderPass renderPass); void endRenderPass(); + void present(MTL::Drawable* drawable); + void end(PEvent signal); void executeCommands(const Array& commands); void executeCommands(const Array& commands); + void waitDeviceIdle(); + void signalEvent(PEvent event); + void waitForEvent(PEvent event); + MTL::RenderCommandEncoder* createRenderEncoder() { return renderEncoder->renderCommandEncoder(); } + MTL::ComputeCommandEncoder* createComputeEncoder() { return cmdBuffer->computeCommandEncoder(); } + PEvent getCompletedEvent() const { return completed; } private: PGraphics graphics; PCommandQueue owner; + OEvent completed; MTL::CommandBuffer* cmdBuffer; MTL::ParallelRenderCommandEncoder* renderEncoder; - PFence fence; - PSemaphore semaphore; }; DEFINE_REF(Command) class RenderCommand : public Gfx::RenderCommand @@ -77,11 +85,10 @@ public: PCommand getCommands(); PRenderCommand getRenderCommand(const std::string& name); PComputeCommand getComputeCommand(const std::string& name); - void submitCommands(PSemaphore signalSemaphore = nullptr); + void submitCommands(PEvent signal = nullptr); private: PGraphics graphics; MTL::CommandQueue* queue; - Array allocatedCommands; OCommand activeCommand; }; } diff --git a/src/Engine/Graphics/Metal/Command.mm b/src/Engine/Graphics/Metal/Command.mm index 5e10ee0..113de46 100644 --- a/src/Engine/Graphics/Metal/Command.mm +++ b/src/Engine/Graphics/Metal/Command.mm @@ -1,5 +1,5 @@ #include "Command.h" -#include "Metal/MTLComputeCommandEncoder.hpp" +#include "Graphics/Metal/Resources.h" #include "Metal/MTLRenderCommandEncoder.hpp" #include "Window.h" @@ -7,166 +7,166 @@ using namespace Seele; using namespace Seele::Metal; Command::Command(PGraphics graphics, PCommandQueue owner) - : graphics(graphics) - , owner(owner) - , cmdBuffer(owner->getHandle()->commandBuffer()) - , renderEncoder(nullptr) -{ + : graphics(graphics), owner(owner), signalEvent(new Event(graphics)), + cmdBuffer(owner->getHandle()->commandBuffer()), renderEncoder(nullptr) {} + +Command::~Command() { cmdBuffer->release(); } + +void Command::beginRenderPass(PRenderPass renderPass) { + renderEncoder = + cmdBuffer->parallelRenderCommandEncoder(renderPass->getDescriptor()); } -Command::~Command() -{ - cmdBuffer->release(); +void Command::endRenderPass() { renderEncoder->endEncoding(); } + +void Command::present(MTL::Drawable *drawable) { + cmdBuffer->presentDrawable(drawable); } -void Command::beginRenderPass(PRenderPass renderPass) -{ - renderEncoder = cmdBuffer->parallelRenderCommandEncoder(renderPass->getDescriptor()); +void Command::end(PEvent signal) { + if (signal != nullptr) { + cmdBuffer->encodeSignalEvent(signal->getHandle(), 1); + } + cmdBuffer->encodeSignalEvent(completed->getHandle(), 1); + cmdBuffer->commit(); } -void Command::endRenderPass() -{ - renderEncoder->endEncoding(); +void Command::executeCommands(const Array &commands) { + for (auto command : commands) { + auto cmd = command.cast(); + cmd->end(); + } } -void Command::executeCommands(const Array& commands) -{ - for(auto command : commands) - { - auto cmd = command.cast(); - cmd->end(); - } +void Command::executeCommands(const Array &commands) { + for (auto command : commands) { + auto cmd = command.cast(); + cmd->end(); + } } -void Command::executeCommands(const Array& commands) -{ - for(auto command : commands) - { - auto cmd = command.cast(); - cmd->end(); - } +void Command::waitDeviceIdle() { + cmdBuffer->waitUntilCompleted(); } -RenderCommand::RenderCommand(MTL::RenderCommandEncoder* encoder) - : encoder(encoder) -{} - -RenderCommand::~RenderCommand() -{ - encoder->release(); +void Command::signalEvent(PEvent event) { + cmdBuffer->encodeSignalEvent(event->getHandle(), 1); } -void RenderCommand::end() -{ - encoder->endEncoding(); +void Command::waitForEvent(PEvent event) { + cmdBuffer->encodeWait(event->getHandle(), 1); } -void RenderCommand::setViewport(Gfx::PViewport viewport) -{ - encoder->setViewport(viewport.cast()->getHandle()); +RenderCommand::RenderCommand(MTL::RenderCommandEncoder *encoder) + : encoder(encoder) {} + +RenderCommand::~RenderCommand() { encoder->release(); } + +void RenderCommand::end() { encoder->endEncoding(); } + +void RenderCommand::setViewport(Gfx::PViewport viewport) { + MTL::Viewport vp = viewport.cast()->getHandle(); + MTL::ScissorRect rect = { + .x = static_cast(vp.originX), + .y = static_cast(vp.originY), + .width = static_cast(vp.width), + .height = static_cast(vp.height), + }; + encoder->setViewport(vp); + encoder->setScissorRect(rect); } -void RenderCommand::bindPipeline(Gfx::PGraphicsPipeline pipeline) -{ - encoder->setRenderPipelineState(pipeline.cast()->getState()); +void RenderCommand::bindPipeline(Gfx::PGraphicsPipeline pipeline) { + encoder->setRenderPipelineState( + pipeline.cast()->getState()); } -void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) -{ - encoder->set????? +void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) { + encoder->set ? ? ? ? ? } -void RenderCommand::bindDescriptor(const Array& descriptorSets) -{ - encoder->set????? - +void RenderCommand::bindDescriptor( + const Array &descriptorSets) { + encoder->set ? ? ? ? ? } -void RenderCommand::bindVertexBuffer(const Array& buffers) -{ - encoder->setVertexBuffers(); +void RenderCommand::bindVertexBuffer(const Array &buffers) { + encoder->setVertexBuffers(); } -void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) -{ +void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) { encoder->setObjectBuffer(??, NS::UInteger offset, NS::UInteger index) } -void RenderCommand::pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) -{ -??? +void RenderCommand::pushConstants(Gfx::PPipelineLayout layout, + Gfx::SeShaderStageFlags stage, uint32 offset, + uint32 size, const void *data) { + ? ? ? } -void RenderCommand::draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance) -{ +void RenderCommand::draw(uint32 vertexCount, uint32 instanceCount, + int32 firstVertex, uint32 firstInstance) { encoder->drawPrimitives(???, firstVertex, vertexCount, instanceCount, firstInstance); } -void RenderCommand::drawIndexed(uint32 indexCount, uint32 instanceCount, int32 firstIndex, uint32 vertexOffset, uint32 firstInstance) -{ +void RenderCommand::drawIndexed(uint32 indexCount, uint32 instanceCount, + int32 firstIndex, uint32 vertexOffset, + uint32 firstInstance) { encoder->drawIndexedPrimitives(???, indexCount, indexbuffer->getType(), indexBuffer->getBuffer(), firstIndex, instanceCount, vertexOffset, firstInstance); } -void RenderCommand::drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) -{ - encoder->drawMeshThreads(MTL::Size threadsPerGrid, MTL::Size threadsPerObjectThreadgroup, MTL::Size threadsPerMeshThreadgroup) +void RenderCommand::drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ){ + encoder->drawMeshThreads(MTL::Size threadsPerGrid, + MTL::Size threadsPerObjectThreadgroup, + MTL::Size threadsPerMeshThreadgroup)} + +ComputeCommand::ComputeCommand(MTL::ComputeCommandEncoder *encoder) + : encoder(encoder) {} + +ComputeCommand::~ComputeCommand() { encoder->release(); } + +void ComputeCommand::end() { encoder->endEncoding(); } + +void ComputeCommand::bindPipeline(Gfx::PComputePipeline pipeline) { + encoder->setComputePipelineState(pipeline.cast()); } -ComputeCommand::ComputeCommand(MTL::ComputeCommandEncoder* encoder) - : encoder(encoder) -{} - -ComputeCommand::~ComputeCommand() -{ - encoder->release(); +void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet set) { + encoder->set ? ? ? } -void ComputeCommand::end() -{ - encoder->endEncoding(); +void ComputeCommand::bindDescriptor(const Array &sets) { + encoder->set ? ? ? } -void ComputeCommand::bindPipeline(Gfx::PComputePipeline pipeline) -{ - encoder->setComputePipelineState(pipeline); +void ComputeCommand::pushConstants(Gfx::PPipelineLayout layout, + Gfx::SeShaderStageFlags stage, uint32 offset, + uint32 size, const void *data) { + ? ? ? } -void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet set) -{ - encoder->set??? -} - -void ComputeCommand::bindDescriptor(const Array& sets) -{ - encoder->set??? -} - -void ComputeCommand::pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) -{ - ??? -} - -void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) -{ +void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) { encoder->dispatchThreadgroups(???); } -CommandQueue::CommandQueue(PGraphics graphics) - : graphics(graphics) -{ +CommandQueue::CommandQueue(PGraphics graphics) : graphics(graphics) { queue = graphics->getDevice()->newCommandQueue(); + activeCommand = new Command(graphics, this); } -CommandQueue::~CommandQueue() -{ - queue->release(); +CommandQueue::~CommandQueue() { queue->release(); } + +PRenderCommand CommandQueue::getRenderCommand(const std::string &name) { + return new RenderCommand(activeCommand->createRenderEncoder()); } -PRenderCommand CommandQueue::getRenderCommand(const std::string& name) -{ +PComputeCommand CommandQueue::getComputeCommand(const std::string &name) { + return new ComputeCommand(activeCommand->createComputeEncoder()); } -PComputeCommand CommandQueue::getComputeCommand(const std::string& name) -{ - +void CommandQueue::submitCommands(PEvent signalSemaphore) { + activeCommand->end(signalSemaphore); + MTL::Event* prevCmdEvent = activeCommand->getCompletedEvent(); + activeCommand = new Command(graphics, this); + activeCommand->waitForEvent(prevCmdEvent); } diff --git a/src/Engine/Graphics/Metal/Graphics.h b/src/Engine/Graphics/Metal/Graphics.h index e792ec2..21bfa86 100644 --- a/src/Engine/Graphics/Metal/Graphics.h +++ b/src/Engine/Graphics/Metal/Graphics.h @@ -1,5 +1,4 @@ #pragma once -#include "Metal/MTLRenderCommandEncoder.hpp" #include "Metal/Metal.hpp" #include "Graphics/Graphics.h" @@ -7,6 +6,7 @@ namespace Seele { namespace Metal { +DECLARE_REF(CommandQueue) class Graphics : public Gfx::Graphics { public: @@ -54,11 +54,11 @@ public: virtual void resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) override; MTL::Device* getDevice() const { return device; } + PCommandQueue getQueue() const { return queue; } protected: MTL::Device* device; MTL::Library* library; - MTL::CommandQueue* queue; - MTL::RenderCommandEncoder* encoder; + OCommandQueue queue; }; DEFINE_REF(Graphics) } // namespace Metal diff --git a/src/Engine/Graphics/Metal/Graphics.mm b/src/Engine/Graphics/Metal/Graphics.mm index d3d7149..050f96c 100644 --- a/src/Engine/Graphics/Metal/Graphics.mm +++ b/src/Engine/Graphics/Metal/Graphics.mm @@ -1,5 +1,6 @@ #include "Graphics.h" -#include "Graphics/Metal/RenderPass.h" +#include "RenderPass.h" +#include "Command.h" #include "Window.h" using namespace Seele; @@ -20,7 +21,7 @@ void Graphics::init(GraphicsInitializer) device = MTL::CreateSystemDefaultDevice(); library = device->newDefaultLibrary(); assert(library); - queue = device->newCommandQueue(); + queue = new CommandQueue(this); } Gfx::OWindow Graphics::createWindow(const WindowCreateInfo &createInfo) @@ -40,37 +41,41 @@ Gfx::ORenderPass Graphics::createRenderPass(Gfx::RenderTargetLayout layout, Arra void Graphics::beginRenderPass(Gfx::PRenderPass renderPass) { + queue->getCommands()->beginRenderPass(renderPass.cast()); } void Graphics::endRenderPass() { - + queue->getCommands()->endRenderPass(); } + void Graphics::waitDeviceIdle() { - + queue->getCommands()->waitDeviceIdle(); } void Graphics::executeCommands(const Array& commands) { - + queue->getCommands()->executeCommands(commands); } + void Graphics::executeCommands(const Array& commands) { - + queue->getCommands()->executeCommands(commands); } Gfx::OTexture2D Graphics::createTexture2D(const TextureCreateInfo &createInfo) { - + return new Texture2D(this, createInfo); } Gfx::OTexture3D Graphics::createTexture3D(const TextureCreateInfo &createInfo) { + return new Texture3D(this, createInfo); } Gfx::OTextureCube Graphics::createTextureCube(const TextureCreateInfo &createInfo) { - + return new TextureCube(this, createInfo); } Gfx::OUniformBuffer Graphics::createUniformBuffer(const UniformBufferCreateInfo &bulkData) { diff --git a/src/Engine/Graphics/Metal/RenderPass.mm b/src/Engine/Graphics/Metal/RenderPass.mm index c0cf747..4eaa092 100644 --- a/src/Engine/Graphics/Metal/RenderPass.mm +++ b/src/Engine/Graphics/Metal/RenderPass.mm @@ -36,7 +36,6 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::RenderTargetLayout layout, desc->setResolveTexture( resolve.getTexture().cast()->getTexture()); } - colorAttachments->setObject(desc, i); } if (layout.depthAttachment.getTexture() != nullptr) { depth = MTL::RenderPassDepthAttachmentDescriptor::alloc()->init(); diff --git a/src/Engine/Graphics/Metal/Resources.h b/src/Engine/Graphics/Metal/Resources.h index d91121a..88e46a7 100644 --- a/src/Engine/Graphics/Metal/Resources.h +++ b/src/Engine/Graphics/Metal/Resources.h @@ -1,6 +1,33 @@ #pragma once +#include "Graphics/Resources.h" #include #include -#include #include -#include \ No newline at end of file +#include +#include + +namespace Seele { +namespace Metal { +DECLARE_REF(Graphics); +class Fence { +public: + Fence(PGraphics graphics); + ~Fence(); + MTL::Fence *getHandle() const { return handle; } + +private: + MTL::Fence *handle; +}; +DEFINE_REF(Fence); +class Event { +public: + Event(PGraphics graphics); + ~Event(); + MTL::Event *getHandle() const { return handle; } + +private: + MTL::Event *handle; +}; +DEFINE_REF(Event) +} // namespace Metal +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Metal/Resources.mm b/src/Engine/Graphics/Metal/Resources.mm new file mode 100644 index 0000000..ffb2f80 --- /dev/null +++ b/src/Engine/Graphics/Metal/Resources.mm @@ -0,0 +1,13 @@ +#include "Resources.h" +#include "Graphics.h" + +using namespace Seele; +using namespace Seele::Metal; + +Fence::Fence(PGraphics graphics) : handle(graphics->getDevice()->newFence()) {} + +Fence::~Fence() { handle->release(); } + +Event::Event(PGraphics graphics) : handle(graphics->getDevice()->newEvent()) {} + +Event::~Event() { handle->release(); } \ No newline at end of file diff --git a/src/Engine/Graphics/Metal/Window.mm b/src/Engine/Graphics/Metal/Window.mm index 9d041fa..f91bd69 100644 --- a/src/Engine/Graphics/Metal/Window.mm +++ b/src/Engine/Graphics/Metal/Window.mm @@ -1,8 +1,8 @@ #include "Window.h" -#include "Foundation/NSSharedPtr.hpp" #include "Graphics/Initializer.h" #include "Graphics/Metal/Enums.h" #include "Graphics/Texture.h" +#include "Command.h" #include "Metal/MTLTexture.hpp" using namespace Seele; using namespace Seele::Metal; @@ -117,6 +117,7 @@ void Window::beginFrame() void Window::endFrame() { + graphics->getQueue()->getCommands()->present(drawable); } void Window::onWindowCloseEvent()