Basic sync primitives

This commit is contained in:
Dynamitos
2024-04-10 09:58:39 +02:00
parent d7b228d856
commit 2a7643ddf3
10 changed files with 182 additions and 127 deletions
+2
View File
@@ -158,4 +158,6 @@
"**/external": true, "**/external": true,
"**/res": true, "**/res": true,
}, },
"editor.tabSize": 2,
"editor.detectIndentation": false,
} }
+1
View File
@@ -10,6 +10,7 @@ target_sources(Engine
RenderPass.h RenderPass.h
RenderPass.mm RenderPass.mm
Resources.h Resources.h
Resources.mm
Texture.h Texture.h
Texture.mm Texture.mm
Window.h Window.h
+11 -4
View File
@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "Graphics/Command.h" #include "Graphics/Command.h"
#include "Metal/MTLComputeCommandEncoder.hpp" #include "Metal/MTLComputeCommandEncoder.hpp"
#include "Metal/MTLDrawable.hpp"
#include "Metal/MTLRenderCommandEncoder.hpp" #include "Metal/MTLRenderCommandEncoder.hpp"
#include "MinimalEngine.h" #include "MinimalEngine.h"
#include "RenderPass.h" #include "RenderPass.h"
@@ -19,15 +20,22 @@ public:
~Command(); ~Command();
void beginRenderPass(PRenderPass renderPass); void beginRenderPass(PRenderPass renderPass);
void endRenderPass(); void endRenderPass();
void present(MTL::Drawable* drawable);
void end(PEvent signal);
void executeCommands(const Array<Gfx::PRenderCommand>& commands); void executeCommands(const Array<Gfx::PRenderCommand>& commands);
void executeCommands(const Array<Gfx::PComputeCommand>& commands); void executeCommands(const Array<Gfx::PComputeCommand>& 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: private:
PGraphics graphics; PGraphics graphics;
PCommandQueue owner; PCommandQueue owner;
OEvent completed;
MTL::CommandBuffer* cmdBuffer; MTL::CommandBuffer* cmdBuffer;
MTL::ParallelRenderCommandEncoder* renderEncoder; MTL::ParallelRenderCommandEncoder* renderEncoder;
PFence fence;
PSemaphore semaphore;
}; };
DEFINE_REF(Command) DEFINE_REF(Command)
class RenderCommand : public Gfx::RenderCommand class RenderCommand : public Gfx::RenderCommand
@@ -77,11 +85,10 @@ public:
PCommand getCommands(); PCommand getCommands();
PRenderCommand getRenderCommand(const std::string& name); PRenderCommand getRenderCommand(const std::string& name);
PComputeCommand getComputeCommand(const std::string& name); PComputeCommand getComputeCommand(const std::string& name);
void submitCommands(PSemaphore signalSemaphore = nullptr); void submitCommands(PEvent signal = nullptr);
private: private:
PGraphics graphics; PGraphics graphics;
MTL::CommandQueue* queue; MTL::CommandQueue* queue;
Array<OCommand> allocatedCommands;
OCommand activeCommand; OCommand activeCommand;
}; };
} }
+108 -108
View File
@@ -1,5 +1,5 @@
#include "Command.h" #include "Command.h"
#include "Metal/MTLComputeCommandEncoder.hpp" #include "Graphics/Metal/Resources.h"
#include "Metal/MTLRenderCommandEncoder.hpp" #include "Metal/MTLRenderCommandEncoder.hpp"
#include "Window.h" #include "Window.h"
@@ -7,166 +7,166 @@ using namespace Seele;
using namespace Seele::Metal; using namespace Seele::Metal;
Command::Command(PGraphics graphics, PCommandQueue owner) Command::Command(PGraphics graphics, PCommandQueue owner)
: graphics(graphics) : graphics(graphics), owner(owner), signalEvent(new Event(graphics)),
, owner(owner) cmdBuffer(owner->getHandle()->commandBuffer()), renderEncoder(nullptr) {}
, cmdBuffer(owner->getHandle()->commandBuffer())
, renderEncoder(nullptr) Command::~Command() { cmdBuffer->release(); }
{
void Command::beginRenderPass(PRenderPass renderPass) {
renderEncoder =
cmdBuffer->parallelRenderCommandEncoder(renderPass->getDescriptor());
} }
Command::~Command() void Command::endRenderPass() { renderEncoder->endEncoding(); }
{
cmdBuffer->release(); void Command::present(MTL::Drawable *drawable) {
cmdBuffer->presentDrawable(drawable);
} }
void Command::beginRenderPass(PRenderPass renderPass) void Command::end(PEvent signal) {
{ if (signal != nullptr) {
renderEncoder = cmdBuffer->parallelRenderCommandEncoder(renderPass->getDescriptor()); cmdBuffer->encodeSignalEvent(signal->getHandle(), 1);
}
cmdBuffer->encodeSignalEvent(completed->getHandle(), 1);
cmdBuffer->commit();
} }
void Command::endRenderPass() void Command::executeCommands(const Array<Gfx::PRenderCommand> &commands) {
{ for (auto command : commands) {
renderEncoder->endEncoding(); auto cmd = command.cast<RenderCommand>();
cmd->end();
}
} }
void Command::executeCommands(const Array<Gfx::PRenderCommand>& commands) void Command::executeCommands(const Array<Gfx::PComputeCommand> &commands) {
{ for (auto command : commands) {
for(auto command : commands) auto cmd = command.cast<ComputeCommand>();
{ cmd->end();
auto cmd = command.cast<RenderCommand>(); }
cmd->end();
}
} }
void Command::executeCommands(const Array<Gfx::PComputeCommand>& commands) void Command::waitDeviceIdle() {
{ cmdBuffer->waitUntilCompleted();
for(auto command : commands)
{
auto cmd = command.cast<ComputeCommand>();
cmd->end();
}
} }
RenderCommand::RenderCommand(MTL::RenderCommandEncoder* encoder) void Command::signalEvent(PEvent event) {
: encoder(encoder) cmdBuffer->encodeSignalEvent(event->getHandle(), 1);
{}
RenderCommand::~RenderCommand()
{
encoder->release();
} }
void RenderCommand::end() void Command::waitForEvent(PEvent event) {
{ cmdBuffer->encodeWait(event->getHandle(), 1);
encoder->endEncoding();
} }
void RenderCommand::setViewport(Gfx::PViewport viewport) RenderCommand::RenderCommand(MTL::RenderCommandEncoder *encoder)
{ : encoder(encoder) {}
encoder->setViewport(viewport.cast<Viewport>()->getHandle());
RenderCommand::~RenderCommand() { encoder->release(); }
void RenderCommand::end() { encoder->endEncoding(); }
void RenderCommand::setViewport(Gfx::PViewport viewport) {
MTL::Viewport vp = viewport.cast<Viewport>()->getHandle();
MTL::ScissorRect rect = {
.x = static_cast<NS::UInteger>(vp.originX),
.y = static_cast<NS::UInteger>(vp.originY),
.width = static_cast<NS::UInteger>(vp.width),
.height = static_cast<NS::UInteger>(vp.height),
};
encoder->setViewport(vp);
encoder->setScissorRect(rect);
} }
void RenderCommand::bindPipeline(Gfx::PGraphicsPipeline pipeline) void RenderCommand::bindPipeline(Gfx::PGraphicsPipeline pipeline) {
{ encoder->setRenderPipelineState(
encoder->setRenderPipelineState(pipeline.cast<GraphicsPipeline>()->getState()); pipeline.cast<GraphicsPipeline>()->getState());
} }
void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) {
{ encoder->set ? ? ? ? ?
encoder->set?????
} }
void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets) void RenderCommand::bindDescriptor(
{ const Array<Gfx::PDescriptorSet> &descriptorSets) {
encoder->set????? encoder->set ? ? ? ? ?
} }
void RenderCommand::bindVertexBuffer(const Array<Gfx::PVertexBuffer>& buffers) void RenderCommand::bindVertexBuffer(const Array<Gfx::PVertexBuffer> &buffers) {
{ encoder->setVertexBuffers();
encoder->setVertexBuffers();
} }
void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) {
{
encoder->setObjectBuffer(??, NS::UInteger offset, NS::UInteger index) 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); 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); encoder->drawIndexedPrimitives(???, indexCount, indexbuffer->getType(), indexBuffer->getBuffer(), firstIndex, instanceCount, vertexOffset, firstInstance);
} }
void RenderCommand::drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) void RenderCommand::drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ){
{ encoder->drawMeshThreads(MTL::Size threadsPerGrid,
encoder->drawMeshThreads(MTL::Size threadsPerGrid, MTL::Size threadsPerObjectThreadgroup, MTL::Size threadsPerMeshThreadgroup) 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<ComputePipeline>());
} }
ComputeCommand::ComputeCommand(MTL::ComputeCommandEncoder* encoder) void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet set) {
: encoder(encoder) encoder->set ? ? ?
{}
ComputeCommand::~ComputeCommand()
{
encoder->release();
} }
void ComputeCommand::end() void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet> &sets) {
{ encoder->set ? ? ?
encoder->endEncoding();
} }
void ComputeCommand::bindPipeline(Gfx::PComputePipeline pipeline) void ComputeCommand::pushConstants(Gfx::PPipelineLayout layout,
{ Gfx::SeShaderStageFlags stage, uint32 offset,
encoder->setComputePipelineState(pipeline); uint32 size, const void *data) {
? ? ?
} }
void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet set) void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) {
{
encoder->set???
}
void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& 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)
{
encoder->dispatchThreadgroups(???); encoder->dispatchThreadgroups(???);
} }
CommandQueue::CommandQueue(PGraphics graphics) CommandQueue::CommandQueue(PGraphics graphics) : graphics(graphics) {
: graphics(graphics)
{
queue = graphics->getDevice()->newCommandQueue(); queue = graphics->getDevice()->newCommandQueue();
activeCommand = new Command(graphics, this);
} }
CommandQueue::~CommandQueue() CommandQueue::~CommandQueue() { queue->release(); }
{
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);
} }
+3 -3
View File
@@ -1,5 +1,4 @@
#pragma once #pragma once
#include "Metal/MTLRenderCommandEncoder.hpp"
#include "Metal/Metal.hpp" #include "Metal/Metal.hpp"
#include "Graphics/Graphics.h" #include "Graphics/Graphics.h"
@@ -7,6 +6,7 @@ namespace Seele
{ {
namespace Metal namespace Metal
{ {
DECLARE_REF(CommandQueue)
class Graphics : public Gfx::Graphics class Graphics : public Gfx::Graphics
{ {
public: public:
@@ -54,11 +54,11 @@ public:
virtual void resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) override; virtual void resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) override;
MTL::Device* getDevice() const { return device; } MTL::Device* getDevice() const { return device; }
PCommandQueue getQueue() const { return queue; }
protected: protected:
MTL::Device* device; MTL::Device* device;
MTL::Library* library; MTL::Library* library;
MTL::CommandQueue* queue; OCommandQueue queue;
MTL::RenderCommandEncoder* encoder;
}; };
DEFINE_REF(Graphics) DEFINE_REF(Graphics)
} // namespace Metal } // namespace Metal
+13 -8
View File
@@ -1,5 +1,6 @@
#include "Graphics.h" #include "Graphics.h"
#include "Graphics/Metal/RenderPass.h" #include "RenderPass.h"
#include "Command.h"
#include "Window.h" #include "Window.h"
using namespace Seele; using namespace Seele;
@@ -20,7 +21,7 @@ void Graphics::init(GraphicsInitializer)
device = MTL::CreateSystemDefaultDevice(); device = MTL::CreateSystemDefaultDevice();
library = device->newDefaultLibrary(); library = device->newDefaultLibrary();
assert(library); assert(library);
queue = device->newCommandQueue(); queue = new CommandQueue(this);
} }
Gfx::OWindow Graphics::createWindow(const WindowCreateInfo &createInfo) 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) void Graphics::beginRenderPass(Gfx::PRenderPass renderPass)
{ {
queue->getCommands()->beginRenderPass(renderPass.cast<RenderPass>());
} }
void Graphics::endRenderPass() void Graphics::endRenderPass()
{ {
queue->getCommands()->endRenderPass();
} }
void Graphics::waitDeviceIdle() void Graphics::waitDeviceIdle()
{ {
queue->getCommands()->waitDeviceIdle();
} }
void Graphics::executeCommands(const Array<Gfx::PRenderCommand>& commands) void Graphics::executeCommands(const Array<Gfx::PRenderCommand>& commands)
{ {
queue->getCommands()->executeCommands(commands);
} }
void Graphics::executeCommands(const Array<Gfx::PComputeCommand>& commands) void Graphics::executeCommands(const Array<Gfx::PComputeCommand>& commands)
{ {
queue->getCommands()->executeCommands(commands);
} }
Gfx::OTexture2D Graphics::createTexture2D(const TextureCreateInfo &createInfo) Gfx::OTexture2D Graphics::createTexture2D(const TextureCreateInfo &createInfo)
{ {
return new Texture2D(this, createInfo);
} }
Gfx::OTexture3D Graphics::createTexture3D(const TextureCreateInfo &createInfo) Gfx::OTexture3D Graphics::createTexture3D(const TextureCreateInfo &createInfo)
{ {
return new Texture3D(this, createInfo);
} }
Gfx::OTextureCube Graphics::createTextureCube(const TextureCreateInfo &createInfo) Gfx::OTextureCube Graphics::createTextureCube(const TextureCreateInfo &createInfo)
{ {
return new TextureCube(this, createInfo);
} }
Gfx::OUniformBuffer Graphics::createUniformBuffer(const UniformBufferCreateInfo &bulkData) Gfx::OUniformBuffer Graphics::createUniformBuffer(const UniformBufferCreateInfo &bulkData)
{ {
-1
View File
@@ -36,7 +36,6 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::RenderTargetLayout layout,
desc->setResolveTexture( desc->setResolveTexture(
resolve.getTexture().cast<TextureBase>()->getTexture()); resolve.getTexture().cast<TextureBase>()->getTexture());
} }
colorAttachments->setObject(desc, i);
} }
if (layout.depthAttachment.getTexture() != nullptr) { if (layout.depthAttachment.getTexture() != nullptr) {
depth = MTL::RenderPassDepthAttachmentDescriptor::alloc()->init(); depth = MTL::RenderPassDepthAttachmentDescriptor::alloc()->init();
+29 -2
View File
@@ -1,6 +1,33 @@
#pragma once #pragma once
#include "Graphics/Resources.h"
#include <Foundation/Foundation.hpp> #include <Foundation/Foundation.hpp>
#include <Metal/Metal.hpp> #include <Metal/Metal.hpp>
#include <QuartzCore/CAMetalLayer.hpp>
#include <QuartzCore/CAMetalLayer.h> #include <QuartzCore/CAMetalLayer.h>
#include <QuartzCore/QuartzCore.hpp> #include <QuartzCore/CAMetalLayer.hpp>
#include <QuartzCore/QuartzCore.hpp>
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
+13
View File
@@ -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(); }
+2 -1
View File
@@ -1,8 +1,8 @@
#include "Window.h" #include "Window.h"
#include "Foundation/NSSharedPtr.hpp"
#include "Graphics/Initializer.h" #include "Graphics/Initializer.h"
#include "Graphics/Metal/Enums.h" #include "Graphics/Metal/Enums.h"
#include "Graphics/Texture.h" #include "Graphics/Texture.h"
#include "Command.h"
#include "Metal/MTLTexture.hpp" #include "Metal/MTLTexture.hpp"
using namespace Seele; using namespace Seele;
using namespace Seele::Metal; using namespace Seele::Metal;
@@ -117,6 +117,7 @@ void Window::beginFrame()
void Window::endFrame() void Window::endFrame()
{ {
graphics->getQueue()->getCommands()->present(drawable);
} }
void Window::onWindowCloseEvent() void Window::onWindowCloseEvent()