mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-12-02 05:54:18 +01:00
rework command encoder system
This commit is contained in:
parent
89a2c23dd7
commit
f01130022a
@ -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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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?
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user