mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-12-24 09:20:58 +01:00
gl_rasterizer_cache: Use SurfaceParams as a key for surface caching.
This commit is contained in:
parent
6a28a66832
commit
c7c379bd19
2 changed files with 71 additions and 42 deletions
|
@ -29,29 +29,37 @@ struct FormatTuple {
|
||||||
bool compressed;
|
bool compressed;
|
||||||
};
|
};
|
||||||
|
|
||||||
SurfaceParams::SurfaceParams(const Tegra::Texture::FullTextureInfo& config)
|
/*static*/ SurfaceParams SurfaceParams::CreateForTexture(
|
||||||
: addr(config.tic.Address()), is_tiled(config.tic.IsTiled()),
|
const Tegra::Texture::FullTextureInfo& config) {
|
||||||
block_height(is_tiled ? config.tic.BlockHeight() : 0),
|
|
||||||
pixel_format(PixelFormatFromTextureFormat(config.tic.format)),
|
|
||||||
component_type(ComponentTypeFromTexture(config.tic.r_type.Value())),
|
|
||||||
type(GetFormatType(pixel_format)),
|
|
||||||
width(Common::AlignUp(config.tic.Width(), GetCompressionFactor(pixel_format))),
|
|
||||||
height(Common::AlignUp(config.tic.Height(), GetCompressionFactor(pixel_format))),
|
|
||||||
size_in_bytes(SizeInBytes()) {
|
|
||||||
|
|
||||||
// TODO(Subv): Different types per component are not supported.
|
SurfaceParams params{};
|
||||||
ASSERT(config.tic.r_type.Value() == config.tic.g_type.Value() &&
|
params.addr = config.tic.Address();
|
||||||
config.tic.r_type.Value() == config.tic.b_type.Value() &&
|
params.is_tiled = config.tic.IsTiled();
|
||||||
config.tic.r_type.Value() == config.tic.a_type.Value());
|
params.block_height = params.is_tiled ? config.tic.BlockHeight() : 0,
|
||||||
|
params.pixel_format = PixelFormatFromTextureFormat(config.tic.format);
|
||||||
|
params.component_type = ComponentTypeFromTexture(config.tic.r_type.Value());
|
||||||
|
params.type = GetFormatType(params.pixel_format);
|
||||||
|
params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format));
|
||||||
|
params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format));
|
||||||
|
params.size_in_bytes = params.SizeInBytes();
|
||||||
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceParams::SurfaceParams(const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config)
|
/*static*/ SurfaceParams SurfaceParams::CreateForFramebuffer(
|
||||||
: addr(config.Address()), is_tiled(true),
|
const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config) {
|
||||||
block_height(Tegra::Texture::TICEntry::DefaultBlockHeight),
|
|
||||||
pixel_format(PixelFormatFromRenderTargetFormat(config.format)),
|
SurfaceParams params{};
|
||||||
component_type(ComponentTypeFromRenderTarget(config.format)),
|
params.addr = config.Address();
|
||||||
type(GetFormatType(pixel_format)), width(config.width), height(config.height),
|
params.is_tiled = true;
|
||||||
size_in_bytes(SizeInBytes()) {}
|
params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight;
|
||||||
|
params.pixel_format = PixelFormatFromRenderTargetFormat(config.format);
|
||||||
|
params.component_type = ComponentTypeFromRenderTarget(config.format);
|
||||||
|
params.type = GetFormatType(params.pixel_format);
|
||||||
|
params.width = config.width;
|
||||||
|
params.height = config.height;
|
||||||
|
params.size_in_bytes = params.SizeInBytes();
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{
|
static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{
|
||||||
{GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false}, // ABGR8
|
{GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false}, // ABGR8
|
||||||
|
@ -358,7 +366,7 @@ RasterizerCacheOpenGL::RasterizerCacheOpenGL() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextureInfo& config) {
|
Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextureInfo& config) {
|
||||||
return GetSurface(SurfaceParams(config));
|
return GetSurface(SurfaceParams::CreateForTexture(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
|
SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
|
||||||
|
@ -369,8 +377,8 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
|
||||||
NGLOG_WARNING(Render_OpenGL, "hard-coded for render target 0!");
|
NGLOG_WARNING(Render_OpenGL, "hard-coded for render target 0!");
|
||||||
|
|
||||||
// get color and depth surfaces
|
// get color and depth surfaces
|
||||||
SurfaceParams color_params(regs.rt[0]);
|
const SurfaceParams color_params{SurfaceParams::CreateForFramebuffer(regs.rt[0])};
|
||||||
SurfaceParams depth_params = color_params;
|
const SurfaceParams depth_params{color_params};
|
||||||
|
|
||||||
ASSERT_MSG(!using_depth_fb, "depth buffer is unimplemented");
|
ASSERT_MSG(!using_depth_fb, "depth buffer is unimplemented");
|
||||||
|
|
||||||
|
@ -423,13 +431,14 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for an exact match in existing surfaces
|
// Check for an exact match in existing surfaces
|
||||||
auto search = surface_cache.find(params.addr);
|
const auto& surface_key{SurfaceKey::Create(params)};
|
||||||
|
const auto& search{surface_cache.find(surface_key)};
|
||||||
Surface surface;
|
Surface surface;
|
||||||
if (search != surface_cache.end()) {
|
if (search != surface_cache.end()) {
|
||||||
surface = search->second;
|
surface = search->second;
|
||||||
} else {
|
} else {
|
||||||
surface = std::make_shared<CachedSurface>(params);
|
surface = std::make_shared<CachedSurface>(params);
|
||||||
surface_cache[params.addr] = surface;
|
surface_cache[surface_key] = surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadSurface(surface);
|
LoadSurface(surface);
|
||||||
|
@ -439,10 +448,10 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) {
|
||||||
|
|
||||||
Surface RasterizerCacheOpenGL::TryFindFramebufferSurface(VAddr cpu_addr) const {
|
Surface RasterizerCacheOpenGL::TryFindFramebufferSurface(VAddr cpu_addr) const {
|
||||||
// Tries to find the GPU address of a framebuffer based on the CPU address. This is because
|
// Tries to find the GPU address of a framebuffer based on the CPU address. This is because
|
||||||
// final output framebuffers are specified by CPU address, but internally our GPU cache uses GPU
|
// final output framebuffers are specified by CPU address, but internally our GPU cache uses
|
||||||
// addresses. We iterate through all cached framebuffers, and compare their starting CPU address
|
// GPU addresses. We iterate through all cached framebuffers, and compare their starting CPU
|
||||||
// to the one provided. This is obviously not great, and won't work if the framebuffer overlaps
|
// address to the one provided. This is obviously not great, and won't work if the
|
||||||
// surfaces.
|
// framebuffer overlaps surfaces.
|
||||||
|
|
||||||
std::vector<Surface> surfaces;
|
std::vector<Surface> surfaces;
|
||||||
for (const auto& surface : surface_cache) {
|
for (const auto& surface : surface_cache) {
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "common/hash.h"
|
||||||
#include "common/math_util.h"
|
#include "common/math_util.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||||
|
@ -253,22 +254,41 @@ struct SurfaceParams {
|
||||||
GetFormatBpp(pixel_format) / CHAR_BIT;
|
GetFormatBpp(pixel_format) / CHAR_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceParams(const Tegra::Texture::FullTextureInfo& config);
|
|
||||||
SurfaceParams(const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config);
|
|
||||||
|
|
||||||
VAddr GetCpuAddr() const;
|
VAddr GetCpuAddr() const;
|
||||||
|
|
||||||
const Tegra::GPUVAddr addr;
|
static SurfaceParams CreateForTexture(const Tegra::Texture::FullTextureInfo& config);
|
||||||
const bool is_tiled;
|
|
||||||
const u32 block_height;
|
static SurfaceParams CreateForFramebuffer(
|
||||||
const PixelFormat pixel_format;
|
const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config);
|
||||||
const ComponentType component_type;
|
|
||||||
const SurfaceType type;
|
Tegra::GPUVAddr addr;
|
||||||
const u32 width;
|
bool is_tiled;
|
||||||
const u32 height;
|
u32 block_height;
|
||||||
const size_t size_in_bytes;
|
PixelFormat pixel_format;
|
||||||
|
ComponentType component_type;
|
||||||
|
SurfaceType type;
|
||||||
|
u32 width;
|
||||||
|
u32 height;
|
||||||
|
size_t size_in_bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SurfaceKey : Common::HashableStruct<SurfaceParams> {
|
||||||
|
static SurfaceKey Create(const SurfaceParams& params) {
|
||||||
|
SurfaceKey res;
|
||||||
|
res.state = params;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template <>
|
||||||
|
struct hash<SurfaceKey> {
|
||||||
|
size_t operator()(const SurfaceKey& k) const {
|
||||||
|
return k.Hash();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
class CachedSurface final {
|
class CachedSurface final {
|
||||||
public:
|
public:
|
||||||
CachedSurface(const SurfaceParams& params);
|
CachedSurface(const SurfaceParams& params);
|
||||||
|
@ -317,7 +337,7 @@ public:
|
||||||
private:
|
private:
|
||||||
Surface GetSurface(const SurfaceParams& params);
|
Surface GetSurface(const SurfaceParams& params);
|
||||||
|
|
||||||
std::map<Tegra::GPUVAddr, Surface> surface_cache;
|
std::unordered_map<SurfaceKey, Surface> surface_cache;
|
||||||
OGLFramebuffer read_framebuffer;
|
OGLFramebuffer read_framebuffer;
|
||||||
OGLFramebuffer draw_framebuffer;
|
OGLFramebuffer draw_framebuffer;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue