rasterizer_cache: Shorten filenames and general cleanup

* AllocateSurfaceTexture now takes the PixelFormat directly as FormatTuple is an OpenGL struct and will be moved there
This commit is contained in:
emufan4568
2022-09-06 22:15:39 +03:00
committed by GPUCode
parent db7cdb741c
commit 1963b649e8
14 changed files with 195 additions and 160 deletions

View File

@ -32,9 +32,9 @@ add_library(video_core STATIC
rasterizer_cache/pixel_format.h
rasterizer_cache/rasterizer_cache.cpp
rasterizer_cache/rasterizer_cache.h
rasterizer_cache/rasterizer_cache_types.h
rasterizer_cache/rasterizer_cache_utils.cpp
rasterizer_cache/rasterizer_cache_utils.h
rasterizer_cache/types.h
rasterizer_cache/utils.cpp
rasterizer_cache/utils.h
rasterizer_cache/surface_params.cpp
rasterizer_cache/surface_params.h
rasterizer_cache/texture_runtime.cpp

View File

@ -35,9 +35,9 @@ static Aspect ToAspect(SurfaceType type) {
CachedSurface::~CachedSurface() {
if (texture.handle) {
auto tag = is_custom ? HostTextureTag{GetFormatTuple(PixelFormat::RGBA8),
auto tag = is_custom ? HostTextureTag{PixelFormat::RGBA8,
custom_tex_info.width, custom_tex_info.height}
: HostTextureTag{GetFormatTuple(pixel_format), GetScaledWidth(),
: HostTextureTag{pixel_format, GetScaledWidth(),
GetScaledHeight()};
owner.host_texture_recycler.emplace(tag, std::move(texture));
@ -297,7 +297,6 @@ void CachedSurface::UploadGLTexture(Common::Rectangle<u32> rect) {
GLint y0 = static_cast<GLint>(rect.bottom);
std::size_t buffer_offset = (y0 * stride + x0) * GetBytesPerPixel(pixel_format);
const FormatTuple& tuple = GetFormatTuple(pixel_format);
GLuint target_tex = texture.handle;
// If not 1x scale, create 1x texture that we will blit from to replace texture subrect in
@ -308,11 +307,10 @@ void CachedSurface::UploadGLTexture(Common::Rectangle<u32> rect) {
y0 = 0;
if (is_custom) {
const auto& tuple = GetFormatTuple(PixelFormat::RGBA8);
unscaled_tex =
owner.AllocateSurfaceTexture(tuple, custom_tex_info.width, custom_tex_info.height);
owner.AllocateSurfaceTexture(PixelFormat::RGBA8, custom_tex_info.width, custom_tex_info.height);
} else {
unscaled_tex = owner.AllocateSurfaceTexture(tuple, rect.GetWidth(), rect.GetHeight());
unscaled_tex = owner.AllocateSurfaceTexture(pixel_format, rect.GetWidth(), rect.GetHeight());
}
target_tex = unscaled_tex.handle;
@ -324,11 +322,13 @@ void CachedSurface::UploadGLTexture(Common::Rectangle<u32> rect) {
cur_state.texture_units[0].texture_2d = target_tex;
cur_state.Apply();
const FormatTuple& tuple = GetFormatTuple(pixel_format);
// Ensure no bad interactions with GL_UNPACK_ALIGNMENT
ASSERT(stride * GetBytesPerPixel(pixel_format) % 4 == 0);
if (is_custom) {
if (res_scale == 1) {
texture = owner.AllocateSurfaceTexture(GetFormatTuple(PixelFormat::RGBA8),
texture = owner.AllocateSurfaceTexture(PixelFormat::RGBA8,
custom_tex_info.width, custom_tex_info.height);
cur_state.texture_units[0].texture_2d = texture.handle;
cur_state.Apply();
@ -344,6 +344,7 @@ void CachedSurface::UploadGLTexture(Common::Rectangle<u32> rect) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(stride));
glActiveTexture(GL_TEXTURE0);
glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, static_cast<GLsizei>(rect.GetWidth()),
static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
&gl_buffer[buffer_offset]);
@ -395,14 +396,14 @@ void CachedSurface::DownloadGLTexture(const Common::Rectangle<u32>& rect) {
OpenGLState prev_state = state;
SCOPE_EXIT({ prev_state.Apply(); });
const FormatTuple& tuple = GetFormatTuple(pixel_format);
// Ensure no bad interactions with GL_PACK_ALIGNMENT
ASSERT(stride * GetBytesPerPixel(pixel_format) % 4 == 0);
glPixelStorei(GL_PACK_ROW_LENGTH, static_cast<GLint>(stride));
const std::size_t buffer_offset =
(rect.bottom * stride + rect.left) * GetBytesPerPixel(pixel_format);
const FormatTuple& tuple = GetFormatTuple(pixel_format);
// If not 1x scale, blit scaled texture to a new 1x texture and use that to flush
const Aspect aspect = ToAspect(type);
if (res_scale != 1) {
@ -413,7 +414,7 @@ void CachedSurface::DownloadGLTexture(const Common::Rectangle<u32>& rect) {
scaled_rect.bottom *= res_scale;
const Common::Rectangle<u32> unscaled_tex_rect{0, rect.GetHeight(), rect.GetWidth(), 0};
auto unscaled_tex = owner.AllocateSurfaceTexture(tuple, rect.GetWidth(), rect.GetHeight());
auto unscaled_tex = owner.AllocateSurfaceTexture(pixel_format, rect.GetWidth(), rect.GetHeight());
// Blit scaled texture to the unscaled one
runtime.BlitTextures(texture, {aspect, scaled_rect}, unscaled_tex,
{aspect, unscaled_tex_rect});

View File

@ -11,6 +11,8 @@
namespace OpenGL {
using SurfaceRegions = boost::icl::interval_set<PAddr, std::less, SurfaceInterval>;
/**
* A watcher that notifies whether a cached surface has been changed. This is useful for caching
* surface collection objects, including texture cube and mipmap.

View File

@ -12,7 +12,7 @@ namespace OpenGL {
constexpr u32 PIXEL_FORMAT_COUNT = 18;
enum class PixelFormat : u8 {
enum class PixelFormat : u32 {
// First 5 formats are shared between textures and color buffers
RGBA8 = 0,
RGB8 = 1,

View File

@ -35,50 +35,15 @@ static Aspect ToAspect(SurfaceType type) {
return Aspect::Color;
}
static ClearValue ToClearValue(Aspect aspect, PixelFormat format, const u8* fill_data) {
ClearValue result{};
switch (aspect) {
case Aspect::Color: {
Pica::Texture::TextureInfo tex_info{};
tex_info.format = static_cast<Pica::TexturingRegs::TextureFormat>(format);
Common::Vec4<u8> color = Pica::Texture::LookupTexture(fill_data, 0, 0, tex_info);
result.color = color / 255.f;
break;
}
case Aspect::Depth: {
u32 depth_uint = 0;
if (format == PixelFormat::D16) {
std::memcpy(&depth_uint, fill_data, 2);
result.depth = depth_uint / 65535.0f; // 2^16 - 1
} else if (format == PixelFormat::D24) {
std::memcpy(&depth_uint, fill_data, 3);
result.depth = depth_uint / 16777215.0f; // 2^24 - 1
}
break;
}
case Aspect::DepthStencil: {
u32 clear_value_uint;
std::memcpy(&clear_value_uint, fill_data, sizeof(u32));
result.depth = (clear_value_uint & 0xFFFFFF) / 16777215.0f; // 2^24 - 1
result.stencil = (clear_value_uint >> 24);
break;
}
}
return result;
}
template <typename Map, typename Interval>
static constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
return boost::make_iterator_range(map.equal_range(interval));
}
// Allocate an uninitialized texture of appropriate size and format for the surface
OGLTexture RasterizerCacheOpenGL::AllocateSurfaceTexture(const FormatTuple& tuple, u32 width,
u32 height) {
auto recycled_tex = host_texture_recycler.find({tuple, width, height});
OGLTexture RasterizerCacheOpenGL::AllocateSurfaceTexture(PixelFormat format, u32 width, u32 height) {
const FormatTuple& tuple = GetFormatTuple(format);
auto recycled_tex = host_texture_recycler.find({format, width, height});
if (recycled_tex != host_texture_recycler.end()) {
OGLTexture texture = std::move(recycled_tex->second);
host_texture_recycler.erase(recycled_tex);
@ -101,11 +66,14 @@ void RasterizerCacheOpenGL::CopySurface(const Surface& src_surface, const Surfac
MICROPROFILE_SCOPE(RasterizerCache_CopySurface);
SurfaceParams subrect_params = dst_surface->FromInterval(copy_interval);
ASSERT(subrect_params.GetInterval() == copy_interval);
ASSERT(src_surface != dst_surface);
ASSERT(subrect_params.GetInterval() == copy_interval && src_surface != dst_surface);
// This is only called when CanCopy is true, no need to run checks here
const Aspect aspect = ToAspect(dst_surface->type);
const Subresource dst_subresource = {
.aspect = aspect,
.region = dst_surface->GetScaledSubRect(subrect_params)
};
if (src_surface->type == SurfaceType::Fill) {
// FillSurface needs a 4 bytes buffer
const u32 fill_offset =
@ -117,20 +85,21 @@ void RasterizerCacheOpenGL::CopySurface(const Surface& src_surface, const Surfac
fill_buffer[i] = src_surface->fill_data[fill_buff_pos++ % src_surface->fill_size];
}
const auto clear_rect = dst_surface->GetScaledSubRect(subrect_params);
const ClearValue clear_value =
ToClearValue(aspect, dst_surface->pixel_format, fill_buffer.data());
MakeClearValue(aspect, dst_surface->pixel_format, fill_buffer.data());
runtime.ClearTexture(dst_surface->texture, {aspect, clear_rect}, clear_value);
runtime.ClearTexture(dst_surface->texture, dst_subresource, clear_value);
return;
}
if (src_surface->CanSubRect(subrect_params)) {
const auto src_rect = src_surface->GetScaledSubRect(subrect_params);
const auto dst_rect = dst_surface->GetScaledSubRect(subrect_params);
const Subresource src_subresource = {
.aspect = aspect,
.region = src_surface->GetScaledSubRect(subrect_params)
};
runtime.BlitTextures(src_surface->texture, {aspect, src_rect}, dst_surface->texture,
{aspect, dst_rect});
runtime.BlitTextures(src_surface->texture, src_subresource, dst_surface->texture,
dst_subresource);
return;
}
@ -268,8 +237,18 @@ bool RasterizerCacheOpenGL::BlitSurfaces(const Surface& src_surface,
dst_surface->InvalidateAllWatcher();
const Aspect aspect = ToAspect(src_surface->type);
return runtime.BlitTextures(src_surface->texture, {aspect, src_rect}, dst_surface->texture,
{aspect, dst_rect});
const Subresource src_subresource = {
.aspect = aspect,
.region = src_rect
};
const Subresource dst_subresource = {
.aspect = aspect,
.region = dst_rect
};
return runtime.BlitTextures(src_surface->texture, src_subresource,
dst_surface->texture, dst_subresource);
}
return false;
@ -489,12 +468,19 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Pica::Texture::TextureInf
}
if (!surface->is_custom && texture_filterer->IsNull()) {
const auto src_rect = level_surface->GetScaledRect();
const auto dst_rect = surface_params.GetScaledRect();
const Aspect aspect = ToAspect(surface->type);
const Subresource src_subresource = {
.aspect = aspect,
.region = level_surface->GetScaledRect()
};
runtime.BlitTextures(level_surface->texture, {aspect, src_rect},
surface->texture, {aspect, dst_rect, level});
const Subresource dst_subresource = {
.aspect = aspect,
.region = surface_params.GetScaledRect()
};
runtime.BlitTextures(level_surface->texture, src_subresource,
surface->texture, dst_subresource);
}
watcher->Validate();
@ -571,11 +557,19 @@ const CachedTextureCube& RasterizerCacheOpenGL::GetTextureCube(const TextureCube
ValidateSurface(surface, surface->addr, surface->size);
}
const auto src_rect = surface->GetScaledRect();
const auto dst_rect = Common::Rectangle<u32>{0, scaled_size, scaled_size, 0};
const Aspect aspect = ToAspect(surface->type);
runtime.BlitTextures(surface->texture, {aspect, src_rect}, cube.texture,
{aspect, dst_rect, 0, static_cast<u32>(i)}, true);
const Subresource src_subresource = {
.aspect = aspect,
.region = surface->GetScaledRect()
};
const Subresource dst_subresource = {
.aspect = aspect,
.region = Common::Rectangle<u32>{0, scaled_size, scaled_size, 0}
};
runtime.BlitTextures(surface->texture, src_subresource,
cube.texture, dst_subresource);
face.watcher->Validate();
}
@ -864,7 +858,6 @@ bool RasterizerCacheOpenGL::ValidateByReinterpretation(const Surface& surface,
const SurfaceInterval& interval) {
const PixelFormat dst_format = surface->pixel_format;
const SurfaceType type = GetFormatType(dst_format);
const FormatTuple& tuple = GetFormatTuple(dst_format);
for (auto& reinterpreter :
format_reinterpreter->GetPossibleReinterpretations(surface->pixel_format)) {
@ -888,7 +881,7 @@ bool RasterizerCacheOpenGL::ValidateByReinterpretation(const Surface& surface,
const u32 height = dest_rect.GetWidth() / resolution_scale_factor;
const Common::Rectangle<u32> tmp_rect{0, width, height, 0};
OGLTexture tmp_tex = AllocateSurfaceTexture(tuple, height, width);
OGLTexture tmp_tex = AllocateSurfaceTexture(dst_format, height, width);
reinterpreter->Reinterpret(reinterpret_surface->texture, src_rect, tmp_tex,
tmp_rect);
@ -896,8 +889,18 @@ bool RasterizerCacheOpenGL::ValidateByReinterpretation(const Surface& surface,
type)) {
const Aspect aspect = ToAspect(type);
runtime.BlitTextures(tmp_tex, {aspect, tmp_rect}, surface->texture,
{aspect, dest_rect});
const Subresource src_subresource = {
.aspect = aspect,
.region = tmp_rect
};
const Subresource dst_subresource = {
.aspect = aspect,
.region = dest_rect
};
runtime.BlitTextures(tmp_tex, src_subresource,
surface->texture, dst_subresource);
}
} else {
reinterpreter->Reinterpret(reinterpret_surface->texture, src_rect, surface->texture,
@ -1042,9 +1045,8 @@ Surface RasterizerCacheOpenGL::CreateSurface(const SurfaceParams& params) {
surface->invalid_regions.insert(surface->GetInterval());
// Allocate surface texture
const FormatTuple& tuple = GetFormatTuple(surface->pixel_format);
surface->texture =
AllocateSurfaceTexture(tuple, surface->GetScaledWidth(), surface->GetScaledHeight());
AllocateSurfaceTexture(params.pixel_format, surface->GetScaledWidth(), surface->GetScaledHeight());
return surface;
}

View File

@ -5,7 +5,7 @@
#pragma once
#include <unordered_map>
#include "video_core/rasterizer_cache/cached_surface.h"
#include "video_core/rasterizer_cache/rasterizer_cache_utils.h"
#include "video_core/rasterizer_cache/utils.h"
#include "video_core/rasterizer_cache/surface_params.h"
#include "video_core/texture/texture_decode.h"
@ -15,10 +15,27 @@ class RasterizerAccelerated;
namespace OpenGL {
// Declare rasterizer interval types
using SurfaceSet = std::set<Surface>;
using SurfaceMap =
boost::icl::interval_map<PAddr, Surface, boost::icl::partial_absorber, std::less,
boost::icl::inplace_plus, boost::icl::inter_section, SurfaceInterval>;
using SurfaceCache =
boost::icl::interval_map<PAddr, SurfaceSet, boost::icl::partial_absorber, std::less,
boost::icl::inplace_plus, boost::icl::inter_section, SurfaceInterval>;
static_assert(std::is_same<SurfaceRegions::interval_type, SurfaceCache::interval_type>() &&
std::is_same<SurfaceMap::interval_type, SurfaceCache::interval_type>(),
"Incorrect interval types");
using SurfaceRect_Tuple = std::tuple<Surface, Common::Rectangle<u32>>;
using SurfaceSurfaceRect_Tuple = std::tuple<Surface, Surface, Common::Rectangle<u32>>;
using PageMap = boost::icl::interval_map<u32, int>;
enum class ScaleMatch {
Exact, // only accept same res scale
Upscale, // only allow higher scale than params
Ignore // accept every scaled res
Exact, // Only accept same res scale
Upscale, // Only allow higher scale than params
Ignore // Accept every scaled res
};
class TextureDownloaderES;
@ -123,7 +140,7 @@ private:
std::recursive_mutex mutex;
public:
OGLTexture AllocateSurfaceTexture(const FormatTuple& format_tuple, u32 width, u32 height);
OGLTexture AllocateSurfaceTexture(PixelFormat format, u32 width, u32 height);
std::unique_ptr<TextureFilterer> texture_filterer;
std::unique_ptr<FormatReinterpreterOpenGL> format_reinterpreter;

View File

@ -1,38 +0,0 @@
// Copyright 2022 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <set>
#include <tuple>
#include <boost/icl/interval_map.hpp>
#include <boost/icl/interval_set.hpp>
#include "common/common_types.h"
#include "common/math_util.h"
namespace OpenGL {
class CachedSurface;
using Surface = std::shared_ptr<CachedSurface>;
// Declare rasterizer interval types
using SurfaceInterval = boost::icl::right_open_interval<PAddr>;
using SurfaceSet = std::set<Surface>;
using SurfaceRegions = boost::icl::interval_set<PAddr, std::less, SurfaceInterval>;
using SurfaceMap =
boost::icl::interval_map<PAddr, Surface, boost::icl::partial_absorber, std::less,
boost::icl::inplace_plus, boost::icl::inter_section, SurfaceInterval>;
using SurfaceCache =
boost::icl::interval_map<PAddr, SurfaceSet, boost::icl::partial_absorber, std::less,
boost::icl::inplace_plus, boost::icl::inter_section, SurfaceInterval>;
static_assert(std::is_same<SurfaceRegions::interval_type, SurfaceCache::interval_type>() &&
std::is_same<SurfaceMap::interval_type, SurfaceCache::interval_type>(),
"Incorrect interval types");
using SurfaceRect_Tuple = std::tuple<Surface, Common::Rectangle<u32>>;
using SurfaceSurfaceRect_Tuple = std::tuple<Surface, Surface, Common::Rectangle<u32>>;
using PageMap = boost::icl::interval_map<u32, int>;
} // namespace OpenGL

View File

@ -6,11 +6,18 @@
#include <array>
#include <climits>
#include <boost/icl/interval_map.hpp>
#include <boost/icl/interval_set.hpp>
#include "common/math_util.h"
#include "video_core/rasterizer_cache/pixel_format.h"
#include "video_core/rasterizer_cache/rasterizer_cache_types.h"
namespace OpenGL {
class CachedSurface;
using Surface = std::shared_ptr<CachedSurface>;
using SurfaceInterval = boost::icl::right_open_interval<PAddr>;
class SurfaceParams {
public:
// Surface match traits

View File

@ -3,7 +3,7 @@
// Refer to the license.txt file included.
#include "common/scope_exit.h"
#include "video_core/rasterizer_cache/rasterizer_cache_utils.h"
#include "video_core/rasterizer_cache/utils.h"
#include "video_core/rasterizer_cache/texture_runtime.h"
#include "video_core/renderer_opengl/gl_state.h"

View File

@ -3,34 +3,11 @@
// Refer to the license.txt file included.
#pragma once
#include "common/math_util.h"
#include "common/vector_math.h"
#include "video_core/rasterizer_cache/types.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
namespace OpenGL {
// Describes the type of data a texture holds
enum class Aspect { Color = 0, Depth = 1, DepthStencil = 2 };
// A union for both color and depth/stencil clear values
union ClearValue {
Common::Vec4f color;
struct {
float depth;
u8 stencil;
};
};
struct Subresource {
Subresource(Aspect aspect, Common::Rectangle<u32> region, u32 level = 0, u32 layer = 0)
: aspect(aspect), region(region), level(level), layer(layer) {}
Aspect aspect;
Common::Rectangle<u32> region;
u32 level = 0;
u32 layer = 0;
};
struct FormatTuple;
/**

View File

@ -0,0 +1,36 @@
// Copyright 2022 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <set>
#include <tuple>
#include "common/common_types.h"
#include "common/math_util.h"
#include "common/vector_math.h"
namespace OpenGL {
// Describes the type of data a texture holds
enum class Aspect { Color = 0, Depth = 1, DepthStencil = 2 };
// A union for both color and depth/stencil clear values
union ClearValue {
Common::Vec4f color;
struct {
float depth;
u8 stencil;
};
};
struct Subresource {
auto operator<=>(const Subresource&) const = default;
Aspect aspect;
Common::Rectangle<u32> region;
u32 level = 0;
u32 layer = 0;
};
} // namespace OpenGL

View File

@ -4,7 +4,8 @@
#pragma once
#include <glad/glad.h>
#include "video_core/rasterizer_cache/rasterizer_cache_utils.h"
#include "video_core/texture/texture_decode.h"
#include "video_core/rasterizer_cache/utils.h"
#include "video_core/renderer_opengl/gl_vars.h"
namespace OpenGL {
@ -53,4 +54,39 @@ const FormatTuple& GetFormatTuple(PixelFormat pixel_format) {
return tex_tuple;
}
ClearValue MakeClearValue(Aspect aspect, PixelFormat format, const u8* fill_data) {
ClearValue result{};
switch (aspect) {
case Aspect::Color: {
Pica::Texture::TextureInfo tex_info{};
tex_info.format = static_cast<Pica::TexturingRegs::TextureFormat>(format);
Common::Vec4<u8> color = Pica::Texture::LookupTexture(fill_data, 0, 0, tex_info);
result.color = color / 255.f;
break;
}
case Aspect::Depth: {
u32 depth_uint = 0;
if (format == PixelFormat::D16) {
std::memcpy(&depth_uint, fill_data, 2);
result.depth = depth_uint / 65535.0f; // 2^16 - 1
} else if (format == PixelFormat::D24) {
std::memcpy(&depth_uint, fill_data, 3);
result.depth = depth_uint / 16777215.0f; // 2^24 - 1
}
break;
}
case Aspect::DepthStencil: {
u32 clear_value_uint;
std::memcpy(&clear_value_uint, fill_data, sizeof(u32));
result.depth = (clear_value_uint & 0xFFFFFF) / 16777215.0f; // 2^24 - 1
result.stencil = (clear_value_uint >> 24);
break;
}
}
return result;
}
} // namespace OpenGL

View File

@ -6,6 +6,7 @@
#include <functional>
#include "common/hash.h"
#include "video_core/rasterizer_cache/pixel_format.h"
#include "video_core/rasterizer_cache/types.h"
namespace OpenGL {
@ -18,13 +19,11 @@ struct FormatTuple {
const FormatTuple& GetFormatTuple(PixelFormat pixel_format);
struct HostTextureTag {
FormatTuple format_tuple{};
PixelFormat format{};
u32 width = 0;
u32 height = 0;
bool operator==(const HostTextureTag& rhs) const noexcept {
return std::memcmp(this, &rhs, sizeof(HostTextureTag)) == 0;
};
auto operator<=>(const HostTextureTag&) const noexcept = default;
const u64 Hash() const {
return Common::ComputeHash64(this, sizeof(HostTextureTag));
@ -41,19 +40,15 @@ struct TextureCubeConfig {
u32 width;
Pica::TexturingRegs::TextureFormat format;
bool operator==(const TextureCubeConfig& rhs) const {
return std::memcmp(this, &rhs, sizeof(TextureCubeConfig)) == 0;
}
bool operator!=(const TextureCubeConfig& rhs) const {
return std::memcmp(this, &rhs, sizeof(TextureCubeConfig)) != 0;
}
auto operator<=>(const TextureCubeConfig&) const noexcept = default;
const u64 Hash() const {
return Common::ComputeHash64(this, sizeof(TextureCubeConfig));
}
};
[[nodiscard]] ClearValue MakeClearValue(Aspect aspect, PixelFormat format, const u8* fill_data);
} // namespace OpenGL
namespace std {

View File

@ -6,7 +6,7 @@
#include <vector>
#include <fmt/chrono.h>
#include "common/logging/log.h"
#include "video_core/rasterizer_cache/rasterizer_cache_utils.h"
#include "video_core/rasterizer_cache/utils.h"
#include "video_core/renderer_opengl/gl_state.h"
#include "video_core/renderer_opengl/texture_downloader_es.h"