rework command encoder system

This commit is contained in:
Samuliak 2024-07-29 19:00:13 +02:00
parent 89a2c23dd7
commit f01130022a
8 changed files with 149 additions and 77 deletions

View File

@ -134,7 +134,7 @@ namespace LatteDecompiler
//shaderSrc->addFmt("UNIFORM_BUFFER_LAYOUT({}, {}, {}) ", (sint32)decompilerContext->output->resourceMappingGL.uniformBuffersBindingPoint[i], (sint32)decompilerContext->output->resourceMappingVK.setIndex, (sint32)decompilerContext->output->resourceMappingVK.uniformBuffersBindingPoint[i]); //shaderSrc->addFmt("UNIFORM_BUFFER_LAYOUT({}, {}, {}) ", (sint32)decompilerContext->output->resourceMappingGL.uniformBuffersBindingPoint[i], (sint32)decompilerContext->output->resourceMappingVK.setIndex, (sint32)decompilerContext->output->resourceMappingVK.uniformBuffersBindingPoint[i]);
shaderSrc->addFmt("struct UBuff{} {" _CRLF, i); shaderSrc->addFmt("struct UBuff{} {{" _CRLF, i);
shaderSrc->addFmt("float4 d{}[{}];" _CRLF, i, decompilerContext->analyzer.uniformBufferAccessTracker[i].DetermineSize(decompilerContext->shaderBaseHash, LATTE_GLSL_DYNAMIC_UNIFORM_BLOCK_SIZE)); shaderSrc->addFmt("float4 d{}[{}];" _CRLF, i, decompilerContext->analyzer.uniformBufferAccessTracker[i].DetermineSize(decompilerContext->shaderBaseHash, LATTE_GLSL_DYNAMIC_UNIFORM_BLOCK_SIZE));
shaderSrc->add("};" _CRLF _CRLF); shaderSrc->add("};" _CRLF _CRLF);
} }
@ -307,7 +307,7 @@ namespace LatteDecompiler
cemu_assert_debug(decompilerContext->output->resourceMappingGL.uniformBuffersBindingPoint[i] >= 0); cemu_assert_debug(decompilerContext->output->resourceMappingGL.uniformBuffersBindingPoint[i] >= 0);
cemu_assert_debug(decompilerContext->output->resourceMappingVK.uniformBuffersBindingPoint[i] >= 0); cemu_assert_debug(decompilerContext->output->resourceMappingVK.uniformBuffersBindingPoint[i] >= 0);
src->addFmt("constant UBuff{}& ubuff{} [[buffer({})]]" _CRLF, i, i, (sint32)decompilerContext->output->resourceMappingGL.uniformBuffersBindingPoint[i]); src->addFmt(", constant UBuff{}& ubuff{} [[buffer({})]]", i, i, (sint32)decompilerContext->output->resourceMappingGL.uniformBuffersBindingPoint[i]);
} }
} }
} }

View File

@ -5,7 +5,7 @@
LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
Latte::E_HWTILEMODE tileMode, bool isDepth) Latte::E_HWTILEMODE tileMode, bool isDepth)
: LatteTexture(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth), m_mtlr(mtlRenderer), m_format(format) : LatteTexture(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth), m_mtlr(mtlRenderer), m_format(format), m_isDepth(isDepth)
{ {
MTL::TextureDescriptor* desc = MTL::TextureDescriptor::alloc()->init(); MTL::TextureDescriptor* desc = MTL::TextureDescriptor::alloc()->init();
desc->setStorageMode(MTL::StorageModeShared); // TODO: use private? desc->setStorageMode(MTL::StorageModeShared); // TODO: use private?
@ -34,7 +34,7 @@ LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, Latte::E_DIM
desc->setArrayLength(effectiveBaseDepth); desc->setArrayLength(effectiveBaseDepth);
} }
auto formatInfo = GetMtlPixelFormatInfo(format); auto formatInfo = GetMtlPixelFormatInfo(format, isDepth);
desc->setPixelFormat(formatInfo.pixelFormat); desc->setPixelFormat(formatInfo.pixelFormat);
// TODO: is write needed? // TODO: is write needed?

View File

@ -21,23 +21,20 @@ public:
return m_format; return m_format;
} }
bool IsDepth() const {
return m_isDepth;
}
void AllocateOnHost() override; void AllocateOnHost() override;
protected: protected:
LatteTextureView* CreateView(Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount) override; LatteTextureView* CreateView(Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount) override;
public:
uint64 m_vkFlushIndex{}; // used to track read-write dependencies within the same renderpass
uint64 m_vkFlushIndex_read{};
uint64 m_vkFlushIndex_write{};
uint32 m_collisionCheckIndex{}; // used to track if texture is being both sampled and output to during drawcall
private: private:
class MetalRenderer* m_mtlr; class MetalRenderer* m_mtlr;
MTL::Texture* m_texture; MTL::Texture* m_texture;
Latte::E_GX2SURFFMT m_format; Latte::E_GX2SURFFMT m_format;
bool m_isDepth;
}; };

View File

@ -52,7 +52,7 @@ LatteTextureViewMtl::LatteTextureViewMtl(MetalRenderer* mtlRenderer, LatteTextur
// TODO: swizzle // TODO: swizzle
auto formatInfo = GetMtlPixelFormatInfo(format); auto formatInfo = GetMtlPixelFormatInfo(format, texture->IsDepth());
m_texture = texture->GetTexture()->newTextureView(formatInfo.pixelFormat, textureType, NS::Range::Make(baseLevel, levelCount), NS::Range::Make(baseLayer, layerCount)); m_texture = texture->GetTexture()->newTextureView(formatInfo.pixelFormat, textureType, NS::Range::Make(baseLevel, levelCount), NS::Range::Make(baseLayer, layerCount));
} }

View File

@ -3,8 +3,7 @@
#include "Metal/MTLPixelFormat.hpp" #include "Metal/MTLPixelFormat.hpp"
#include "Metal/MTLVertexDescriptor.hpp" #include "Metal/MTLVertexDescriptor.hpp"
// TODO: separate color and depth formats std::map<Latte::E_GX2SURFFMT, MtlPixelFormatInfo> MTL_COLOR_FORMAT_TABLE = {
std::map<Latte::E_GX2SURFFMT, MtlPixelFormatInfo> MTL_FORMAT_TABLE = {
{Latte::E_GX2SURFFMT::R4_G4_UNORM, {MTL::PixelFormatRG8Unorm, 2}}, // TODO: correct? {Latte::E_GX2SURFFMT::R4_G4_UNORM, {MTL::PixelFormatRG8Unorm, 2}}, // TODO: correct?
{Latte::E_GX2SURFFMT::R5_G6_B5_UNORM, {MTL::PixelFormatB5G6R5Unorm, 2}}, // TODO: correct? {Latte::E_GX2SURFFMT::R5_G6_B5_UNORM, {MTL::PixelFormatB5G6R5Unorm, 2}}, // TODO: correct?
{Latte::E_GX2SURFFMT::R5_G5_B5_A1_UNORM, {MTL::PixelFormatBGR5A1Unorm, 2}}, // TODO: correct? {Latte::E_GX2SURFFMT::R5_G5_B5_A1_UNORM, {MTL::PixelFormatBGR5A1Unorm, 2}}, // TODO: correct?
@ -60,11 +59,6 @@ std::map<Latte::E_GX2SURFFMT, MtlPixelFormatInfo> MTL_FORMAT_TABLE = {
{Latte::E_GX2SURFFMT::R32_G32_B32_A32_UINT, {MTL::PixelFormatRGBA32Uint, 16}}, {Latte::E_GX2SURFFMT::R32_G32_B32_A32_UINT, {MTL::PixelFormatRGBA32Uint, 16}},
{Latte::E_GX2SURFFMT::R32_G32_B32_A32_SINT, {MTL::PixelFormatRGBA32Sint, 16}}, {Latte::E_GX2SURFFMT::R32_G32_B32_A32_SINT, {MTL::PixelFormatRGBA32Sint, 16}},
{Latte::E_GX2SURFFMT::R32_G32_B32_A32_FLOAT, {MTL::PixelFormatRGBA32Float, 16}}, {Latte::E_GX2SURFFMT::R32_G32_B32_A32_FLOAT, {MTL::PixelFormatRGBA32Float, 16}},
{Latte::E_GX2SURFFMT::D24_S8_UNORM, {MTL::PixelFormatDepth24Unorm_Stencil8, 4}}, // TODO: not supported on Apple sillicon, maybe find something else
{Latte::E_GX2SURFFMT::D24_S8_FLOAT, {MTL::PixelFormatDepth32Float_Stencil8, 4}}, // TODO: correct?
{Latte::E_GX2SURFFMT::D32_S8_FLOAT, {MTL::PixelFormatDepth32Float_Stencil8, 5}},
{Latte::E_GX2SURFFMT::D16_UNORM, {MTL::PixelFormatDepth16Unorm, 2}},
{Latte::E_GX2SURFFMT::D32_FLOAT, {MTL::PixelFormatDepth32Float, 4}},
{Latte::E_GX2SURFFMT::BC1_UNORM, {MTL::PixelFormatBC1_RGBA, 8, {4, 4}}}, // TODO: correct? {Latte::E_GX2SURFFMT::BC1_UNORM, {MTL::PixelFormatBC1_RGBA, 8, {4, 4}}}, // TODO: correct?
{Latte::E_GX2SURFFMT::BC1_SRGB, {MTL::PixelFormatBC1_RGBA_sRGB, 8, {4, 4}}}, // TODO: correct? {Latte::E_GX2SURFFMT::BC1_SRGB, {MTL::PixelFormatBC1_RGBA_sRGB, 8, {4, 4}}}, // TODO: correct?
{Latte::E_GX2SURFFMT::BC2_UNORM, {MTL::PixelFormatBC2_RGBA, 16, {4, 4}}}, // TODO: correct? {Latte::E_GX2SURFFMT::BC2_UNORM, {MTL::PixelFormatBC2_RGBA, 16, {4, 4}}}, // TODO: correct?
@ -77,11 +71,29 @@ std::map<Latte::E_GX2SURFFMT, MtlPixelFormatInfo> MTL_FORMAT_TABLE = {
{Latte::E_GX2SURFFMT::BC5_SNORM, {MTL::PixelFormatBC5_RGSnorm, 16, {4, 4}}}, // TODO: correct? {Latte::E_GX2SURFFMT::BC5_SNORM, {MTL::PixelFormatBC5_RGSnorm, 16, {4, 4}}}, // TODO: correct?
}; };
const MtlPixelFormatInfo GetMtlPixelFormatInfo(Latte::E_GX2SURFFMT format) std::map<Latte::E_GX2SURFFMT, MtlPixelFormatInfo> MTL_DEPTH_FORMAT_TABLE = {
{ {Latte::E_GX2SURFFMT::D24_S8_UNORM, {MTL::PixelFormatDepth24Unorm_Stencil8, 4}}, // TODO: not supported on Apple sillicon, maybe find something else
cemu_assert_debug(static_cast<size_t>(format) < MTL_FORMAT_TABLE.size()); {Latte::E_GX2SURFFMT::D24_S8_FLOAT, {MTL::PixelFormatDepth32Float_Stencil8, 4}}, // TODO: correct?
{Latte::E_GX2SURFFMT::D32_S8_FLOAT, {MTL::PixelFormatDepth32Float_Stencil8, 5}},
{Latte::E_GX2SURFFMT::D16_UNORM, {MTL::PixelFormatDepth16Unorm, 2}},
{Latte::E_GX2SURFFMT::D32_FLOAT, {MTL::PixelFormatDepth32Float, 4}},
};
const MtlPixelFormatInfo GetMtlPixelFormatInfo(Latte::E_GX2SURFFMT format, bool isDepth)
{
MtlPixelFormatInfo formatInfo;
if (isDepth)
formatInfo = MTL_DEPTH_FORMAT_TABLE[format];
else
formatInfo = MTL_COLOR_FORMAT_TABLE[format];
// Depth24Unorm_Stencil8 is not supported on Apple sillicon
// TODO: query if format is available instead
if (formatInfo.pixelFormat == MTL::PixelFormatDepth24Unorm_Stencil8)
{
formatInfo.pixelFormat = MTL::PixelFormatDepth32Float_Stencil8;
}
MtlPixelFormatInfo formatInfo = MTL_FORMAT_TABLE[format];
if (formatInfo.pixelFormat == MTL::PixelFormatInvalid) if (formatInfo.pixelFormat == MTL::PixelFormatInvalid)
{ {
printf("invalid pixel format: %u\n", (uint32)format); printf("invalid pixel format: %u\n", (uint32)format);
@ -94,16 +106,16 @@ inline uint32 CeilDivide(uint32 a, uint32 b) {
return (a + b - 1) / b; return (a + b - 1) / b;
} }
size_t GetMtlTextureBytesPerRow(Latte::E_GX2SURFFMT format, uint32 width) size_t GetMtlTextureBytesPerRow(Latte::E_GX2SURFFMT format, bool isDepth, uint32 width)
{ {
const auto& formatInfo = GetMtlPixelFormatInfo(format); const auto& formatInfo = GetMtlPixelFormatInfo(format, isDepth);
return CeilDivide(width, formatInfo.blockTexelSize.x) * formatInfo.bytesPerBlock; return CeilDivide(width, formatInfo.blockTexelSize.x) * formatInfo.bytesPerBlock;
} }
size_t GetMtlTextureBytesPerImage(Latte::E_GX2SURFFMT format, uint32 height, size_t bytesPerRow) size_t GetMtlTextureBytesPerImage(Latte::E_GX2SURFFMT format, bool isDepth, uint32 height, size_t bytesPerRow)
{ {
const auto& formatInfo = GetMtlPixelFormatInfo(format); const auto& formatInfo = GetMtlPixelFormatInfo(format, isDepth);
return CeilDivide(height, formatInfo.blockTexelSize.y) * bytesPerRow; return CeilDivide(height, formatInfo.blockTexelSize.y) * bytesPerRow;
} }

View File

@ -18,11 +18,11 @@ struct MtlPixelFormatInfo {
Uvec2 blockTexelSize = {1, 1}; Uvec2 blockTexelSize = {1, 1};
}; };
const MtlPixelFormatInfo GetMtlPixelFormatInfo(Latte::E_GX2SURFFMT format); const MtlPixelFormatInfo GetMtlPixelFormatInfo(Latte::E_GX2SURFFMT format, bool isDepth);
size_t GetMtlTextureBytesPerRow(Latte::E_GX2SURFFMT format, uint32 width); size_t GetMtlTextureBytesPerRow(Latte::E_GX2SURFFMT format, bool isDepth, uint32 width);
size_t GetMtlTextureBytesPerImage(Latte::E_GX2SURFFMT format, uint32 height, size_t bytesPerRow); size_t GetMtlTextureBytesPerImage(Latte::E_GX2SURFFMT format, bool isDepth, uint32 height, size_t bytesPerRow);
MTL::PrimitiveType GetMtlPrimitiveType(LattePrimitiveMode mode); MTL::PrimitiveType GetMtlPrimitiveType(LattePrimitiveMode mode);

View File

@ -12,6 +12,7 @@
#include "Cafe/HW/Latte/Core/LatteShader.h" #include "Cafe/HW/Latte/Core/LatteShader.h"
#include "Cafe/HW/Latte/Core/LatteIndices.h" #include "Cafe/HW/Latte/Core/LatteIndices.h"
#include "Foundation/NSTypes.hpp" #include "Foundation/NSTypes.hpp"
#include "Metal/MTLRenderCommandEncoder.hpp"
#include "gui/guiWrapper.h" #include "gui/guiWrapper.h"
extern bool hasValidFramebufferAttached; extern bool hasValidFramebufferAttached;
@ -147,14 +148,14 @@ void MetalRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutput
MTL::Texture* colorRenderTargets[8] = {nullptr}; MTL::Texture* colorRenderTargets[8] = {nullptr};
colorRenderTargets[0] = m_drawable->texture(); colorRenderTargets[0] = m_drawable->texture();
BeginRenderPassIfNeeded(renderPassDescriptor, colorRenderTargets, nullptr); auto renderCommandEncoder = GetRenderCommandEncoder(renderPassDescriptor, colorRenderTargets, nullptr);
// Draw to Metal layer // Draw to Metal layer
m_renderCommandEncoder->setRenderPipelineState(m_presentPipeline); renderCommandEncoder->setRenderPipelineState(m_presentPipeline);
m_renderCommandEncoder->setFragmentTexture(presentTexture, 0); renderCommandEncoder->setFragmentTexture(presentTexture, 0);
m_renderCommandEncoder->setFragmentSamplerState(m_nearestSampler, 0); renderCommandEncoder->setFragmentSamplerState(m_nearestSampler, 0);
m_renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), NS::UInteger(3)); renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), NS::UInteger(3));
} }
bool MetalRenderer::BeginFrame(bool mainWindow) bool MetalRenderer::BeginFrame(bool mainWindow)
@ -351,8 +352,8 @@ void MetalRenderer::texture_loadSlice(LatteTexture* hostTexture, sint32 width, s
{ {
auto mtlTexture = (LatteTextureMtl*)hostTexture; auto mtlTexture = (LatteTextureMtl*)hostTexture;
size_t bytesPerRow = GetMtlTextureBytesPerRow(mtlTexture->GetFormat(), width); size_t bytesPerRow = GetMtlTextureBytesPerRow(mtlTexture->GetFormat(), mtlTexture->IsDepth(), width);
size_t bytesPerImage = GetMtlTextureBytesPerImage(mtlTexture->GetFormat(), height, bytesPerRow); size_t bytesPerImage = GetMtlTextureBytesPerImage(mtlTexture->GetFormat(), mtlTexture->IsDepth(), height, bytesPerRow);
mtlTexture->GetTexture()->replaceRegion(MTL::Region(0, 0, width, height), mipIndex, sliceIndex, pixelData, bytesPerRow, bytesPerImage); mtlTexture->GetTexture()->replaceRegion(MTL::Region(0, 0, width, height), mipIndex, sliceIndex, pixelData, bytesPerRow, bytesPerImage);
} }
@ -535,7 +536,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
{ {
depthRenderTarget = depthTexture->GetTexture(); depthRenderTarget = depthTexture->GetTexture();
} }
BeginRenderPassIfNeeded(renderPassDescriptor, colorRenderTargets, depthRenderTarget); auto renderCommandEncoder = GetRenderCommandEncoder(renderPassDescriptor, colorRenderTargets, depthRenderTarget);
// Shaders // Shaders
LatteSHRC_UpdateActiveShaders(); LatteSHRC_UpdateActiveShaders();
@ -622,7 +623,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
printf("error creating render pipeline state: %s\n", error->localizedDescription()->utf8String()); printf("error creating render pipeline state: %s\n", error->localizedDescription()->utf8String());
return; return;
} }
m_renderCommandEncoder->setRenderPipelineState(renderPipelineState); renderCommandEncoder->setRenderPipelineState(renderPipelineState);
// Primitive type // Primitive type
const LattePrimitiveMode primitiveMode = static_cast<LattePrimitiveMode>(LatteGPUState.contextRegister[mmVGT_PRIMITIVE_TYPE]); const LattePrimitiveMode primitiveMode = static_cast<LattePrimitiveMode>(LatteGPUState.contextRegister[mmVGT_PRIMITIVE_TYPE]);
@ -648,25 +649,25 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
auto& vertexBufferRange = m_state.vertexBuffers[i]; auto& vertexBufferRange = m_state.vertexBuffers[i];
if (vertexBufferRange.needsRebind) if (vertexBufferRange.needsRebind)
{ {
m_renderCommandEncoder->setVertexBuffer(m_memoryManager->GetBufferCache(), vertexBufferRange.offset, GET_MTL_VERTEX_BUFFER_INDEX(i)); renderCommandEncoder->setVertexBuffer(m_memoryManager->GetBufferCache(), vertexBufferRange.offset, GET_MTL_VERTEX_BUFFER_INDEX(i));
// TODO: uncomment // TODO: uncomment
//vertexBufferRange.needsRebind = false; //vertexBufferRange.needsRebind = false;
} }
} }
// Uniform buffers, textures and samplers // Uniform buffers, textures and samplers
BindStageResources(vertexShader); BindStageResources(renderCommandEncoder, vertexShader);
BindStageResources(pixelShader); BindStageResources(renderCommandEncoder, pixelShader);
// Draw // Draw
if (hostIndexType != INDEX_TYPE::NONE) if (hostIndexType != INDEX_TYPE::NONE)
{ {
auto mtlIndexType = GetMtlIndexType(hostIndexType); auto mtlIndexType = GetMtlIndexType(hostIndexType);
MTL::Buffer* indexBuffer = m_memoryManager->GetBuffer(indexBufferIndex); MTL::Buffer* indexBuffer = m_memoryManager->GetBuffer(indexBufferIndex);
m_renderCommandEncoder->drawIndexedPrimitives(mtlPrimitiveType, hostIndexCount, mtlIndexType, indexBuffer, 0, instanceCount, baseVertex, baseInstance); renderCommandEncoder->drawIndexedPrimitives(mtlPrimitiveType, hostIndexCount, mtlIndexType, indexBuffer, 0, instanceCount, baseVertex, baseInstance);
} else } else
{ {
m_renderCommandEncoder->drawPrimitives(mtlPrimitiveType, baseVertex, count, instanceCount, baseInstance); renderCommandEncoder->drawPrimitives(mtlPrimitiveType, baseVertex, count, instanceCount, baseInstance);
} }
} }
@ -689,7 +690,7 @@ void MetalRenderer::indexData_uploadIndexMemory(uint32 offset, uint32 size)
printf("MetalRenderer::indexData_uploadIndexMemory not implemented\n"); printf("MetalRenderer::indexData_uploadIndexMemory not implemented\n");
} }
void MetalRenderer::BindStageResources(LatteDecompilerShader* shader) void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandEncoder, LatteDecompilerShader* shader)
{ {
sint32 textureCount = shader->resourceMapping.getTextureCount(); sint32 textureCount = shader->resourceMapping.getTextureCount();
@ -722,12 +723,12 @@ void MetalRenderer::BindStageResources(LatteDecompilerShader* shader)
{ {
case LatteConst::ShaderType::Vertex: case LatteConst::ShaderType::Vertex:
{ {
m_renderCommandEncoder->setVertexSamplerState(sampler, binding); renderCommandEncoder->setVertexSamplerState(sampler, binding);
break; break;
} }
case LatteConst::ShaderType::Pixel: case LatteConst::ShaderType::Pixel:
{ {
m_renderCommandEncoder->setFragmentSamplerState(sampler, binding); renderCommandEncoder->setFragmentSamplerState(sampler, binding);
break; break;
} }
default: default:
@ -739,12 +740,12 @@ void MetalRenderer::BindStageResources(LatteDecompilerShader* shader)
{ {
case LatteConst::ShaderType::Vertex: case LatteConst::ShaderType::Vertex:
{ {
m_renderCommandEncoder->setVertexTexture(textureView->GetTexture(), binding); renderCommandEncoder->setVertexTexture(textureView->GetTexture(), binding);
break; break;
} }
case LatteConst::ShaderType::Pixel: case LatteConst::ShaderType::Pixel:
{ {
m_renderCommandEncoder->setFragmentTexture(textureView->GetTexture(), binding); renderCommandEncoder->setFragmentTexture(textureView->GetTexture(), binding);
break; break;
} }
default: default:
@ -840,12 +841,12 @@ void MetalRenderer::BindStageResources(LatteDecompilerShader* shader)
{ {
case LatteConst::ShaderType::Vertex: case LatteConst::ShaderType::Vertex:
{ {
m_renderCommandEncoder->setVertexBytes(supportBufferData, sizeof(supportBufferData), MTL_SUPPORT_BUFFER_BINDING); renderCommandEncoder->setVertexBytes(supportBufferData, sizeof(supportBufferData), MTL_SUPPORT_BUFFER_BINDING);
break; break;
} }
case LatteConst::ShaderType::Pixel: case LatteConst::ShaderType::Pixel:
{ {
m_renderCommandEncoder->setFragmentBytes(supportBufferData, sizeof(supportBufferData), MTL_SUPPORT_BUFFER_BINDING); renderCommandEncoder->setFragmentBytes(supportBufferData, sizeof(supportBufferData), MTL_SUPPORT_BUFFER_BINDING);
break; break;
} }
default: default:
@ -865,12 +866,12 @@ void MetalRenderer::BindStageResources(LatteDecompilerShader* shader)
{ {
case LatteConst::ShaderType::Vertex: case LatteConst::ShaderType::Vertex:
{ {
m_renderCommandEncoder->setVertexBuffer(m_memoryManager->GetBufferCache(), offset, binding); renderCommandEncoder->setVertexBuffer(m_memoryManager->GetBufferCache(), offset, binding);
break; break;
} }
case LatteConst::ShaderType::Pixel: case LatteConst::ShaderType::Pixel:
{ {
m_renderCommandEncoder->setFragmentBuffer(m_memoryManager->GetBufferCache(), offset, binding); renderCommandEncoder->setFragmentBuffer(m_memoryManager->GetBufferCache(), offset, binding);
break; break;
} }
default: default:

View File

@ -6,6 +6,7 @@
#include "Cafe/HW/Latte/Renderer/Renderer.h" #include "Cafe/HW/Latte/Renderer/Renderer.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h" #include "Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h"
#include "Metal/MTLComputeCommandEncoder.hpp"
#include "Metal/MTLRenderCommandEncoder.hpp" #include "Metal/MTLRenderCommandEncoder.hpp"
#include "Metal/MTLRenderPass.hpp" #include "Metal/MTLRenderPass.hpp"
#include "Metal/MTLRenderPipeline.hpp" #include "Metal/MTLRenderPipeline.hpp"
@ -33,6 +34,14 @@ struct MetalState
MTL::Texture* depthRenderTarget = nullptr; MTL::Texture* depthRenderTarget = nullptr;
}; };
enum class MetalEncoderType
{
None,
Render,
Compute,
Blit,
};
class MetalRenderer : public Renderer class MetalRenderer : public Renderer
{ {
public: public:
@ -197,7 +206,8 @@ private:
// Active objects // Active objects
MTL::CommandBuffer* m_commandBuffer = nullptr; MTL::CommandBuffer* m_commandBuffer = nullptr;
MTL::RenderCommandEncoder* m_renderCommandEncoder = nullptr; MetalEncoderType m_encoderType = MetalEncoderType::None;
MTL::CommandEncoder* m_commandEncoder = nullptr;
CA::MetalDrawable* m_drawable; CA::MetalDrawable* m_drawable;
// State // State
@ -215,12 +225,14 @@ private:
} }
} }
void BeginRenderPassIfNeeded(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* colorRenderTargets[8], MTL::Texture* depthRenderTarget) MTL::RenderCommandEncoder* GetRenderCommandEncoder(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* colorRenderTargets[8], MTL::Texture* depthRenderTarget)
{ {
EnsureCommandBuffer(); EnsureCommandBuffer();
// Check if we need to begin a new render pass // Check if we need to begin a new render pass
if (m_renderCommandEncoder) if (m_commandEncoder)
{
if (m_encoderType == MetalEncoderType::Render)
{ {
bool needsNewRenderPass = false; bool needsNewRenderPass = false;
for (uint8 i = 0; i < 8; i++) for (uint8 i = 0; i < 8; i++)
@ -242,22 +254,72 @@ private:
if (!needsNewRenderPass) if (!needsNewRenderPass)
{ {
return; return (MTL::RenderCommandEncoder*)m_commandEncoder;
}
} }
EndEncoding(); EndEncoding();
} }
m_renderCommandEncoder = m_commandBuffer->renderCommandEncoder(renderPassDescriptor); // Update state
for (uint8 i = 0; i < 8; i++)
{
m_state.colorRenderTargets[i] = colorRenderTargets[i];
}
m_state.depthRenderTarget = depthRenderTarget;
auto renderCommandEncoder = m_commandBuffer->renderCommandEncoder(renderPassDescriptor);
m_commandEncoder = renderCommandEncoder;
m_encoderType = MetalEncoderType::Render;
return renderCommandEncoder;
}
MTL::ComputeCommandEncoder* GetComputeCommandEncoder()
{
if (m_commandEncoder)
{
if (m_encoderType != MetalEncoderType::Compute)
{
return (MTL::ComputeCommandEncoder*)m_commandEncoder;
}
EndEncoding();
}
auto computeCommandEncoder = m_commandBuffer->computeCommandEncoder();
m_commandEncoder = computeCommandEncoder;
m_encoderType = MetalEncoderType::Compute;
return computeCommandEncoder;
}
MTL::BlitCommandEncoder* GetBlitCommandEncoder()
{
if (m_commandEncoder)
{
if (m_encoderType != MetalEncoderType::Blit)
{
return (MTL::BlitCommandEncoder*)m_commandEncoder;
}
EndEncoding();
}
auto blitCommandEncoder = m_commandBuffer->blitCommandEncoder();
m_commandEncoder = blitCommandEncoder;
m_encoderType = MetalEncoderType::Blit;
return blitCommandEncoder;
} }
void EndEncoding() void EndEncoding()
{ {
if (m_renderCommandEncoder) if (m_commandEncoder)
{ {
m_renderCommandEncoder->endEncoding(); m_commandEncoder->endEncoding();
m_renderCommandEncoder->release(); m_commandEncoder->release();
m_renderCommandEncoder = nullptr; m_commandEncoder = nullptr;
} }
} }
@ -276,5 +338,5 @@ private:
} }
} }
void BindStageResources(LatteDecompilerShader* shader); void BindStageResources(MTL::RenderCommandEncoder* renderCommandEncoder, LatteDecompilerShader* shader);
}; };