diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h index 0e2c6ac9..19ac7ab7 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h @@ -1,5 +1,6 @@ #pragma once +#include "Foundation/NSString.hpp" #include #define MAX_MTL_BUFFERS 31 @@ -27,3 +28,20 @@ inline std::string GetColorAttachmentTypeStr(uint32 index) { 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(identifier)) + ")"); +} diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalHybridComputePipeline.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalHybridComputePipeline.cpp index 3802939b..3be1cf52 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalHybridComputePipeline.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalHybridComputePipeline.cpp @@ -3,7 +3,7 @@ MetalHybridComputePipeline::MetalHybridComputePipeline(class MetalRenderer* mtlRenderer, MTL::Library* library, const char* vertexFunctionName, const char* kernelFunctionName) { // 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(); renderPipelineDescriptor->setVertexFunction(vertexFunction); diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp index b059adf4..63ded223 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp @@ -46,6 +46,9 @@ MetalBufferAllocation MetalBufferAllocator::GetBufferAllocation(size_t size, siz // 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); +#ifdef CEMU_DEBUG_ASSERT + buffer->setLabel(GetLabel("Buffer from buffer allocator", buffer)); +#endif MetalBufferAllocation allocation; allocation.bufferIndex = m_buffers.size(); @@ -184,21 +187,24 @@ void MetalMemoryManager::InitBufferCache(size_t size) } 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) { - 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) { debug_printf("MetalMemoryManager::UploadToBufferCache: buffer cache not initialized\n"); 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); // Notify vertex buffer cache about the change diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp index faf67c3c..616ceeb1 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp @@ -187,6 +187,9 @@ MTL::RenderPipelineState* MetalPipelineCache::GetPipelineState(const LatteFetchS LoadBinary(desc); 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); //static uint32 oldPipelineCount = 0; @@ -199,6 +202,9 @@ MTL::RenderPipelineState* MetalPipelineCache::GetPipelineState(const LatteFetchS error->release(); error = nullptr; +#ifdef CEMU_DEBUG_ASSERT + desc->setLabel(GetLabel("New render pipeline state", desc)); +#endif pipeline = m_mtlr->GetDevice()->newRenderPipelineState(desc, &error); if (error) { @@ -304,7 +310,7 @@ void MetalPipelineCache::TryLoadBinaryArchive() const std::string cacheFilename = fmt::format("{:016x}_mtl_pipelines.bin", s_cacheTitleId); 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(); desc->setUrl(m_binaryArchiveURL); diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index 9454d62c..bdd3c2ac 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -49,9 +49,15 @@ MetalRenderer::MetalRenderer() // Texture readback 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 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 for (uint32 i = 0; i < METAL_SHADER_TYPE_TOTAL; i++) @@ -70,7 +76,7 @@ MetalRenderer::MetalRenderer() // Create the library 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) { debug_printf("failed to create utility library (error: %s)\n", error->localizedDescription()->utf8String()); @@ -80,8 +86,8 @@ MetalRenderer::MetalRenderer() } // Present pipeline - MTL::Function* presentVertexFunction = utilityLibrary->newFunction(NS::String::string("vertexFullscreen", NS::ASCIIStringEncoding)); - MTL::Function* presentFragmentFunction = utilityLibrary->newFunction(NS::String::string("fragmentPresent", NS::ASCIIStringEncoding)); + MTL::Function* presentVertexFunction = utilityLibrary->newFunction(ToNSString("vertexFullscreen")); + MTL::Function* presentFragmentFunction = utilityLibrary->newFunction(ToNSString("fragmentPresent")); MTL::RenderPipelineDescriptor* renderPipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init(); renderPipelineDescriptor->setVertexFunction(presentVertexFunction); @@ -91,6 +97,9 @@ MetalRenderer::MetalRenderer() error = nullptr; 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); if (error) { @@ -100,6 +109,9 @@ MetalRenderer::MetalRenderer() error = nullptr; 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); renderPipelineDescriptor->release(); if (error) @@ -971,6 +983,9 @@ MTL::RenderCommandEncoder* MetalRenderer::GetTemporaryRenderCommandEncoder(MTL:: auto commandBuffer = GetCommandBuffer(); auto renderCommandEncoder = commandBuffer->renderCommandEncoder(renderPassDescriptor); +#ifdef CEMU_DEBUG_ASSERT + renderCommandEncoder->setLabel(GetLabel("Temporary render command encoder", renderCommandEncoder)); +#endif m_commandEncoder = renderCommandEncoder; m_encoderType = MetalEncoderType::Render; @@ -1024,6 +1039,9 @@ MTL::RenderCommandEncoder* MetalRenderer::GetRenderCommandEncoder(bool forceRecr m_state.m_lastUsedFBO = m_state.m_activeFBO; 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_encoderType = MetalEncoderType::Render; diff --git a/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp index 47c796bf..465e9316 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp @@ -78,13 +78,13 @@ void RendererShaderMtl::CompileFragmentFunction(CachedFBOMtl* activeFBO) void RendererShaderMtl::Compile(const std::string& mslCode) { 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) { printf("failed to create library (error: %s) -> source:\n%s\n", error->localizedDescription()->utf8String(), mslCode.c_str()); error->release(); return; } - m_function = library->newFunction(NS::String::string("main0", NS::ASCIIStringEncoding)); + m_function = library->newFunction(ToNSString("main0")); library->release(); }