Skip to content

Commit

Permalink
Latte: Enable framebuffer size optimization if gfx packs are aware
Browse files Browse the repository at this point in the history
Graphic packs can now set "colorbufferOptimizationAware = true" to enable the framebuffer texture size optimization added in cemu-project#706.
If no graphic packs with texture rules are active then the optimization is enabled automatically now.
  • Loading branch information
Exzap committed Mar 25, 2024
1 parent 731713d commit bd6bb2c
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 13 deletions.
4 changes: 4 additions & 0 deletions src/Cafe/GraphicPack/GraphicPack2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
m_enabled = m_default_enabled;
}

auto option_allowRendertargetSizeOptimization = rules.FindOption("colorbufferOptimizationAware");
if (option_allowRendertargetSizeOptimization)
m_allowRendertargetSizeOptimization = boost::iequals(*option_allowRendertargetSizeOptimization, "true") || boost::iequals(*option_allowRendertargetSizeOptimization, "1");

auto option_vendorFilter = rules.FindOption("vendorFilter");
if (option_vendorFilter)
{
Expand Down
3 changes: 3 additions & 0 deletions src/Cafe/GraphicPack/GraphicPack2.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ class GraphicPack2
const std::string& GetVirtualPath() const { return m_virtualPath; } // returns the path in the gfx tree hierarchy
const std::string& GetDescription() const { return m_description; }
bool IsDefaultEnabled() const { return m_default_enabled; }
bool AllowRendertargetSizeOptimization() const { return m_allowRendertargetSizeOptimization; }

void SetEnabled(bool state) { m_enabled = state; }

Expand Down Expand Up @@ -217,6 +218,8 @@ class GraphicPack2

bool m_default_enabled = false;

bool m_allowRendertargetSizeOptimization = false; // gfx pack supports framebuffers with non-padded sizes, which is an optional optimization introduced with Cemu 2.0-74

// filter
std::optional<RendererAPI> m_renderer_api;
std::optional<GfxVendor> m_gfx_vendor;
Expand Down
2 changes: 2 additions & 0 deletions src/Cafe/HW/Latte/Core/Latte.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ struct LatteGPUState_t
// context control
uint32 contextControl0;
uint32 contextControl1;
// optional features
bool allowFramebufferSizeOptimization{false}; // allow using scissor box as size hint to determine non-padded rendertarget size
// draw context
struct
{
Expand Down
21 changes: 11 additions & 10 deletions src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,14 +267,15 @@ LatteTextureView* LatteMRT::GetColorAttachmentTexture(uint32 index, bool createN

// colorbuffer width/height has to be padded to 8/32 alignment but the actual resolution might be smaller
// use the scissor box as a clue to figure out the original resolution if possible
#if 0
uint32 scissorBoxWidth = LatteGPUState.contextNew.PA_SC_GENERIC_SCISSOR_BR.get_BR_X();
uint32 scissorBoxHeight = LatteGPUState.contextNew.PA_SC_GENERIC_SCISSOR_BR.get_BR_Y();
if (((scissorBoxWidth + 7) & ~7) == colorBufferWidth)
colorBufferWidth = scissorBoxWidth;
if (((colorBufferHeight + 31) & ~31) == colorBufferHeight)
colorBufferHeight = scissorBoxHeight;
#endif
if(LatteGPUState.allowFramebufferSizeOptimization)
{
uint32 scissorBoxWidth = LatteGPUState.contextNew.PA_SC_GENERIC_SCISSOR_BR.get_BR_X();
uint32 scissorBoxHeight = LatteGPUState.contextNew.PA_SC_GENERIC_SCISSOR_BR.get_BR_Y();
if (((scissorBoxWidth + 7) & ~7) == colorBufferWidth)
colorBufferWidth = scissorBoxWidth;
if (((colorBufferHeight + 31) & ~31) == colorBufferHeight)
colorBufferHeight = scissorBoxHeight;
}

// log resolution changes if the above heuristic takes effect
// this is useful to find resolutions which need to be updated in gfx pack texture rules
Expand Down Expand Up @@ -303,7 +304,7 @@ LatteTextureView* LatteMRT::GetColorAttachmentTexture(uint32 index, bool createN
if (colorBufferView == nullptr)
{
// create color buffer view
colorBufferView = LatteTexture_CreateMapping(colorBufferPhysMem, 0, colorBufferWidth, colorBufferHeight, (viewFirstSlice + viewNumSlices), colorBufferPitch, colorBufferTileMode, colorBufferSwizzle>>8, viewFirstMip, 1, viewFirstSlice, viewNumSlices, (Latte::E_GX2SURFFMT)colorBufferFormat, (viewFirstSlice + viewNumSlices)>1? Latte::E_DIM::DIM_2D_ARRAY: Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, false);
colorBufferView = LatteTexture_CreateMapping(colorBufferPhysMem, 0, colorBufferWidth, colorBufferHeight, (viewFirstSlice + viewNumSlices), colorBufferPitch, colorBufferTileMode, colorBufferSwizzle>>8, viewFirstMip, 1, viewFirstSlice, viewNumSlices, (Latte::E_GX2SURFFMT)colorBufferFormat, (viewFirstSlice + viewNumSlices)>1? Latte::E_DIM::DIM_2D_ARRAY: Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, false, true);
LatteGPUState.repeatTextureInitialization = true;
checkForTextureChanges = false;
}
Expand Down Expand Up @@ -582,7 +583,7 @@ bool LatteMRT::UpdateCurrentFBO()
if (!depthBufferView)
{
// create new depth buffer view and if it doesn't exist then also create the texture
depthBufferView = LatteTexture_CreateMapping(depthBufferPhysMem, 0, depthBufferWidth, depthBufferHeight, depthBufferViewFirstSlice+1, depthBufferPitch, depthBufferTileMode, depthBufferSwizzle, 0, 1, depthBufferViewFirstSlice, 1, depthBufferFormat, depthBufferViewFirstSlice > 0 ? Latte::E_DIM::DIM_2D_ARRAY : Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, true);
depthBufferView = LatteTexture_CreateMapping(depthBufferPhysMem, 0, depthBufferWidth, depthBufferHeight, depthBufferViewFirstSlice+1, depthBufferPitch, depthBufferTileMode, depthBufferSwizzle, 0, 1, depthBufferViewFirstSlice, 1, depthBufferFormat, depthBufferViewFirstSlice > 0 ? Latte::E_DIM::DIM_2D_ARRAY : Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, true, true);
LatteGPUState.repeatTextureInitialization = true;
}
else
Expand Down
7 changes: 4 additions & 3 deletions src/Cafe/HW/Latte/Core/LatteTexture.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "Cafe/HW/Latte/Core/Latte.h"
#include "Cafe/HW/Latte/Core/LatteDraw.h"
#include "Cafe/HW/Latte/Core/LatteShader.h"
#include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h"
#include "Cafe/HW/Latte/Core/LatteTexture.h"
Expand All @@ -9,6 +8,8 @@

#include "Cafe/GraphicPack/GraphicPack2.h"

#include <boost/container/small_vector.hpp>

struct TexMemOccupancyEntry
{
uint32 addrStart;
Expand Down Expand Up @@ -963,7 +964,7 @@ void LatteTexture_RecreateTextureWithDifferentMipSliceCount(LatteTexture* textur
}

// create new texture representation
// if allowCreateNewDataTexture is true, a new texture will be created if necessary. If it is false, only existing textures may be used, except if a data-compatible version of the requested texture already exists and it's not view compatible
// if allowCreateNewDataTexture is true, a new texture will be created if necessary. If it is false, only existing textures may be used, except if a data-compatible version of the requested texture already exists and it's not view compatible (todo - we should differentiate between Latte compatible views and renderer compatible)
// the returned view will map to the provided mip and slice range within the created texture, this is to match the behavior of lookupSliceEx
LatteTextureView* LatteTexture_CreateMapping(MPTR physAddr, MPTR physMipAddr, sint32 width, sint32 height, sint32 depth, sint32 pitch, Latte::E_HWTILEMODE tileMode, uint32 swizzle, sint32 firstMip, sint32 numMip, sint32 firstSlice, sint32 numSlice, Latte::E_GX2SURFFMT format, Latte::E_DIM dimBase, Latte::E_DIM dimView, bool isDepth, bool allowCreateNewDataTexture)
{
Expand All @@ -980,7 +981,7 @@ LatteTextureView* LatteTexture_CreateMapping(MPTR physAddr, MPTR physMipAddr, si
// todo, depth and numSlice are redundant

sint32 sliceCount = firstSlice + numSlice;
std::vector<LatteTexture*> list_overlappingTextures;
boost::container::small_vector<LatteTexture*, 16> list_overlappingTextures;
for (sint32 sliceIndex = 0; sliceIndex < sliceCount; sliceIndex++)
{
sint32 mipIndex = 0;
Expand Down
17 changes: 17 additions & 0 deletions src/Cafe/HW/Latte/Core/LatteThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,23 @@ int Latte_ThreadEntry()

// before doing anything with game specific shaders, we need to wait for graphic packs to finish loading
GraphicPack2::WaitUntilReady();
// if legacy packs are enabled we cannot use the colorbuffer resolution optimization
LatteGPUState.allowFramebufferSizeOptimization = true;
for(auto& pack : GraphicPack2::GetActiveGraphicPacks())
{
if(pack->AllowRendertargetSizeOptimization())
continue;
for(auto& rule : pack->GetTextureRules())
{
if(rule.filter_settings.width >= 0 || rule.filter_settings.height >= 0 || rule.filter_settings.depth >= 0 ||
rule.overwrite_settings.width >= 0 || rule.overwrite_settings.height >= 0 || rule.overwrite_settings.depth >= 0)
{
LatteGPUState.allowFramebufferSizeOptimization = false;
cemuLog_log(LogType::Force, "Graphic pack {} prevents rendertarget size optimization.", pack->GetName());
break;
}
}
}
// load disk shader cache
LatteShaderCache_Load();
// init registers
Expand Down

0 comments on commit bd6bb2c

Please sign in to comment.