create stack scoped helper macro

This commit is contained in:
Samuliak 2025-01-25 08:59:48 +01:00
parent b50b9135a0
commit 14f42fc653
No known key found for this signature in database
10 changed files with 39 additions and 64 deletions

View file

@ -7,7 +7,7 @@ LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, Latte::E_DIM
Latte::E_HWTILEMODE tileMode, bool isDepth) Latte::E_HWTILEMODE tileMode, bool isDepth)
: LatteTexture(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth), m_mtlr(mtlRenderer) : LatteTexture(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth), m_mtlr(mtlRenderer)
{ {
MTL::TextureDescriptor* desc = MTL::TextureDescriptor::alloc()->init(); NS_STACK_SCOPED MTL::TextureDescriptor* desc = MTL::TextureDescriptor::alloc()->init();
desc->setStorageMode(MTL::StorageModePrivate); desc->setStorageMode(MTL::StorageModePrivate);
//desc->setCpuCacheMode(MTL::CPUCacheModeWriteCombined); //desc->setCpuCacheMode(MTL::CPUCacheModeWriteCombined);
@ -83,7 +83,6 @@ LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, Latte::E_DIM
desc->setUsage(usage); desc->setUsage(usage);
m_texture = mtlRenderer->GetDevice()->newTexture(desc); m_texture = mtlRenderer->GetDevice()->newTexture(desc);
desc->release();
} }
LatteTextureMtl::~LatteTextureMtl() LatteTextureMtl::~LatteTextureMtl()

View file

@ -50,10 +50,12 @@ inline size_t Align(size_t size, size_t alignment)
return (size + alignment - 1) & ~(alignment - 1); return (size + alignment - 1) & ~(alignment - 1);
} }
//inline std::string GetColorAttachmentTypeStr(uint32 index) __attribute__((unused)) static inline void ETStackAutoRelease(void* object)
//{ {
// return "COLOR_ATTACHMENT" + std::to_string(index) + "_TYPE"; (*(NS::Object**)object)->release();
//} }
#define NS_STACK_SCOPED __attribute__((cleanup(ETStackAutoRelease))) __attribute__((unused))
// Cast from const char* to NS::String* // Cast from const char* to NS::String*
inline NS::String* ToNSString(const char* str) inline NS::String* ToNSString(const char* str)

View file

@ -25,7 +25,7 @@ MTL::DepthStencilState* MetalDepthStencilCache::GetDepthStencilState(const Latte
auto depthFunc = lcr.DB_DEPTH_CONTROL.get_Z_FUNC(); auto depthFunc = lcr.DB_DEPTH_CONTROL.get_Z_FUNC();
bool depthWriteEnable = lcr.DB_DEPTH_CONTROL.get_Z_WRITE_ENABLE(); bool depthWriteEnable = lcr.DB_DEPTH_CONTROL.get_Z_WRITE_ENABLE();
MTL::DepthStencilDescriptor* desc = MTL::DepthStencilDescriptor::alloc()->init(); NS_STACK_SCOPED MTL::DepthStencilDescriptor* desc = MTL::DepthStencilDescriptor::alloc()->init();
if (depthEnable) if (depthEnable)
{ {
desc->setDepthWriteEnabled(depthWriteEnable); desc->setDepthWriteEnabled(depthWriteEnable);
@ -52,7 +52,7 @@ MTL::DepthStencilState* MetalDepthStencilCache::GetDepthStencilState(const Latte
uint32 stencilCompareMaskBack = lcr.DB_STENCILREFMASK_BF.get_STENCILMASK_B(); uint32 stencilCompareMaskBack = lcr.DB_STENCILREFMASK_BF.get_STENCILMASK_B();
uint32 stencilWriteMaskBack = lcr.DB_STENCILREFMASK_BF.get_STENCILWRITEMASK_B(); uint32 stencilWriteMaskBack = lcr.DB_STENCILREFMASK_BF.get_STENCILWRITEMASK_B();
MTL::StencilDescriptor* frontStencil = MTL::StencilDescriptor::alloc()->init(); NS_STACK_SCOPED MTL::StencilDescriptor* frontStencil = MTL::StencilDescriptor::alloc()->init();
frontStencil->setReadMask(stencilCompareMaskFront); frontStencil->setReadMask(stencilCompareMaskFront);
frontStencil->setWriteMask(stencilWriteMaskFront); frontStencil->setWriteMask(stencilWriteMaskFront);
frontStencil->setStencilCompareFunction(GetMtlCompareFunc(frontStencilFunc)); frontStencil->setStencilCompareFunction(GetMtlCompareFunc(frontStencilFunc));
@ -61,7 +61,7 @@ MTL::DepthStencilState* MetalDepthStencilCache::GetDepthStencilState(const Latte
frontStencil->setDepthStencilPassOperation(GetMtlStencilOp(frontStencilZPass)); frontStencil->setDepthStencilPassOperation(GetMtlStencilOp(frontStencilZPass));
desc->setFrontFaceStencil(frontStencil); desc->setFrontFaceStencil(frontStencil);
MTL::StencilDescriptor* backStencil = MTL::StencilDescriptor::alloc()->init(); NS_STACK_SCOPED MTL::StencilDescriptor* backStencil = MTL::StencilDescriptor::alloc()->init();
if (backStencilEnable) if (backStencilEnable)
{ {
backStencil->setReadMask(stencilCompareMaskBack); backStencil->setReadMask(stencilCompareMaskBack);
@ -81,13 +81,9 @@ MTL::DepthStencilState* MetalDepthStencilCache::GetDepthStencilState(const Latte
backStencil->setDepthStencilPassOperation(GetMtlStencilOp(frontStencilZPass)); backStencil->setDepthStencilPassOperation(GetMtlStencilOp(frontStencilZPass));
} }
desc->setBackFaceStencil(backStencil); desc->setBackFaceStencil(backStencil);
frontStencil->release();
backStencil->release();
} }
depthStencilState = m_mtlr->GetDevice()->newDepthStencilState(desc); depthStencilState = m_mtlr->GetDevice()->newDepthStencilState(desc);
desc->release();
return depthStencilState; return depthStencilState;
} }

View file

@ -21,14 +21,13 @@ MTL::RenderPipelineState* MetalOutputShaderCache::GetPipeline(RendererOutputShad
auto vertexShaderMtl = static_cast<RendererShaderMtl*>(shader->GetVertexShader())->GetFunction(); auto vertexShaderMtl = static_cast<RendererShaderMtl*>(shader->GetVertexShader())->GetFunction();
auto fragmentShaderMtl = static_cast<RendererShaderMtl*>(shader->GetFragmentShader())->GetFunction(); auto fragmentShaderMtl = static_cast<RendererShaderMtl*>(shader->GetFragmentShader())->GetFunction();
auto renderPipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init(); NS_STACK_SCOPED auto renderPipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init();
renderPipelineDescriptor->setVertexFunction(vertexShaderMtl); renderPipelineDescriptor->setVertexFunction(vertexShaderMtl);
renderPipelineDescriptor->setFragmentFunction(fragmentShaderMtl); renderPipelineDescriptor->setFragmentFunction(fragmentShaderMtl);
renderPipelineDescriptor->colorAttachments()->object(0)->setPixelFormat(usesSRGB ? MTL::PixelFormatBGRA8Unorm_sRGB : MTL::PixelFormatBGRA8Unorm); renderPipelineDescriptor->colorAttachments()->object(0)->setPixelFormat(usesSRGB ? MTL::PixelFormatBGRA8Unorm_sRGB : MTL::PixelFormatBGRA8Unorm);
NS::Error* error = nullptr; NS::Error* error = nullptr;
renderPipelineState = m_mtlr->GetDevice()->newRenderPipelineState(renderPipelineDescriptor, &error); renderPipelineState = m_mtlr->GetDevice()->newRenderPipelineState(renderPipelineDescriptor, &error);
renderPipelineDescriptor->release();
if (error) if (error)
{ {
cemuLog_log(LogType::Force, "error creating output render pipeline state: {}", error->localizedDescription()->utf8String()); cemuLog_log(LogType::Force, "error creating output render pipeline state: {}", error->localizedDescription()->utf8String());

View file

@ -413,7 +413,7 @@ void MetalPipelineCompiler::InitFromStateRender(const LatteFetchShader* fetchSha
// Vertex descriptor // Vertex descriptor
if (!fetchShader->mtlFetchVertexManually) if (!fetchShader->mtlFetchVertexManually)
{ {
MTL::VertexDescriptor* vertexDescriptor = MTL::VertexDescriptor::alloc()->init(); NS_STACK_SCOPED MTL::VertexDescriptor* vertexDescriptor = MTL::VertexDescriptor::alloc()->init();
for (auto& bufferGroup : fetchShader->bufferGroups) for (auto& bufferGroup : fetchShader->bufferGroups)
{ {
std::optional<LatteConst::VertexFetchType2> fetchType; std::optional<LatteConst::VertexFetchType2> fetchType;
@ -476,7 +476,6 @@ void MetalPipelineCompiler::InitFromStateRender(const LatteFetchShader* fetchSha
} }
desc->setVertexDescriptor(vertexDescriptor); desc->setVertexDescriptor(vertexDescriptor);
vertexDescriptor->release();
} }
SetFragmentState(desc, lastUsedAttachmentsInfo, activeAttachmentsInfo, m_rasterizationEnabled, lcr); SetFragmentState(desc, lastUsedAttachmentsInfo, activeAttachmentsInfo, m_rasterizationEnabled, lcr);

View file

@ -21,7 +21,6 @@
#include "Cemu/Logging/CemuLogging.h" #include "Cemu/Logging/CemuLogging.h"
#include "Cafe/HW/Latte/Core/FetchShader.h" #include "Cafe/HW/Latte/Core/FetchShader.h"
#include "Cafe/HW/Latte/Core/LatteConst.h" #include "Cafe/HW/Latte/Core/LatteConst.h"
#include "HW/Latte/Renderer/Metal/MetalBufferAllocator.h"
#include "HW/Latte/Renderer/Metal/MetalCommon.h" #include "HW/Latte/Renderer/Metal/MetalCommon.h"
#include "config/CemuConfig.h" #include "config/CemuConfig.h"
#include "gui/guiWrapper.h" #include "gui/guiWrapper.h"
@ -41,7 +40,7 @@ void LatteDraw_handleSpecialState8_clearAsDepth();
std::vector<MetalRenderer::DeviceInfo> MetalRenderer::GetDevices() std::vector<MetalRenderer::DeviceInfo> MetalRenderer::GetDevices()
{ {
auto devices = MTL::CopyAllDevices(); NS_STACK_SCOPED auto devices = MTL::CopyAllDevices();
std::vector<MetalRenderer::DeviceInfo> result; std::vector<MetalRenderer::DeviceInfo> result;
result.reserve(devices->count()); result.reserve(devices->count());
for (uint32 i = 0; i < devices->count(); i++) for (uint32 i = 0; i < devices->count(); i++)
@ -49,7 +48,6 @@ std::vector<MetalRenderer::DeviceInfo> MetalRenderer::GetDevices()
MTL::Device* device = static_cast<MTL::Device*>(devices->object(i)); MTL::Device* device = static_cast<MTL::Device*>(devices->object(i));
result.emplace_back(std::string(device->name()->utf8String()), device->registryID()); result.emplace_back(std::string(device->name()->utf8String()), device->registryID());
} }
devices->release();
return result; return result;
} }
@ -126,7 +124,7 @@ MetalRenderer::MetalRenderer()
// If a device is set, try to find it // If a device is set, try to find it
if (hasDeviceSet) if (hasDeviceSet)
{ {
auto devices = MTL::CopyAllDevices(); NS_STACK_SCOPED auto devices = MTL::CopyAllDevices();
for (uint32 i = 0; i < devices->count(); i++) for (uint32 i = 0; i < devices->count(); i++)
{ {
MTL::Device* device = static_cast<MTL::Device*>(devices->object(i)); MTL::Device* device = static_cast<MTL::Device*>(devices->object(i));
@ -136,7 +134,6 @@ MetalRenderer::MetalRenderer()
break; break;
} }
} }
devices->release();
} }
if (!m_device) if (!m_device)
@ -167,7 +164,7 @@ MetalRenderer::MetalRenderer()
m_event = m_device->newEvent(); m_event = m_device->newEvent();
// Resources // Resources
MTL::SamplerDescriptor* samplerDescriptor = MTL::SamplerDescriptor::alloc()->init(); NS_STACK_SCOPED MTL::SamplerDescriptor* samplerDescriptor = MTL::SamplerDescriptor::alloc()->init();
#ifdef CEMU_DEBUG_ASSERT #ifdef CEMU_DEBUG_ASSERT
samplerDescriptor->setLabel(GetLabel("Nearest sampler state", samplerDescriptor)); samplerDescriptor->setLabel(GetLabel("Nearest sampler state", samplerDescriptor));
#endif #endif
@ -179,10 +176,9 @@ MetalRenderer::MetalRenderer()
samplerDescriptor->setLabel(GetLabel("Linear sampler state", samplerDescriptor)); samplerDescriptor->setLabel(GetLabel("Linear sampler state", samplerDescriptor));
#endif #endif
m_linearSampler = m_device->newSamplerState(samplerDescriptor); m_linearSampler = m_device->newSamplerState(samplerDescriptor);
samplerDescriptor->release();
// Null resources // Null resources
MTL::TextureDescriptor* textureDescriptor = MTL::TextureDescriptor::alloc()->init(); NS_STACK_SCOPED MTL::TextureDescriptor* textureDescriptor = MTL::TextureDescriptor::alloc()->init();
textureDescriptor->setTextureType(MTL::TextureType1D); textureDescriptor->setTextureType(MTL::TextureType1D);
textureDescriptor->setWidth(1); textureDescriptor->setWidth(1);
textureDescriptor->setUsage(MTL::TextureUsageShaderRead); textureDescriptor->setUsage(MTL::TextureUsageShaderRead);
@ -198,7 +194,6 @@ MetalRenderer::MetalRenderer()
#ifdef CEMU_DEBUG_ASSERT #ifdef CEMU_DEBUG_ASSERT
m_nullTexture2D->setLabel(GetLabel("Null texture 2D", m_nullTexture2D)); m_nullTexture2D->setLabel(GetLabel("Null texture 2D", m_nullTexture2D));
#endif #endif
textureDescriptor->release();
m_memoryManager = new MetalMemoryManager(this); m_memoryManager = new MetalMemoryManager(this);
m_outputShaderCache = new MetalOutputShaderCache(this); m_outputShaderCache = new MetalOutputShaderCache(this);
@ -233,28 +228,24 @@ MetalRenderer::MetalRenderer()
// Create the library // Create the library
NS::Error* error = nullptr; NS::Error* error = nullptr;
MTL::Library* utilityLibrary = m_device->newLibrary(ToNSString(utilityShaderSource), nullptr, &error); NS_STACK_SCOPED MTL::Library* utilityLibrary = m_device->newLibrary(ToNSString(utilityShaderSource), nullptr, &error);
if (error) if (error)
{ {
cemuLog_log(LogType::Force, "failed to create utility library (error: {})", error->localizedDescription()->utf8String()); cemuLog_log(LogType::Force, "failed to create utility library (error: {})", error->localizedDescription()->utf8String());
} }
// Pipelines // Pipelines
MTL::Function* vertexFullscreenFunction = utilityLibrary->newFunction(ToNSString("vertexFullscreen")); NS_STACK_SCOPED MTL::Function* vertexFullscreenFunction = utilityLibrary->newFunction(ToNSString("vertexFullscreen"));
MTL::Function* fragmentCopyDepthToColorFunction = utilityLibrary->newFunction(ToNSString("fragmentCopyDepthToColor")); NS_STACK_SCOPED MTL::Function* fragmentCopyDepthToColorFunction = utilityLibrary->newFunction(ToNSString("fragmentCopyDepthToColor"));
m_copyDepthToColorDesc = MTL::RenderPipelineDescriptor::alloc()->init(); m_copyDepthToColorDesc = MTL::RenderPipelineDescriptor::alloc()->init();
m_copyDepthToColorDesc->setVertexFunction(vertexFullscreenFunction); m_copyDepthToColorDesc->setVertexFunction(vertexFullscreenFunction);
m_copyDepthToColorDesc->setFragmentFunction(fragmentCopyDepthToColorFunction); m_copyDepthToColorDesc->setFragmentFunction(fragmentCopyDepthToColorFunction);
vertexFullscreenFunction->release();
fragmentCopyDepthToColorFunction->release();
// Void vertex pipelines // Void vertex pipelines
if (m_isAppleGPU) if (m_isAppleGPU)
m_copyBufferToBufferPipeline = new MetalVoidVertexPipeline(this, utilityLibrary, "vertexCopyBufferToBuffer"); m_copyBufferToBufferPipeline = new MetalVoidVertexPipeline(this, utilityLibrary, "vertexCopyBufferToBuffer");
utilityLibrary->release();
// HACK: for some reason, this variable ends up being initialized to some garbage data, even though its declared as bool m_captureFrame = false; // HACK: for some reason, this variable ends up being initialized to some garbage data, even though its declared as bool m_captureFrame = false;
m_occlusionQuery.m_lastCommandBuffer = nullptr; m_occlusionQuery.m_lastCommandBuffer = nullptr;
m_captureFrame = false; m_captureFrame = false;
@ -414,13 +405,12 @@ void MetalRenderer::HandleScreenshotRequest(LatteTextureView* texView, bool padV
uint32 bytesPerRow = GetMtlTextureBytesPerRow(texMtl->format, texMtl->isDepth, width); uint32 bytesPerRow = GetMtlTextureBytesPerRow(texMtl->format, texMtl->isDepth, width);
uint32 size = GetMtlTextureBytesPerImage(texMtl->format, texMtl->isDepth, height, bytesPerRow); uint32 size = GetMtlTextureBytesPerImage(texMtl->format, texMtl->isDepth, height, bytesPerRow);
// TODO: get a buffer from the memory manager
MTL::Buffer* buffer = m_device->newBuffer(size, MTL::ResourceStorageModeShared);
auto blitCommandEncoder = GetBlitCommandEncoder(); auto blitCommandEncoder = GetBlitCommandEncoder();
blitCommandEncoder->copyFromTexture(texMtl->GetTexture(), 0, 0, MTL::Origin(0, 0, 0), MTL::Size(width, height, 1), buffer, 0, bytesPerRow, 0);
uint8* bufferPtr = (uint8*)buffer->contents(); auto& bufferAllocator = m_memoryManager->GetStagingAllocator();
auto buffer = bufferAllocator.AllocateBufferMemory(size, 1);
blitCommandEncoder->copyFromTexture(texMtl->GetTexture(), 0, 0, MTL::Origin(0, 0, 0), MTL::Size(width, height, 1), buffer.mtlBuffer, buffer.bufferOffset, bytesPerRow, 0);
bool formatValid = true; bool formatValid = true;
std::vector<uint8> rgb_data; std::vector<uint8> rgb_data;
@ -431,7 +421,7 @@ void MetalRenderer::HandleScreenshotRequest(LatteTextureView* texView, bool padV
switch (pixelFormat) switch (pixelFormat)
{ {
case MTL::PixelFormatRGBA8Unorm: case MTL::PixelFormatRGBA8Unorm:
for (auto ptr = bufferPtr; ptr < bufferPtr + size; ptr += 4) for (auto ptr = buffer.memPtr; ptr < buffer.memPtr + size; ptr += 4)
{ {
rgb_data.emplace_back(*ptr); rgb_data.emplace_back(*ptr);
rgb_data.emplace_back(*(ptr + 1)); rgb_data.emplace_back(*(ptr + 1));
@ -439,7 +429,7 @@ void MetalRenderer::HandleScreenshotRequest(LatteTextureView* texView, bool padV
} }
break; break;
case MTL::PixelFormatRGBA8Unorm_sRGB: case MTL::PixelFormatRGBA8Unorm_sRGB:
for (auto ptr = bufferPtr; ptr < bufferPtr + size; ptr += 4) for (auto ptr = buffer.memPtr; ptr < buffer.memPtr + size; ptr += 4)
{ {
rgb_data.emplace_back(SRGBComponentToRGB(*ptr)); rgb_data.emplace_back(SRGBComponentToRGB(*ptr));
rgb_data.emplace_back(SRGBComponentToRGB(*(ptr + 1))); rgb_data.emplace_back(SRGBComponentToRGB(*(ptr + 1)));
@ -452,8 +442,6 @@ void MetalRenderer::HandleScreenshotRequest(LatteTextureView* texView, bool padV
break; break;
} }
buffer->release();
if (formatValid) if (formatValid)
SaveScreenshot(rgb_data, width, height, !padView); SaveScreenshot(rgb_data, width, height, !padView);
} }
@ -470,14 +458,13 @@ void MetalRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutput
// Create render pass // Create render pass
auto& layer = GetLayer(!padView); auto& layer = GetLayer(!padView);
MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init(); NS_STACK_SCOPED MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
auto colorAttachment = renderPassDescriptor->colorAttachments()->object(0); auto colorAttachment = renderPassDescriptor->colorAttachments()->object(0);
colorAttachment->setTexture(layer.GetDrawable()->texture()); colorAttachment->setTexture(layer.GetDrawable()->texture());
colorAttachment->setLoadAction(clearBackground ? MTL::LoadActionClear : MTL::LoadActionLoad); colorAttachment->setLoadAction(clearBackground ? MTL::LoadActionClear : MTL::LoadActionLoad);
colorAttachment->setStoreAction(MTL::StoreActionStore); colorAttachment->setStoreAction(MTL::StoreActionStore);
auto renderCommandEncoder = GetTemporaryRenderCommandEncoder(renderPassDescriptor); auto renderCommandEncoder = GetTemporaryRenderCommandEncoder(renderPassDescriptor);
renderPassDescriptor->release();
// Get a render pipeline // Get a render pipeline
@ -557,7 +544,7 @@ bool MetalRenderer::ImguiBegin(bool mainWindow)
auto& layer = GetLayer(mainWindow); auto& layer = GetLayer(mainWindow);
// Render pass descriptor // Render pass descriptor
MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init(); NS_STACK_SCOPED MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
auto colorAttachment = renderPassDescriptor->colorAttachments()->object(0); auto colorAttachment = renderPassDescriptor->colorAttachments()->object(0);
colorAttachment->setTexture(layer.GetDrawable()->texture()); colorAttachment->setTexture(layer.GetDrawable()->texture());
colorAttachment->setLoadAction(MTL::LoadActionLoad); colorAttachment->setLoadAction(MTL::LoadActionLoad);
@ -570,7 +557,6 @@ bool MetalRenderer::ImguiBegin(bool mainWindow)
if (m_encoderType != MetalEncoderType::Render) if (m_encoderType != MetalEncoderType::Render)
GetTemporaryRenderCommandEncoder(renderPassDescriptor); GetTemporaryRenderCommandEncoder(renderPassDescriptor);
renderPassDescriptor->release();
return true; return true;
} }
@ -605,7 +591,7 @@ ImTextureID MetalRenderer::GenerateTexture(const std::vector<uint8>& data, const
tmp[(i * 4) + 3] = 0xFF; tmp[(i * 4) + 3] = 0xFF;
} }
MTL::TextureDescriptor* desc = MTL::TextureDescriptor::alloc()->init(); NS_STACK_SCOPED MTL::TextureDescriptor* desc = MTL::TextureDescriptor::alloc()->init();
desc->setTextureType(MTL::TextureType2D); desc->setTextureType(MTL::TextureType2D);
desc->setPixelFormat(MTL::PixelFormatRGBA8Unorm); desc->setPixelFormat(MTL::PixelFormatRGBA8Unorm);
desc->setWidth(size.x); desc->setWidth(size.x);
@ -614,7 +600,6 @@ ImTextureID MetalRenderer::GenerateTexture(const std::vector<uint8>& data, const
desc->setUsage(MTL::TextureUsageShaderRead); desc->setUsage(MTL::TextureUsageShaderRead);
MTL::Texture* texture = m_device->newTexture(desc); MTL::Texture* texture = m_device->newTexture(desc);
desc->release();
// TODO: do a GPU copy? // TODO: do a GPU copy?
texture->replaceRegion(MTL::Region(0, 0, size.x, size.y), 0, 0, tmp.data(), size.x * 4, 0); texture->replaceRegion(MTL::Region(0, 0, size.x, size.y), 0, 0, tmp.data(), size.x * 4, 0);
@ -768,11 +753,8 @@ void MetalRenderer::texture_loadSlice(LatteTexture* hostTexture, sint32 width, s
// Allocate a temporary buffer // Allocate a temporary buffer
auto& bufferAllocator = m_memoryManager->GetStagingAllocator(); auto& bufferAllocator = m_memoryManager->GetStagingAllocator();
auto allocation = bufferAllocator.AllocateBufferMemory(compressedImageSize, 1); auto allocation = bufferAllocator.AllocateBufferMemory(compressedImageSize, 1);
bufferAllocator.FlushReservation(allocation);
// Copy the data to the temporary buffer
memcpy(allocation.memPtr, pixelData, compressedImageSize); memcpy(allocation.memPtr, pixelData, compressedImageSize);
//buffer->didModifyRange(NS::Range(allocation.offset, allocation.size)); bufferAllocator.FlushReservation(allocation);
// TODO: specify blit options when copying to a depth stencil texture? // TODO: specify blit options when copying to a depth stencil texture?
// Copy the data from the temporary buffer to the texture // Copy the data from the temporary buffer to the texture
@ -804,7 +786,7 @@ void MetalRenderer::texture_clearDepthSlice(LatteTexture* hostTexture, uint32 sl
auto mtlTexture = static_cast<LatteTextureMtl*>(hostTexture)->GetTexture(); auto mtlTexture = static_cast<LatteTextureMtl*>(hostTexture)->GetTexture();
MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init(); NS_STACK_SCOPED MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
if (clearDepth) if (clearDepth)
{ {
auto depthAttachment = renderPassDescriptor->depthAttachment(); auto depthAttachment = renderPassDescriptor->depthAttachment();
@ -827,7 +809,6 @@ void MetalRenderer::texture_clearDepthSlice(LatteTexture* hostTexture, uint32 sl
} }
GetTemporaryRenderCommandEncoder(renderPassDescriptor); GetTemporaryRenderCommandEncoder(renderPassDescriptor);
renderPassDescriptor->release();
EndEncoding(); EndEncoding();
// Debug // Debug
@ -2195,7 +2176,7 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
void MetalRenderer::ClearColorTextureInternal(MTL::Texture* mtlTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a) void MetalRenderer::ClearColorTextureInternal(MTL::Texture* mtlTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a)
{ {
MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init(); NS_STACK_SCOPED MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
auto colorAttachment = renderPassDescriptor->colorAttachments()->object(0); auto colorAttachment = renderPassDescriptor->colorAttachments()->object(0);
colorAttachment->setTexture(mtlTexture); colorAttachment->setTexture(mtlTexture);
colorAttachment->setClearColor(MTL::ClearColor(r, g, b, a)); colorAttachment->setClearColor(MTL::ClearColor(r, g, b, a));
@ -2205,7 +2186,6 @@ void MetalRenderer::ClearColorTextureInternal(MTL::Texture* mtlTexture, sint32 s
colorAttachment->setLevel(mipIndex); colorAttachment->setLevel(mipIndex);
GetTemporaryRenderCommandEncoder(renderPassDescriptor); GetTemporaryRenderCommandEncoder(renderPassDescriptor);
renderPassDescriptor->release();
EndEncoding(); EndEncoding();
// Debug // Debug

View file

@ -6,6 +6,7 @@
#include "Cafe/HW/Latte/Renderer/Metal/MetalPerformanceMonitor.h" #include "Cafe/HW/Latte/Renderer/Metal/MetalPerformanceMonitor.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalOutputShaderCache.h" #include "Cafe/HW/Latte/Renderer/Metal/MetalOutputShaderCache.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalAttachmentsInfo.h" #include "Cafe/HW/Latte/Renderer/Metal/MetalAttachmentsInfo.h"
#include "Foundation/NSAutoreleasePool.hpp"
enum MetalGeneralShaderType enum MetalGeneralShaderType
{ {
@ -527,6 +528,9 @@ private:
MTL::CommandBuffer* m_lastCommandBuffer = nullptr; MTL::CommandBuffer* m_lastCommandBuffer = nullptr;
} m_occlusionQuery; } m_occlusionQuery;
// Autorelease pool
NS::AutoreleasePool* m_autoreleasePool;
// Active objects // Active objects
MetalCommandBuffer m_currentCommandBuffer{}; MetalCommandBuffer m_currentCommandBuffer{};
std::vector<MTL::CommandBuffer*> m_executingCommandBuffers; std::vector<MTL::CommandBuffer*> m_executingCommandBuffers;

View file

@ -21,7 +21,7 @@ MTL::SamplerState* MetalSamplerCache::GetSamplerState(const LatteContextRegister
// Sampler state // Sampler state
const _LatteRegisterSetSampler* samplerWords = lcr.SQ_TEX_SAMPLER + samplerIndex; const _LatteRegisterSetSampler* samplerWords = lcr.SQ_TEX_SAMPLER + samplerIndex;
MTL::SamplerDescriptor* samplerDescriptor = MTL::SamplerDescriptor::alloc()->init(); NS_STACK_SCOPED MTL::SamplerDescriptor* samplerDescriptor = MTL::SamplerDescriptor::alloc()->init();
// lod // lod
uint32 iMinLOD = samplerWords->WORD1.get_MIN_LOD(); uint32 iMinLOD = samplerWords->WORD1.get_MIN_LOD();
@ -115,7 +115,6 @@ MTL::SamplerState* MetalSamplerCache::GetSamplerState(const LatteContextRegister
} }
samplerState = m_mtlr->GetDevice()->newSamplerState(samplerDescriptor); samplerState = m_mtlr->GetDevice()->newSamplerState(samplerDescriptor);
samplerDescriptor->release();
return samplerState; return samplerState;
} }

View file

@ -3,16 +3,14 @@
MetalVoidVertexPipeline::MetalVoidVertexPipeline(class MetalRenderer* mtlRenderer, MTL::Library* library, const std::string& vertexFunctionName) MetalVoidVertexPipeline::MetalVoidVertexPipeline(class MetalRenderer* mtlRenderer, MTL::Library* library, const std::string& vertexFunctionName)
{ {
// Render pipeline state // Render pipeline state
MTL::Function* vertexFunction = library->newFunction(ToNSString(vertexFunctionName)); NS_STACK_SCOPED MTL::Function* vertexFunction = library->newFunction(ToNSString(vertexFunctionName));
MTL::RenderPipelineDescriptor* renderPipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init(); NS_STACK_SCOPED MTL::RenderPipelineDescriptor* renderPipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init();
renderPipelineDescriptor->setVertexFunction(vertexFunction); renderPipelineDescriptor->setVertexFunction(vertexFunction);
renderPipelineDescriptor->setRasterizationEnabled(false); renderPipelineDescriptor->setRasterizationEnabled(false);
NS::Error* error = nullptr; NS::Error* error = nullptr;
m_renderPipelineState = mtlRenderer->GetDevice()->newRenderPipelineState(renderPipelineDescriptor, &error); m_renderPipelineState = mtlRenderer->GetDevice()->newRenderPipelineState(renderPipelineDescriptor, &error);
renderPipelineDescriptor->release();
vertexFunction->release();
if (error) if (error)
{ {
cemuLog_log(LogType::Force, "error creating hybrid render pipeline state: {}", error->localizedDescription()->utf8String()); cemuLog_log(LogType::Force, "error creating hybrid render pipeline state: {}", error->localizedDescription()->utf8String());

View file

@ -276,7 +276,7 @@ bool RendererShaderMtl::ShouldCountCompilation() const
MTL::Library* RendererShaderMtl::LibraryFromSource() MTL::Library* RendererShaderMtl::LibraryFromSource()
{ {
// Compile from source // Compile from source
MTL::CompileOptions* options = MTL::CompileOptions::alloc()->init(); NS_STACK_SCOPED MTL::CompileOptions* options = MTL::CompileOptions::alloc()->init();
if (g_current_game_profile->GetFastMath()) if (g_current_game_profile->GetFastMath())
options->setFastMathEnabled(true); options->setFastMathEnabled(true);
@ -288,7 +288,6 @@ MTL::Library* RendererShaderMtl::LibraryFromSource()
NS::Error* error = nullptr; NS::Error* error = nullptr;
MTL::Library* library = m_mtlr->GetDevice()->newLibrary(ToNSString(m_mslCode), options, &error); MTL::Library* library = m_mtlr->GetDevice()->newLibrary(ToNSString(m_mslCode), options, &error);
options->release();
if (error) if (error)
{ {
cemuLog_log(LogType::Force, "failed to create library from source: {} -> {}", error->localizedDescription()->utf8String(), m_mslCode.c_str()); cemuLog_log(LogType::Force, "failed to create library from source: {} -> {}", error->localizedDescription()->utf8String(), m_mslCode.c_str());