gl_rasterizer_cache: Use SurfaceParams as a key for surface caching.

This commit is contained in:
bunnei 2018-06-26 14:59:45 -04:00
parent 6a28a66832
commit c7c379bd19
2 changed files with 71 additions and 42 deletions

View File

@ -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) {

View File

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