diff --git a/include/renderer_mtl/mtl_blit_pipeline_cache.hpp b/include/renderer_mtl/mtl_blit_pipeline_cache.hpp index 399d3005..93d847a6 100644 --- a/include/renderer_mtl/mtl_blit_pipeline_cache.hpp +++ b/include/renderer_mtl/mtl_blit_pipeline_cache.hpp @@ -43,6 +43,7 @@ public: desc->setDepthAttachmentPixelFormat(toMTLPixelFormatDepth(hash.depthFmt)); NS::Error* error = nullptr; + desc->setLabel(toNSString("Blit pipeline")); pipeline = device->newRenderPipelineState(desc, &error); if (error) { Helpers::panic("Error creating blit pipeline state: %s", error->description()->cString(NS::ASCIIStringEncoding)); diff --git a/include/renderer_mtl/mtl_draw_pipeline_cache.hpp b/include/renderer_mtl/mtl_draw_pipeline_cache.hpp index fec36b8f..6c6e5a83 100644 --- a/include/renderer_mtl/mtl_draw_pipeline_cache.hpp +++ b/include/renderer_mtl/mtl_draw_pipeline_cache.hpp @@ -95,6 +95,7 @@ public: desc->setDepthAttachmentPixelFormat(toMTLPixelFormatDepth(hash.depthFmt)); NS::Error* error = nullptr; + desc->setLabel(toNSString("Draw pipeline")); pipeline = device->newRenderPipelineState(desc, &error); if (error) { Helpers::panic("Error creating draw pipeline state: %s", error->description()->cString(NS::ASCIIStringEncoding)); diff --git a/include/renderer_mtl/mtl_render_target.hpp b/include/renderer_mtl/mtl_render_target.hpp index a35ff89e..d3866c67 100644 --- a/include/renderer_mtl/mtl_render_target.hpp +++ b/include/renderer_mtl/mtl_render_target.hpp @@ -7,6 +7,7 @@ #include "math_util.hpp" #include "opengl.hpp" #include "pica_to_mtl.hpp" +#include "objc_helper.hpp" template using Interval = boost::icl::right_open_interval; @@ -68,6 +69,7 @@ struct RenderTarget { descriptor->setUsage(MTL::TextureUsageRenderTarget | MTL::TextureUsageShaderRead); descriptor->setStorageMode(MTL::StorageModePrivate); texture = device->newTexture(descriptor); + texture->setLabel(toNSString(std::string(std::is_same::value ? "Color" : "Depth") + " render target " + std::to_string(size.u()) + "x" + std::to_string(size.v()))); } void free() { diff --git a/include/renderer_mtl/mtl_vertex_buffer_cache.hpp b/include/renderer_mtl/mtl_vertex_buffer_cache.hpp index 778499cf..0f78d5ac 100644 --- a/include/renderer_mtl/mtl_vertex_buffer_cache.hpp +++ b/include/renderer_mtl/mtl_vertex_buffer_cache.hpp @@ -26,6 +26,7 @@ public: void set(MTL::Device* dev) { device = dev; buffer = device->newBuffer(CACHE_BUFFER_SIZE, MTL::ResourceStorageModeShared); + buffer->setLabel(toNSString("Shared vertex buffer")); } void endFrame() { @@ -40,6 +41,7 @@ public: // If the vertex buffer is too large, just create a new one if (ptr + vertices.size_bytes() > CACHE_BUFFER_SIZE) { MTL::Buffer* newBuffer = device->newBuffer(vertices.data(), vertices.size_bytes(), MTL::ResourceStorageModeShared); + newBuffer->setLabel(toNSString("Additional vertex buffer")); additionalAllocations.push_back(newBuffer); Helpers::warn("Vertex buffer doesn't have enough space, creating a new buffer"); diff --git a/include/renderer_mtl/objc_helper.hpp b/include/renderer_mtl/objc_helper.hpp index 04823978..d00682e4 100644 --- a/include/renderer_mtl/objc_helper.hpp +++ b/include/renderer_mtl/objc_helper.hpp @@ -7,3 +7,8 @@ namespace Metal { dispatch_data_t createDispatchData(const void* data, size_t size); } // namespace Metal + +// Cast from std::string to NS::String* +inline NS::String* toNSString(const std::string& str) { + return NS::String::string(str.c_str(), NS::ASCIIStringEncoding); +} diff --git a/include/renderer_mtl/renderer_mtl.hpp b/include/renderer_mtl/renderer_mtl.hpp index 13aa013c..500fa587 100644 --- a/include/renderer_mtl/renderer_mtl.hpp +++ b/include/renderer_mtl/renderer_mtl.hpp @@ -72,6 +72,9 @@ class RendererMTL final : public Renderer { MTL::Texture* lastColorTexture = nullptr; MTL::Texture* lastDepthTexture = nullptr; + // Debug + std::string nextRenderPassName; + void createCommandBufferIfNeeded() { if (!commandBuffer) { commandBuffer = commandQueue->commandBuffer(); @@ -92,6 +95,7 @@ class RendererMTL final : public Renderer { endRenderPass(); renderCommandEncoder = commandBuffer->renderCommandEncoder(renderPassDescriptor); + renderCommandEncoder->setLabel(toNSString(nextRenderPassName)); lastColorTexture = colorTexture; lastDepthTexture = depthTexture; diff --git a/src/core/renderer_mtl/mtl_texture.cpp b/src/core/renderer_mtl/mtl_texture.cpp index 53e6806c..40ae9bf2 100644 --- a/src/core/renderer_mtl/mtl_texture.cpp +++ b/src/core/renderer_mtl/mtl_texture.cpp @@ -1,5 +1,6 @@ #include "renderer_mtl/mtl_texture.hpp" #include "renderer_mtl/pica_to_mtl.hpp" +#include "renderer_mtl/objc_helper.hpp" #include "colour.hpp" #include @@ -10,12 +11,13 @@ namespace Metal { void Texture::allocate() { MTL::TextureDescriptor* descriptor = MTL::TextureDescriptor::alloc()->init(); descriptor->setTextureType(MTL::TextureType2D); - descriptor->setPixelFormat(MTL::PixelFormatRGBA8Unorm); + descriptor->setPixelFormat(MTL::PixelFormatRGBA8Unorm); // TODO: format descriptor->setWidth(size.u()); descriptor->setHeight(size.v()); descriptor->setUsage(MTL::TextureUsageShaderRead); descriptor->setStorageMode(MTL::StorageModeShared); // TODO: use private + staging buffers? texture = device->newTexture(descriptor); + texture->setLabel(toNSString("Texture " + std::to_string(size.u()) + "x" + std::to_string(size.v()))); setNewConfig(config); } @@ -39,6 +41,7 @@ void Texture::setNewConfig(u32 cfg) { samplerDescriptor->setSAddressMode(wrapS); samplerDescriptor->setTAddressMode(wrapT); + samplerDescriptor->setLabel(toNSString("Sampler")); sampler = device->newSamplerState(samplerDescriptor); } diff --git a/src/core/renderer_mtl/renderer_mtl.cpp b/src/core/renderer_mtl/renderer_mtl.cpp index 94ff7657..cd97ce0e 100644 --- a/src/core/renderer_mtl/renderer_mtl.cpp +++ b/src/core/renderer_mtl/renderer_mtl.cpp @@ -74,6 +74,8 @@ void RendererMTL::display() { } // -------- Draw -------- + commandBuffer->pushDebugGroup(toNSString("Display")); + MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init(); MTL::RenderPassColorAttachmentDescriptor* colorAttachment = renderPassDescriptor->colorAttachments()->object(0); colorAttachment->setTexture(drawable->texture()); @@ -81,6 +83,7 @@ void RendererMTL::display() { colorAttachment->setClearColor(MTL::ClearColor{0.0f, 0.0f, 0.0f, 1.0f}); colorAttachment->setStoreAction(MTL::StoreActionStore); + nextRenderPassName = "Display"; beginRenderPassIfNeeded(renderPassDescriptor, false, drawable->texture()); renderCommandEncoder->setRenderPipelineState(displayPipeline); renderCommandEncoder->setFragmentSamplerState(nearestSampler, 0); @@ -102,6 +105,9 @@ void RendererMTL::display() { endRenderPass(); commandBuffer->presentDrawable(drawable); + + commandBuffer->popDebugGroup(); + commitCommandBuffer(); // Inform the vertex buffer cache that the frame ended @@ -128,14 +134,17 @@ void RendererMTL::initGraphicsContext(SDL_Window* window) { textureDescriptor->setStorageMode(MTL::StorageModePrivate); lightLUTTextureArray = device->newTexture(textureDescriptor); + lightLUTTextureArray->setLabel(toNSString("LUT texture")); textureDescriptor->release(); // Samplers MTL::SamplerDescriptor* samplerDescriptor = MTL::SamplerDescriptor::alloc()->init(); + samplerDescriptor->setLabel(toNSString("Sampler (nearest)")); nearestSampler = device->newSamplerState(samplerDescriptor); samplerDescriptor->setMinFilter(MTL::SamplerMinMagFilterLinear); samplerDescriptor->setMagFilter(MTL::SamplerMinMagFilterLinear); + samplerDescriptor->setLabel(toNSString("Sampler (linear)")); linearSampler = device->newSamplerState(samplerDescriptor); samplerDescriptor->release(); @@ -158,6 +167,7 @@ void RendererMTL::initGraphicsContext(SDL_Window* window) { displayColorAttachment->setPixelFormat(MTL::PixelFormat::PixelFormatBGRA8Unorm); NS::Error* error = nullptr; + displayPipelineDescriptor->setLabel(toNSString("Display pipeline")); displayPipeline = device->newRenderPipelineState(displayPipelineDescriptor, &error); if (error) { Helpers::panic("Error creating display pipeline state: %s", error->description()->cString(NS::ASCIIStringEncoding)); @@ -247,6 +257,7 @@ void RendererMTL::initGraphicsContext(SDL_Window* window) { copyToLutTexturePipelineDescriptor->setRasterizationEnabled(false); error = nullptr; + copyToLutTexturePipelineDescriptor->setLabel(toNSString("Copy to LUT texture pipeline")); copyToLutTexturePipeline = device->newRenderPipelineState(copyToLutTexturePipelineDescriptor, &error); if (error) { Helpers::panic("Error creating copy_to_lut_texture pipeline state: %s", error->description()->cString(NS::ASCIIStringEncoding)); @@ -260,6 +271,7 @@ void RendererMTL::initGraphicsContext(SDL_Window* window) { // -------- Depth stencil state -------- MTL::DepthStencilDescriptor* depthStencilDescriptor = MTL::DepthStencilDescriptor::alloc()->init(); + depthStencilDescriptor->setLabel(toNSString("Default depth stencil state")); defaultDepthStencilState = device->newDepthStencilState(depthStencilDescriptor); } @@ -311,6 +323,7 @@ void RendererMTL::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputHeight = outputSize >> 16; auto srcFramebuffer = getColorRenderTarget(inputAddr, inputFormat, inputWidth, outputHeight); + nextRenderPassName = "Clear before display transfer"; clearColor(nullptr, srcFramebuffer->texture); Math::Rect srcRect = srcFramebuffer->getSubRect(inputAddr, outputWidth, outputHeight); @@ -347,6 +360,7 @@ void RendererMTL::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, Metal::BlitPipelineHash hash{destFramebuffer->format, DepthFmt::Unknown1}; auto blitPipeline = blitPipelineCache.get(hash); + nextRenderPassName = "Display transfer"; beginRenderPassIfNeeded(renderPassDescriptor, false, destFramebuffer->texture); renderCommandEncoder->setRenderPipelineState(blitPipeline); renderCommandEncoder->setFragmentTexture(srcFramebuffer->texture, 0); @@ -407,6 +421,8 @@ void RendererMTL::textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 Helpers::warn("RendererGL::TextureCopy failed to locate src framebuffer!\n"); return; } + nextRenderPassName = "Clear before texture copy"; + clearColor(nullptr, srcFramebuffer->texture); Math::Rect srcRect = srcFramebuffer->getSubRect(inputAddr, copyWidth, copyHeight); @@ -427,6 +443,7 @@ void RendererMTL::textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 Metal::BlitPipelineHash hash{destFramebuffer->format, DepthFmt::Unknown1}; auto blitPipeline = blitPipelineCache.get(hash); + nextRenderPassName = "Texture copy"; beginRenderPassIfNeeded(renderPassDescriptor, false, destFramebuffer->texture); renderCommandEncoder->setRenderPipelineState(blitPipeline); renderCommandEncoder->setFragmentTexture(srcFramebuffer->texture, 0); @@ -521,6 +538,7 @@ void RendererMTL::drawVertices(PICA::PrimType primType, std::spantexture, (depthStencilRenderTarget ? depthStencilRenderTarget->texture : nullptr)); // Update the LUT texture if necessary