9764c13d6d
The current texture cache has several points that hurt maintainability and performance. It's easy to break unrelated parts of the cache when doing minor changes. The cache can easily forget valuable information about the cached textures by CPU writes or simply by its normal usage.The current texture cache has several points that hurt maintainability and performance. It's easy to break unrelated parts of the cache when doing minor changes. The cache can easily forget valuable information about the cached textures by CPU writes or simply by its normal usage. This commit aims to address those issues.
287 lines
10 KiB
C++
287 lines
10 KiB
C++
// Copyright 2014 Citra Emulator Project
|
|
// Licensed under GPLv2 or any later version
|
|
// Refer to the license.txt file included.
|
|
|
|
#include "common/common_types.h"
|
|
#include "common/math_util.h"
|
|
#include "video_core/surface.h"
|
|
|
|
namespace VideoCore::Surface {
|
|
|
|
SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_type) {
|
|
switch (texture_type) {
|
|
case Tegra::Texture::TextureType::Texture1D:
|
|
return SurfaceTarget::Texture1D;
|
|
case Tegra::Texture::TextureType::Texture1DBuffer:
|
|
return SurfaceTarget::TextureBuffer;
|
|
case Tegra::Texture::TextureType::Texture2D:
|
|
case Tegra::Texture::TextureType::Texture2DNoMipmap:
|
|
return SurfaceTarget::Texture2D;
|
|
case Tegra::Texture::TextureType::Texture3D:
|
|
return SurfaceTarget::Texture3D;
|
|
case Tegra::Texture::TextureType::TextureCubemap:
|
|
return SurfaceTarget::TextureCubemap;
|
|
case Tegra::Texture::TextureType::TextureCubeArray:
|
|
return SurfaceTarget::TextureCubeArray;
|
|
case Tegra::Texture::TextureType::Texture1DArray:
|
|
return SurfaceTarget::Texture1DArray;
|
|
case Tegra::Texture::TextureType::Texture2DArray:
|
|
return SurfaceTarget::Texture2DArray;
|
|
default:
|
|
LOG_CRITICAL(HW_GPU, "Unimplemented texture_type={}", texture_type);
|
|
UNREACHABLE();
|
|
return SurfaceTarget::Texture2D;
|
|
}
|
|
}
|
|
|
|
bool SurfaceTargetIsLayered(SurfaceTarget target) {
|
|
switch (target) {
|
|
case SurfaceTarget::Texture1D:
|
|
case SurfaceTarget::TextureBuffer:
|
|
case SurfaceTarget::Texture2D:
|
|
case SurfaceTarget::Texture3D:
|
|
return false;
|
|
case SurfaceTarget::Texture1DArray:
|
|
case SurfaceTarget::Texture2DArray:
|
|
case SurfaceTarget::TextureCubemap:
|
|
case SurfaceTarget::TextureCubeArray:
|
|
return true;
|
|
default:
|
|
LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", target);
|
|
UNREACHABLE();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool SurfaceTargetIsArray(SurfaceTarget target) {
|
|
switch (target) {
|
|
case SurfaceTarget::Texture1D:
|
|
case SurfaceTarget::TextureBuffer:
|
|
case SurfaceTarget::Texture2D:
|
|
case SurfaceTarget::Texture3D:
|
|
case SurfaceTarget::TextureCubemap:
|
|
return false;
|
|
case SurfaceTarget::Texture1DArray:
|
|
case SurfaceTarget::Texture2DArray:
|
|
case SurfaceTarget::TextureCubeArray:
|
|
return true;
|
|
default:
|
|
LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", target);
|
|
UNREACHABLE();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) {
|
|
switch (format) {
|
|
case Tegra::DepthFormat::S8_UINT_Z24_UNORM:
|
|
return PixelFormat::S8_UINT_D24_UNORM;
|
|
case Tegra::DepthFormat::D24S8_UNORM:
|
|
return PixelFormat::D24_UNORM_S8_UINT;
|
|
case Tegra::DepthFormat::D32_FLOAT:
|
|
return PixelFormat::D32_FLOAT;
|
|
case Tegra::DepthFormat::D16_UNORM:
|
|
return PixelFormat::D16_UNORM;
|
|
case Tegra::DepthFormat::D32_FLOAT_S8X24_UINT:
|
|
return PixelFormat::D32_FLOAT_S8_UINT;
|
|
default:
|
|
UNIMPLEMENTED_MSG("Unimplemented format={}", format);
|
|
return PixelFormat::S8_UINT_D24_UNORM;
|
|
}
|
|
}
|
|
|
|
PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) {
|
|
switch (format) {
|
|
case Tegra::RenderTargetFormat::R32B32G32A32_FLOAT:
|
|
return PixelFormat::R32G32B32A32_FLOAT;
|
|
case Tegra::RenderTargetFormat::R32G32B32A32_SINT:
|
|
return PixelFormat::R32G32B32A32_SINT;
|
|
case Tegra::RenderTargetFormat::R32G32B32A32_UINT:
|
|
return PixelFormat::R32G32B32A32_UINT;
|
|
case Tegra::RenderTargetFormat::R16G16B16A16_UNORM:
|
|
return PixelFormat::R16G16B16A16_UNORM;
|
|
case Tegra::RenderTargetFormat::R16G16B16A16_SNORM:
|
|
return PixelFormat::R16G16B16A16_SNORM;
|
|
case Tegra::RenderTargetFormat::R16G16B16A16_SINT:
|
|
return PixelFormat::R16G16B16A16_SINT;
|
|
case Tegra::RenderTargetFormat::R16G16B16A16_UINT:
|
|
return PixelFormat::R16G16B16A16_UINT;
|
|
case Tegra::RenderTargetFormat::R16G16B16A16_FLOAT:
|
|
return PixelFormat::R16G16B16A16_FLOAT;
|
|
case Tegra::RenderTargetFormat::R32G32_FLOAT:
|
|
return PixelFormat::R32G32_FLOAT;
|
|
case Tegra::RenderTargetFormat::R32G32_SINT:
|
|
return PixelFormat::R32G32_SINT;
|
|
case Tegra::RenderTargetFormat::R32G32_UINT:
|
|
return PixelFormat::R32G32_UINT;
|
|
case Tegra::RenderTargetFormat::R16G16B16X16_FLOAT:
|
|
return PixelFormat::R16G16B16X16_FLOAT;
|
|
case Tegra::RenderTargetFormat::B8G8R8A8_UNORM:
|
|
return PixelFormat::B8G8R8A8_UNORM;
|
|
case Tegra::RenderTargetFormat::B8G8R8A8_SRGB:
|
|
return PixelFormat::B8G8R8A8_SRGB;
|
|
case Tegra::RenderTargetFormat::A2B10G10R10_UNORM:
|
|
return PixelFormat::A2B10G10R10_UNORM;
|
|
case Tegra::RenderTargetFormat::A2B10G10R10_UINT:
|
|
return PixelFormat::A2B10G10R10_UINT;
|
|
case Tegra::RenderTargetFormat::A8B8G8R8_UNORM:
|
|
return PixelFormat::A8B8G8R8_UNORM;
|
|
case Tegra::RenderTargetFormat::A8B8G8R8_SRGB:
|
|
return PixelFormat::A8B8G8R8_SRGB;
|
|
case Tegra::RenderTargetFormat::A8B8G8R8_SNORM:
|
|
return PixelFormat::A8B8G8R8_SNORM;
|
|
case Tegra::RenderTargetFormat::A8B8G8R8_SINT:
|
|
return PixelFormat::A8B8G8R8_SINT;
|
|
case Tegra::RenderTargetFormat::A8B8G8R8_UINT:
|
|
return PixelFormat::A8B8G8R8_UINT;
|
|
case Tegra::RenderTargetFormat::R16G16_UNORM:
|
|
return PixelFormat::R16G16_UNORM;
|
|
case Tegra::RenderTargetFormat::R16G16_SNORM:
|
|
return PixelFormat::R16G16_SNORM;
|
|
case Tegra::RenderTargetFormat::R16G16_SINT:
|
|
return PixelFormat::R16G16_SINT;
|
|
case Tegra::RenderTargetFormat::R16G16_UINT:
|
|
return PixelFormat::R16G16_UINT;
|
|
case Tegra::RenderTargetFormat::R16G16_FLOAT:
|
|
return PixelFormat::R16G16_FLOAT;
|
|
case Tegra::RenderTargetFormat::B10G11R11_FLOAT:
|
|
return PixelFormat::B10G11R11_FLOAT;
|
|
case Tegra::RenderTargetFormat::R32_SINT:
|
|
return PixelFormat::R32_SINT;
|
|
case Tegra::RenderTargetFormat::R32_UINT:
|
|
return PixelFormat::R32_UINT;
|
|
case Tegra::RenderTargetFormat::R32_FLOAT:
|
|
return PixelFormat::R32_FLOAT;
|
|
case Tegra::RenderTargetFormat::R5G6B5_UNORM:
|
|
return PixelFormat::R5G6B5_UNORM;
|
|
case Tegra::RenderTargetFormat::A1R5G5B5_UNORM:
|
|
return PixelFormat::A1R5G5B5_UNORM;
|
|
case Tegra::RenderTargetFormat::R8G8_UNORM:
|
|
return PixelFormat::R8G8_UNORM;
|
|
case Tegra::RenderTargetFormat::R8G8_SNORM:
|
|
return PixelFormat::R8G8_SNORM;
|
|
case Tegra::RenderTargetFormat::R8G8_SINT:
|
|
return PixelFormat::R8G8_SINT;
|
|
case Tegra::RenderTargetFormat::R8G8_UINT:
|
|
return PixelFormat::R8G8_UINT;
|
|
case Tegra::RenderTargetFormat::R16_UNORM:
|
|
return PixelFormat::R16_UNORM;
|
|
case Tegra::RenderTargetFormat::R16_SNORM:
|
|
return PixelFormat::R16_SNORM;
|
|
case Tegra::RenderTargetFormat::R16_SINT:
|
|
return PixelFormat::R16_SINT;
|
|
case Tegra::RenderTargetFormat::R16_UINT:
|
|
return PixelFormat::R16_UINT;
|
|
case Tegra::RenderTargetFormat::R16_FLOAT:
|
|
return PixelFormat::R16_FLOAT;
|
|
case Tegra::RenderTargetFormat::R8_UNORM:
|
|
return PixelFormat::R8_UNORM;
|
|
case Tegra::RenderTargetFormat::R8_SNORM:
|
|
return PixelFormat::R8_SNORM;
|
|
case Tegra::RenderTargetFormat::R8_SINT:
|
|
return PixelFormat::R8_SINT;
|
|
case Tegra::RenderTargetFormat::R8_UINT:
|
|
return PixelFormat::R8_UINT;
|
|
default:
|
|
UNIMPLEMENTED_MSG("Unimplemented format={}", format);
|
|
return PixelFormat::A8B8G8R8_UNORM;
|
|
}
|
|
}
|
|
|
|
PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) {
|
|
switch (format) {
|
|
case Tegra::FramebufferConfig::PixelFormat::A8B8G8R8_UNORM:
|
|
return PixelFormat::A8B8G8R8_UNORM;
|
|
case Tegra::FramebufferConfig::PixelFormat::RGB565_UNORM:
|
|
return PixelFormat::R5G6B5_UNORM;
|
|
case Tegra::FramebufferConfig::PixelFormat::B8G8R8A8_UNORM:
|
|
return PixelFormat::B8G8R8A8_UNORM;
|
|
default:
|
|
UNIMPLEMENTED_MSG("Unimplemented format={}", format);
|
|
return PixelFormat::A8B8G8R8_UNORM;
|
|
}
|
|
}
|
|
|
|
SurfaceType GetFormatType(PixelFormat pixel_format) {
|
|
if (static_cast<std::size_t>(pixel_format) <
|
|
static_cast<std::size_t>(PixelFormat::MaxColorFormat)) {
|
|
return SurfaceType::ColorTexture;
|
|
}
|
|
|
|
if (static_cast<std::size_t>(pixel_format) <
|
|
static_cast<std::size_t>(PixelFormat::MaxDepthFormat)) {
|
|
return SurfaceType::Depth;
|
|
}
|
|
|
|
if (static_cast<std::size_t>(pixel_format) <
|
|
static_cast<std::size_t>(PixelFormat::MaxDepthStencilFormat)) {
|
|
return SurfaceType::DepthStencil;
|
|
}
|
|
|
|
// TODO(Subv): Implement the other formats
|
|
ASSERT(false);
|
|
|
|
return SurfaceType::Invalid;
|
|
}
|
|
|
|
bool IsPixelFormatASTC(PixelFormat format) {
|
|
switch (format) {
|
|
case PixelFormat::ASTC_2D_4X4_UNORM:
|
|
case PixelFormat::ASTC_2D_5X4_UNORM:
|
|
case PixelFormat::ASTC_2D_5X5_UNORM:
|
|
case PixelFormat::ASTC_2D_8X8_UNORM:
|
|
case PixelFormat::ASTC_2D_8X5_UNORM:
|
|
case PixelFormat::ASTC_2D_4X4_SRGB:
|
|
case PixelFormat::ASTC_2D_5X4_SRGB:
|
|
case PixelFormat::ASTC_2D_5X5_SRGB:
|
|
case PixelFormat::ASTC_2D_8X8_SRGB:
|
|
case PixelFormat::ASTC_2D_8X5_SRGB:
|
|
case PixelFormat::ASTC_2D_10X8_UNORM:
|
|
case PixelFormat::ASTC_2D_10X8_SRGB:
|
|
case PixelFormat::ASTC_2D_6X6_UNORM:
|
|
case PixelFormat::ASTC_2D_6X6_SRGB:
|
|
case PixelFormat::ASTC_2D_10X10_UNORM:
|
|
case PixelFormat::ASTC_2D_10X10_SRGB:
|
|
case PixelFormat::ASTC_2D_12X12_UNORM:
|
|
case PixelFormat::ASTC_2D_12X12_SRGB:
|
|
case PixelFormat::ASTC_2D_8X6_UNORM:
|
|
case PixelFormat::ASTC_2D_8X6_SRGB:
|
|
case PixelFormat::ASTC_2D_6X5_UNORM:
|
|
case PixelFormat::ASTC_2D_6X5_SRGB:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool IsPixelFormatSRGB(PixelFormat format) {
|
|
switch (format) {
|
|
case PixelFormat::A8B8G8R8_SRGB:
|
|
case PixelFormat::B8G8R8A8_SRGB:
|
|
case PixelFormat::BC1_RGBA_SRGB:
|
|
case PixelFormat::BC2_SRGB:
|
|
case PixelFormat::BC3_SRGB:
|
|
case PixelFormat::BC7_SRGB:
|
|
case PixelFormat::ASTC_2D_4X4_SRGB:
|
|
case PixelFormat::ASTC_2D_8X8_SRGB:
|
|
case PixelFormat::ASTC_2D_8X5_SRGB:
|
|
case PixelFormat::ASTC_2D_5X4_SRGB:
|
|
case PixelFormat::ASTC_2D_5X5_SRGB:
|
|
case PixelFormat::ASTC_2D_10X8_SRGB:
|
|
case PixelFormat::ASTC_2D_6X6_SRGB:
|
|
case PixelFormat::ASTC_2D_10X10_SRGB:
|
|
case PixelFormat::ASTC_2D_12X12_SRGB:
|
|
case PixelFormat::ASTC_2D_8X6_SRGB:
|
|
case PixelFormat::ASTC_2D_6X5_SRGB:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) {
|
|
return {DefaultBlockWidth(format), DefaultBlockHeight(format)};
|
|
}
|
|
|
|
} // namespace VideoCore::Surface
|