diff --git a/src/Engine/Graphics/Metal/Buffer.h b/src/Engine/Graphics/Metal/Buffer.h index 06998e4..140cf0d 100644 --- a/src/Engine/Graphics/Metal/Buffer.h +++ b/src/Engine/Graphics/Metal/Buffer.h @@ -13,7 +13,7 @@ DECLARE_REF(Graphics) class BufferAllocation : public CommandBoundResource { public: BufferAllocation(PGraphics graphics, const std::string& name, uint64 size, - MTL::ResourceOptions options = MTL::ResourceOptionCPUCacheModeDefault); + MTL::ResourceOptions options = MTL::ResourceStorageModeShared); virtual ~BufferAllocation(); void pipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage); diff --git a/src/Engine/Graphics/Metal/Buffer.mm b/src/Engine/Graphics/Metal/Buffer.mm index 35ae8c2..71307a9 100644 --- a/src/Engine/Graphics/Metal/Buffer.mm +++ b/src/Engine/Graphics/Metal/Buffer.mm @@ -18,9 +18,7 @@ BufferAllocation::BufferAllocation(PGraphics graphics, const std::string& name, } BufferAllocation::~BufferAllocation() { - if (buffer != nullptr) { - buffer->release(); - } + buffer->release(); } void BufferAllocation::pipelineBarrier(Gfx::SeAccessFlags, Gfx::SePipelineStageFlags, Gfx::SeAccessFlags, Gfx::SePipelineStageFlags) {} @@ -50,7 +48,7 @@ Buffer::Buffer(PGraphics graphics, uint64 size, Gfx::SeBufferUsageFlags usage, G Buffer::~Buffer() { for (size_t i = 0; i < buffers.size(); ++i) { - // TODO + graphics->getDestructionManager()->queueResourceForDestruction(std::move(buffers[i])); } buffers.clear(); } diff --git a/src/Engine/Graphics/Metal/Command.h b/src/Engine/Graphics/Metal/Command.h index 6e15af6..cfa7ec2 100644 --- a/src/Engine/Graphics/Metal/Command.h +++ b/src/Engine/Graphics/Metal/Command.h @@ -7,6 +7,7 @@ #include "Metal/MTLCommandBuffer.hpp" #include "Metal/MTLComputeCommandEncoder.hpp" #include "Metal/MTLRenderCommandEncoder.hpp" +#include "MinimalEngine.h" #include "RenderPass.h" #include "Resources.h" @@ -19,17 +20,30 @@ DECLARE_REF(Graphics) DECLARE_REF(IndexBuffer) DECLARE_REF(GraphicsPipeline) DECLARE_REF(ComputePipeline) +DECLARE_REF(DescriptorSet) class Command { public: Command(PGraphics graphics, MTL::CommandBuffer* cmdBuffer); ~Command(); + void begin(); + void end(PEvent signal = nullptr); void beginRenderPass(PRenderPass renderPass); void endRenderPass(); void present(MTL::Drawable* drawable); - void end(PEvent signal); void waitDeviceIdle(); + void reset(); void signalEvent(PEvent event); void waitForEvent(PEvent event); + void bindResource(PCommandBoundResource res) { + res->bind(); + boundResources.add(res); + } + enum State { + Init, + Begin, + RenderPass, + Submit, + }; MTL::RenderCommandEncoder* createRenderEncoder() { return parallelEncoder->renderCommandEncoder(); } MTL::BlitCommandEncoder* getBlitEncoder() { assert(!parallelEncoder); @@ -44,9 +58,12 @@ class Command { private: PGraphics graphics; OEvent completed; + State state; MTL::CommandBuffer* cmdBuffer; MTL::ParallelRenderCommandEncoder* parallelEncoder = nullptr; MTL::BlitCommandEncoder* blitEncoder = nullptr; + Array boundResources; + friend class CommandQueue; }; DEFINE_REF(Command) class RenderCommand : public Gfx::RenderCommand { @@ -72,8 +89,10 @@ class RenderCommand : public Gfx::RenderCommand { private: PGraphicsPipeline boundPipeline; PIndexBuffer boundIndexBuffer; + Array boundResources; MTL::RenderCommandEncoder* encoder; std::string name; + friend class CommandQueue; }; DEFINE_REF(RenderCommand) class ComputeCommand : public Gfx::ComputeCommand { @@ -91,8 +110,10 @@ class ComputeCommand : public Gfx::ComputeCommand { private: PComputePipeline boundPipeline; MTL::CommandBuffer* commandBuffer; + Array boundResources; MTL::ComputeCommandEncoder* encoder; std::string name; + friend class CommandQueue; }; DEFINE_REF(ComputeCommand) class CommandQueue { diff --git a/src/Engine/Graphics/Metal/Command.mm b/src/Engine/Graphics/Metal/Command.mm index 9c02d23..1dc4f79 100644 --- a/src/Engine/Graphics/Metal/Command.mm +++ b/src/Engine/Graphics/Metal/Command.mm @@ -22,7 +22,9 @@ using namespace Seele; using namespace Seele::Metal; Command::Command(PGraphics graphics, MTL::CommandBuffer* cmdBuffer) - : graphics(graphics), completed(new Event(graphics)), cmdBuffer(cmdBuffer) {} + : graphics(graphics), completed(new Event(graphics)), cmdBuffer(cmdBuffer) { + state = State::Init; +} Command::~Command() { assert(parallelEncoder == nullptr); @@ -33,25 +35,11 @@ Command::~Command() { cmdBuffer->release(); } -void Command::beginRenderPass(PRenderPass renderPass) { - if (blitEncoder) { - blitEncoder->endEncoding(); - blitEncoder->release(); - blitEncoder = nullptr; - } - renderPass->updateRenderPass(); - parallelEncoder = cmdBuffer->parallelRenderCommandEncoder(renderPass->getDescriptor()); - parallelEncoder->setLabel(NS::String::string(renderPass->getName().c_str(), NS::ASCIIStringEncoding)); -} -void Command::endRenderPass() { - parallelEncoder->endEncoding(); - parallelEncoder->release(); - parallelEncoder = nullptr; +void Command::begin() { + state = State::Begin; } -void Command::present(MTL::Drawable* drawable) { cmdBuffer->presentDrawable(drawable); } - void Command::end(PEvent signal) { assert(!parallelEncoder); if (blitEncoder) { @@ -59,18 +47,58 @@ void Command::end(PEvent signal) { blitEncoder->release(); blitEncoder = nullptr; } + // todo acceleration encoder maybe? if (signal != nullptr) { cmdBuffer->encodeSignalEvent(signal->getHandle(), 1); } cmdBuffer->encodeSignalEvent(completed->getHandle(), 1); cmdBuffer->commit(); + state = State::Submit; } +void Command::beginRenderPass(PRenderPass renderPass) { + assert(state == Begin); + if (blitEncoder) { + blitEncoder->endEncoding(); + blitEncoder->release(); + blitEncoder = nullptr; + } + renderPass->updateRenderPass(); + parallelEncoder = cmdBuffer->parallelRenderCommandEncoder(renderPass->getDescriptor()); + parallelEncoder->setLabel(NS::String::string(renderPass->getName().c_str(), NS::ASCIIStringEncoding)); + state = State::RenderPass; +} + +void Command::endRenderPass() { + assert(state == RenderPass); + parallelEncoder->endEncoding(); + parallelEncoder->release(); + parallelEncoder = nullptr; + state = State::Begin; +} + +void Command::present(MTL::Drawable* drawable) { cmdBuffer->presentDrawable(drawable); } + void Command::waitDeviceIdle() { cmdBuffer->waitUntilCompleted(); } +void Command::reset() { + for(auto& descriptor : boundResources) { + descriptor->unbind(); + } + boundResources.clear(); +} + void Command::signalEvent(PEvent event) { cmdBuffer->encodeSignalEvent(event->getHandle(), 1); } -void Command::waitForEvent(PEvent event) { cmdBuffer->encodeWait(event->getHandle(), 1); } +void Command::waitForEvent(PEvent event) { + assert(state == State::Begin); + if(blitEncoder != nullptr) { + blitEncoder->endEncoding(); + blitEncoder->release(); + blitEncoder = nullptr; + } + cmdBuffer->encodeWait(event->getHandle(), 1); +} RenderCommand::RenderCommand(MTL::RenderCommandEncoder* encoder, const std::string& name) : encoder(encoder), name(name) {} @@ -101,6 +129,7 @@ void RenderCommand::bindPipeline(Gfx::PRayTracingPipeline pipeline) {} void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) { auto metalSet = descriptorSet.cast(); metalSet->bind(); + boundResources.add(metalSet); uint32 descriptorIndex = boundPipeline->getPipelineLayout()->findParameter(metalSet->getLayout()->getName()); auto createEncoder = [&metalSet, descriptorIndex](MTL::Function* function, const Array& usedSets) { @@ -117,32 +146,38 @@ void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) { createEncoder(boundPipeline->vertexFunction, boundPipeline->vertexSets); createEncoder(boundPipeline->fragmentFunction, boundPipeline->fragmentSets); if(metalSet->argumentBuffer == nullptr) { - metalSet->argumentBuffer = metalSet->graphics->getDevice()->newBuffer(metalSet->encoder->encodedLength(), MTL::ResourceOptionCPUCacheModeDefault); - metalSet->encoder->setArgumentBuffer(metalSet->argumentBuffer, 0); + metalSet->argumentBuffer = new BufferAllocation(metalSet->graphics, "ArgumentBuffer", metalSet->encoder->encodedLength()); + metalSet->encoder->setArgumentBuffer(metalSet->argumentBuffer->buffer, 0); } + metalSet->argumentBuffer->bind(); + boundResources.add(PBufferAllocation(metalSet->argumentBuffer)); for (const auto& write : metalSet->uniformWrites) { write.apply(metalSet->encoder); } for (const auto& write : metalSet->bufferWrites) { write.apply(metalSet->encoder); - encoder->useResource(write.buffer, write.access); + encoder->useResource(write.buffer->buffer, write.access); } for (const auto& write : metalSet->samplerWrites) { write.apply(metalSet->encoder); } for (const auto& write : metalSet->textureWrites) { write.apply(metalSet->encoder); - encoder->useResource(write.texture, write.access); + encoder->useResource(write.texture->texture, write.access); } for (const auto& write : metalSet->accelerationWrites) { write.apply(metalSet->encoder); encoder->useResource(write.accelerationStructure, write.access); } - encoder->useResource(metalSet->argumentBuffer, MTL::ResourceUsageRead); - encoder->setObjectBuffer(metalSet->argumentBuffer, 0, descriptorIndex); - encoder->setMeshBuffer(metalSet->argumentBuffer, 0, descriptorIndex); - encoder->setVertexBuffer(metalSet->argumentBuffer, 0, descriptorIndex); - encoder->setFragmentBuffer(metalSet->argumentBuffer, 0, descriptorIndex); + for(auto& res : metalSet->boundResources) { + res->bind(); + boundResources.add(res); + } + encoder->useResource(metalSet->argumentBuffer->buffer, MTL::ResourceUsageRead); + encoder->setObjectBuffer(metalSet->argumentBuffer->buffer, 0, descriptorIndex); + encoder->setMeshBuffer(metalSet->argumentBuffer->buffer, 0, descriptorIndex); + encoder->setVertexBuffer(metalSet->argumentBuffer->buffer, 0, descriptorIndex); + encoder->setFragmentBuffer(metalSet->argumentBuffer->buffer, 0, descriptorIndex); } void RenderCommand::bindDescriptor(const Array& descriptorSets) { @@ -157,7 +192,9 @@ void RenderCommand::bindVertexBuffer(const Array& buffers) { } } -void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer gfxIndexBuffer) { boundIndexBuffer = gfxIndexBuffer.cast(); } +void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer gfxIndexBuffer) { + boundIndexBuffer = gfxIndexBuffer.cast(); +} void RenderCommand::pushConstants(Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) { uint pushIndex = boundPipeline->getPipelineLayout()->findParameter("pOffsets"); @@ -200,7 +237,10 @@ void RenderCommand::traceRays(uint32 width, uint32 height, uint32 depth) {} ComputeCommand::ComputeCommand(MTL::CommandBuffer* cmdBuffer, const std::string& name) : commandBuffer(cmdBuffer), encoder(cmdBuffer->computeCommandEncoder()), name(name) {} -ComputeCommand::~ComputeCommand() { encoder->release(); commandBuffer->release(); } +ComputeCommand::~ComputeCommand() { + encoder->release(); + commandBuffer->release(); +} void ComputeCommand::end() { encoder->endEncoding(); @@ -215,6 +255,7 @@ void ComputeCommand::bindPipeline(Gfx::PComputePipeline pipeline) { void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet set) { auto metalSet = set.cast(); metalSet->bind(); + boundResources.add(metalSet); uint32 descriptorIndex = boundPipeline->getPipelineLayout()->findParameter(metalSet->getLayout()->getName()); if(metalSet->encoder == nullptr) { if (metalSet->isPlainDescriptor()) { @@ -222,29 +263,35 @@ void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet set) { } else { metalSet->encoder = boundPipeline->computeFunction->newArgumentEncoder(descriptorIndex); } - metalSet->argumentBuffer = metalSet->graphics->getDevice()->newBuffer(metalSet->encoder->encodedLength(), MTL::ResourceOptionCPUCacheModeDefault); - metalSet->encoder->setArgumentBuffer(metalSet->argumentBuffer, 0); + metalSet->argumentBuffer = new BufferAllocation(metalSet->graphics, "ArgumentBuffer", metalSet->encoder->encodedLength()); + metalSet->encoder->setArgumentBuffer(metalSet->argumentBuffer->buffer, 0); } + metalSet->argumentBuffer->bind(); + boundResources.add(PBufferAllocation(metalSet->argumentBuffer)); for (const auto& write : metalSet->uniformWrites) { write.apply(metalSet->encoder); } for (const auto& write : metalSet->bufferWrites) { write.apply(metalSet->encoder); - encoder->useResource(write.buffer, write.access); + encoder->useResource(write.buffer->buffer, write.access); } for (const auto& write : metalSet->samplerWrites) { write.apply(metalSet->encoder); } for (const auto& write : metalSet->textureWrites) { write.apply(metalSet->encoder); - encoder->useResource(write.texture, write.access); + encoder->useResource(write.texture->texture, write.access); } for (const auto& write : metalSet->accelerationWrites) { write.apply(metalSet->encoder); encoder->useResource(write.accelerationStructure, write.access); } - encoder->useResource(metalSet->argumentBuffer, MTL::ResourceUsageRead); - encoder->setBuffer(metalSet->argumentBuffer, 0, descriptorIndex); + for(auto& res : metalSet->boundResources) { + res->bind(); + boundResources.add(res); + } + encoder->useResource(metalSet->argumentBuffer->buffer, MTL::ResourceUsageRead); + encoder->setBuffer(metalSet->argumentBuffer->buffer, 0, descriptorIndex); } void ComputeCommand::bindDescriptor(const Array& sets) { @@ -286,6 +333,10 @@ OComputeCommand CommandQueue::getComputeCommand(const std::string& name) { retur void CommandQueue::executeCommands(Array commands) { for (auto& command : commands) { auto metalCmd = Gfx::PRenderCommand(command).cast(); + for(auto& descriptor : metalCmd->boundResources) { + // have already bind marked as bound when added to subcommand + activeCommand->boundResources.add(descriptor); + } metalCmd->end(); } } @@ -293,35 +344,48 @@ void CommandQueue::executeCommands(Array commands) { void CommandQueue::executeCommands(Array commands) { for (auto& command : commands) { auto metalCmd = Gfx::PComputeCommand(command).cast(); + for(auto& descriptor : metalCmd->boundResources) { + // have already bind marked as bound when added to subcommand + activeCommand->boundResources.add(descriptor); + } metalCmd->end(); } } void CommandQueue::submitCommands(PEvent signalSemaphore) { - activeCommand->getHandle()->addCompletedHandler(MTL::CommandBufferHandler([&](MTL::CommandBuffer* cmdBuffer) { + /*activeCommand->getHandle()->addCompletedHandler(MTL::CommandBufferHandler([&](MTL::CommandBuffer* cmdBuffer) { for (auto it = pendingCommands.begin(); it != pendingCommands.end(); it++) { if ((*it)->getHandle() == cmdBuffer) { + auto& cmd = *it; + cmd->reset(); readyCommands.add(std::move(*it)); pendingCommands.erase(it); return; } } })); + PEvent prevCmdEvent = activeCommand->getCompletedEvent(); activeCommand->end(signalSemaphore); activeCommand->waitDeviceIdle(); - PEvent prevCmdEvent = activeCommand->getCompletedEvent(); pendingCommands.add(std::move(activeCommand)); if (!readyCommands.empty()) { activeCommand = std::move(readyCommands.front()); + activeCommand->begin(); readyCommands.removeAt(0); activeCommand->waitForEvent(prevCmdEvent); } else { MTL::CommandBufferDescriptor* descriptor = MTL::CommandBufferDescriptor::alloc()->init(); descriptor->setErrorOptions(MTL::CommandBufferErrorOptionEncoderExecutionStatus); activeCommand = new Command(graphics, queue->commandBuffer(descriptor)); + activeCommand->begin(); activeCommand->waitForEvent(prevCmdEvent); descriptor->release(); - } + }*/ + activeCommand->end(); + activeCommand->waitDeviceIdle(); + activeCommand->reset(); + activeCommand = new Command(graphics, queue->commandBuffer()); + activeCommand->begin(); } IOCommandQueue::IOCommandQueue(PGraphics graphics) : graphics(graphics) { diff --git a/src/Engine/Graphics/Metal/Descriptor.h b/src/Engine/Graphics/Metal/Descriptor.h index 2e81911..947c72f 100644 --- a/src/Engine/Graphics/Metal/Descriptor.h +++ b/src/Engine/Graphics/Metal/Descriptor.h @@ -6,6 +6,7 @@ #include "Graphics/Initializer.h" #include "Graphics/Metal/Command.h" #include "Graphics/Metal/Resources.h" +#include "Graphics/Metal/Texture.h" #include "Metal/MTLAccelerationStructure.hpp" #include "Metal/MTLArgumentEncoder.hpp" #include "Metal/MTLCommandEncoder.hpp" @@ -80,8 +81,9 @@ class DescriptorSet : public Gfx::DescriptorSet, public CommandBoundResource { private: PGraphics graphics; PDescriptorPool owner; - MTL::Buffer* argumentBuffer = nullptr; + OBufferAllocation argumentBuffer = nullptr; MTL::ArgumentEncoder* encoder = nullptr; + Array boundResources; struct UniformWriteInfo { @@ -94,23 +96,23 @@ class DescriptorSet : public Gfx::DescriptorSet, public CommandBoundResource { { uint32 index; MTL::ResourceUsage access; - MTL::Buffer* buffer; - void apply(MTL::ArgumentEncoder* encoder) const { encoder->setBuffer(buffer, 0, index); } + PBufferAllocation buffer; + void apply(MTL::ArgumentEncoder* encoder) const { encoder->setBuffer(buffer->buffer, 0, index); } }; Array bufferWrites; struct TextureWriteInfo { uint32 index; MTL::ResourceUsage access; - MTL::Texture* texture; - void apply(MTL::ArgumentEncoder* encoder) const { encoder->setTexture(texture, index); } + PTextureHandle texture; + void apply(MTL::ArgumentEncoder* encoder) const { encoder->setTexture(texture->texture, index); } }; Array textureWrites; struct SamplerWriteInfo { uint32 index; - MTL::SamplerState* sampler; - void apply(MTL::ArgumentEncoder* encoder) const { encoder->setSamplerState(sampler, index); } + PSampler sampler; + void apply(MTL::ArgumentEncoder* encoder) const { encoder->setSamplerState(sampler->getHandle(), index); } }; Array samplerWrites; struct AccelerationStructureWriteInfo diff --git a/src/Engine/Graphics/Metal/Descriptor.mm b/src/Engine/Graphics/Metal/Descriptor.mm index 09f9227..0c33c0b 100644 --- a/src/Engine/Graphics/Metal/Descriptor.mm +++ b/src/Engine/Graphics/Metal/Descriptor.mm @@ -80,20 +80,17 @@ void DescriptorPool::reset() {} DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner) : Gfx::DescriptorSet(owner->getLayout()), CommandBoundResource(graphics), graphics(graphics), owner(owner) { - std::cout << "New Descriptor set" << std::endl; } DescriptorSet::~DescriptorSet() { if(encoder != nullptr) { encoder->release(); } - if(argumentBuffer != nullptr) { - argumentBuffer->release(); - } std::cout << "destroying descriptor set" << std::endl; } void DescriptorSet::reset() { + boundResources.clear(); uniformWrites.clear(); bufferWrites.clear(); textureWrites.clear(); @@ -118,9 +115,10 @@ void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PSh PShaderBuffer buffer = uniformBuffer.cast(); bufferWrites.add(BufferWriteInfo{ .index = flattenedIndex, - .buffer = buffer->getHandle(), + .buffer = buffer->getAlloc(), .access = owner->getLayout()->variableMapping[name].access, }); + boundResources.add(buffer->getAlloc()); } void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PVertexBuffer uniformBuffer) { @@ -128,9 +126,10 @@ void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PVe PVertexBuffer buffer = uniformBuffer.cast(); bufferWrites.add(BufferWriteInfo{ .index = flattenedIndex, - .buffer = buffer->getHandle(), + .buffer = buffer->getAlloc(), .access = owner->getLayout()->variableMapping[name].access, }); + boundResources.add(buffer->getAlloc()); } void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PIndexBuffer uniformBuffer) { @@ -138,9 +137,10 @@ void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PIn PIndexBuffer buffer = uniformBuffer.cast(); bufferWrites.add(BufferWriteInfo{ .index = flattenedIndex, - .buffer = buffer->getHandle(), + .buffer = buffer->getAlloc(), .access = owner->getLayout()->variableMapping[name].access, }); + boundResources.add(buffer->getAlloc()); } void DescriptorSet::updateSampler(const std::string& name, uint32 index, Gfx::PSampler samplerState) { @@ -148,7 +148,7 @@ void DescriptorSet::updateSampler(const std::string& name, uint32 index, Gfx::PS PSampler sampler = samplerState.cast(); samplerWrites.add(SamplerWriteInfo{ .index = flattenedIndex, - .sampler = sampler->getHandle(), + .sampler = sampler, }); } @@ -157,9 +157,10 @@ void DescriptorSet::updateTexture(const std::string& name, uint32 index, Gfx::PT PTextureBase tex = texture.cast(); textureWrites.add(TextureWriteInfo{ .index = flattenedIndex, - .texture = tex->getImage(), + .texture = tex->getHandle(), .access = owner->getLayout()->variableMapping[name].access, }); + boundResources.add(tex->getHandle()); } void DescriptorSet::updateTexture(const std::string& name, uint32 index, Gfx::PTexture3D texture) { @@ -167,9 +168,10 @@ void DescriptorSet::updateTexture(const std::string& name, uint32 index, Gfx::PT PTextureBase tex = texture.cast(); textureWrites.add(TextureWriteInfo{ .index = flattenedIndex, - .texture = tex->getImage(), + .texture = tex->getHandle(), .access = owner->getLayout()->variableMapping[name].access, }); + boundResources.add(tex->getHandle()); } void DescriptorSet::updateTexture(const std::string& name, uint32 index, Gfx::PTextureCube texture) { @@ -177,9 +179,10 @@ void DescriptorSet::updateTexture(const std::string& name, uint32 index, Gfx::PT PTextureBase tex = texture.cast(); textureWrites.add(TextureWriteInfo{ .index = flattenedIndex, - .texture = tex->getImage(), + .texture = tex->getHandle(), .access = owner->getLayout()->variableMapping[name].access, }); + boundResources.add(tex->getHandle()); } void DescriptorSet::updateAccelerationStructure(const std::string& name, uint32 index, Gfx::PTopLevelAS as) { assert(false && "TODO"); } diff --git a/src/Engine/Graphics/Metal/Graphics.h b/src/Engine/Graphics/Metal/Graphics.h index 2f9f8c6..e4319ef 100644 --- a/src/Engine/Graphics/Metal/Graphics.h +++ b/src/Engine/Graphics/Metal/Graphics.h @@ -1,5 +1,6 @@ #pragma once #include "Graphics/Graphics.h" +#include "Graphics/Metal/Resources.h" #include "Metal/Metal.hpp" namespace Seele { @@ -80,12 +81,14 @@ class Graphics : public Gfx::Graphics { virtual Gfx::OCallableShader createCallableShader(const ShaderCreateInfo& createInfo) override; MTL::Device* getDevice() const { return device; } + PDestructionManager getDestructionManager() const { return destructionManager; } PCommandQueue getQueue() const { return queue; } PIOCommandQueue getIOQueue() const { return ioQueue; } protected: MTL::Device* device; OCommandQueue queue; + ODestructionManager destructionManager; OIOCommandQueue ioQueue; OPipelineCache cache; }; diff --git a/src/Engine/Graphics/Metal/Graphics.mm b/src/Engine/Graphics/Metal/Graphics.mm index f60bd6c..8d27183 100644 --- a/src/Engine/Graphics/Metal/Graphics.mm +++ b/src/Engine/Graphics/Metal/Graphics.mm @@ -25,6 +25,7 @@ Graphics::~Graphics() {} void Graphics::init(GraphicsInitializer) { glfwInit(); device = MTL::CreateSystemDefaultDevice(); + destructionManager = new DestructionManager(this); queue = new CommandQueue(this); ioQueue = new IOCommandQueue(this); cache = new PipelineCache(this, "pipelines.metal"); diff --git a/src/Engine/Graphics/Metal/Resources.h b/src/Engine/Graphics/Metal/Resources.h index 3b4bb47..7d8b6d6 100644 --- a/src/Engine/Graphics/Metal/Resources.h +++ b/src/Engine/Graphics/Metal/Resources.h @@ -1,16 +1,29 @@ #pragma once #include "Graphics/Initializer.h" #include "Graphics/Resources.h" -#include "Metal/MTLSampler.hpp" +#include "Containers/List.h" #include #include -#include -#include #include namespace Seele { namespace Metal { DECLARE_REF(Graphics); + +DECLARE_REF(CommandBoundResource) +class DestructionManager { + public: + DestructionManager(PGraphics graphics); + ~DestructionManager(); + void queueResourceForDestruction(OCommandBoundResource resource); + void notifyCommandComplete(); + + private: + PGraphics graphics; + Array resources; // todo: maybe list? +}; +DEFINE_REF(DestructionManager) + class CommandBoundResource { public: CommandBoundResource(PGraphics graphics) : graphics(graphics) {} @@ -59,4 +72,4 @@ class Sampler : public Gfx::Sampler { }; DEFINE_REF(Sampler) } // namespace Metal -} // namespace Seele \ No newline at end of file +} // namespace Seele diff --git a/src/Engine/Graphics/Metal/Resources.mm b/src/Engine/Graphics/Metal/Resources.mm index f14bbba..91885e5 100644 --- a/src/Engine/Graphics/Metal/Resources.mm +++ b/src/Engine/Graphics/Metal/Resources.mm @@ -6,6 +6,27 @@ using namespace Seele; using namespace Seele::Metal; +DestructionManager::DestructionManager(PGraphics graphics) : graphics(graphics) {} + +DestructionManager::~DestructionManager() {} + +void DestructionManager::queueResourceForDestruction(OCommandBoundResource resource) { + if (resource == nullptr) + return; + if (resource->isCurrentlyBound()) { + resources.add(std::move(resource)); + } +} + +void DestructionManager::notifyCommandComplete() { + for (size_t i = 0; i < resources.size(); ++i) { + if (!resources[i]->isCurrentlyBound()) { + resources.removeAt(i, false); + i--; + } + } +} + Fence::Fence(PGraphics graphics) : handle(graphics->getDevice()->newFence()) {} Fence::~Fence() { handle->release(); } @@ -34,4 +55,4 @@ Sampler::Sampler(PGraphics graphics, const SamplerCreateInfo& createInfo) { desc->release(); } -Sampler::~Sampler() { sampler->release(); } \ No newline at end of file +Sampler::~Sampler() { sampler->release(); } diff --git a/src/Engine/Graphics/Metal/Texture.h b/src/Engine/Graphics/Metal/Texture.h index 70b0ed2..752dc3e 100644 --- a/src/Engine/Graphics/Metal/Texture.h +++ b/src/Engine/Graphics/Metal/Texture.h @@ -1,12 +1,13 @@ #pragma once #include "Graphics.h" #include "Graphics/Enums.h" +#include "Graphics/Metal/Resources.h" #include "Graphics/Texture.h" #include "Metal/MTLTexture.hpp" namespace Seele { namespace Metal { -class TextureHandle { +class TextureHandle : public CommandBoundResource{ public: TextureHandle(PGraphics graphics, MTL::TextureType type, const TextureCreateInfo& createInfo, MTL::Texture* existingImage); virtual ~TextureHandle(); diff --git a/src/Engine/Graphics/Metal/Texture.mm b/src/Engine/Graphics/Metal/Texture.mm index 5f56976..7adc3d9 100644 --- a/src/Engine/Graphics/Metal/Texture.mm +++ b/src/Engine/Graphics/Metal/Texture.mm @@ -2,8 +2,10 @@ #include "Enums.h" #include "Graphics/Enums.h" #include "Graphics/Initializer.h" +#include "Graphics/Metal/Buffer.h" #include "Graphics/Metal/Graphics.h" #include "Command.h" +#include "Graphics/Metal/Resources.h" #include "Metal/MTLTexture.hpp" #include "Metal/MTLTypes.hpp" @@ -11,7 +13,7 @@ using namespace Seele; using namespace Seele::Metal; TextureHandle::TextureHandle(PGraphics graphics, MTL::TextureType type, const TextureCreateInfo& createInfo, MTL::Texture* existingImage) - : texture(existingImage), type(type), width(createInfo.width), height(createInfo.height), depth(createInfo.depth), + : CommandBoundResource(graphics), 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) { @@ -50,8 +52,8 @@ TextureHandle::TextureHandle(PGraphics graphics, MTL::TextureType type, const Te } if(createInfo.sourceData.data != nullptr) { - MTL::Buffer* stagingBuffer = graphics->getDevice()->newBuffer(createInfo.sourceData.size, MTL::ResourceStorageModeShared); - std::memcpy(stagingBuffer->contents(), createInfo.sourceData.data, createInfo.sourceData.size); + OBufferAllocation stagingBuffer = new BufferAllocation(graphics, "TextureStaging", createInfo.sourceData.size, MTL::ResourceStorageModeShared); + std::memcpy(stagingBuffer->map(), createInfo.sourceData.data, createInfo.sourceData.size); MTL::BlitCommandEncoder* blitEnc = graphics->getQueue()->getCommands()->getBlitEncoder(); uint32 sliceSize = createInfo.sourceData.size / arrayCount; uint32 numSlices = arrayCount; @@ -61,12 +63,14 @@ TextureHandle::TextureHandle(PGraphics graphics, MTL::TextureType type, const Te } uint32 offset = 0; for(uint32 slice = 0; slice < numSlices; ++slice){ - blitEnc->copyFromBuffer(stagingBuffer, offset, sliceSize / createInfo.height, arrayCount == 1 ? 0 : sliceSize, MTL::Size(createInfo.width, createInfo.height, createInfo.depth), texture, slice, 0, MTL::Origin()); + blitEnc->copyFromBuffer(stagingBuffer->buffer, offset, sliceSize / createInfo.height, arrayCount == 1 ? 0 : sliceSize, MTL::Size(createInfo.width, createInfo.height, createInfo.depth), texture, slice, 0, MTL::Origin()); offset += sliceSize; } if(mipLevels > 1) { blitEnc->generateMipmaps(texture); } + graphics->getQueue()->getCommands()->bindResource(PBufferAllocation(stagingBuffer)); + graphics->getDestructionManager()->queueResourceForDestruction(std::move(stagingBuffer)); } } diff --git a/src/Engine/Graphics/Metal/Window.h b/src/Engine/Graphics/Metal/Window.h index c5b9362..8218489 100644 --- a/src/Engine/Graphics/Metal/Window.h +++ b/src/Engine/Graphics/Metal/Window.h @@ -49,7 +49,7 @@ class Window : public Gfx::Window { WindowCreateInfo preferences; GLFWwindow* windowHandle; NSWindow* metalWindow; - CAMetalLayer* metalLayer; + CA::MetalLayer* metalLayer; CA::MetalDrawable* drawable; OTexture2D backBuffer; diff --git a/src/Engine/Graphics/Metal/Window.mm b/src/Engine/Graphics/Metal/Window.mm index 93fcbc5..2645508 100644 --- a/src/Engine/Graphics/Metal/Window.mm +++ b/src/Engine/Graphics/Metal/Window.mm @@ -85,15 +85,15 @@ Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo) : graphic framebufferHeight = height; metalWindow = glfwGetCocoaWindow(handle); - metalLayer = [CAMetalLayer layer]; - metalLayer.device = (__bridge id)graphics->getDevice(); - metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB; - metalLayer.drawableSize = CGSizeMake(createInfo.width, createInfo.height); - metalWindow.contentView.layer = metalLayer; - metalWindow.contentView.wantsLayer = YES; + metalLayer = CA::MetalLayer::layer(); + metalLayer->setDevice(graphics->getDevice()); + metalLayer->setPixelFormat(MTL::PixelFormatBGRA8Unorm_sRGB); + metalLayer->setDrawableSize(CGSizeMake(createInfo.width, createInfo.height)); + [[metalWindow contentView] setLayer:(__bridge id)metalLayer]; + [[metalWindow contentView] setWantsLayer:YES]; framebufferFormat = Gfx::SE_FORMAT_B8G8R8A8_SRGB; - drawable = (__bridge CA::MetalDrawable*)[metalLayer nextDrawable]; + drawable = metalLayer->nextDrawable(); createBackBuffer(); } @@ -116,7 +116,8 @@ void Window::endFrame() { graphics->getQueue()->getCommands()->present(drawable); graphics->getQueue()->submitCommands(); currentFrameIndex++; - drawable = (__bridge CA::MetalDrawable*)[metalLayer nextDrawable]; + drawable->release(); + drawable = metalLayer->nextDrawable(); createBackBuffer(); } @@ -156,18 +157,18 @@ void Window::resize(int width, int height) { return; } paused = true; - metalLayer.drawableSize = CGSizeMake(width, height); - [drawable release]; + metalLayer->setDrawableSize(CGSizeMake(width, height)); + drawable->release(); framebufferWidth = width; framebufferHeight = height; // Deallocate the textures if they have been created - drawable = (__bridge CA::MetalDrawable*)[metalLayer nextDrawable]; + drawable = metalLayer->nextDrawable(); createBackBuffer(); resizeCallback(width, height); } void Window::createBackBuffer() { - MTL::Texture* buf = (__bridge MTL::Texture*)[drawable texture]; + MTL::Texture* buf = drawable->texture(); backBuffer = new Texture2D(graphics, TextureCreateInfo{ .width = static_cast(buf->width()), diff --git a/src/Engine/Graphics/Vulkan/Command.h b/src/Engine/Graphics/Vulkan/Command.h index 98a7797..eaffadf 100644 --- a/src/Engine/Graphics/Vulkan/Command.h +++ b/src/Engine/Graphics/Vulkan/Command.h @@ -55,7 +55,7 @@ class Command { Array waitFlags; Array executingRenders; Array executingComputes; - Array boundResources; + Array boundResources; VkQueryPipelineStatisticFlags statisticsFlags; friend class RenderCommand; friend class CommandPool;