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

219 lines
7.9 KiB
Plaintext
Raw Normal View History

2024-04-13 23:51:38 +02:00
#include "PipelineCache.h"
#include "Descriptor.h"
2024-04-14 11:35:37 +02:00
#include "Enums.h"
#include "Foundation/NSError.hpp"
2024-04-17 14:33:06 +02:00
#include "Foundation/NSString.hpp"
2024-04-13 23:51:38 +02:00
#include "Graphics.h"
#include "Graphics/Descriptor.h"
#include "Graphics/Enums.h"
2024-04-14 11:35:37 +02:00
#include "Graphics/Metal/Pipeline.h"
#include "Metal/MTLComputePipeline.hpp"
#include "Metal/MTLDevice.hpp"
#include "Metal/MTLRenderCommandEncoder.hpp"
2024-04-13 23:51:38 +02:00
#include "Metal/MTLRenderPipeline.hpp"
#include "Metal/MTLVertexDescriptor.hpp"
2024-04-14 11:35:37 +02:00
#include "Shader.h"
#include "Texture.h"
2024-04-17 14:33:06 +02:00
#include <iostream>
2024-04-13 23:51:38 +02:00
using namespace Seele;
using namespace Seele::Metal;
2024-06-09 12:20:04 +02:00
PipelineCache::PipelineCache(PGraphics graphics, const std::string &name)
: graphics(graphics), cacheFile(name) {}
2024-04-13 23:51:38 +02:00
PipelineCache::~PipelineCache() {}
2024-06-09 12:20:04 +02:00
PGraphicsPipeline
PipelineCache::createPipeline(Gfx::LegacyPipelineCreateInfo createInfo) {
PPipelineLayout layout =
Gfx::PPipelineLayout(createInfo.pipelineLayout).cast<PipelineLayout>();
2024-04-14 11:35:37 +02:00
2024-06-09 12:20:04 +02:00
MTL::RenderPipelineDescriptor *pipelineDescriptor =
MTL::RenderPipelineDescriptor::alloc()->init();
2024-04-13 23:51:38 +02:00
2024-06-09 12:20:04 +02:00
MTL::VertexDescriptor *vertexDescriptor =
pipelineDescriptor->vertexDescriptor()->init();
MTL::VertexAttributeDescriptorArray *attributes =
vertexDescriptor->attributes()->init();
2024-04-17 14:33:06 +02:00
if (createInfo.vertexInput != nullptr) {
2024-06-09 12:20:04 +02:00
const auto &vertexInfo = createInfo.vertexInput->getInfo();
2024-04-15 13:48:34 +02:00
for (size_t attr = 0; attr < vertexInfo.attributes.size(); ++attr) {
2024-06-09 12:20:04 +02:00
MTL::VertexAttributeDescriptor *attribute =
attributes->object(attr + METAL_VERTEXATTRIBUTE_OFFSET)->init();
attribute->setBufferIndex(vertexInfo.attributes[attr].binding +
METAL_VERTEXBUFFER_OFFSET);
2024-04-15 13:48:34 +02:00
switch (vertexInfo.attributes[attr].format) {
case Gfx::SE_FORMAT_R32G32B32_SFLOAT:
attribute->setFormat(MTL::VertexFormatFloat3);
break;
default:
throw std::logic_error("TODO");
}
attribute->setOffset(vertexInfo.attributes[attr].offset);
2024-04-13 23:51:38 +02:00
}
2024-06-09 12:20:04 +02:00
MTL::VertexBufferLayoutDescriptorArray *bufferLayout =
vertexDescriptor->layouts()->init();
2024-04-15 13:48:34 +02:00
for (size_t binding = 0; binding < vertexInfo.bindings.size(); ++binding) {
2024-06-09 12:20:04 +02:00
MTL::VertexBufferLayoutDescriptor *buffer =
bufferLayout->object(binding + METAL_VERTEXBUFFER_OFFSET)->init();
2024-04-15 13:48:34 +02:00
buffer->setStride(vertexInfo.bindings[binding].stride);
buffer->setStepRate(1);
switch (vertexInfo.bindings[binding].inputRate) {
case Gfx::SE_VERTEX_INPUT_RATE_VERTEX:
buffer->setStepFunction(MTL::VertexStepFunctionPerVertex);
break;
case Gfx::SE_VERTEX_INPUT_RATE_INSTANCE:
buffer->setStepFunction(MTL::VertexStepFunctionPerInstance);
break;
}
2024-04-13 23:51:38 +02:00
}
}
pipelineDescriptor->setVertexDescriptor(vertexDescriptor);
2024-06-09 12:20:04 +02:00
pipelineDescriptor->setVertexFunction(
createInfo.vertexShader.cast<VertexShader>()->getFunction());
2024-04-14 11:35:37 +02:00
if (createInfo.fragmentShader != nullptr) {
2024-06-09 12:20:04 +02:00
pipelineDescriptor->setFragmentFunction(
createInfo.fragmentShader.cast<FragmentShader>()->getFunction());
2024-04-14 11:35:37 +02:00
}
pipelineDescriptor->setInputPrimitiveTopology(cast(createInfo.topology));
2024-06-09 12:20:04 +02:00
if (createInfo.renderPass->getLayout().depthAttachment.getTexture() !=
nullptr) {
2024-04-14 11:35:37 +02:00
pipelineDescriptor->setDepthAttachmentPixelFormat(
2024-06-09 12:20:04 +02:00
cast(createInfo.renderPass->getLayout()
.depthAttachment.getTexture()
.cast<Texture2D>()
->getFormat()));
2024-04-14 11:35:37 +02:00
}
2024-06-09 12:20:04 +02:00
pipelineDescriptor->setAlphaToCoverageEnabled(
createInfo.multisampleState.alphaCoverageEnable);
pipelineDescriptor->setAlphaToOneEnabled(
createInfo.multisampleState.alphaToOneEnable);
2024-04-14 11:35:37 +02:00
pipelineDescriptor->setRasterSampleCount(createInfo.multisampleState.samples);
2024-06-09 12:20:04 +02:00
pipelineDescriptor->setRasterizationEnabled(
!createInfo.rasterizationState.rasterizerDiscardEnable);
2024-04-14 11:35:37 +02:00
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;
}
2024-06-09 12:20:04 +02:00
NS::Error *error;
graphicsPipelines[hash] = new GraphicsPipeline(
graphics, type,
graphics->getDevice()->newRenderPipelineState(pipelineDescriptor, &error),
std::move(createInfo.pipelineLayout));
2024-04-17 14:33:06 +02:00
if (error) {
2024-06-09 12:20:04 +02:00
std::cout << error->localizedDescription()->cString(NS::ASCIIStringEncoding)
<< std::endl;
2024-04-17 14:33:06 +02:00
assert(false);
}
2024-04-13 23:51:38 +02:00
pipelineDescriptor->release();
2024-04-14 11:35:37 +02:00
return graphicsPipelines[hash];
2024-04-13 23:51:38 +02:00
}
2024-06-09 12:20:04 +02:00
PGraphicsPipeline
PipelineCache::createPipeline(Gfx::MeshPipelineCreateInfo createInfo) {
MTL::MeshRenderPipelineDescriptor *pipelineDescriptor =
MTL::MeshRenderPipelineDescriptor::alloc()->init();
2024-04-13 23:51:38 +02:00
2024-06-09 12:20:04 +02:00
pipelineDescriptor->setMeshFunction(
createInfo.meshShader.cast<MeshShader>()->getFunction());
2024-04-14 11:35:37 +02:00
if (createInfo.taskShader != nullptr) {
2024-06-09 12:20:04 +02:00
pipelineDescriptor->setObjectFunction(
createInfo.taskShader.cast<TaskShader>()->getFunction());
2024-04-14 11:35:37 +02:00
}
if (createInfo.fragmentShader != nullptr) {
2024-06-09 12:20:04 +02:00
pipelineDescriptor->setFragmentFunction(
createInfo.fragmentShader.cast<FragmentShader>()->getFunction());
2024-04-14 11:35:37 +02:00
}
2024-06-09 12:20:04 +02:00
if (createInfo.renderPass->getLayout().depthAttachment.getTexture() !=
nullptr) {
2024-04-14 11:35:37 +02:00
pipelineDescriptor->setDepthAttachmentPixelFormat(
2024-06-09 12:20:04 +02:00
cast(createInfo.renderPass->getLayout()
.depthAttachment.getTexture()
.cast<Texture2D>()
->getFormat()));
2024-04-14 11:35:37 +02:00
}
2024-06-09 12:20:04 +02:00
pipelineDescriptor->setAlphaToCoverageEnabled(
createInfo.multisampleState.alphaCoverageEnable);
pipelineDescriptor->setAlphaToOneEnabled(
createInfo.multisampleState.alphaToOneEnable);
2024-04-14 11:35:37 +02:00
pipelineDescriptor->setRasterSampleCount(createInfo.multisampleState.samples);
2024-06-09 12:20:04 +02:00
pipelineDescriptor->setRasterizationEnabled(
!createInfo.rasterizationState.rasterizerDiscardEnable);
2024-04-14 11:35:37 +02:00
uint32 hash = pipelineDescriptor->hash();
if (graphicsPipelines.contains(hash)) {
return graphicsPipelines[hash];
}
2024-06-09 12:20:04 +02:00
NS::Error *error = nullptr;
2024-04-17 14:33:06 +02:00
MTL::AutoreleasedRenderPipelineReflection reflection;
graphicsPipelines[hash] = new GraphicsPipeline(
graphics, MTL::PrimitiveTypeTriangle,
2024-06-09 12:20:04 +02:00
graphics->getDevice()->newRenderPipelineState(
pipelineDescriptor, MTL::PipelineOptionNone, &reflection, &error),
2024-04-17 14:33:06 +02:00
std::move(createInfo.pipelineLayout));
2024-04-14 11:35:37 +02:00
pipelineDescriptor->release();
return graphicsPipelines[hash];
}
2024-06-09 12:20:04 +02:00
PComputePipeline
PipelineCache::createPipeline(Gfx::ComputePipelineCreateInfo createInfo) {
2024-04-14 11:35:37 +02:00
PComputeShader shader = createInfo.computeShader.cast<ComputeShader>();
uint32 hash = shader->getShaderHash();
if (computePipelines.contains(hash)) {
return computePipelines[hash];
}
2024-06-09 12:20:04 +02:00
NS::Error *error;
2024-04-14 11:35:37 +02:00
computePipelines[hash] =
2024-06-09 12:20:04 +02:00
new ComputePipeline(graphics,
graphics->getDevice()->newComputePipelineState(
shader->getFunction(), &error),
2024-04-14 11:35:37 +02:00
std::move(createInfo.pipelineLayout));
assert(!error);
return computePipelines[hash];
}