Metal is impossible to debug, thanks apple
This commit is contained in:
@@ -3,8 +3,6 @@
|
||||
#include "Graphics/Buffer.h"
|
||||
#include "Graphics/Enums.h"
|
||||
#include "Graphics/Initializer.h"
|
||||
#include "Metal/MTLResource.hpp"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Metal;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "Graphics/Command.h"
|
||||
#include "Metal/MTLCommandBuffer.hpp"
|
||||
#include "Buffer.h"
|
||||
#include "RenderPass.h"
|
||||
#include "Resources.h"
|
||||
|
||||
@@ -10,6 +10,8 @@ DECLARE_REF(CommandQueue)
|
||||
DECLARE_REF(ComputeCommand)
|
||||
DECLARE_REF(RenderCommand)
|
||||
DECLARE_REF(Graphics)
|
||||
DECLARE_REF(IndexBuffer)
|
||||
DECLARE_REF(GraphicsPipeline)
|
||||
class Command
|
||||
{
|
||||
public:
|
||||
@@ -56,6 +58,8 @@ public:
|
||||
virtual void drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) override;
|
||||
private:
|
||||
MTL::RenderCommandEncoder* encoder;
|
||||
PIndexBuffer boundIndexBuffer;
|
||||
PGraphicsPipeline boundPipeline;
|
||||
};
|
||||
DEFINE_REF(RenderCommand)
|
||||
class ComputeCommand : public Gfx::ComputeCommand
|
||||
|
||||
@@ -1,30 +1,28 @@
|
||||
#include "Command.h"
|
||||
#include "Buffer.h"
|
||||
#include "Descriptor.h"
|
||||
#include "Enums.h"
|
||||
#include "Graphics/Enums.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Graphics/Metal/Resources.h"
|
||||
#include "Metal/MTLCommandBuffer.hpp"
|
||||
#include "Metal/MTLIOCommandQueue.hpp"
|
||||
#include "Metal/MTLRenderCommandEncoder.hpp"
|
||||
#include "Pipeline.h"
|
||||
#include "Resources.h"
|
||||
#include "Window.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Metal;
|
||||
|
||||
Command::Command(PGraphics graphics, MTL::CommandBuffer* cmdBuffer)
|
||||
: graphics(graphics), completed(new Event(graphics)),
|
||||
cmdBuffer(cmdBuffer), renderEncoder(nullptr) {}
|
||||
: graphics(graphics), completed(new Event(graphics)), cmdBuffer(cmdBuffer), renderEncoder(nullptr) {}
|
||||
|
||||
Command::~Command() { cmdBuffer->release(); }
|
||||
|
||||
void Command::beginRenderPass(PRenderPass renderPass) {
|
||||
renderEncoder =
|
||||
cmdBuffer->parallelRenderCommandEncoder(renderPass->getDescriptor());
|
||||
renderEncoder = cmdBuffer->parallelRenderCommandEncoder(renderPass->getDescriptor());
|
||||
}
|
||||
|
||||
void Command::endRenderPass() { renderEncoder->endEncoding(); }
|
||||
|
||||
void Command::present(MTL::Drawable *drawable) {
|
||||
cmdBuffer->presentDrawable(drawable);
|
||||
}
|
||||
void Command::present(MTL::Drawable* drawable) { cmdBuffer->presentDrawable(drawable); }
|
||||
|
||||
void Command::end(PEvent signal) {
|
||||
if (signal != nullptr) {
|
||||
@@ -35,14 +33,14 @@ void Command::end(PEvent signal) {
|
||||
}
|
||||
|
||||
void Command::executeCommands(Array<Gfx::ORenderCommand> commands) {
|
||||
for (auto &command : commands) {
|
||||
for (auto& command : commands) {
|
||||
auto cmd = Gfx::PRenderCommand(command).cast<RenderCommand>();
|
||||
cmd->end();
|
||||
}
|
||||
}
|
||||
|
||||
void Command::executeCommands(Array<Gfx::OComputeCommand> commands) {
|
||||
for (auto &command : commands) {
|
||||
for (auto& command : commands) {
|
||||
auto cmd = Gfx::PComputeCommand(command).cast<ComputeCommand>();
|
||||
cmd->end();
|
||||
}
|
||||
@@ -50,16 +48,11 @@ void Command::executeCommands(Array<Gfx::OComputeCommand> commands) {
|
||||
|
||||
void Command::waitDeviceIdle() { cmdBuffer->waitUntilCompleted(); }
|
||||
|
||||
void Command::signalEvent(PEvent event) {
|
||||
cmdBuffer->encodeSignalEvent(event->getHandle(), 1);
|
||||
}
|
||||
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) { cmdBuffer->encodeWait(event->getHandle(), 1); }
|
||||
|
||||
RenderCommand::RenderCommand(MTL::RenderCommandEncoder *encoder)
|
||||
: encoder(encoder) {}
|
||||
RenderCommand::RenderCommand(MTL::RenderCommandEncoder* encoder) : encoder(encoder) {}
|
||||
|
||||
RenderCommand::~RenderCommand() { encoder->release(); }
|
||||
|
||||
@@ -78,98 +71,109 @@ void RenderCommand::setViewport(Gfx::PViewport viewport) {
|
||||
}
|
||||
|
||||
void RenderCommand::bindPipeline(Gfx::PGraphicsPipeline pipeline) {
|
||||
// encoder->setRenderPipelineState(
|
||||
// pipeline.cast<GraphicsPipeline>()->getState());
|
||||
boundPipeline = pipeline.cast<GraphicsPipeline>();
|
||||
encoder->setRenderPipelineState(boundPipeline->getHandle());
|
||||
}
|
||||
|
||||
void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) {
|
||||
encoder->setVertexBuffer(descriptorSet.cast<DescriptorSet>()->getBuffer(), 0, descriptorSet->getSetIndex());
|
||||
encoder->setFragmentBuffer(descriptorSet.cast<DescriptorSet>()->getBuffer(), 0, descriptorSet->getSetIndex());
|
||||
encoder->setMeshBuffer(descriptorSet.cast<DescriptorSet>()->getBuffer(), 0, descriptorSet->getSetIndex());
|
||||
encoder->setObjectBuffer(descriptorSet.cast<DescriptorSet>()->getBuffer(), 0, descriptorSet->getSetIndex());
|
||||
}
|
||||
|
||||
void RenderCommand::bindDescriptor(
|
||||
const Array<Gfx::PDescriptorSet> &descriptorSets) {
|
||||
// encoder->set ? ? ? ? ?
|
||||
void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets) {
|
||||
for (auto set : descriptorSets) {
|
||||
bindDescriptor(set);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderCommand::bindVertexBuffer(const Array<Gfx::PVertexBuffer> &buffers) {
|
||||
// encoder->setVertexBuffers();
|
||||
void RenderCommand::bindVertexBuffer(const Array<Gfx::PVertexBuffer>& buffers) {
|
||||
uint32 i = 0;
|
||||
for (auto buffer : buffers) {
|
||||
encoder->setVertexBuffer(buffer.cast<VertexBuffer>()->getHandle(), 0, i++);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) {
|
||||
// encoder->setObjectBuffer(??, NS::UInteger offset, NS::UInteger index)
|
||||
void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer gfxIndexBuffer) {
|
||||
boundIndexBuffer = gfxIndexBuffer.cast<IndexBuffer>();
|
||||
}
|
||||
|
||||
void RenderCommand::pushConstants(Gfx::PPipelineLayout layout,
|
||||
Gfx::SeShaderStageFlags stage, uint32 offset,
|
||||
uint32 size, const void *data) {
|
||||
// ? ? ?
|
||||
void RenderCommand::pushConstants(Gfx::PPipelineLayout, 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);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderCommand::draw(uint32 vertexCount, uint32 instanceCount,
|
||||
int32 firstVertex, uint32 firstInstance) {
|
||||
// encoder->drawPrimitives(???, firstVertex, vertexCount, instanceCount, firstInstance);
|
||||
void RenderCommand::draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance) {
|
||||
encoder->drawPrimitives(boundPipeline->getPrimitive(), firstVertex, vertexCount, instanceCount, firstInstance);
|
||||
}
|
||||
|
||||
void RenderCommand::drawIndexed(uint32 indexCount, uint32 instanceCount,
|
||||
int32 firstIndex, uint32 vertexOffset,
|
||||
void RenderCommand::drawIndexed(uint32 indexCount, uint32 instanceCount, int32 firstIndex, uint32 vertexOffset,
|
||||
uint32 firstInstance) {
|
||||
// encoder->drawIndexedPrimitives(???, indexCount, indexbuffer->getType(), indexBuffer->getBuffer(), firstIndex, instanceCount, vertexOffset, firstInstance);
|
||||
encoder->drawIndexedPrimitives(boundPipeline->getPrimitive(), indexCount, cast(boundIndexBuffer->getIndexType()),
|
||||
boundIndexBuffer->getHandle(), firstIndex, instanceCount, vertexOffset, firstInstance);
|
||||
}
|
||||
|
||||
void RenderCommand::drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ){
|
||||
// encoder->drawMeshThreads(MTL::Size threadsPerGrid,
|
||||
// MTL::Size threadsPerObjectThreadgroup,
|
||||
// MTL::Size threadsPerMeshThreadgroup)
|
||||
}
|
||||
void RenderCommand::drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) {
|
||||
//TODO:
|
||||
encoder->drawMeshThreadgroups(MTL::Size(groupX, groupY, groupZ), MTL::Size(128, 128, 128), MTL::Size(32, 32, 32));
|
||||
}
|
||||
|
||||
ComputeCommand::ComputeCommand(MTL::ComputeCommandEncoder *encoder)
|
||||
: encoder(encoder) {}
|
||||
ComputeCommand::ComputeCommand(MTL::ComputeCommandEncoder* encoder) : encoder(encoder) {}
|
||||
|
||||
ComputeCommand::~ComputeCommand() { encoder->release(); }
|
||||
|
||||
void ComputeCommand::end() { encoder->endEncoding(); }
|
||||
|
||||
void ComputeCommand::bindPipeline(Gfx::PComputePipeline pipeline) {
|
||||
// encoder->setComputePipelineState(pipeline.cast<ComputePipeline>());
|
||||
encoder->setComputePipelineState(pipeline.cast<ComputePipeline>()->getHandle());
|
||||
}
|
||||
|
||||
void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet set) {
|
||||
// encoder->set ? ? ?
|
||||
encoder->setBuffer(set.cast<DescriptorSet>()->getBuffer(), 0, set->getSetIndex());
|
||||
}
|
||||
|
||||
void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet> &sets) {
|
||||
// encoder->set ? ? ?
|
||||
void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& sets) {
|
||||
for (auto& set : sets) {
|
||||
bindDescriptor(set);
|
||||
}
|
||||
}
|
||||
|
||||
void ComputeCommand::pushConstants(Gfx::PPipelineLayout layout,
|
||||
Gfx::SeShaderStageFlags stage, uint32 offset,
|
||||
uint32 size, const void *data) {
|
||||
// ? ? ?
|
||||
void ComputeCommand::pushConstants(Gfx::PPipelineLayout, Gfx::SeShaderStageFlags, uint32 offset,
|
||||
uint32 size, const void* data) {
|
||||
encoder->setBytes((char*)data + offset, size, 0);
|
||||
}
|
||||
|
||||
void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) {
|
||||
// encoder->dispatchThreadgroups(???);
|
||||
//TODO
|
||||
encoder->dispatchThreadgroups(MTL::Size(threadX, threadY, threadZ), MTL::Size(32, 32, 32));
|
||||
}
|
||||
|
||||
CommandQueue::CommandQueue(PGraphics graphics) : graphics(graphics) {
|
||||
queue = graphics->getDevice()->newCommandQueue();
|
||||
activeCommand = new Command(graphics, queue->commandBuffer());
|
||||
queue = graphics->getDevice()->newCommandQueue();
|
||||
activeCommand = new Command(graphics, queue->commandBuffer());
|
||||
}
|
||||
|
||||
CommandQueue::~CommandQueue() { queue->release(); }
|
||||
|
||||
ORenderCommand CommandQueue::getRenderCommand(const std::string &name) {
|
||||
return new RenderCommand(activeCommand->createRenderEncoder());
|
||||
ORenderCommand CommandQueue::getRenderCommand(const std::string& name) {
|
||||
return new RenderCommand(activeCommand->createRenderEncoder());
|
||||
}
|
||||
|
||||
OComputeCommand CommandQueue::getComputeCommand(const std::string &name) {
|
||||
return new ComputeCommand(activeCommand->createComputeEncoder());
|
||||
OComputeCommand CommandQueue::getComputeCommand(const std::string& name) {
|
||||
return new ComputeCommand(activeCommand->createComputeEncoder());
|
||||
}
|
||||
|
||||
void CommandQueue::submitCommands(PEvent signalSemaphore) {
|
||||
activeCommand->end(signalSemaphore);
|
||||
PEvent prevCmdEvent = activeCommand->getCompletedEvent();
|
||||
activeCommand = new Command(graphics, queue->commandBuffer());
|
||||
activeCommand->waitForEvent(prevCmdEvent);
|
||||
activeCommand->end(signalSemaphore);
|
||||
PEvent prevCmdEvent = activeCommand->getCompletedEvent();
|
||||
activeCommand = new Command(graphics, queue->commandBuffer());
|
||||
activeCommand->waitForEvent(prevCmdEvent);
|
||||
}
|
||||
|
||||
IOCommandQueue::IOCommandQueue(PGraphics graphics) : graphics(graphics) {
|
||||
@@ -177,16 +181,16 @@ IOCommandQueue::IOCommandQueue(PGraphics graphics) : graphics(graphics) {
|
||||
desc->setType(MTL::IOCommandQueueTypeConcurrent);
|
||||
desc->setPriority(MTL::IOPriorityNormal);
|
||||
queue = graphics->getDevice()->newIOCommandQueue(desc, nullptr);
|
||||
//activeCommand = new Command(graphics, queue->commandBuffer());
|
||||
// activeCommand = new Command(graphics, queue->commandBuffer());
|
||||
desc->release();
|
||||
}
|
||||
|
||||
IOCommandQueue::~IOCommandQueue() { queue->release(); }
|
||||
|
||||
void IOCommandQueue::submitCommands(PEvent signalSemaphore) {
|
||||
//TODO: scratch buffer
|
||||
activeCommand->end(signalSemaphore);
|
||||
PEvent prevCmdEvent = activeCommand->getCompletedEvent();
|
||||
//activeCommand = new Command(graphics, queue->commandBuffer());
|
||||
activeCommand->waitForEvent(prevCmdEvent);
|
||||
// TODO: scratch buffer
|
||||
activeCommand->end(signalSemaphore);
|
||||
PEvent prevCmdEvent = activeCommand->getCompletedEvent();
|
||||
// activeCommand = new Command(graphics, queue->commandBuffer());
|
||||
activeCommand->waitForEvent(prevCmdEvent);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#pragma once
|
||||
#include "Foundation/NSArray.hpp"
|
||||
#include "Graphics/Descriptor.h"
|
||||
#include "Graphics/Initializer.h"
|
||||
#include "Metal/MTLArgumentEncoder.hpp"
|
||||
#include "MinimalEngine.h"
|
||||
#include "Buffer.h"
|
||||
|
||||
namespace Seele {
|
||||
namespace Metal {
|
||||
@@ -58,6 +57,8 @@ public:
|
||||
constexpr void allocate() { currentlyInUse = true; }
|
||||
constexpr void free() { currentlyInUse = false; }
|
||||
|
||||
constexpr MTL::Buffer* getBuffer() const { return buffer; }
|
||||
|
||||
private:
|
||||
PGraphics graphics;
|
||||
PDescriptorPool owner;
|
||||
|
||||
@@ -47,6 +47,7 @@ void DescriptorLayout::create() {
|
||||
descriptors.add(desc);
|
||||
}
|
||||
arguments = NS::Array::array(descriptors.data(), descriptors.size());
|
||||
pool = new DescriptorPool(graphics, this);
|
||||
}
|
||||
|
||||
DescriptorPool::DescriptorPool(PGraphics graphics, PDescriptorLayout layout) : graphics(graphics), layout(layout) {}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
#include "Graphics/Enums.h"
|
||||
#include "Metal/MTLDepthStencil.hpp"
|
||||
#include "Metal/MTLSampler.hpp"
|
||||
#include "Metal/MTLStageInputOutputDescriptor.hpp"
|
||||
#include "Resources.h"
|
||||
|
||||
namespace Seele
|
||||
@@ -26,5 +25,9 @@ MTL::SamplerMipFilter cast(Gfx::SeSamplerMipmapMode filter);
|
||||
Gfx::SeSamplerMipmapMode cast(MTL::SamplerMipFilter filter);
|
||||
MTL::SamplerAddressMode cast(Gfx::SeSamplerAddressMode mode);
|
||||
Gfx::SeSamplerAddressMode cast(MTL::SamplerAddressMode mode);
|
||||
MTL::PrimitiveTopologyClass cast(Gfx::SePrimitiveTopology topology);
|
||||
Gfx::SePrimitiveTopology cast(MTL::PrimitiveTopologyClass topology);
|
||||
MTL::IndexType cast(Gfx::SeIndexType indexType);
|
||||
Gfx::SeIndexType cast(MTL::IndexType indexType);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
#include "Enums.h"
|
||||
#include "Graphics/Enums.h"
|
||||
#include "Metal/MTLArgument.hpp"
|
||||
#include "Metal/MTLDepthStencil.hpp"
|
||||
#include "Metal/MTLSampler.hpp"
|
||||
#include "Metal/MTLStageInputOutputDescriptor.hpp"
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace Seele;
|
||||
@@ -768,3 +766,50 @@ Gfx::SeSamplerAddressMode Seele::Metal::cast(MTL::SamplerAddressMode mode) {
|
||||
return Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
}
|
||||
}
|
||||
|
||||
MTL::PrimitiveTopologyClass Seele::Metal::cast(Gfx::SePrimitiveTopology topology) {
|
||||
switch (topology) {
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_POINT_LIST:
|
||||
return MTL::PrimitiveTopologyClassPoint;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_LINE_LIST:
|
||||
return MTL::PrimitiveTopologyClassLine;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_LINE_STRIP:
|
||||
return MTL::PrimitiveTopologyClassLine;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
|
||||
return MTL::PrimitiveTopologyClassTriangle;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
|
||||
return MTL::PrimitiveTopologyClassTriangle;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
|
||||
return MTL::PrimitiveTopologyClassTriangle;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
|
||||
return MTL::PrimitiveTopologyClassLine;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
|
||||
return MTL::PrimitiveTopologyClassLine;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
|
||||
return MTL::PrimitiveTopologyClassTriangle;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
|
||||
return MTL::PrimitiveTopologyClassTriangle;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_PATCH_LIST:
|
||||
return MTL::PrimitiveTopologyClassUnspecified;
|
||||
}
|
||||
}
|
||||
|
||||
MTL::IndexType Seele::Metal::cast(Gfx::SeIndexType indexType) {
|
||||
switch (indexType) {
|
||||
case Gfx::SE_INDEX_TYPE_UINT16:
|
||||
return MTL::IndexTypeUInt16;
|
||||
case Gfx::SE_INDEX_TYPE_UINT32:
|
||||
return MTL::IndexTypeUInt32;
|
||||
default:
|
||||
throw std::logic_error("Not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
Gfx::SeIndexType Seele::Metal::cast(MTL::IndexType indexType) {
|
||||
switch (indexType) {
|
||||
case MTL::IndexTypeUInt16:
|
||||
return Gfx::SE_INDEX_TYPE_UINT16;
|
||||
case MTL::IndexTypeUInt32:
|
||||
return Gfx::SE_INDEX_TYPE_UINT32;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Metal
|
||||
{
|
||||
DECLARE_REF(CommandQueue)
|
||||
DECLARE_REF(IOCommandQueue)
|
||||
DECLARE_REF(PipelineCache)
|
||||
class Graphics : public Gfx::Graphics
|
||||
{
|
||||
public:
|
||||
@@ -61,6 +62,7 @@ protected:
|
||||
MTL::Device* device;
|
||||
OCommandQueue queue;
|
||||
OIOCommandQueue ioQueue;
|
||||
OPipelineCache cache;
|
||||
};
|
||||
DEFINE_REF(Graphics)
|
||||
} // namespace Metal
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
#include "Graphics.h"
|
||||
#include "Graphics/Initializer.h"
|
||||
#include "Graphics/Metal/Descriptor.h"
|
||||
#include "Graphics/Metal/Pipeline.h"
|
||||
#include "Graphics/Metal/PipelineCache.h"
|
||||
#include "Graphics/Metal/Resources.h"
|
||||
#include "Shader.h"
|
||||
#include "RenderPass.h"
|
||||
#include "Resources.h"
|
||||
#include "Command.h"
|
||||
#include "Window.h"
|
||||
#include "Buffer.h"
|
||||
@@ -24,6 +29,7 @@ void Graphics::init(GraphicsInitializer)
|
||||
device = MTL::CreateSystemDefaultDevice();
|
||||
queue = new CommandQueue(this);
|
||||
ioQueue = new IOCommandQueue(this);
|
||||
cache = new PipelineCache(this, "pipelines.metal");
|
||||
}
|
||||
|
||||
Gfx::OWindow Graphics::createWindow(const WindowCreateInfo &createInfo)
|
||||
@@ -118,12 +124,14 @@ Gfx::OVertexShader Graphics::createVertexShader(const ShaderCreateInfo& createIn
|
||||
result->create(createInfo);
|
||||
return result;
|
||||
}
|
||||
|
||||
Gfx::OFragmentShader Graphics::createFragmentShader(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
OFragmentShader result = new FragmentShader(this);
|
||||
result->create(createInfo);
|
||||
return result;
|
||||
}
|
||||
|
||||
Gfx::OComputeShader Graphics::createComputeShader(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
OComputeShader result = new ComputeShader(this);
|
||||
@@ -137,6 +145,7 @@ Gfx::OMeshShader Graphics::createMeshShader(const ShaderCreateInfo& createInfo)
|
||||
result->create(createInfo);
|
||||
return result;
|
||||
}
|
||||
|
||||
Gfx::OTaskShader Graphics::createTaskShader(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
OTaskShader result = new TaskShader(this);
|
||||
@@ -146,39 +155,41 @@ Gfx::OTaskShader Graphics::createTaskShader(const ShaderCreateInfo& createInfo)
|
||||
|
||||
Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(Gfx::LegacyPipelineCreateInfo createInfo)
|
||||
{
|
||||
|
||||
return cache->createPipeline(std::move(createInfo));
|
||||
}
|
||||
|
||||
Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(Gfx::MeshPipelineCreateInfo createInfo)
|
||||
{
|
||||
|
||||
return cache->createPipeline(std::move(createInfo));
|
||||
}
|
||||
|
||||
Gfx::PComputePipeline Graphics::createComputePipeline(Gfx::ComputePipelineCreateInfo createInfo)
|
||||
{
|
||||
|
||||
return cache->createPipeline(std::move(createInfo));
|
||||
}
|
||||
|
||||
Gfx::OSampler Graphics::createSampler(const SamplerCreateInfo& createInfo)
|
||||
{
|
||||
|
||||
return new Sampler(this, createInfo);
|
||||
}
|
||||
|
||||
Gfx::ODescriptorLayout Graphics::createDescriptorLayout(const std::string& name)
|
||||
{
|
||||
|
||||
return new DescriptorLayout(this, name);
|
||||
}
|
||||
|
||||
Gfx::OPipelineLayout Graphics::createPipelineLayout(Gfx::PPipelineLayout baseLayout)
|
||||
{
|
||||
|
||||
return new PipelineLayout(this, baseLayout);
|
||||
}
|
||||
|
||||
Gfx::OVertexInput Graphics::createVertexInput(VertexInputStateCreateInfo createInfo)
|
||||
{
|
||||
|
||||
return new VertexInput(createInfo);
|
||||
}
|
||||
|
||||
void Graphics::resolveTexture(Gfx::PTexture source, Gfx::PTexture destination)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,37 +1,40 @@
|
||||
#pragma once
|
||||
#include "Graphics/Initializer.h"
|
||||
#include "Graphics/Pipeline.h"
|
||||
#include "Resources.h"
|
||||
#include "MinimalEngine.h"
|
||||
#include "Resources.h"
|
||||
|
||||
namespace Seele {
|
||||
namespace Metal {
|
||||
class VertexInput : public Gfx::VertexInput
|
||||
{
|
||||
class VertexInput : public Gfx::VertexInput {
|
||||
public:
|
||||
VertexInput(VertexInputStateCreateInfo createInfo);
|
||||
virtual ~VertexInput();
|
||||
};
|
||||
DECLARE_REF(PipelineLayout)
|
||||
DECLARE_REF(Graphics)
|
||||
class GraphicsPipeline : public Gfx::GraphicsPipeline
|
||||
{
|
||||
class GraphicsPipeline : public Gfx::GraphicsPipeline {
|
||||
public:
|
||||
GraphicsPipeline(PGraphics graphics, Gfx::LegacyPipelineCreateInfo createInfo);
|
||||
GraphicsPipeline(PGraphics graphics, Gfx::MeshPipelineCreateInfo createInfo);
|
||||
GraphicsPipeline(PGraphics graphics, MTL::PrimitiveType primitive, MTL::RenderPipelineState* pipeline, Gfx::OPipelineLayout createInfo);
|
||||
virtual ~GraphicsPipeline();
|
||||
constexpr MTL::RenderPipelineState* getHandle() const { return state; }
|
||||
constexpr MTL::PrimitiveType getPrimitive() const { return primitiveType; }
|
||||
private:
|
||||
PGraphics graphics;
|
||||
MTL::RenderPipelineState* state;
|
||||
MTL::PrimitiveType primitiveType;
|
||||
};
|
||||
DEFINE_REF(GraphicsPipeline)
|
||||
class ComputePipeline : public Gfx::ComputePipeline
|
||||
{
|
||||
class ComputePipeline : public Gfx::ComputePipeline {
|
||||
public:
|
||||
ComputePipeline(PGraphics graphics, Gfx::ComputePipelineCreateInfo createInfo);
|
||||
ComputePipeline(PGraphics graphics, MTL::ComputePipelineState* pipeline, Gfx::OPipelineLayout);
|
||||
virtual ~ComputePipeline();
|
||||
constexpr MTL::ComputePipelineState* getHandle() const { return state; }
|
||||
|
||||
private:
|
||||
PGraphics graphics;
|
||||
MTL::ComputePipelineState* state;
|
||||
};
|
||||
DEFINE_REF(ComputePipeline)
|
||||
}
|
||||
}
|
||||
} // namespace Metal
|
||||
} // namespace Seele
|
||||
@@ -1,17 +1,24 @@
|
||||
#include "Pipeline.h"
|
||||
#include "Graphics/Initializer.h"
|
||||
#include "Graphics/Metal/Graphics.h"
|
||||
#include "Graphics/Pipeline.h"
|
||||
#include "Graphics/Resources.h"
|
||||
#include "Metal/MTLRenderPipeline.hpp"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Metal;
|
||||
|
||||
VertexInput::VertexInput(VertexInputStateCreateInfo createInfo)
|
||||
: Gfx::VertexInput(createInfo)
|
||||
{
|
||||
}
|
||||
VertexInput::VertexInput(VertexInputStateCreateInfo createInfo) : Gfx::VertexInput(createInfo) {}
|
||||
|
||||
VertexInput::~VertexInput()
|
||||
{
|
||||
}
|
||||
VertexInput::~VertexInput() {}
|
||||
|
||||
GraphicsPipeline::GraphicsPipeline(PGraphics graphics, MTL::PrimitiveType primitive, MTL::RenderPipelineState* pipeline,
|
||||
Gfx::OPipelineLayout createInfo)
|
||||
: Gfx::GraphicsPipeline(std::move(createInfo)), graphics(graphics), state(pipeline), primitiveType(primitive) {}
|
||||
|
||||
GraphicsPipeline::~GraphicsPipeline() {}
|
||||
|
||||
ComputePipeline::ComputePipeline(PGraphics graphics, MTL::ComputePipelineState* pipeline,
|
||||
Gfx::OPipelineLayout createInfo)
|
||||
: Gfx::ComputePipeline(std::move(createInfo)), graphics(graphics), state(pipeline) {}
|
||||
|
||||
ComputePipeline::~ComputePipeline() {}
|
||||
|
||||
@@ -15,7 +15,7 @@ public:
|
||||
private:
|
||||
PGraphics graphics;
|
||||
Map<uint32, OGraphicsPipeline> graphicsPipelines;
|
||||
Map<uint32, OComputePipeline> computePipeline;
|
||||
Map<uint32, OComputePipeline> computePipelines;
|
||||
std::string cacheFile;
|
||||
};
|
||||
DEFINE_REF(PipelineCache)
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
#include "PipelineCache.h"
|
||||
#include "Descriptor.h"
|
||||
#include "Enums.h"
|
||||
#include "Foundation/NSError.hpp"
|
||||
#include "Graphics.h"
|
||||
#include "Shader.h"
|
||||
#include "Graphics/Descriptor.h"
|
||||
#include "Graphics/Enums.h"
|
||||
#include "Graphics/Metal/Pipeline.h"
|
||||
#include "Metal/MTLComputePipeline.hpp"
|
||||
#include "Metal/MTLDevice.hpp"
|
||||
#include "Metal/MTLRenderCommandEncoder.hpp"
|
||||
#include "Metal/MTLRenderPipeline.hpp"
|
||||
#include "Metal/MTLVertexDescriptor.hpp"
|
||||
#include "Shader.h"
|
||||
#include "Texture.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Metal;
|
||||
@@ -16,15 +23,12 @@ PipelineCache::~PipelineCache() {}
|
||||
|
||||
PGraphicsPipeline PipelineCache::createPipeline(Gfx::LegacyPipelineCreateInfo createInfo) {
|
||||
PPipelineLayout layout = Gfx::PPipelineLayout(createInfo.pipelineLayout).cast<PipelineLayout>();
|
||||
uint32 hash = layout->getHash();
|
||||
|
||||
MTL::RenderPipelineDescriptor* pipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init();
|
||||
|
||||
MTL::VertexDescriptor* vertexDescriptor = MTL::VertexDescriptor::alloc()->init();
|
||||
|
||||
MTL::VertexAttributeDescriptorArray* attributes = vertexDescriptor->attributes();
|
||||
|
||||
const auto& vertexInfo = createInfo.vertexInput->getInfo();
|
||||
|
||||
for (size_t attr = 0; attr < vertexInfo.attributes.size(); ++attr) {
|
||||
MTL::VertexAttributeDescriptor* attribute = MTL::VertexAttributeDescriptor::alloc()->init();
|
||||
attribute->setBufferIndex(vertexInfo.attributes[attr].binding);
|
||||
@@ -40,7 +44,6 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::LegacyPipelineCreateInfo cr
|
||||
}
|
||||
|
||||
MTL::VertexBufferLayoutDescriptorArray* bufferLayout = vertexDescriptor->layouts();
|
||||
|
||||
for (size_t binding = 0; binding < vertexInfo.bindings.size(); ++binding) {
|
||||
MTL::VertexBufferLayoutDescriptor* buffer = MTL::VertexBufferLayoutDescriptor::alloc()->init();
|
||||
buffer->setStride(vertexInfo.bindings[binding].stride);
|
||||
@@ -55,16 +58,123 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::LegacyPipelineCreateInfo cr
|
||||
}
|
||||
bufferLayout->setObject(buffer, binding);
|
||||
}
|
||||
|
||||
pipelineDescriptor->setVertexDescriptor(vertexDescriptor);
|
||||
|
||||
pipelineDescriptor->setVertexFunction(createInfo.vertexShader.cast<VertexShader>()->getFunction());
|
||||
|
||||
if (createInfo.fragmentShader != nullptr) {
|
||||
pipelineDescriptor->setFragmentFunction(createInfo.fragmentShader.cast<FragmentShader>()->getFunction());
|
||||
}
|
||||
pipelineDescriptor->setInputPrimitiveTopology(cast(createInfo.topology));
|
||||
if (createInfo.renderPass->getLayout().depthAttachment.getTexture() != nullptr) {
|
||||
pipelineDescriptor->setDepthAttachmentPixelFormat(
|
||||
cast(createInfo.renderPass->getLayout().depthAttachment.getTexture().cast<Texture2D>()->getFormat()));
|
||||
}
|
||||
pipelineDescriptor->setAlphaToCoverageEnabled(createInfo.multisampleState.alphaCoverageEnable);
|
||||
pipelineDescriptor->setAlphaToOneEnabled(createInfo.multisampleState.alphaToOneEnable);
|
||||
pipelineDescriptor->setRasterSampleCount(createInfo.multisampleState.samples);
|
||||
pipelineDescriptor->setRasterizationEnabled(!createInfo.rasterizationState.rasterizerDiscardEnable);
|
||||
|
||||
uint32 hash = pipelineDescriptor->hash();
|
||||
|
||||
if (graphicsPipelines.contains(hash)) {
|
||||
return graphicsPipelines[hash];
|
||||
}
|
||||
MTL::PrimitiveType type = MTL::PrimitiveTypeTriangle;
|
||||
switch (createInfo.topology) {
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_POINT_LIST:
|
||||
type = MTL::PrimitiveTypePoint;
|
||||
break;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_LINE_LIST:
|
||||
type = MTL::PrimitiveTypeLine;
|
||||
break;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_LINE_STRIP:
|
||||
type = MTL::PrimitiveTypeLineStrip;
|
||||
break;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
|
||||
type = MTL::PrimitiveTypeTriangle;
|
||||
break;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
|
||||
type = MTL::PrimitiveTypeTriangleStrip;
|
||||
break;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
|
||||
type = MTL::PrimitiveTypeTriangle;
|
||||
break;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
|
||||
type = MTL::PrimitiveTypeLine;
|
||||
break;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
|
||||
type = MTL::PrimitiveTypeLineStrip;
|
||||
break;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
|
||||
type = MTL::PrimitiveTypeTriangle;
|
||||
break;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
|
||||
type = MTL::PrimitiveTypeTriangleStrip;
|
||||
break;
|
||||
case Gfx::SE_PRIMITIVE_TOPOLOGY_PATCH_LIST:
|
||||
type = MTL::PrimitiveTypeTriangle;
|
||||
break;
|
||||
}
|
||||
|
||||
NS::Error* error;
|
||||
graphicsPipelines[hash] =
|
||||
new GraphicsPipeline(graphics, type, graphics->getDevice()->newRenderPipelineState(pipelineDescriptor, &error),
|
||||
std::move(createInfo.pipelineLayout));
|
||||
assert(!error);
|
||||
|
||||
vertexDescriptor->release();
|
||||
pipelineDescriptor->release();
|
||||
return graphicsPipelines[hash];
|
||||
}
|
||||
|
||||
PGraphicsPipeline PipelineCache::createPipeline(Gfx::MeshPipelineCreateInfo createInfo) {}
|
||||
PGraphicsPipeline PipelineCache::createPipeline(Gfx::MeshPipelineCreateInfo createInfo) {
|
||||
MTL::MeshRenderPipelineDescriptor* pipelineDescriptor = MTL::MeshRenderPipelineDescriptor::alloc()->init();
|
||||
|
||||
PComputePipeline PipelineCache::createPipeline(Gfx::ComputePipelineCreateInfo createInfo) {}
|
||||
pipelineDescriptor->setMeshFunction(createInfo.meshShader.cast<VertexShader>()->getFunction());
|
||||
if (createInfo.taskShader != nullptr) {
|
||||
pipelineDescriptor->setObjectFunction(createInfo.taskShader.cast<TaskShader>()->getFunction());
|
||||
}
|
||||
if (createInfo.fragmentShader != nullptr) {
|
||||
pipelineDescriptor->setFragmentFunction(createInfo.fragmentShader.cast<FragmentShader>()->getFunction());
|
||||
}
|
||||
if (createInfo.renderPass->getLayout().depthAttachment.getTexture() != nullptr) {
|
||||
pipelineDescriptor->setDepthAttachmentPixelFormat(
|
||||
cast(createInfo.renderPass->getLayout().depthAttachment.getTexture().cast<Texture2D>()->getFormat()));
|
||||
}
|
||||
pipelineDescriptor->setAlphaToCoverageEnabled(createInfo.multisampleState.alphaCoverageEnable);
|
||||
pipelineDescriptor->setAlphaToOneEnabled(createInfo.multisampleState.alphaToOneEnable);
|
||||
pipelineDescriptor->setRasterSampleCount(createInfo.multisampleState.samples);
|
||||
pipelineDescriptor->setRasterizationEnabled(!createInfo.rasterizationState.rasterizerDiscardEnable);
|
||||
|
||||
uint32 hash = pipelineDescriptor->hash();
|
||||
|
||||
if (graphicsPipelines.contains(hash)) {
|
||||
return graphicsPipelines[hash];
|
||||
}
|
||||
|
||||
graphics->getDevice()->newRenderPipelineState(
|
||||
pipelineDescriptor, MTL::PipelineOptionNone,
|
||||
[&](MTL::RenderPipelineState* state, MTL::RenderPipelineReflection*, NS::Error* error) {
|
||||
assert(!error);
|
||||
graphicsPipelines[hash] =
|
||||
new GraphicsPipeline(graphics, MTL::PrimitiveTypeLine, state, std::move(createInfo.pipelineLayout));
|
||||
});
|
||||
|
||||
pipelineDescriptor->release();
|
||||
return graphicsPipelines[hash];
|
||||
}
|
||||
|
||||
PComputePipeline PipelineCache::createPipeline(Gfx::ComputePipelineCreateInfo createInfo) {
|
||||
PComputeShader shader = createInfo.computeShader.cast<ComputeShader>();
|
||||
uint32 hash = shader->getShaderHash();
|
||||
if (computePipelines.contains(hash)) {
|
||||
return computePipelines[hash];
|
||||
}
|
||||
|
||||
NS::Error* error;
|
||||
computePipelines[hash] =
|
||||
new ComputePipeline(graphics, graphics->getDevice()->newComputePipelineState(shader->getFunction(), &error),
|
||||
std::move(createInfo.pipelineLayout));
|
||||
assert(!error);
|
||||
return computePipelines[hash];
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
using namespace Seele;
|
||||
using namespace Seele::Metal;
|
||||
|
||||
Shader::Shader(PGraphics graphics, Gfx::SeShaderStageFlags stage)
|
||||
: stage(stage), graphics(graphics) {}
|
||||
Shader::Shader(PGraphics graphics, Gfx::SeShaderStageFlags stage) : stage(stage), graphics(graphics) {}
|
||||
|
||||
Shader::~Shader() {
|
||||
if (function) {
|
||||
function->release();
|
||||
@@ -23,29 +23,27 @@ Shader::~Shader() {
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::create(const ShaderCreateInfo &createInfo) {
|
||||
Slang::ComPtr<slang::IBlob> kernelBlob =
|
||||
generateShader(createInfo, SLANG_SPIRV);
|
||||
spirv_cross::CompilerMSL comp((const uint32 *)kernelBlob->getBufferPointer(),
|
||||
kernelBlob->getBufferSize() / 4);
|
||||
void Shader::create(const ShaderCreateInfo& createInfo) {
|
||||
Slang::ComPtr<slang::IBlob> kernelBlob = generateShader(createInfo, SLANG_SPIRV);
|
||||
hash = CRC::Calculate(kernelBlob->getBufferPointer(), kernelBlob->getBufferSize(), CRC::CRC_32());
|
||||
spirv_cross::CompilerMSL comp((const uint32*)kernelBlob->getBufferPointer(), kernelBlob->getBufferSize() / 4);
|
||||
auto options = comp.get_msl_options();
|
||||
options.argument_buffers = true;
|
||||
options.argument_buffers_tier =
|
||||
spirv_cross::CompilerMSL::Options::ArgumentBuffersTier::Tier2;
|
||||
options.argument_buffers_tier = spirv_cross::CompilerMSL::Options::ArgumentBuffersTier::Tier2;
|
||||
options.set_msl_version(3);
|
||||
comp.set_msl_options(options);
|
||||
std::string metalCode = comp.compile();
|
||||
NS::Error *error = nullptr;
|
||||
MTL::CompileOptions *mtlOptions = MTL::CompileOptions::alloc()->init();
|
||||
NS::Error* error = nullptr;
|
||||
MTL::CompileOptions* mtlOptions = MTL::CompileOptions::alloc()->init();
|
||||
|
||||
library = graphics->getDevice()->newLibrary(
|
||||
NS::String::string(metalCode.c_str(), NS::ASCIIStringEncoding),
|
||||
mtlOptions, &error);
|
||||
library = graphics->getDevice()->newLibrary(NS::String::string(metalCode.c_str(), NS::ASCIIStringEncoding),
|
||||
mtlOptions, &error);
|
||||
if (error) {
|
||||
std::cout << error->debugDescription() << std::endl;
|
||||
assert(false);
|
||||
}
|
||||
function =
|
||||
library->newFunction(NS::String::string("main", NS::ASCIIStringEncoding));
|
||||
function = library->newFunction(NS::String::string("main", NS::ASCIIStringEncoding));
|
||||
mtlOptions->release();
|
||||
}
|
||||
}
|
||||
|
||||
uint32 Shader::getShaderHash() const { return hash; }
|
||||
Reference in New Issue
Block a user