Files
Seele/src/Engine/Graphics/Metal/Command.mm
T

239 lines
9.1 KiB
Plaintext
Raw Normal View History

2024-04-10 08:43:56 +02:00
#include "Command.h"
2024-04-14 11:35:37 +02:00
#include "Buffer.h"
2024-04-17 14:33:06 +02:00
#include "Containers/Array.h"
2024-04-14 11:35:37 +02:00
#include "Descriptor.h"
#include "Enums.h"
2024-04-17 14:33:06 +02:00
#include "Graphics/Command.h"
2024-04-14 11:35:37 +02:00
#include "Graphics/Enums.h"
2024-04-10 10:23:06 +02:00
#include "Graphics/Graphics.h"
2024-04-17 14:33:06 +02:00
#include "Graphics/Resources.h"
2024-04-19 18:23:36 +02:00
#include "Metal/MTLCaptureManager.hpp"
2024-04-14 11:35:37 +02:00
#include "Pipeline.h"
#include "Resources.h"
2024-04-10 08:43:56 +02:00
#include "Window.h"
2024-04-20 21:35:43 +02:00
#include <iostream>
2024-04-10 08:43:56 +02:00
using namespace Seele;
using namespace Seele::Metal;
2024-08-28 17:54:14 +02:00
Command::Command(PGraphics graphics, MTL::CommandBuffer* cmdBuffer)
: graphics(graphics), completed(new Event(graphics)), cmdBuffer(cmdBuffer) {}
2024-04-10 09:58:39 +02:00
2024-04-17 14:33:06 +02:00
Command::~Command() {}
2024-04-10 09:58:39 +02:00
void Command::beginRenderPass(PRenderPass renderPass) {
2024-08-28 17:54:14 +02:00
if (blitEncoder) {
blitEncoder->endEncoding();
blitEncoder = nullptr;
}
renderPass->updateRenderPass();
parallelEncoder = cmdBuffer->parallelRenderCommandEncoder(renderPass->getDescriptor());
2024-04-10 08:43:56 +02:00
}
2024-04-17 14:33:06 +02:00
void Command::endRenderPass() {
2024-08-28 17:54:14 +02:00
parallelEncoder->endEncoding();
parallelEncoder = nullptr;
2024-04-17 14:33:06 +02:00
}
2024-04-10 09:58:39 +02:00
2024-08-28 17:54:14 +02:00
void Command::present(MTL::Drawable* drawable) { cmdBuffer->presentDrawable(drawable); }
2024-04-10 08:43:56 +02:00
2024-04-10 09:58:39 +02:00
void Command::end(PEvent signal) {
2024-08-28 17:54:14 +02:00
assert(!parallelEncoder);
blitEncoder->endEncoding();
if (signal != nullptr) {
cmdBuffer->encodeSignalEvent(signal->getHandle(), 1);
}
cmdBuffer->encodeSignalEvent(completed->getHandle(), 1);
cmdBuffer->commit();
2024-04-10 08:43:56 +02:00
}
2024-04-10 15:50:20 +02:00
void Command::waitDeviceIdle() { cmdBuffer->waitUntilCompleted(); }
2024-04-10 08:43:56 +02:00
2024-08-28 17:54:14 +02:00
void Command::signalEvent(PEvent event) { cmdBuffer->encodeSignalEvent(event->getHandle(), 1); }
2024-04-10 08:43:56 +02:00
2024-08-28 17:54:14 +02:00
void Command::waitForEvent(PEvent event) { cmdBuffer->encodeWait(event->getHandle(), 1); }
2024-04-10 08:43:56 +02:00
2024-08-28 17:54:14 +02:00
RenderCommand::RenderCommand(MTL::RenderCommandEncoder* encoder, const std::string& name) : encoder(encoder), name(name) {}
2024-04-10 09:58:39 +02:00
2024-04-17 14:33:06 +02:00
RenderCommand::~RenderCommand() {}
2024-04-10 09:58:39 +02:00
void RenderCommand::end() { encoder->endEncoding(); }
void RenderCommand::setViewport(Gfx::PViewport viewport) {
2024-08-28 17:54:14 +02:00
MTL::Viewport vp = viewport.cast<Viewport>()->getHandle();
MTL::ScissorRect rect = {
.x = static_cast<NS::UInteger>(vp.originX),
.y = static_cast<NS::UInteger>(vp.originY),
.width = static_cast<NS::UInteger>(vp.width),
.height = static_cast<NS::UInteger>(vp.height),
};
encoder->setViewport(vp);
encoder->setScissorRect(rect);
2024-04-10 08:43:56 +02:00
}
2024-04-10 09:58:39 +02:00
void RenderCommand::bindPipeline(Gfx::PGraphicsPipeline pipeline) {
2024-08-28 17:54:14 +02:00
boundPipeline = pipeline.cast<GraphicsPipeline>();
encoder->setRenderPipelineState(boundPipeline->getHandle());
2024-08-26 21:49:09 +02:00
}
2024-08-28 17:54:14 +02:00
void RenderCommand::bindPipeline(Gfx::PRayTracingPipeline pipeline) {}
void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet, Array<uint32> offsets) {
auto metalSet = descriptorSet.cast<DescriptorSet>();
metalSet->bind();
2024-04-10 08:43:56 +02:00
}
2024-08-28 17:54:14 +02:00
void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets, Array<uint32> offsets) {
for (auto set : descriptorSets) {
bindDescriptor(set, offsets);
2024-04-20 21:35:43 +02:00
}
2024-08-28 17:54:14 +02:00
}
void RenderCommand::bindVertexBuffer(const Array<Gfx::PVertexBuffer>& buffers) {
uint32 i = 0;
for (auto buffer : buffers) {
encoder->setVertexBuffer(buffer.cast<VertexBuffer>()->getHandle(), 0, METAL_VERTEXBUFFER_OFFSET + i++);
2024-04-20 21:35:43 +02:00
}
2024-08-28 17:54:14 +02:00
}
void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer gfxIndexBuffer) { boundIndexBuffer = gfxIndexBuffer.cast<IndexBuffer>(); }
void RenderCommand::pushConstants(Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) {
if (stage & Gfx::SE_SHADER_STAGE_VERTEX_BIT) {
encoder->setVertexBytes((char*)data + offset, size, 0);
}
if (stage & Gfx::SE_SHADER_STAGE_FRAGMENT_BIT) {
encoder->setFragmentBytes((char*)data + offset, size, 0);
2024-08-26 21:49:09 +02:00
}
2024-04-10 08:43:56 +02:00
}
2024-08-28 17:54:14 +02:00
void RenderCommand::draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance) {
encoder->drawPrimitives(boundPipeline->getPrimitive(), firstVertex, vertexCount, instanceCount, firstInstance);
2024-04-10 08:43:56 +02:00
}
2024-08-28 17:54:14 +02:00
void RenderCommand::drawIndexed(uint32 indexCount, uint32 instanceCount, int32 firstIndex, uint32 vertexOffset, uint32 firstInstance) {
encoder->drawIndexedPrimitives(boundPipeline->getPrimitive(), indexCount, cast(boundIndexBuffer->getIndexType()),
boundIndexBuffer->getHandle(), firstIndex, instanceCount, vertexOffset, firstInstance);
2024-04-10 08:43:56 +02:00
}
2024-04-14 11:35:37 +02:00
void RenderCommand::drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) {
2024-08-28 17:54:14 +02:00
// TODO:
std::cout << "Draw" << std::endl;
encoder->setFragmentBuffer(argumentBuffer, 0, 2);
encoder->setMeshBuffer(argumentBuffer, 0, 2);
encoder->setObjectBuffer(argumentBuffer, 0, 2);
encoder->drawMeshThreadgroups(MTL::Size(groupX, groupY, groupZ), MTL::Size(128, 1, 1), MTL::Size(32, 1, 1));
2024-04-14 11:35:37 +02:00
}
2024-04-10 09:58:39 +02:00
2024-08-28 17:54:14 +02:00
void RenderCommand::drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) {
// encoder->drawMeshThreadgroups()
2024-05-17 18:08:11 +02:00
}
2024-08-28 17:54:14 +02:00
void RenderCommand::traceRays(uint32 width, uint32 height, uint32 depth) {}
2024-08-26 21:49:09 +02:00
2024-08-28 17:54:14 +02:00
ComputeCommand::ComputeCommand(MTL::CommandBuffer* cmdBuffer, const std::string& name)
: commandBuffer(cmdBuffer), encoder(cmdBuffer->computeCommandEncoder()), name(name) {}
2024-04-10 09:58:39 +02:00
2024-04-17 14:33:06 +02:00
ComputeCommand::~ComputeCommand() {}
2024-04-10 09:58:39 +02:00
2024-04-17 14:33:06 +02:00
void ComputeCommand::end() {
2024-08-28 17:54:14 +02:00
encoder->endEncoding();
commandBuffer->commit();
2024-04-17 14:33:06 +02:00
}
2024-04-10 09:58:39 +02:00
void ComputeCommand::bindPipeline(Gfx::PComputePipeline pipeline) {
2024-08-28 17:54:14 +02:00
boundPipeline = pipeline.cast<ComputePipeline>();
encoder->setComputePipelineState(boundPipeline->getHandle());
argumentBuffer = boundPipeline->graphics->getDevice()->newBuffer(
sizeof(uint64) * (boundPipeline->getPipelineLayout()->getLayouts().size() + 1), MTL::ResourceStorageModeShared);
argumentBuffer->setLabel(NS::String::string(pipeline->getPipelineLayout()->getName().c_str(), NS::ASCIIStringEncoding));
2024-04-10 08:43:56 +02:00
}
2024-08-28 17:54:14 +02:00
void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet set, Array<uint32> offsets) {
auto metalSet = set.cast<DescriptorSet>();
metalSet->bind();
2024-04-10 08:43:56 +02:00
}
2024-08-28 17:54:14 +02:00
void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& sets, Array<uint32> offsets) {
for (auto& set : sets) {
bindDescriptor(set, offsets);
}
2024-04-10 08:43:56 +02:00
}
2024-08-28 17:54:14 +02:00
void ComputeCommand::pushConstants(Gfx::SeShaderStageFlags, uint32 offset, uint32 size, const void* data) {
encoder->setBytes((char*)data + offset, size, 0);
2024-04-10 08:43:56 +02:00
}
2024-04-10 09:58:39 +02:00
void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) {
2024-08-28 17:54:14 +02:00
// TODO
encoder->setBuffer(argumentBuffer, 0, 2);
encoder->dispatchThreadgroups(MTL::Size(threadX, threadY, threadZ), MTL::Size(32, 32, 1));
2024-04-10 08:43:56 +02:00
}
2024-04-10 09:58:39 +02:00
CommandQueue::CommandQueue(PGraphics graphics) : graphics(graphics) {
2024-08-28 17:54:14 +02:00
queue = graphics->getDevice()->newCommandQueue();
MTL::CommandBufferDescriptor* descriptor = MTL::CommandBufferDescriptor::alloc()->init();
activeCommand = new Command(graphics, queue->commandBuffer(descriptor));
descriptor->release();
2024-04-10 08:43:56 +02:00
}
2024-04-10 09:58:39 +02:00
CommandQueue::~CommandQueue() { queue->release(); }
2024-08-28 17:54:14 +02:00
ORenderCommand CommandQueue::getRenderCommand(const std::string& name) {
return new RenderCommand(activeCommand->createRenderEncoder(), name);
2024-04-10 08:43:56 +02:00
}
2024-08-28 17:54:14 +02:00
OComputeCommand CommandQueue::getComputeCommand(const std::string& name) { return new ComputeCommand(queue->commandBuffer(), name); }
2024-04-17 14:33:06 +02:00
void CommandQueue::executeCommands(Array<Gfx::ORenderCommand> commands) {
2024-08-28 17:54:14 +02:00
for (auto& command : commands) {
auto metalCmd = Gfx::PRenderCommand(command).cast<RenderCommand>();
metalCmd->end();
}
2024-04-17 14:33:06 +02:00
}
void CommandQueue::executeCommands(Array<Gfx::OComputeCommand> commands) {
2024-08-28 17:54:14 +02:00
submitCommands();
for (auto& command : commands) {
auto metalCmd = Gfx::PComputeCommand(command).cast<ComputeCommand>();
metalCmd->end();
}
2024-04-10 08:43:56 +02:00
}
2024-04-10 09:58:39 +02:00
void CommandQueue::submitCommands(PEvent signalSemaphore) {
2024-08-28 17:54:14 +02:00
activeCommand->getHandle()->addCompletedHandler(MTL::CommandBufferHandler([&](MTL::CommandBuffer* cmdBuffer) {
for (auto it = pendingCommands.begin(); it != pendingCommands.end(); it++) {
if ((*it)->getHandle() == cmdBuffer) {
pendingCommands.remove(it);
return;
}
2024-06-09 12:20:04 +02:00
}
2024-08-28 17:54:14 +02:00
}));
activeCommand->end(signalSemaphore);
activeCommand->waitDeviceIdle();
PEvent prevCmdEvent = activeCommand->getCompletedEvent();
pendingCommands.add(std::move(activeCommand));
MTL::CommandBufferDescriptor* descriptor = MTL::CommandBufferDescriptor::alloc()->init();
descriptor->setErrorOptions(MTL::CommandBufferErrorOptionEncoderExecutionStatus);
activeCommand = new Command(graphics, queue->commandBuffer(descriptor));
activeCommand->waitForEvent(prevCmdEvent);
2024-04-10 15:50:20 +02:00
}
IOCommandQueue::IOCommandQueue(PGraphics graphics) : graphics(graphics) {
2024-08-28 17:54:14 +02:00
MTL::IOCommandQueueDescriptor* desc = MTL::IOCommandQueueDescriptor::alloc()->init();
desc->setType(MTL::IOCommandQueueTypeConcurrent);
desc->setPriority(MTL::IOPriorityNormal);
queue = graphics->getDevice()->newIOCommandQueue(desc, nullptr);
// activeCommand = new Command(graphics, queue->commandBuffer());
desc->release();
2024-04-10 15:50:20 +02:00
}
IOCommandQueue::~IOCommandQueue() { queue->release(); }
void IOCommandQueue::submitCommands(PEvent signalSemaphore) {
2024-08-28 17:54:14 +02:00
// TODO: scratch buffer
activeCommand->end(signalSemaphore);
PEvent prevCmdEvent = activeCommand->getCompletedEvent();
// activeCommand = new Command(graphics, queue->commandBuffer());
activeCommand->waitForEvent(prevCmdEvent);
2024-04-10 08:43:56 +02:00
}