implement texture view & fix: crashes

This commit is contained in:
Samuliak 2024-07-25 14:05:56 +02:00
parent 98370260d3
commit 6db893c446
7 changed files with 97 additions and 17 deletions

View File

@ -532,6 +532,8 @@ if(ENABLE_METAL)
HW/Latte/Renderer/Metal/MetalCppImpl.cpp HW/Latte/Renderer/Metal/MetalCppImpl.cpp
HW/Latte/Renderer/Metal/LatteTextureMtl.cpp HW/Latte/Renderer/Metal/LatteTextureMtl.cpp
HW/Latte/Renderer/Metal/LatteTextureMtl.h HW/Latte/Renderer/Metal/LatteTextureMtl.h
HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp
HW/Latte/Renderer/Metal/LatteTextureViewMtl.h
) )
#target_link_libraries(CemuCafe PRIVATE #target_link_libraries(CemuCafe PRIVATE

View File

@ -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) 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); g_renderer->texture_clearDepthSlice(texture, sliceIndex, mipIndex, hasDepthClear, hasStencilClear, depthValue, stencilValue);
} }
else else
@ -884,7 +884,7 @@ void LatteRenderTarget_copyToBackbuffer(LatteTextureView* textureView, bool isPa
textureView->baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, 0); textureView->baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, 0);
_currentOutputImageWidth = effectiveWidth; _currentOutputImageWidth = effectiveWidth;
_currentOutputImageHeight = effectiveHeight; _currentOutputImageHeight = effectiveHeight;
sint32 imageX, imageY; sint32 imageX, imageY;
sint32 imageWidth, imageHeight; sint32 imageWidth, imageHeight;
sint32 fullscreenWidth, fullscreenHeight; sint32 fullscreenWidth, fullscreenHeight;
@ -933,7 +933,7 @@ void LatteRenderTarget_copyToBackbuffer(LatteTextureView* textureView, bool isPa
if (shader == nullptr) if (shader == nullptr)
{ {
sint32 scaling_filter = downscaling ? GetConfig().downscale_filter : GetConfig().upscale_filter; sint32 scaling_filter = downscaling ? GetConfig().downscale_filter : GetConfig().upscale_filter;
if (g_renderer->GetType() == RendererAPI::Vulkan) if (g_renderer->GetType() == RendererAPI::Vulkan)
{ {
// force linear or nearest neighbor filter // force linear or nearest neighbor filter
@ -978,7 +978,8 @@ void LatteRenderTarget_copyToBackbuffer(LatteTextureView* textureView, bool isPa
filter = LatteTextureView::MagFilter::kNearestNeighbor; 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->DrawBackbufferQuad(textureView, shader, filter==LatteTextureView::MagFilter::kLinear, imageX, imageY, imageWidth, imageHeight, isPadView, clearBackground);
g_renderer->HandleScreenshotRequest(textureView, isPadView); g_renderer->HandleScreenshotRequest(textureView, isPadView);
if (!g_renderer->ImguiBegin(!isPadView)) if (!g_renderer->ImguiBegin(!isPadView))
@ -1029,7 +1030,7 @@ void LatteRenderTarget_itHLECopyColorBufferToScanBuffer(MPTR colorBufferPtr, uin
{ {
controller = InputManager::instance().get_vpad_controller(1); controller = InputManager::instance().get_vpad_controller(1);
if (controller && controller->is_screen_active()) 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 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 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(); 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(); bool halfZ = LatteGPUState.contextNew.PA_CL_CLIP_CNTL.get_DX_CLIP_SPACE_DEF();
// calculate near/far // calculate near/far

View File

@ -41,7 +41,7 @@ struct
sint32 pixelShaderCount; sint32 pixelShaderCount;
}shaderCacheScreenStats; }shaderCacheScreenStats;
struct struct
{ {
ImTextureID textureTVId; ImTextureID textureTVId;
ImTextureID textureDRCId; ImTextureID textureDRCId;
@ -328,7 +328,7 @@ void LatteShaderCache_Load()
}; };
LatteShaderCache_ShowProgress(LoadShadersUpdate, false); LatteShaderCache_ShowProgress(LoadShadersUpdate, false);
LatteShaderCache_updateCompileQueue(0); LatteShaderCache_updateCompileQueue(0);
// write load time and RAM usage to log file (in dev build) // write load time and RAM usage to log file (in dev build)
#if BOOST_OS_WINDOWS #if BOOST_OS_WINDOWS
@ -371,7 +371,7 @@ void LatteShaderCache_ShowProgress(const std::function <bool(void)>& loadUpdateF
{ {
const auto kPopupFlags = ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_AlwaysAutoResize; const auto kPopupFlags = ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_AlwaysAutoResize;
const auto textColor = 0xFF888888; const auto textColor = 0xFF888888;
auto lastFrameUpdate = tick_cached(); auto lastFrameUpdate = tick_cached();
while (true) 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 // 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."); 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"), wxMessageDialog dialog(nullptr, infoMsg, _("Outdated shader cache"),
wxYES_NO | wxCENTRE | wxICON_EXCLAMATION); wxYES_NO | wxCENTRE | wxICON_EXCLAMATION);

View File

@ -1,5 +1,5 @@
#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.h" #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" #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, 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((firstMip + mipCount) <= this->mipLevels);
cemu_assert_debug((firstSlice + sliceCount) <= this->depth); cemu_assert_debug((firstSlice + sliceCount) <= this->depth);
//return new LatteTextureViewMtl(m_mtlr, this, dim, format, firstMip, mipCount, firstSlice, sliceCount); return new LatteTextureViewMtl(m_mtlr, this, dim, format, firstMip, mipCount, firstSlice, sliceCount);
cemuLog_logDebug(LogType::Force, "not implemented");
return nullptr;
} }
void LatteTextureMtl::AllocateOnHost() void LatteTextureMtl::AllocateOnHost()

View File

@ -10,9 +10,12 @@ class LatteTextureMtl : public LatteTexture
public: 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, 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); uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth);
~LatteTextureMtl(); ~LatteTextureMtl();
MTL::Texture* GetTexture() const {
return m_texture;
}
void AllocateOnHost() override; void AllocateOnHost() override;
protected: protected:

View File

@ -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();
}

View File

@ -0,0 +1,21 @@
#pragma once
#include <Metal/Metal.hpp>
#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;
};