i hate metal

This commit is contained in:
Dynamitos
2025-03-05 09:41:34 +01:00
parent 5693802215
commit 4d7c5db2c3
15 changed files with 218 additions and 86 deletions
+1 -1
View File
@@ -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);
+2 -4
View File
@@ -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();
}
+22 -1
View File
@@ -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<PCommandBoundResource> 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<PCommandBoundResource> 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<PCommandBoundResource> boundResources;
MTL::ComputeCommandEncoder* encoder;
std::string name;
friend class CommandQueue;
};
DEFINE_REF(ComputeCommand)
class CommandQueue {
+102 -38
View File
@@ -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<DescriptorSet>();
metalSet->bind();
boundResources.add(metalSet);
uint32 descriptorIndex = boundPipeline->getPipelineLayout()->findParameter(metalSet->getLayout()->getName());
auto createEncoder = [&metalSet, descriptorIndex](MTL::Function* function, const Array<uint32>& 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<Gfx::PDescriptorSet>& descriptorSets) {
@@ -157,7 +192,9 @@ void RenderCommand::bindVertexBuffer(const Array<Gfx::PVertexBuffer>& buffers) {
}
}
void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer gfxIndexBuffer) { boundIndexBuffer = gfxIndexBuffer.cast<IndexBuffer>(); }
void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer gfxIndexBuffer) {
boundIndexBuffer = gfxIndexBuffer.cast<IndexBuffer>();
}
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<DescriptorSet>();
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<Gfx::PDescriptorSet>& sets) {
@@ -286,6 +333,10 @@ OComputeCommand CommandQueue::getComputeCommand(const std::string& name) { retur
void CommandQueue::executeCommands(Array<Gfx::ORenderCommand> commands) {
for (auto& command : commands) {
auto metalCmd = Gfx::PRenderCommand(command).cast<RenderCommand>();
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<Gfx::ORenderCommand> commands) {
void CommandQueue::executeCommands(Array<Gfx::OComputeCommand> commands) {
for (auto& command : commands) {
auto metalCmd = Gfx::PComputeCommand(command).cast<ComputeCommand>();
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) {
+9 -7
View File
@@ -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<PCommandBoundResource> 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<BufferWriteInfo> 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<TextureWriteInfo> 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<SamplerWriteInfo> samplerWrites;
struct AccelerationStructureWriteInfo
+14 -11
View File
@@ -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<ShaderBuffer>();
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<VertexBuffer>();
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<IndexBuffer>();
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<Sampler>();
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<TextureBase>();
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<TextureBase>();
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<TextureBase>();
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"); }
+3
View File
@@ -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;
};
+1
View File
@@ -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");
+17 -4
View File
@@ -1,16 +1,29 @@
#pragma once
#include "Graphics/Initializer.h"
#include "Graphics/Resources.h"
#include "Metal/MTLSampler.hpp"
#include "Containers/List.h"
#include <Foundation/Foundation.hpp>
#include <Metal/Metal.hpp>
#include <QuartzCore/CAMetalLayer.h>
#include <QuartzCore/CAMetalLayer.hpp>
#include <QuartzCore/QuartzCore.hpp>
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<OCommandBoundResource> 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
} // namespace Seele
+22 -1
View File
@@ -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(); }
Sampler::~Sampler() { sampler->release(); }
+2 -1
View File
@@ -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();
+8 -4
View File
@@ -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));
}
}
+1 -1
View File
@@ -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;
+13 -12
View File
@@ -85,15 +85,15 @@ Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo) : graphic
framebufferHeight = height;
metalWindow = glfwGetCocoaWindow(handle);
metalLayer = [CAMetalLayer layer];
metalLayer.device = (__bridge id<MTLDevice>)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<uint32>(buf->width()),
+1 -1
View File
@@ -55,7 +55,7 @@ class Command {
Array<VkPipelineStageFlags> waitFlags;
Array<ORenderCommand> executingRenders;
Array<OComputeCommand> executingComputes;
Array<PDescriptorSet> boundResources;
Array<PCommandBoundResource> boundResources;
VkQueryPipelineStatisticFlags statisticsFlags;
friend class RenderCommand;
friend class CommandPool;