include debug information

This commit is contained in:
Samuliak 2024-08-16 16:38:01 +02:00
parent 0d0152d6e0
commit 502d5b8b2f
6 changed files with 60 additions and 12 deletions

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "Foundation/NSString.hpp"
#include <Metal/Metal.hpp> #include <Metal/Metal.hpp>
#define MAX_MTL_BUFFERS 31 #define MAX_MTL_BUFFERS 31
@ -27,3 +28,20 @@ inline std::string GetColorAttachmentTypeStr(uint32 index)
{ {
return "COLOR_ATTACHMENT" + std::to_string(index) + "_TYPE"; return "COLOR_ATTACHMENT" + std::to_string(index) + "_TYPE";
} }
// Cast from const char* to NS::String*
inline NS::String* ToNSString(const char* str)
{
return NS::String::string(str, NS::ASCIIStringEncoding);
}
// Cast from std::string to NS::String*
inline NS::String* ToNSString(const std::string& str)
{
return ToNSString(str.c_str());
}
inline NS::String* GetLabel(const std::string& label, const void* identifier)
{
return ToNSString(label + " (" + std::to_string(reinterpret_cast<uintptr_t>(identifier)) + ")");
}

View File

@ -3,7 +3,7 @@
MetalHybridComputePipeline::MetalHybridComputePipeline(class MetalRenderer* mtlRenderer, MTL::Library* library, const char* vertexFunctionName, const char* kernelFunctionName) MetalHybridComputePipeline::MetalHybridComputePipeline(class MetalRenderer* mtlRenderer, MTL::Library* library, const char* vertexFunctionName, const char* kernelFunctionName)
{ {
// Render pipeline state // Render pipeline state
MTL::Function* vertexFunction = library->newFunction(NS::String::string(vertexFunctionName, NS::ASCIIStringEncoding)); MTL::Function* vertexFunction = library->newFunction(ToNSString(vertexFunctionName));
MTL::RenderPipelineDescriptor* renderPipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init(); MTL::RenderPipelineDescriptor* renderPipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init();
renderPipelineDescriptor->setVertexFunction(vertexFunction); renderPipelineDescriptor->setVertexFunction(vertexFunction);

View File

@ -46,6 +46,9 @@ MetalBufferAllocation MetalBufferAllocator::GetBufferAllocation(size_t size, siz
// If no free range was found, allocate a new buffer // If no free range was found, allocate a new buffer
MTL::Buffer* buffer = m_mtlr->GetDevice()->newBuffer(std::max(size, BUFFER_ALLOCATION_SIZE), MTL::ResourceStorageModeShared); MTL::Buffer* buffer = m_mtlr->GetDevice()->newBuffer(std::max(size, BUFFER_ALLOCATION_SIZE), MTL::ResourceStorageModeShared);
#ifdef CEMU_DEBUG_ASSERT
buffer->setLabel(GetLabel("Buffer from buffer allocator", buffer));
#endif
MetalBufferAllocation allocation; MetalBufferAllocation allocation;
allocation.bufferIndex = m_buffers.size(); allocation.bufferIndex = m_buffers.size();
@ -184,21 +187,24 @@ void MetalMemoryManager::InitBufferCache(size_t size)
} }
m_bufferCache = m_mtlr->GetDevice()->newBuffer(size, MTL::ResourceStorageModeShared); m_bufferCache = m_mtlr->GetDevice()->newBuffer(size, MTL::ResourceStorageModeShared);
#ifdef CEMU_DEBUG_ASSERT
m_bufferCache->setLabel(GetLabel("Buffer cache", m_bufferCache));
#endif
} }
void MetalMemoryManager::UploadToBufferCache(const void* data, size_t offset, size_t size) void MetalMemoryManager::UploadToBufferCache(const void* data, size_t offset, size_t size)
{ {
if ((offset + size) > m_bufferCache->length())
{
throw std::runtime_error(std::to_string(offset) + " + " + std::to_string(size) + " > " + std::to_string(m_bufferCache->length()));
}
if (!m_bufferCache) if (!m_bufferCache)
{ {
debug_printf("MetalMemoryManager::UploadToBufferCache: buffer cache not initialized\n"); debug_printf("MetalMemoryManager::UploadToBufferCache: buffer cache not initialized\n");
return; return;
} }
if ((offset + size) > m_bufferCache->length())
{
debug_printf("MetalMemoryManager::UploadToBufferCache: out of bounds access (offset: %zu, size: %zu, buffer size: %zu)\n", offset, size, m_bufferCache->length());
}
memcpy((uint8*)m_bufferCache->contents() + offset, data, size); memcpy((uint8*)m_bufferCache->contents() + offset, data, size);
// Notify vertex buffer cache about the change // Notify vertex buffer cache about the change

View File

@ -187,6 +187,9 @@ MTL::RenderPipelineState* MetalPipelineCache::GetPipelineState(const LatteFetchS
LoadBinary(desc); LoadBinary(desc);
NS::Error* error = nullptr; NS::Error* error = nullptr;
#ifdef CEMU_DEBUG_ASSERT
desc->setLabel(GetLabel("Cached render pipeline state", desc));
#endif
pipeline = m_mtlr->GetDevice()->newRenderPipelineState(desc, MTL::PipelineOptionFailOnBinaryArchiveMiss, nullptr, &error); pipeline = m_mtlr->GetDevice()->newRenderPipelineState(desc, MTL::PipelineOptionFailOnBinaryArchiveMiss, nullptr, &error);
//static uint32 oldPipelineCount = 0; //static uint32 oldPipelineCount = 0;
@ -199,6 +202,9 @@ MTL::RenderPipelineState* MetalPipelineCache::GetPipelineState(const LatteFetchS
error->release(); error->release();
error = nullptr; error = nullptr;
#ifdef CEMU_DEBUG_ASSERT
desc->setLabel(GetLabel("New render pipeline state", desc));
#endif
pipeline = m_mtlr->GetDevice()->newRenderPipelineState(desc, &error); pipeline = m_mtlr->GetDevice()->newRenderPipelineState(desc, &error);
if (error) if (error)
{ {
@ -304,7 +310,7 @@ void MetalPipelineCache::TryLoadBinaryArchive()
const std::string cacheFilename = fmt::format("{:016x}_mtl_pipelines.bin", s_cacheTitleId); const std::string cacheFilename = fmt::format("{:016x}_mtl_pipelines.bin", s_cacheTitleId);
const fs::path cachePath = ActiveSettings::GetCachePath("shaderCache/precompiled/{}", cacheFilename); const fs::path cachePath = ActiveSettings::GetCachePath("shaderCache/precompiled/{}", cacheFilename);
m_binaryArchiveURL = NS::URL::fileURLWithPath(NS::String::string((const char*)cachePath.generic_u8string().c_str(), NS::ASCIIStringEncoding)); m_binaryArchiveURL = NS::URL::fileURLWithPath(ToNSString((const char*)cachePath.generic_u8string().c_str()));
MTL::BinaryArchiveDescriptor* desc = MTL::BinaryArchiveDescriptor::alloc()->init(); MTL::BinaryArchiveDescriptor* desc = MTL::BinaryArchiveDescriptor::alloc()->init();
desc->setUrl(m_binaryArchiveURL); desc->setUrl(m_binaryArchiveURL);

View File

@ -49,9 +49,15 @@ MetalRenderer::MetalRenderer()
// Texture readback // Texture readback
m_readbackBuffer = m_device->newBuffer(TEXTURE_READBACK_SIZE, MTL::StorageModeShared); m_readbackBuffer = m_device->newBuffer(TEXTURE_READBACK_SIZE, MTL::StorageModeShared);
#ifdef CEMU_DEBUG_ASSERT
m_readbackBuffer->setLabel(GetLabel("Texture readback buffer", m_readbackBuffer));
#endif
// Transform feedback // Transform feedback
m_xfbRingBuffer = m_device->newBuffer(LatteStreamout_GetRingBufferSize(), MTL::StorageModeShared); m_xfbRingBuffer = m_device->newBuffer(LatteStreamout_GetRingBufferSize(), MTL::StorageModeShared);
#ifdef CEMU_DEBUG_ASSERT
m_xfbRingBuffer->setLabel(GetLabel("Transform feedback buffer", m_xfbRingBuffer));
#endif
// Initialize state // Initialize state
for (uint32 i = 0; i < METAL_SHADER_TYPE_TOTAL; i++) for (uint32 i = 0; i < METAL_SHADER_TYPE_TOTAL; i++)
@ -70,7 +76,7 @@ MetalRenderer::MetalRenderer()
// Create the library // Create the library
NS::Error* error = nullptr; NS::Error* error = nullptr;
MTL::Library* utilityLibrary = m_device->newLibrary(NS::String::string(processedUtilityShaderSource.c_str(), NS::ASCIIStringEncoding), nullptr, &error); MTL::Library* utilityLibrary = m_device->newLibrary(ToNSString(processedUtilityShaderSource.c_str()), nullptr, &error);
if (error) if (error)
{ {
debug_printf("failed to create utility library (error: %s)\n", error->localizedDescription()->utf8String()); debug_printf("failed to create utility library (error: %s)\n", error->localizedDescription()->utf8String());
@ -80,8 +86,8 @@ MetalRenderer::MetalRenderer()
} }
// Present pipeline // Present pipeline
MTL::Function* presentVertexFunction = utilityLibrary->newFunction(NS::String::string("vertexFullscreen", NS::ASCIIStringEncoding)); MTL::Function* presentVertexFunction = utilityLibrary->newFunction(ToNSString("vertexFullscreen"));
MTL::Function* presentFragmentFunction = utilityLibrary->newFunction(NS::String::string("fragmentPresent", NS::ASCIIStringEncoding)); MTL::Function* presentFragmentFunction = utilityLibrary->newFunction(ToNSString("fragmentPresent"));
MTL::RenderPipelineDescriptor* renderPipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init(); MTL::RenderPipelineDescriptor* renderPipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init();
renderPipelineDescriptor->setVertexFunction(presentVertexFunction); renderPipelineDescriptor->setVertexFunction(presentVertexFunction);
@ -91,6 +97,9 @@ MetalRenderer::MetalRenderer()
error = nullptr; error = nullptr;
renderPipelineDescriptor->colorAttachments()->object(0)->setPixelFormat(MTL::PixelFormatRGBA8Unorm); renderPipelineDescriptor->colorAttachments()->object(0)->setPixelFormat(MTL::PixelFormatRGBA8Unorm);
#ifdef CEMU_DEBUG_ASSERT
renderPipelineDescriptor->setLabel(GetLabel("Present pipeline linear", renderPipelineDescriptor));
#endif
m_presentPipelineLinear = m_device->newRenderPipelineState(renderPipelineDescriptor, &error); m_presentPipelineLinear = m_device->newRenderPipelineState(renderPipelineDescriptor, &error);
if (error) if (error)
{ {
@ -100,6 +109,9 @@ MetalRenderer::MetalRenderer()
error = nullptr; error = nullptr;
renderPipelineDescriptor->colorAttachments()->object(0)->setPixelFormat(MTL::PixelFormatRGBA8Unorm_sRGB); renderPipelineDescriptor->colorAttachments()->object(0)->setPixelFormat(MTL::PixelFormatRGBA8Unorm_sRGB);
#ifdef CEMU_DEBUG_ASSERT
renderPipelineDescriptor->setLabel(GetLabel("Present pipeline sRGB", renderPipelineDescriptor));
#endif
m_presentPipelineSRGB = m_device->newRenderPipelineState(renderPipelineDescriptor, &error); m_presentPipelineSRGB = m_device->newRenderPipelineState(renderPipelineDescriptor, &error);
renderPipelineDescriptor->release(); renderPipelineDescriptor->release();
if (error) if (error)
@ -971,6 +983,9 @@ MTL::RenderCommandEncoder* MetalRenderer::GetTemporaryRenderCommandEncoder(MTL::
auto commandBuffer = GetCommandBuffer(); auto commandBuffer = GetCommandBuffer();
auto renderCommandEncoder = commandBuffer->renderCommandEncoder(renderPassDescriptor); auto renderCommandEncoder = commandBuffer->renderCommandEncoder(renderPassDescriptor);
#ifdef CEMU_DEBUG_ASSERT
renderCommandEncoder->setLabel(GetLabel("Temporary render command encoder", renderCommandEncoder));
#endif
m_commandEncoder = renderCommandEncoder; m_commandEncoder = renderCommandEncoder;
m_encoderType = MetalEncoderType::Render; m_encoderType = MetalEncoderType::Render;
@ -1024,6 +1039,9 @@ MTL::RenderCommandEncoder* MetalRenderer::GetRenderCommandEncoder(bool forceRecr
m_state.m_lastUsedFBO = m_state.m_activeFBO; m_state.m_lastUsedFBO = m_state.m_activeFBO;
auto renderCommandEncoder = commandBuffer->renderCommandEncoder(m_state.m_activeFBO->GetRenderPassDescriptor()); auto renderCommandEncoder = commandBuffer->renderCommandEncoder(m_state.m_activeFBO->GetRenderPassDescriptor());
#ifdef CEMU_DEBUG_ASSERT
renderCommandEncoder->setLabel(GetLabel("Render command encoder", renderCommandEncoder));
#endif
m_commandEncoder = renderCommandEncoder; m_commandEncoder = renderCommandEncoder;
m_encoderType = MetalEncoderType::Render; m_encoderType = MetalEncoderType::Render;

View File

@ -78,13 +78,13 @@ void RendererShaderMtl::CompileFragmentFunction(CachedFBOMtl* activeFBO)
void RendererShaderMtl::Compile(const std::string& mslCode) void RendererShaderMtl::Compile(const std::string& mslCode)
{ {
NS::Error* error = nullptr; NS::Error* error = nullptr;
MTL::Library* library = m_mtlr->GetDevice()->newLibrary(NS::String::string(mslCode.c_str(), NS::ASCIIStringEncoding), nullptr, &error); MTL::Library* library = m_mtlr->GetDevice()->newLibrary(ToNSString(mslCode), nullptr, &error);
if (error) if (error)
{ {
printf("failed to create library (error: %s) -> source:\n%s\n", error->localizedDescription()->utf8String(), mslCode.c_str()); printf("failed to create library (error: %s) -> source:\n%s\n", error->localizedDescription()->utf8String(), mslCode.c_str());
error->release(); error->release();
return; return;
} }
m_function = library->newFunction(NS::String::string("main0", NS::ASCIIStringEncoding)); m_function = library->newFunction(ToNSString("main0"));
library->release(); library->release();
} }