video_core: Use native ASTC when available
This commit is contained in:
parent
16270dcfe4
commit
b6571ca9f0
10 changed files with 176 additions and 281 deletions
|
@ -18,15 +18,20 @@ MICROPROFILE_DEFINE(GPU_Flush_Texture, "GPU", "Texture Flush", MP_RGB(128, 192,
|
|||
|
||||
using Tegra::Texture::ConvertFromGuestToHost;
|
||||
using VideoCore::MortonSwizzleMode;
|
||||
using VideoCore::Surface::SurfaceCompression;
|
||||
using VideoCore::Surface::IsPixelFormatASTC;
|
||||
using VideoCore::Surface::PixelFormat;
|
||||
|
||||
StagingCache::StagingCache() = default;
|
||||
|
||||
StagingCache::~StagingCache() = default;
|
||||
|
||||
SurfaceBaseImpl::SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params)
|
||||
: params{params}, host_memory_size{params.GetHostSizeInBytes()}, gpu_addr{gpu_addr},
|
||||
mipmap_sizes(params.num_levels), mipmap_offsets(params.num_levels) {
|
||||
SurfaceBaseImpl::SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params,
|
||||
bool is_astc_supported)
|
||||
: params{params}, gpu_addr{gpu_addr}, mipmap_sizes(params.num_levels),
|
||||
mipmap_offsets(params.num_levels) {
|
||||
is_converted = IsPixelFormatASTC(params.pixel_format) && !is_astc_supported;
|
||||
host_memory_size = params.GetHostSizeInBytes(is_converted);
|
||||
|
||||
std::size_t offset = 0;
|
||||
for (u32 level = 0; level < params.num_levels; ++level) {
|
||||
const std::size_t mipmap_size{params.GetGuestMipmapSize(level)};
|
||||
|
@ -164,7 +169,7 @@ void SurfaceBaseImpl::SwizzleFunc(MortonSwizzleMode mode, u8* memory, const Surf
|
|||
|
||||
std::size_t guest_offset{mipmap_offsets[level]};
|
||||
if (params.is_layered) {
|
||||
std::size_t host_offset{0};
|
||||
std::size_t host_offset = 0;
|
||||
const std::size_t guest_stride = layer_size;
|
||||
const std::size_t host_stride = params.GetHostLayerSize(level);
|
||||
for (u32 layer = 0; layer < params.depth; ++layer) {
|
||||
|
@ -206,7 +211,7 @@ void SurfaceBaseImpl::LoadBuffer(Tegra::MemoryManager& memory_manager,
|
|||
ASSERT_MSG(params.block_width == 0, "Block width is defined as {} on texture target {}",
|
||||
params.block_width, static_cast<u32>(params.target));
|
||||
for (u32 level = 0; level < params.num_levels; ++level) {
|
||||
const std::size_t host_offset{params.GetHostMipmapLevelOffset(level)};
|
||||
const std::size_t host_offset{params.GetHostMipmapLevelOffset(level, false)};
|
||||
SwizzleFunc(MortonSwizzleMode::MortonToLinear, host_ptr, params,
|
||||
staging_buffer.data() + host_offset, level);
|
||||
}
|
||||
|
@ -219,7 +224,7 @@ void SurfaceBaseImpl::LoadBuffer(Tegra::MemoryManager& memory_manager,
|
|||
const u32 height{(params.height + block_height - 1) / block_height};
|
||||
const u32 copy_size{width * bpp};
|
||||
if (params.pitch == copy_size) {
|
||||
std::memcpy(staging_buffer.data(), host_ptr, params.GetHostSizeInBytes());
|
||||
std::memcpy(staging_buffer.data(), host_ptr, params.GetHostSizeInBytes(false));
|
||||
} else {
|
||||
const u8* start{host_ptr};
|
||||
u8* write_to{staging_buffer.data()};
|
||||
|
@ -231,19 +236,15 @@ void SurfaceBaseImpl::LoadBuffer(Tegra::MemoryManager& memory_manager,
|
|||
}
|
||||
}
|
||||
|
||||
auto compression_type = params.GetCompressionType();
|
||||
if (compression_type == SurfaceCompression::None ||
|
||||
compression_type == SurfaceCompression::Compressed)
|
||||
if (!is_converted && params.pixel_format != PixelFormat::S8Z24) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (u32 level_up = params.num_levels; level_up > 0; --level_up) {
|
||||
const u32 level = level_up - 1;
|
||||
const std::size_t in_host_offset{params.GetHostMipmapLevelOffset(level)};
|
||||
const std::size_t out_host_offset = compression_type == SurfaceCompression::Rearranged
|
||||
? in_host_offset
|
||||
: params.GetConvertedMipmapOffset(level);
|
||||
u8* in_buffer = staging_buffer.data() + in_host_offset;
|
||||
u8* out_buffer = staging_buffer.data() + out_host_offset;
|
||||
for (u32 level = params.num_levels; level--;) {
|
||||
const std::size_t in_host_offset{params.GetHostMipmapLevelOffset(level, false)};
|
||||
const std::size_t out_host_offset{params.GetHostMipmapLevelOffset(level, is_converted)};
|
||||
u8* const in_buffer = staging_buffer.data() + in_host_offset;
|
||||
u8* const out_buffer = staging_buffer.data() + out_host_offset;
|
||||
ConvertFromGuestToHost(in_buffer, out_buffer, params.pixel_format,
|
||||
params.GetMipWidth(level), params.GetMipHeight(level),
|
||||
params.GetMipDepth(level), true, true);
|
||||
|
@ -273,7 +274,7 @@ void SurfaceBaseImpl::FlushBuffer(Tegra::MemoryManager& memory_manager,
|
|||
if (params.is_tiled) {
|
||||
ASSERT_MSG(params.block_width == 0, "Block width is defined as {}", params.block_width);
|
||||
for (u32 level = 0; level < params.num_levels; ++level) {
|
||||
const std::size_t host_offset{params.GetHostMipmapLevelOffset(level)};
|
||||
const std::size_t host_offset{params.GetHostMipmapLevelOffset(level, false)};
|
||||
SwizzleFunc(MortonSwizzleMode::LinearToMorton, host_ptr, params,
|
||||
staging_buffer.data() + host_offset, level);
|
||||
}
|
||||
|
|
|
@ -131,6 +131,10 @@ public:
|
|||
return !params.is_tiled;
|
||||
}
|
||||
|
||||
bool IsConverted() const {
|
||||
return is_converted;
|
||||
}
|
||||
|
||||
bool MatchFormat(VideoCore::Surface::PixelFormat pixel_format) const {
|
||||
return params.pixel_format == pixel_format;
|
||||
}
|
||||
|
@ -160,7 +164,8 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
explicit SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params);
|
||||
explicit SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params,
|
||||
bool is_astc_supported);
|
||||
~SurfaceBaseImpl() = default;
|
||||
|
||||
virtual void DecorateSurfaceName() = 0;
|
||||
|
@ -168,12 +173,13 @@ protected:
|
|||
const SurfaceParams params;
|
||||
std::size_t layer_size;
|
||||
std::size_t guest_memory_size;
|
||||
const std::size_t host_memory_size;
|
||||
std::size_t host_memory_size;
|
||||
GPUVAddr gpu_addr{};
|
||||
CacheAddr cache_addr{};
|
||||
CacheAddr cache_addr_end{};
|
||||
VAddr cpu_addr{};
|
||||
bool is_continuous{};
|
||||
bool is_converted{};
|
||||
|
||||
std::vector<std::size_t> mipmap_sizes;
|
||||
std::vector<std::size_t> mipmap_offsets;
|
||||
|
@ -288,8 +294,9 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
explicit SurfaceBase(const GPUVAddr gpu_addr, const SurfaceParams& params)
|
||||
: SurfaceBaseImpl(gpu_addr, params) {}
|
||||
explicit SurfaceBase(const GPUVAddr gpu_addr, const SurfaceParams& params,
|
||||
bool is_astc_supported)
|
||||
: SurfaceBaseImpl(gpu_addr, params, is_astc_supported) {}
|
||||
|
||||
~SurfaceBase() = default;
|
||||
|
||||
|
|
|
@ -309,28 +309,26 @@ std::size_t SurfaceParams::GetGuestMipmapLevelOffset(u32 level) const {
|
|||
return offset;
|
||||
}
|
||||
|
||||
std::size_t SurfaceParams::GetHostMipmapLevelOffset(u32 level) const {
|
||||
std::size_t SurfaceParams::GetHostMipmapLevelOffset(u32 level, bool is_converted) const {
|
||||
std::size_t offset = 0;
|
||||
for (u32 i = 0; i < level; i++) {
|
||||
offset += GetInnerMipmapMemorySize(i, true, false) * GetNumLayers();
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
std::size_t SurfaceParams::GetConvertedMipmapOffset(u32 level) const {
|
||||
std::size_t offset = 0;
|
||||
for (u32 i = 0; i < level; i++) {
|
||||
offset += GetConvertedMipmapSize(i);
|
||||
if (is_converted) {
|
||||
for (u32 i = 0; i < level; ++i) {
|
||||
offset += GetConvertedMipmapSize(i) * GetNumLayers();
|
||||
}
|
||||
} else {
|
||||
for (u32 i = 0; i < level; ++i) {
|
||||
offset += GetInnerMipmapMemorySize(i, true, false) * GetNumLayers();
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
std::size_t SurfaceParams::GetConvertedMipmapSize(u32 level) const {
|
||||
constexpr std::size_t rgba8_bpp = 4ULL;
|
||||
const std::size_t width_t = GetMipWidth(level);
|
||||
const std::size_t height_t = GetMipHeight(level);
|
||||
const std::size_t depth_t = is_layered ? depth : GetMipDepth(level);
|
||||
return width_t * height_t * depth_t * rgba8_bpp;
|
||||
const std::size_t mip_width = GetMipWidth(level);
|
||||
const std::size_t mip_height = GetMipHeight(level);
|
||||
const std::size_t mip_depth = is_layered ? 1 : GetMipDepth(level);
|
||||
return mip_width * mip_height * mip_depth * rgba8_bpp;
|
||||
}
|
||||
|
||||
std::size_t SurfaceParams::GetLayerSize(bool as_host_size, bool uncompressed) const {
|
||||
|
|
|
@ -20,8 +20,6 @@ namespace VideoCommon {
|
|||
|
||||
class FormatLookupTable;
|
||||
|
||||
using VideoCore::Surface::SurfaceCompression;
|
||||
|
||||
class SurfaceParams {
|
||||
public:
|
||||
/// Creates SurfaceCachedParams from a texture configuration.
|
||||
|
@ -67,16 +65,14 @@ public:
|
|||
return GetInnerMemorySize(false, false, false);
|
||||
}
|
||||
|
||||
std::size_t GetHostSizeInBytes() const {
|
||||
std::size_t host_size_in_bytes;
|
||||
if (GetCompressionType() == SurfaceCompression::Converted) {
|
||||
// ASTC is uncompressed in software, in emulated as RGBA8
|
||||
host_size_in_bytes = 0;
|
||||
for (u32 level = 0; level < num_levels; ++level) {
|
||||
host_size_in_bytes += GetConvertedMipmapSize(level);
|
||||
}
|
||||
} else {
|
||||
host_size_in_bytes = GetInnerMemorySize(true, false, false);
|
||||
std::size_t GetHostSizeInBytes(bool is_converted) const {
|
||||
if (!is_converted) {
|
||||
return GetInnerMemorySize(true, false, false);
|
||||
}
|
||||
// ASTC is uncompressed in software, in emulated as RGBA8
|
||||
std::size_t host_size_in_bytes = 0;
|
||||
for (u32 level = 0; level < num_levels; ++level) {
|
||||
host_size_in_bytes += GetConvertedMipmapSize(level) * GetNumLayers();
|
||||
}
|
||||
return host_size_in_bytes;
|
||||
}
|
||||
|
@ -107,9 +103,8 @@ public:
|
|||
u32 GetMipBlockDepth(u32 level) const;
|
||||
|
||||
/// Returns the best possible row/pitch alignment for the surface.
|
||||
u32 GetRowAlignment(u32 level) const {
|
||||
const u32 bpp =
|
||||
GetCompressionType() == SurfaceCompression::Converted ? 4 : GetBytesPerPixel();
|
||||
u32 GetRowAlignment(u32 level, bool is_converted) const {
|
||||
const u32 bpp = is_converted ? 4 : GetBytesPerPixel();
|
||||
return 1U << Common::CountTrailingZeroes32(GetMipWidth(level) * bpp);
|
||||
}
|
||||
|
||||
|
@ -117,11 +112,7 @@ public:
|
|||
std::size_t GetGuestMipmapLevelOffset(u32 level) const;
|
||||
|
||||
/// Returns the offset in bytes in host memory (linear) of a given mipmap level.
|
||||
std::size_t GetHostMipmapLevelOffset(u32 level) const;
|
||||
|
||||
/// Returns the offset in bytes in host memory (linear) of a given mipmap level
|
||||
/// for a texture that is converted in host gpu.
|
||||
std::size_t GetConvertedMipmapOffset(u32 level) const;
|
||||
std::size_t GetHostMipmapLevelOffset(u32 level, bool is_converted) const;
|
||||
|
||||
/// Returns the size in bytes in guest memory of a given mipmap level.
|
||||
std::size_t GetGuestMipmapSize(u32 level) const {
|
||||
|
@ -196,11 +187,6 @@ public:
|
|||
pixel_format < VideoCore::Surface::PixelFormat::MaxDepthStencilFormat;
|
||||
}
|
||||
|
||||
/// Returns how the compression should be handled for this texture.
|
||||
SurfaceCompression GetCompressionType() const {
|
||||
return VideoCore::Surface::GetFormatCompressionType(pixel_format);
|
||||
}
|
||||
|
||||
/// Returns is the surface is a TextureBuffer type of surface.
|
||||
bool IsBuffer() const {
|
||||
return target == VideoCore::Surface::SurfaceTarget::TextureBuffer;
|
||||
|
|
|
@ -289,8 +289,9 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
TextureCache(Core::System& system, VideoCore::RasterizerInterface& rasterizer)
|
||||
: system{system}, rasterizer{rasterizer} {
|
||||
explicit TextureCache(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
|
||||
bool is_astc_supported)
|
||||
: system{system}, is_astc_supported{is_astc_supported}, rasterizer{rasterizer} {
|
||||
for (std::size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
|
||||
SetEmptyColorBuffer(i);
|
||||
}
|
||||
|
@ -381,6 +382,7 @@ protected:
|
|||
}
|
||||
|
||||
Core::System& system;
|
||||
const bool is_astc_supported;
|
||||
|
||||
private:
|
||||
enum class RecycleStrategy : u32 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue