-
-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #578 from SamoZ256/metal2
Metal backend
- Loading branch information
Showing
31 changed files
with
3,225 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,5 +64,9 @@ fb.bat | |
*.elf | ||
*.smdh | ||
|
||
# Compiled Metal shader files | ||
*.ir | ||
*.metallib | ||
|
||
config.toml | ||
CMakeSettings.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
#pragma once | ||
|
||
#include <map> | ||
|
||
#include "objc_helper.hpp" | ||
#include "pica_to_mtl.hpp" | ||
|
||
using namespace PICA; | ||
|
||
namespace Metal { | ||
struct BlitPipelineHash { | ||
// Formats | ||
ColorFmt colorFmt; | ||
DepthFmt depthFmt; | ||
}; | ||
|
||
// This pipeline only caches the pipeline with all of its color and depth attachment variations | ||
class BlitPipelineCache { | ||
public: | ||
BlitPipelineCache() = default; | ||
|
||
~BlitPipelineCache() { | ||
reset(); | ||
vertexFunction->release(); | ||
fragmentFunction->release(); | ||
} | ||
|
||
void set(MTL::Device* dev, MTL::Function* vert, MTL::Function* frag) { | ||
device = dev; | ||
vertexFunction = vert; | ||
fragmentFunction = frag; | ||
} | ||
|
||
MTL::RenderPipelineState* get(BlitPipelineHash hash) { | ||
u8 intHash = ((u8)hash.colorFmt << 3) | (u8)hash.depthFmt; | ||
auto& pipeline = pipelineCache[intHash]; | ||
if (!pipeline) { | ||
MTL::RenderPipelineDescriptor* desc = MTL::RenderPipelineDescriptor::alloc()->init(); | ||
desc->setVertexFunction(vertexFunction); | ||
desc->setFragmentFunction(fragmentFunction); | ||
|
||
auto colorAttachment = desc->colorAttachments()->object(0); | ||
colorAttachment->setPixelFormat(toMTLPixelFormatColor(hash.colorFmt)); | ||
|
||
desc->setDepthAttachmentPixelFormat(toMTLPixelFormatDepth(hash.depthFmt)); | ||
|
||
NS::Error* error = nullptr; | ||
desc->setLabel(toNSString("Blit pipeline")); | ||
pipeline = device->newRenderPipelineState(desc, &error); | ||
if (error) { | ||
Helpers::panic("Error creating blit pipeline state: %s", error->description()->cString(NS::ASCIIStringEncoding)); | ||
} | ||
|
||
desc->release(); | ||
} | ||
|
||
return pipeline; | ||
} | ||
|
||
void reset() { | ||
for (auto& pair : pipelineCache) { | ||
pair.second->release(); | ||
} | ||
pipelineCache.clear(); | ||
} | ||
|
||
private: | ||
std::map<u8, MTL::RenderPipelineState*> pipelineCache; | ||
|
||
MTL::Device* device; | ||
MTL::Function* vertexFunction; | ||
MTL::Function* fragmentFunction; | ||
}; | ||
} // namespace Metal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
#pragma once | ||
|
||
#include <Metal/Metal.hpp> | ||
|
||
namespace Metal { | ||
struct RenderState { | ||
MTL::RenderPipelineState* renderPipelineState = nullptr; | ||
MTL::DepthStencilState* depthStencilState = nullptr; | ||
MTL::Texture* textures[3] = {nullptr}; | ||
MTL::SamplerState* samplerStates[3] = {nullptr}; | ||
}; | ||
|
||
class CommandEncoder { | ||
public: | ||
void newRenderCommandEncoder(MTL::RenderCommandEncoder* rce) { | ||
renderCommandEncoder = rce; | ||
|
||
// Reset the render state | ||
renderState = RenderState{}; | ||
} | ||
|
||
// Resource binding | ||
void setRenderPipelineState(MTL::RenderPipelineState* renderPipelineState) { | ||
if (renderPipelineState != renderState.renderPipelineState) { | ||
renderCommandEncoder->setRenderPipelineState(renderPipelineState); | ||
renderState.renderPipelineState = renderPipelineState; | ||
} | ||
} | ||
|
||
void setDepthStencilState(MTL::DepthStencilState* depthStencilState) { | ||
if (depthStencilState != renderState.depthStencilState) { | ||
renderCommandEncoder->setDepthStencilState(depthStencilState); | ||
renderState.depthStencilState = depthStencilState; | ||
} | ||
} | ||
|
||
void setFragmentTexture(MTL::Texture* texture, u32 index) { | ||
if (texture != renderState.textures[index]) { | ||
renderCommandEncoder->setFragmentTexture(texture, index); | ||
renderState.textures[index] = texture; | ||
} | ||
} | ||
|
||
void setFragmentSamplerState(MTL::SamplerState* samplerState, u32 index) { | ||
if (samplerState != renderState.samplerStates[index]) { | ||
renderCommandEncoder->setFragmentSamplerState(samplerState, index); | ||
renderState.samplerStates[index] = samplerState; | ||
} | ||
} | ||
|
||
private: | ||
MTL::RenderCommandEncoder* renderCommandEncoder = nullptr; | ||
|
||
RenderState renderState; | ||
}; | ||
} // namespace Metal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#pragma once | ||
|
||
#include <Metal/Metal.hpp> | ||
|
||
#define GET_HELPER_TEXTURE_BINDING(binding) (30 - binding) | ||
#define GET_HELPER_SAMPLER_STATE_BINDING(binding) (15 - binding) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
#pragma once | ||
|
||
#include <map> | ||
|
||
#include "pica_to_mtl.hpp" | ||
|
||
using namespace PICA; | ||
|
||
namespace Metal { | ||
struct DepthStencilHash { | ||
u32 stencilConfig; | ||
u16 stencilOpConfig; | ||
bool depthStencilWrite; | ||
u8 depthFunc; | ||
}; | ||
|
||
class DepthStencilCache { | ||
public: | ||
DepthStencilCache() = default; | ||
|
||
~DepthStencilCache() { reset(); } | ||
|
||
void set(MTL::Device* dev) { device = dev; } | ||
|
||
MTL::DepthStencilState* get(DepthStencilHash hash) { | ||
u64 intHash = | ||
((u64)hash.depthStencilWrite << 56) | ((u64)hash.depthFunc << 48) | ((u64)hash.stencilConfig << 16) | (u64)hash.stencilOpConfig; | ||
auto& depthStencilState = depthStencilCache[intHash]; | ||
if (!depthStencilState) { | ||
MTL::DepthStencilDescriptor* desc = MTL::DepthStencilDescriptor::alloc()->init(); | ||
desc->setDepthWriteEnabled(hash.depthStencilWrite); | ||
desc->setDepthCompareFunction(toMTLCompareFunc(hash.depthFunc)); | ||
|
||
const bool stencilEnable = Helpers::getBit<0>(hash.stencilConfig); | ||
MTL::StencilDescriptor* stencilDesc = nullptr; | ||
if (stencilEnable) { | ||
const u8 stencilFunc = Helpers::getBits<4, 3>(hash.stencilConfig); | ||
const u8 stencilRefMask = Helpers::getBits<24, 8>(hash.stencilConfig); | ||
|
||
const u32 stencilBufferMask = hash.depthStencilWrite ? Helpers::getBits<8, 8>(hash.stencilConfig) : 0; | ||
|
||
const u8 stencilFailOp = Helpers::getBits<0, 3>(hash.stencilOpConfig); | ||
const u8 depthFailOp = Helpers::getBits<4, 3>(hash.stencilOpConfig); | ||
const u8 passOp = Helpers::getBits<8, 3>(hash.stencilOpConfig); | ||
|
||
stencilDesc = MTL::StencilDescriptor::alloc()->init(); | ||
stencilDesc->setStencilFailureOperation(toMTLStencilOperation(stencilFailOp)); | ||
stencilDesc->setDepthFailureOperation(toMTLStencilOperation(depthFailOp)); | ||
stencilDesc->setDepthStencilPassOperation(toMTLStencilOperation(passOp)); | ||
stencilDesc->setStencilCompareFunction(toMTLCompareFunc(stencilFunc)); | ||
stencilDesc->setReadMask(stencilRefMask); | ||
stencilDesc->setWriteMask(stencilBufferMask); | ||
|
||
desc->setFrontFaceStencil(stencilDesc); | ||
desc->setBackFaceStencil(stencilDesc); | ||
} | ||
|
||
depthStencilState = device->newDepthStencilState(desc); | ||
|
||
desc->release(); | ||
if (stencilDesc) { | ||
stencilDesc->release(); | ||
} | ||
} | ||
|
||
return depthStencilState; | ||
} | ||
|
||
void reset() { | ||
for (auto& pair : depthStencilCache) { | ||
pair.second->release(); | ||
} | ||
depthStencilCache.clear(); | ||
} | ||
|
||
private: | ||
std::map<u64, MTL::DepthStencilState*> depthStencilCache; | ||
MTL::Device* device; | ||
}; | ||
} // namespace Metal |
Oops, something went wrong.