From 6db893c44681c9290fef64fc1b62111e9b8a8b24 Mon Sep 17 00:00:00 2001 From: Samuliak Date: Thu, 25 Jul 2024 14:05:56 +0200 Subject: [PATCH] implement texture view & fix: crashes --- src/Cafe/CMakeLists.txt | 2 + src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp | 15 ++--- src/Cafe/HW/Latte/Core/LatteShaderCache.cpp | 8 +-- .../Latte/Renderer/Metal/LatteTextureMtl.cpp | 7 +-- .../HW/Latte/Renderer/Metal/LatteTextureMtl.h | 5 +- .../Renderer/Metal/LatteTextureViewMtl.cpp | 56 +++++++++++++++++++ .../Renderer/Metal/LatteTextureViewMtl.h | 21 +++++++ 7 files changed, 97 insertions(+), 17 deletions(-) create mode 100644 src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp create mode 100644 src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h diff --git a/src/Cafe/CMakeLists.txt b/src/Cafe/CMakeLists.txt index 9da5caa9..ce6738d8 100644 --- a/src/Cafe/CMakeLists.txt +++ b/src/Cafe/CMakeLists.txt @@ -532,6 +532,8 @@ if(ENABLE_METAL) HW/Latte/Renderer/Metal/MetalCppImpl.cpp HW/Latte/Renderer/Metal/LatteTextureMtl.cpp HW/Latte/Renderer/Metal/LatteTextureMtl.h + HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp + HW/Latte/Renderer/Metal/LatteTextureViewMtl.h ) #target_link_libraries(CemuCafe PRIVATE diff --git a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp index 60124c02..f8a53b6d 100644 --- a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp +++ b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp @@ -724,8 +724,8 @@ void LatteRenderTarget_applyTextureColorClear(LatteTexture* texture, uint32 slic void LatteRenderTarget_applyTextureDepthClear(LatteTexture* texture, uint32 sliceIndex, uint32 mipIndex, bool hasDepthClear, bool hasStencilClear, float depthValue, uint8 stencilValue, uint64 eventCounter) { - if(texture->isDepth) - { + if(texture->isDepth) + { g_renderer->texture_clearDepthSlice(texture, sliceIndex, mipIndex, hasDepthClear, hasStencilClear, depthValue, stencilValue); } else @@ -884,7 +884,7 @@ void LatteRenderTarget_copyToBackbuffer(LatteTextureView* textureView, bool isPa textureView->baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, 0); _currentOutputImageWidth = effectiveWidth; _currentOutputImageHeight = effectiveHeight; - + sint32 imageX, imageY; sint32 imageWidth, imageHeight; sint32 fullscreenWidth, fullscreenHeight; @@ -933,7 +933,7 @@ void LatteRenderTarget_copyToBackbuffer(LatteTextureView* textureView, bool isPa if (shader == nullptr) { sint32 scaling_filter = downscaling ? GetConfig().downscale_filter : GetConfig().upscale_filter; - + if (g_renderer->GetType() == RendererAPI::Vulkan) { // force linear or nearest neighbor filter @@ -978,7 +978,8 @@ void LatteRenderTarget_copyToBackbuffer(LatteTextureView* textureView, bool isPa filter = LatteTextureView::MagFilter::kNearestNeighbor; } } - cemu_assert(shader); + // HACK: comment out the assert + //cemu_assert(shader); g_renderer->DrawBackbufferQuad(textureView, shader, filter==LatteTextureView::MagFilter::kLinear, imageX, imageY, imageWidth, imageHeight, isPadView, clearBackground); g_renderer->HandleScreenshotRequest(textureView, isPadView); if (!g_renderer->ImguiBegin(!isPadView)) @@ -1029,7 +1030,7 @@ void LatteRenderTarget_itHLECopyColorBufferToScanBuffer(MPTR colorBufferPtr, uin { controller = InputManager::instance().get_vpad_controller(1); if (controller && controller->is_screen_active()) - showDRC = true; + showDRC = true; } } @@ -1054,7 +1055,7 @@ void LatteRenderTarget_updateViewport() float vpX = LatteGPUState.contextNew.PA_CL_VPORT_XOFFSET.get_OFFSET() - LatteGPUState.contextNew.PA_CL_VPORT_XSCALE.get_SCALE(); float vpHeight = LatteGPUState.contextNew.PA_CL_VPORT_YSCALE.get_SCALE() / -0.5f; float vpY = LatteGPUState.contextNew.PA_CL_VPORT_YOFFSET.get_OFFSET() + LatteGPUState.contextNew.PA_CL_VPORT_YSCALE.get_SCALE(); - + bool halfZ = LatteGPUState.contextNew.PA_CL_CLIP_CNTL.get_DX_CLIP_SPACE_DEF(); // calculate near/far diff --git a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp index 9576eb2e..88418650 100644 --- a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp @@ -41,7 +41,7 @@ struct sint32 pixelShaderCount; }shaderCacheScreenStats; -struct +struct { ImTextureID textureTVId; ImTextureID textureDRCId; @@ -328,7 +328,7 @@ void LatteShaderCache_Load() }; LatteShaderCache_ShowProgress(LoadShadersUpdate, false); - + LatteShaderCache_updateCompileQueue(0); // write load time and RAM usage to log file (in dev build) #if BOOST_OS_WINDOWS @@ -371,7 +371,7 @@ void LatteShaderCache_ShowProgress(const std::function & loadUpdateF { const auto kPopupFlags = ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_AlwaysAutoResize; const auto textColor = 0xFF888888; - + auto lastFrameUpdate = tick_cached(); while (true) @@ -793,7 +793,7 @@ void LatteShaderCache_handleDeprecatedCacheFiles(fs::path pathGeneric, fs::path { // ask user if they want to delete or keep the old cache file auto infoMsg = _("Cemu detected that the shader cache for this game is outdated.\nOnly shader caches generated with Cemu 1.25.0 or above are supported.\n\nWe recommend deleting the outdated cache file as it will no longer be used by Cemu."); - + wxMessageDialog dialog(nullptr, infoMsg, _("Outdated shader cache"), wxYES_NO | wxCENTRE | wxICON_EXCLAMATION); diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp index d6a9ac4a..d2c41b73 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp @@ -1,5 +1,5 @@ #include "Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.h" -//#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h" +#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h" #include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h" LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, @@ -80,10 +80,7 @@ LatteTextureView* LatteTextureMtl::CreateView(Latte::E_DIM dim, Latte::E_GX2SURF cemu_assert_debug((firstMip + mipCount) <= this->mipLevels); cemu_assert_debug((firstSlice + sliceCount) <= this->depth); - //return new LatteTextureViewMtl(m_mtlr, this, dim, format, firstMip, mipCount, firstSlice, sliceCount); - cemuLog_logDebug(LogType::Force, "not implemented"); - - return nullptr; + return new LatteTextureViewMtl(m_mtlr, this, dim, format, firstMip, mipCount, firstSlice, sliceCount); } void LatteTextureMtl::AllocateOnHost() diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.h b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.h index 266a69d1..c659e919 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.h @@ -10,9 +10,12 @@ class LatteTextureMtl : public LatteTexture public: LatteTextureMtl(class MetalRenderer* vkRenderer, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth); - ~LatteTextureMtl(); + MTL::Texture* GetTexture() const { + return m_texture; + } + void AllocateOnHost() override; protected: diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp new file mode 100644 index 00000000..3a93e76d --- /dev/null +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp @@ -0,0 +1,56 @@ +#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h" +#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.h" +#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h" + +LatteTextureViewMtl::LatteTextureViewMtl(MetalRenderer* mtlRenderer, LatteTextureMtl* texture, Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount) + : LatteTextureView(texture, firstMip, mipCount, firstSlice, sliceCount, dim, format), m_mtlr(mtlRenderer) +{ + // TODO: don't hardcode the format + MTL::PixelFormat pixelFormat = MTL::PixelFormatRGBA8Unorm; + MTL::TextureType textureType; + switch (dim) + { + case Latte::E_DIM::DIM_1D: + textureType = MTL::TextureType1D; + case Latte::E_DIM::DIM_2D: + case Latte::E_DIM::DIM_2D_MSAA: + textureType = MTL::TextureType2D; + case Latte::E_DIM::DIM_2D_ARRAY: + textureType = MTL::TextureType2DArray; + case Latte::E_DIM::DIM_3D: + textureType = MTL::TextureType3D; + case Latte::E_DIM::DIM_CUBEMAP: + textureType = MTL::TextureTypeCube; // TODO: check this + default: + cemu_assert_unimplemented(); + textureType = MTL::TextureType2D; + } + + uint32 baseLevel = firstMip; + uint32 levelCount = this->numMip; + uint32 baseLayer; + uint32 layerCount; + // TODO: check if base texture is 3D texture as well + if (textureType == MTL::TextureType3D) + { + cemu_assert_debug(firstMip == 0); + // TODO: uncomment + //cemu_assert_debug(this->numSlice == baseTexture->depth); + baseLayer = 0; + layerCount = 1; + } + else + { + baseLayer = firstSlice; + layerCount = this->numSlice; + } + + // TODO: swizzle + + m_texture = texture->GetTexture()->newTextureView(pixelFormat, textureType, NS::Range::Make(baseLevel, levelCount), NS::Range::Make(baseLayer, layerCount)); +} + +LatteTextureViewMtl::~LatteTextureViewMtl() +{ + m_texture->release(); +} diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h new file mode 100644 index 00000000..c5a21b12 --- /dev/null +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +#include "Cafe/HW/Latte/Core/LatteTexture.h" + +class LatteTextureViewMtl : public LatteTextureView +{ +public: + LatteTextureViewMtl(class MetalRenderer* mtlRenderer, class LatteTextureMtl* texture, Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount); + ~LatteTextureViewMtl(); + + MTL::Texture* GetTexture() const { + return m_texture; + } + +private: + class MetalRenderer* m_mtlr; + + MTL::Texture* m_texture; +};