i hate metal
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"); }
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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()),
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user