mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-29 20:44: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("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->add("};" _CRLF _CRLF);
|
||||
}
|
||||
@ -307,7 +307,7 @@ namespace LatteDecompiler
|
||||
cemu_assert_debug(decompilerContext->output->resourceMappingGL.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,
|
||||
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();
|
||||
desc->setStorageMode(MTL::StorageModeShared); // TODO: use private?
|
||||
@ -34,7 +34,7 @@ LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, Latte::E_DIM
|
||||
desc->setArrayLength(effectiveBaseDepth);
|
||||
}
|
||||
|
||||
auto formatInfo = GetMtlPixelFormatInfo(format);
|
||||
auto formatInfo = GetMtlPixelFormatInfo(format, isDepth);
|
||||
desc->setPixelFormat(formatInfo.pixelFormat);
|
||||
|
||||
// TODO: is write needed?
|
||||
|
@ -21,23 +21,20 @@ public:
|
||||
return m_format;
|
||||
}
|
||||
|
||||
bool IsDepth() const {
|
||||
return m_isDepth;
|
||||
}
|
||||
|
||||
void AllocateOnHost() override;
|
||||
|
||||
protected:
|
||||
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:
|
||||
class MetalRenderer* m_mtlr;
|
||||
|
||||
MTL::Texture* m_texture;
|
||||
|
||||
Latte::E_GX2SURFFMT m_format;
|
||||
bool m_isDepth;
|
||||
};
|
||||
|
@ -52,7 +52,7 @@ LatteTextureViewMtl::LatteTextureViewMtl(MetalRenderer* mtlRenderer, LatteTextur
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,7 @@
|
||||
#include "Metal/MTLPixelFormat.hpp"
|
||||
#include "Metal/MTLVertexDescriptor.hpp"
|
||||
|
||||
// TODO: separate color and depth formats
|
||||
std::map<Latte::E_GX2SURFFMT, MtlPixelFormatInfo> MTL_FORMAT_TABLE = {
|
||||
std::map<Latte::E_GX2SURFFMT, MtlPixelFormatInfo> MTL_COLOR_FORMAT_TABLE = {
|
||||
{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_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_SINT, {MTL::PixelFormatRGBA32Sint, 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_SRGB, {MTL::PixelFormatBC1_RGBA_sRGB, 8, {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?
|
||||
};
|
||||
|
||||
const MtlPixelFormatInfo GetMtlPixelFormatInfo(Latte::E_GX2SURFFMT format)
|
||||
{
|
||||
cemu_assert_debug(static_cast<size_t>(format) < MTL_FORMAT_TABLE.size());
|
||||
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
|
||||
{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)
|
||||
{
|
||||
printf("invalid pixel format: %u\n", (uint32)format);
|
||||
@ -94,16 +106,16 @@ inline uint32 CeilDivide(uint32 a, uint32 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -18,11 +18,11 @@ struct MtlPixelFormatInfo {
|
||||
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);
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "Cafe/HW/Latte/Core/LatteShader.h"
|
||||
#include "Cafe/HW/Latte/Core/LatteIndices.h"
|
||||
#include "Foundation/NSTypes.hpp"
|
||||
#include "Metal/MTLRenderCommandEncoder.hpp"
|
||||
#include "gui/guiWrapper.h"
|
||||
|
||||
extern bool hasValidFramebufferAttached;
|
||||
@ -147,14 +148,14 @@ void MetalRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutput
|
||||
|
||||
MTL::Texture* colorRenderTargets[8] = {nullptr};
|
||||
colorRenderTargets[0] = m_drawable->texture();
|
||||
BeginRenderPassIfNeeded(renderPassDescriptor, colorRenderTargets, nullptr);
|
||||
auto renderCommandEncoder = GetRenderCommandEncoder(renderPassDescriptor, colorRenderTargets, nullptr);
|
||||
|
||||
// Draw to Metal layer
|
||||
m_renderCommandEncoder->setRenderPipelineState(m_presentPipeline);
|
||||
m_renderCommandEncoder->setFragmentTexture(presentTexture, 0);
|
||||
m_renderCommandEncoder->setFragmentSamplerState(m_nearestSampler, 0);
|
||||
renderCommandEncoder->setRenderPipelineState(m_presentPipeline);
|
||||
renderCommandEncoder->setFragmentTexture(presentTexture, 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)
|
||||
@ -351,8 +352,8 @@ void MetalRenderer::texture_loadSlice(LatteTexture* hostTexture, sint32 width, s
|
||||
{
|
||||
auto mtlTexture = (LatteTextureMtl*)hostTexture;
|
||||
|
||||
size_t bytesPerRow = GetMtlTextureBytesPerRow(mtlTexture->GetFormat(), width);
|
||||
size_t bytesPerImage = GetMtlTextureBytesPerImage(mtlTexture->GetFormat(), height, bytesPerRow);
|
||||
size_t bytesPerRow = GetMtlTextureBytesPerRow(mtlTexture->GetFormat(), mtlTexture->IsDepth(), width);
|
||||
size_t bytesPerImage = GetMtlTextureBytesPerImage(mtlTexture->GetFormat(), mtlTexture->IsDepth(), height, bytesPerRow);
|
||||
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();
|
||||
}
|
||||
BeginRenderPassIfNeeded(renderPassDescriptor, colorRenderTargets, depthRenderTarget);
|
||||
auto renderCommandEncoder = GetRenderCommandEncoder(renderPassDescriptor, colorRenderTargets, depthRenderTarget);
|
||||
|
||||
// Shaders
|
||||
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());
|
||||
return;
|
||||
}
|
||||
m_renderCommandEncoder->setRenderPipelineState(renderPipelineState);
|
||||
renderCommandEncoder->setRenderPipelineState(renderPipelineState);
|
||||
|
||||
// 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];
|
||||
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
|
||||
//vertexBufferRange.needsRebind = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Uniform buffers, textures and samplers
|
||||
BindStageResources(vertexShader);
|
||||
BindStageResources(pixelShader);
|
||||
BindStageResources(renderCommandEncoder, vertexShader);
|
||||
BindStageResources(renderCommandEncoder, pixelShader);
|
||||
|
||||
// Draw
|
||||
if (hostIndexType != INDEX_TYPE::NONE)
|
||||
{
|
||||
auto mtlIndexType = GetMtlIndexType(hostIndexType);
|
||||
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
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
void MetalRenderer::BindStageResources(LatteDecompilerShader* shader)
|
||||
void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandEncoder, LatteDecompilerShader* shader)
|
||||
{
|
||||
sint32 textureCount = shader->resourceMapping.getTextureCount();
|
||||
|
||||
@ -722,12 +723,12 @@ void MetalRenderer::BindStageResources(LatteDecompilerShader* shader)
|
||||
{
|
||||
case LatteConst::ShaderType::Vertex:
|
||||
{
|
||||
m_renderCommandEncoder->setVertexSamplerState(sampler, binding);
|
||||
renderCommandEncoder->setVertexSamplerState(sampler, binding);
|
||||
break;
|
||||
}
|
||||
case LatteConst::ShaderType::Pixel:
|
||||
{
|
||||
m_renderCommandEncoder->setFragmentSamplerState(sampler, binding);
|
||||
renderCommandEncoder->setFragmentSamplerState(sampler, binding);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -739,12 +740,12 @@ void MetalRenderer::BindStageResources(LatteDecompilerShader* shader)
|
||||
{
|
||||
case LatteConst::ShaderType::Vertex:
|
||||
{
|
||||
m_renderCommandEncoder->setVertexTexture(textureView->GetTexture(), binding);
|
||||
renderCommandEncoder->setVertexTexture(textureView->GetTexture(), binding);
|
||||
break;
|
||||
}
|
||||
case LatteConst::ShaderType::Pixel:
|
||||
{
|
||||
m_renderCommandEncoder->setFragmentTexture(textureView->GetTexture(), binding);
|
||||
renderCommandEncoder->setFragmentTexture(textureView->GetTexture(), binding);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -840,12 +841,12 @@ void MetalRenderer::BindStageResources(LatteDecompilerShader* shader)
|
||||
{
|
||||
case LatteConst::ShaderType::Vertex:
|
||||
{
|
||||
m_renderCommandEncoder->setVertexBytes(supportBufferData, sizeof(supportBufferData), MTL_SUPPORT_BUFFER_BINDING);
|
||||
renderCommandEncoder->setVertexBytes(supportBufferData, sizeof(supportBufferData), MTL_SUPPORT_BUFFER_BINDING);
|
||||
break;
|
||||
}
|
||||
case LatteConst::ShaderType::Pixel:
|
||||
{
|
||||
m_renderCommandEncoder->setFragmentBytes(supportBufferData, sizeof(supportBufferData), MTL_SUPPORT_BUFFER_BINDING);
|
||||
renderCommandEncoder->setFragmentBytes(supportBufferData, sizeof(supportBufferData), MTL_SUPPORT_BUFFER_BINDING);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -865,12 +866,12 @@ void MetalRenderer::BindStageResources(LatteDecompilerShader* shader)
|
||||
{
|
||||
case LatteConst::ShaderType::Vertex:
|
||||
{
|
||||
m_renderCommandEncoder->setVertexBuffer(m_memoryManager->GetBufferCache(), offset, binding);
|
||||
renderCommandEncoder->setVertexBuffer(m_memoryManager->GetBufferCache(), offset, binding);
|
||||
break;
|
||||
}
|
||||
case LatteConst::ShaderType::Pixel:
|
||||
{
|
||||
m_renderCommandEncoder->setFragmentBuffer(m_memoryManager->GetBufferCache(), offset, binding);
|
||||
renderCommandEncoder->setFragmentBuffer(m_memoryManager->GetBufferCache(), offset, binding);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h"
|
||||
#include "Metal/MTLComputeCommandEncoder.hpp"
|
||||
#include "Metal/MTLRenderCommandEncoder.hpp"
|
||||
#include "Metal/MTLRenderPass.hpp"
|
||||
#include "Metal/MTLRenderPipeline.hpp"
|
||||
@ -33,6 +34,14 @@ struct MetalState
|
||||
MTL::Texture* depthRenderTarget = nullptr;
|
||||
};
|
||||
|
||||
enum class MetalEncoderType
|
||||
{
|
||||
None,
|
||||
Render,
|
||||
Compute,
|
||||
Blit,
|
||||
};
|
||||
|
||||
class MetalRenderer : public Renderer
|
||||
{
|
||||
public:
|
||||
@ -197,7 +206,8 @@ private:
|
||||
|
||||
// Active objects
|
||||
MTL::CommandBuffer* m_commandBuffer = nullptr;
|
||||
MTL::RenderCommandEncoder* m_renderCommandEncoder = nullptr;
|
||||
MetalEncoderType m_encoderType = MetalEncoderType::None;
|
||||
MTL::CommandEncoder* m_commandEncoder = nullptr;
|
||||
CA::MetalDrawable* m_drawable;
|
||||
|
||||
// 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();
|
||||
|
||||
// Check if we need to begin a new render pass
|
||||
if (m_renderCommandEncoder)
|
||||
if (m_commandEncoder)
|
||||
{
|
||||
if (m_encoderType == MetalEncoderType::Render)
|
||||
{
|
||||
bool needsNewRenderPass = false;
|
||||
for (uint8 i = 0; i < 8; i++)
|
||||
@ -242,22 +254,72 @@ private:
|
||||
|
||||
if (!needsNewRenderPass)
|
||||
{
|
||||
return;
|
||||
return (MTL::RenderCommandEncoder*)m_commandEncoder;
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
if (m_renderCommandEncoder)
|
||||
if (m_commandEncoder)
|
||||
{
|
||||
m_renderCommandEncoder->endEncoding();
|
||||
m_renderCommandEncoder->release();
|
||||
m_renderCommandEncoder = nullptr;
|
||||
m_commandEncoder->endEncoding();
|
||||
m_commandEncoder->release();
|
||||
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