check for framebuffer fetch support

This commit is contained in:
Samuliak 2025-01-09 16:27:45 +01:00
parent 3fae686f21
commit a0239cb756
No known key found for this signature in database
4 changed files with 49 additions and 38 deletions

View file

@ -10,7 +10,7 @@
#include "Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerInstructions.h" #include "Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerInstructions.h"
#include "Cafe/HW/Latte/Core/FetchShader.h" #include "Cafe/HW/Latte/Core/FetchShader.h"
#include "Cafe/HW/Latte/Renderer/Renderer.h" #include "Cafe/HW/Latte/Renderer/Renderer.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h" #include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h" #include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
#include "config/ActiveSettings.h" #include "config/ActiveSettings.h"
#include "util/helpers/StringBuf.h" #include "util/helpers/StringBuf.h"
@ -2261,19 +2261,22 @@ static void _emitTEXSampleTextureCode(LatteDecompilerShaderContext* shaderContex
} }
// Do a framebuffer fetch if possible // Do a framebuffer fetch if possible
// TODO: filter out more? if (static_cast<MetalRenderer*>(g_renderer.get())->SupportsFramebufferFetch())
uint8 renderTargetIndex = shaderContext->shader->textureRenderTargetIndex[texInstruction->textureFetch.textureIndex];
if (renderTargetIndex != 255)
{ {
src->addFmt("col{}.", renderTargetIndex); // TODO: filter out more?
// TODO: clean up uint8 renderTargetIndex = shaderContext->shader->textureRenderTargetIndex[texInstruction->textureFetch.textureIndex];
std::string components[] = {"x", "y", "z", "w"}; if (renderTargetIndex != 255)
for (sint32 i = 0; i < numWrittenElements; i++) {
{ src->addFmt("col{}.", renderTargetIndex);
src->addFmt("{}", components[i]); // TODO: clean up
} std::string components[] = {"x", "y", "z", "w"};
src->add(");" _CRLF); for (sint32 i = 0; i < numWrittenElements; i++)
return; {
src->addFmt("{}", components[i]);
}
src->add(");" _CRLF);
return;
}
} }
if (emulateCompare) if (emulateCompare)
@ -2646,7 +2649,7 @@ static void _emitTEXGetTextureResInfoCode(LatteDecompilerShaderContext* shaderCo
// todo - mip index parameter? // todo - mip index parameter?
if (shaderContext->shader->textureRenderTargetIndex[texInstruction->textureFetch.textureIndex] != 255) if (static_cast<MetalRenderer*>(g_renderer.get())->SupportsFramebufferFetch() && shaderContext->shader->textureRenderTargetIndex[texInstruction->textureFetch.textureIndex] != 255)
{ {
// TODO: use the render target size // TODO: use the render target size
src->addFmt(" = int4(1920, 1080, 1, 1)."); src->addFmt(" = int4(1920, 1080, 1, 1).");

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "Common/precompiled.h" #include "Common/precompiled.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h" #include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
#include "HW/Latte/Core/LatteShader.h" #include "HW/Latte/Core/LatteShader.h"
namespace LatteDecompiler namespace LatteDecompiler
@ -458,11 +458,19 @@ namespace LatteDecompiler
continue; continue;
uint8 renderTargetIndex = shaderContext->shader->textureRenderTargetIndex[i]; uint8 renderTargetIndex = shaderContext->shader->textureRenderTargetIndex[i];
if (renderTargetIndex == 255) if (static_cast<MetalRenderer*>(g_renderer.get())->SupportsFramebufferFetch() && renderTargetIndex != 255)
{ {
src->add(", "); if (!renderTargetIndexUsed[renderTargetIndex])
{
src->addFmt(", {} col{} [[color({})]]", GetDataTypeStr(GetColorBufferDataType(renderTargetIndex, *shaderContext->contextRegistersNew)), renderTargetIndex, renderTargetIndex);
renderTargetIndexUsed[renderTargetIndex] = true;
}
}
else
{
src->add(", ");
// Only 2D and 2D array textures can be used with comparison samplers // Only certain texture dimensions can be used with comparison samplers
if (shaderContext->shader->textureUsesDepthCompare[i] && IsValidDepthTextureType(shaderContext->shader->textureUnitDim[i])) if (shaderContext->shader->textureUsesDepthCompare[i] && IsValidDepthTextureType(shaderContext->shader->textureUnitDim[i]))
src->add("depth"); src->add("depth");
else else
@ -499,14 +507,6 @@ namespace LatteDecompiler
src->addFmt(" tex{} [[texture({})]]", i, binding); src->addFmt(" tex{} [[texture({})]]", i, binding);
src->addFmt(", sampler samplr{} [[sampler({})]]", i, binding); src->addFmt(", sampler samplr{} [[sampler({})]]", i, binding);
} }
else
{
if (!renderTargetIndexUsed[renderTargetIndex])
{
src->addFmt(", {} col{} [[color({})]]", GetDataTypeStr(GetColorBufferDataType(renderTargetIndex, *shaderContext->contextRegistersNew)), renderTargetIndex, renderTargetIndex);
renderTargetIndexUsed[renderTargetIndex] = true;
}
}
} }
} }

View file

@ -87,6 +87,7 @@ MetalRenderer::MetalRenderer()
// Feature support // Feature support
m_isAppleGPU = m_device->supportsFamily(MTL::GPUFamilyApple1); m_isAppleGPU = m_device->supportsFamily(MTL::GPUFamilyApple1);
m_supportsFramebufferFetch = m_device->supportsFamily(MTL::GPUFamilyApple2);
m_hasUnifiedMemory = m_device->hasUnifiedMemory(); m_hasUnifiedMemory = m_device->hasUnifiedMemory();
m_supportsMetal3 = m_device->supportsFamily(MTL::GPUFamilyMetal3); m_supportsMetal3 = m_device->supportsFamily(MTL::GPUFamilyMetal3);
m_recommendedMaxVRAMUsage = m_device->recommendedMaxWorkingSetSize(); m_recommendedMaxVRAMUsage = m_device->recommendedMaxWorkingSetSize();
@ -584,21 +585,22 @@ void MetalRenderer::DeleteFontTextures()
void MetalRenderer::AppendOverlayDebugInfo() void MetalRenderer::AppendOverlayDebugInfo()
{ {
ImGui::Text("--- GPU info ---"); ImGui::Text("--- GPU info ---");
ImGui::Text("GPU %s", m_device->name()->utf8String()); ImGui::Text("GPU %s", m_device->name()->utf8String());
ImGui::Text("Is Apple GPU %s", (m_isAppleGPU ? "yes" : "no")); ImGui::Text("Is Apple GPU %s", (m_isAppleGPU ? "yes" : "no"));
ImGui::Text("Has unified memory %s", (m_hasUnifiedMemory ? "yes" : "no")); ImGui::Text("Supports framebuffer fetch %s", (m_supportsFramebufferFetch ? "yes" : "no"));
ImGui::Text("Supports Metal3 %s", (m_supportsMetal3 ? "yes" : "no")); ImGui::Text("Has unified memory %s", (m_hasUnifiedMemory ? "yes" : "no"));
ImGui::Text("Supports Metal3 %s", (m_supportsMetal3 ? "yes" : "no"));
ImGui::Text("--- Metal info ---"); ImGui::Text("--- Metal info ---");
ImGui::Text("Render pipeline states %zu", m_pipelineCache->GetPipelineCacheSize()); ImGui::Text("Render pipeline states %zu", m_pipelineCache->GetPipelineCacheSize());
ImGui::Text("Buffer allocator memory %zuMB", m_performanceMonitor.m_bufferAllocatorMemory / 1024 / 1024); ImGui::Text("Buffer allocator memory %zuMB", m_performanceMonitor.m_bufferAllocatorMemory / 1024 / 1024);
ImGui::Text("--- Metal info (per frame) ---"); ImGui::Text("--- Metal info (per frame) ---");
ImGui::Text("Command buffers %u", m_performanceMonitor.m_commandBuffers); ImGui::Text("Command buffers %u", m_performanceMonitor.m_commandBuffers);
ImGui::Text("Render passes %u", m_performanceMonitor.m_renderPasses); ImGui::Text("Render passes %u", m_performanceMonitor.m_renderPasses);
ImGui::Text("Clears %u", m_performanceMonitor.m_clears); ImGui::Text("Clears %u", m_performanceMonitor.m_clears);
ImGui::Text("Manual vertex fetch draws %u (mesh draws: %u)", m_performanceMonitor.m_manualVertexFetchDraws, m_performanceMonitor.m_meshDraws); ImGui::Text("Manual vertex fetch draws %u (mesh draws: %u)", m_performanceMonitor.m_manualVertexFetchDraws, m_performanceMonitor.m_meshDraws);
ImGui::Text("Triangle fans %u", m_performanceMonitor.m_triangleFans); ImGui::Text("Triangle fans %u", m_performanceMonitor.m_triangleFans);
} }
void MetalRenderer::renderTarget_setViewport(float x, float y, float width, float height, float nearZ, float farZ, bool halfZ) void MetalRenderer::renderTarget_setViewport(float x, float y, float width, float height, float nearZ, float farZ, bool halfZ)
@ -1932,7 +1934,7 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
auto hostTextureUnit = relative_textureUnit; auto hostTextureUnit = relative_textureUnit;
// Don't bind textures that are accessed with a framebuffer fetch // Don't bind textures that are accessed with a framebuffer fetch
if (shader->textureRenderTargetIndex[relative_textureUnit] != 255) if (m_supportsFramebufferFetch && shader->textureRenderTargetIndex[relative_textureUnit] != 255)
continue; continue;
auto textureDim = shader->textureUnitDim[relative_textureUnit]; auto textureDim = shader->textureUnitDim[relative_textureUnit];

View file

@ -375,6 +375,11 @@ public:
return m_isAppleGPU; return m_isAppleGPU;
} }
bool SupportsFramebufferFetch() const
{
return m_supportsFramebufferFetch;
}
bool HasUnifiedMemory() const bool HasUnifiedMemory() const
{ {
return m_hasUnifiedMemory; return m_hasUnifiedMemory;
@ -477,6 +482,7 @@ private:
// Feature support // Feature support
bool m_isAppleGPU; bool m_isAppleGPU;
bool m_supportsFramebufferFetch;
bool m_hasUnifiedMemory; bool m_hasUnifiedMemory;
bool m_supportsMetal3; bool m_supportsMetal3;
uint32 m_recommendedMaxVRAMUsage; uint32 m_recommendedMaxVRAMUsage;