mirror of
https://git.suyu.dev/suyu/suyu
synced 2024-11-02 13:27:52 +00:00
GPU: Implemented the Z24S8 depth format and load the depth framebuffer.
This commit is contained in:
parent
066d6184d4
commit
0f929762b3
7 changed files with 124 additions and 24 deletions
|
@ -413,7 +413,7 @@ public:
|
||||||
struct {
|
struct {
|
||||||
u32 address_high;
|
u32 address_high;
|
||||||
u32 address_low;
|
u32 address_low;
|
||||||
u32 format;
|
Tegra::DepthFormat format;
|
||||||
u32 block_dimensions;
|
u32 block_dimensions;
|
||||||
u32 layer_stride;
|
u32 layer_stride;
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,15 @@ enum class RenderTargetFormat : u32 {
|
||||||
R11G11B10_FLOAT = 0xE0,
|
R11G11B10_FLOAT = 0xE0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class DepthFormat : u32 {
|
||||||
|
Z32_FLOAT = 0xA,
|
||||||
|
Z16_UNORM = 0x13,
|
||||||
|
S8_Z24_UNORM = 0x14,
|
||||||
|
Z24_X8_UNORM = 0x15,
|
||||||
|
Z24_S8_UNORM = 0x16,
|
||||||
|
Z24_C8_UNORM = 0x18,
|
||||||
|
};
|
||||||
|
|
||||||
/// Returns the number of bytes per pixel of each rendertarget format.
|
/// Returns the number of bytes per pixel of each rendertarget format.
|
||||||
u32 RenderTargetBytesPerPixel(RenderTargetFormat format);
|
u32 RenderTargetBytesPerPixel(RenderTargetFormat format);
|
||||||
|
|
||||||
|
|
|
@ -307,7 +307,9 @@ void RasterizerOpenGL::DrawArrays() {
|
||||||
// TODO(bunnei): Implement these
|
// TODO(bunnei): Implement these
|
||||||
const bool has_stencil = false;
|
const bool has_stencil = false;
|
||||||
const bool using_color_fb = true;
|
const bool using_color_fb = true;
|
||||||
const bool using_depth_fb = false;
|
|
||||||
|
const bool using_depth_fb = regs.zeta.Address() != 0;
|
||||||
|
|
||||||
const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
|
const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
|
||||||
|
|
||||||
const bool write_color_fb =
|
const bool write_color_fb =
|
||||||
|
|
|
@ -84,22 +84,18 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form
|
||||||
true}, // DXT45
|
true}, // DXT45
|
||||||
{GL_COMPRESSED_RED_RGTC1, GL_RED, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, true}, // DXN1
|
{GL_COMPRESSED_RED_RGTC1, GL_RED, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, true}, // DXN1
|
||||||
{GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4
|
{GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4
|
||||||
|
|
||||||
|
// DepthStencil formats
|
||||||
|
{GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, ComponentType::UNorm,
|
||||||
|
false}, // Z24S8
|
||||||
}};
|
}};
|
||||||
|
|
||||||
static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) {
|
static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) {
|
||||||
const SurfaceType type = SurfaceParams::GetFormatType(pixel_format);
|
|
||||||
if (type == SurfaceType::ColorTexture) {
|
|
||||||
ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size());
|
ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size());
|
||||||
auto& format = tex_format_tuples[static_cast<unsigned int>(pixel_format)];
|
auto& format = tex_format_tuples[static_cast<unsigned int>(pixel_format)];
|
||||||
ASSERT(component_type == format.component_type);
|
ASSERT(component_type == format.component_type);
|
||||||
return format;
|
|
||||||
} else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) {
|
|
||||||
// TODO(Subv): Implement depth formats
|
|
||||||
ASSERT_MSG(false, "Unimplemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
UNREACHABLE();
|
return format;
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VAddr SurfaceParams::GetCpuAddr() const {
|
VAddr SurfaceParams::GetCpuAddr() const {
|
||||||
|
@ -149,11 +145,17 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, Tegra::
|
||||||
const auto& gpu = Core::System::GetInstance().GPU();
|
const auto& gpu = Core::System::GetInstance().GPU();
|
||||||
|
|
||||||
if (morton_to_gl) {
|
if (morton_to_gl) {
|
||||||
|
if (SurfaceParams::GetFormatType(format) == SurfaceType::ColorTexture) {
|
||||||
auto data = Tegra::Texture::UnswizzleTexture(
|
auto data = Tegra::Texture::UnswizzleTexture(
|
||||||
*gpu.memory_manager->GpuToCpuAddress(addr),
|
*gpu.memory_manager->GpuToCpuAddress(addr),
|
||||||
SurfaceParams::TextureFormatFromPixelFormat(format), stride, height, block_height);
|
SurfaceParams::TextureFormatFromPixelFormat(format), stride, height, block_height);
|
||||||
|
|
||||||
std::memcpy(gl_buffer, data.data(), data.size());
|
std::memcpy(gl_buffer, data.data(), data.size());
|
||||||
|
} else {
|
||||||
|
auto data = Tegra::Texture::UnswizzleDepthTexture(
|
||||||
|
*gpu.memory_manager->GpuToCpuAddress(addr),
|
||||||
|
SurfaceParams::DepthFormatFromPixelFormat(format), stride, height, block_height);
|
||||||
|
std::memcpy(gl_buffer, data.data(), data.size());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should
|
// TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should
|
||||||
// check the configuration for this and perform more generic un/swizzle
|
// check the configuration for this and perform more generic un/swizzle
|
||||||
|
@ -174,7 +176,7 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
|
||||||
MortonCopy<true, PixelFormat::R11FG11FB10F>, MortonCopy<true, PixelFormat::RGBA32UI>,
|
MortonCopy<true, PixelFormat::R11FG11FB10F>, MortonCopy<true, PixelFormat::RGBA32UI>,
|
||||||
MortonCopy<true, PixelFormat::DXT1>, MortonCopy<true, PixelFormat::DXT23>,
|
MortonCopy<true, PixelFormat::DXT1>, MortonCopy<true, PixelFormat::DXT23>,
|
||||||
MortonCopy<true, PixelFormat::DXT45>, MortonCopy<true, PixelFormat::DXN1>,
|
MortonCopy<true, PixelFormat::DXT45>, MortonCopy<true, PixelFormat::DXN1>,
|
||||||
MortonCopy<true, PixelFormat::ASTC_2D_4X4>,
|
MortonCopy<true, PixelFormat::ASTC_2D_4X4>, MortonCopy<true, PixelFormat::Z24S8>,
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
|
static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
|
||||||
|
@ -194,6 +196,7 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
MortonCopy<false, PixelFormat::ABGR8>,
|
MortonCopy<false, PixelFormat::ABGR8>,
|
||||||
|
MortonCopy<false, PixelFormat::Z24S8>,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Allocate an uninitialized texture of appropriate size and format for the surface
|
// Allocate an uninitialized texture of appropriate size and format for the surface
|
||||||
|
@ -397,9 +400,15 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
|
||||||
|
|
||||||
// get color and depth surfaces
|
// get color and depth surfaces
|
||||||
const SurfaceParams color_params{SurfaceParams::CreateForFramebuffer(regs.rt[0])};
|
const SurfaceParams color_params{SurfaceParams::CreateForFramebuffer(regs.rt[0])};
|
||||||
const SurfaceParams depth_params{color_params};
|
SurfaceParams depth_params{color_params};
|
||||||
|
|
||||||
ASSERT_MSG(!using_depth_fb, "depth buffer is unimplemented");
|
if (using_depth_fb) {
|
||||||
|
depth_params.addr = regs.zeta.Address();
|
||||||
|
depth_params.pixel_format = SurfaceParams::PixelFormatFromDepthFormat(regs.zeta.format);
|
||||||
|
depth_params.component_type = SurfaceParams::ComponentTypeFromDepthFormat(regs.zeta.format);
|
||||||
|
depth_params.type = SurfaceParams::GetFormatType(depth_params.pixel_format);
|
||||||
|
depth_params.size_in_bytes = depth_params.SizeInBytes();
|
||||||
|
}
|
||||||
|
|
||||||
MathUtil::Rectangle<u32> color_rect{};
|
MathUtil::Rectangle<u32> color_rect{};
|
||||||
Surface color_surface;
|
Surface color_surface;
|
||||||
|
|
|
@ -37,7 +37,14 @@ struct SurfaceParams {
|
||||||
DXN1 = 11, // This is also known as BC4
|
DXN1 = 11, // This is also known as BC4
|
||||||
ASTC_2D_4X4 = 12,
|
ASTC_2D_4X4 = 12,
|
||||||
|
|
||||||
Max,
|
MaxColorFormat,
|
||||||
|
|
||||||
|
// DepthStencil formats
|
||||||
|
Z24S8 = 13,
|
||||||
|
|
||||||
|
MaxDepthStencilFormat,
|
||||||
|
|
||||||
|
Max = MaxDepthStencilFormat,
|
||||||
Invalid = 255,
|
Invalid = 255,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,6 +91,7 @@ struct SurfaceParams {
|
||||||
4, // DXT45
|
4, // DXT45
|
||||||
4, // DXN1
|
4, // DXN1
|
||||||
4, // ASTC_2D_4X4
|
4, // ASTC_2D_4X4
|
||||||
|
1, // Z24S8
|
||||||
}};
|
}};
|
||||||
|
|
||||||
ASSERT(static_cast<size_t>(format) < compression_factor_table.size());
|
ASSERT(static_cast<size_t>(format) < compression_factor_table.size());
|
||||||
|
@ -108,6 +116,7 @@ struct SurfaceParams {
|
||||||
128, // DXT45
|
128, // DXT45
|
||||||
64, // DXN1
|
64, // DXN1
|
||||||
32, // ASTC_2D_4X4
|
32, // ASTC_2D_4X4
|
||||||
|
32, // Z24S8
|
||||||
}};
|
}};
|
||||||
|
|
||||||
ASSERT(static_cast<size_t>(format) < bpp_table.size());
|
ASSERT(static_cast<size_t>(format) < bpp_table.size());
|
||||||
|
@ -117,6 +126,16 @@ struct SurfaceParams {
|
||||||
return GetFormatBpp(pixel_format);
|
return GetFormatBpp(pixel_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case Tegra::DepthFormat::Z24_S8_UNORM:
|
||||||
|
return PixelFormat::Z24S8;
|
||||||
|
default:
|
||||||
|
NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) {
|
static PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case Tegra::RenderTargetFormat::RGBA8_UNORM:
|
case Tegra::RenderTargetFormat::RGBA8_UNORM:
|
||||||
|
@ -205,6 +224,15 @@ struct SurfaceParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Tegra::DepthFormat DepthFormatFromPixelFormat(PixelFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case PixelFormat::Z24S8:
|
||||||
|
return Tegra::DepthFormat::Z24_S8_UNORM;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static ComponentType ComponentTypeFromTexture(Tegra::Texture::ComponentType type) {
|
static ComponentType ComponentTypeFromTexture(Tegra::Texture::ComponentType type) {
|
||||||
// TODO(Subv): Implement more component types
|
// TODO(Subv): Implement more component types
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -244,11 +272,26 @@ struct SurfaceParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ComponentType ComponentTypeFromDepthFormat(Tegra::DepthFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case Tegra::DepthFormat::Z24_S8_UNORM:
|
||||||
|
return ComponentType::UNorm;
|
||||||
|
default:
|
||||||
|
NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static SurfaceType GetFormatType(PixelFormat pixel_format) {
|
static SurfaceType GetFormatType(PixelFormat pixel_format) {
|
||||||
if (static_cast<size_t>(pixel_format) < MaxPixelFormat) {
|
if (static_cast<size_t>(pixel_format) < static_cast<size_t>(PixelFormat::MaxColorFormat)) {
|
||||||
return SurfaceType::ColorTexture;
|
return SurfaceType::ColorTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (static_cast<size_t>(pixel_format) <
|
||||||
|
static_cast<size_t>(PixelFormat::MaxDepthStencilFormat)) {
|
||||||
|
return SurfaceType::DepthStencil;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(Subv): Implement the other formats
|
// TODO(Subv): Implement the other formats
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
#include "video_core/gpu.h"
|
||||||
#include "video_core/textures/decoders.h"
|
#include "video_core/textures/decoders.h"
|
||||||
#include "video_core/textures/texture.h"
|
#include "video_core/textures/texture.h"
|
||||||
|
|
||||||
|
@ -73,6 +74,16 @@ u32 BytesPerPixel(TextureFormat format) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 DepthBytesPerPixel(DepthFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case DepthFormat::Z24_S8_UNORM:
|
||||||
|
return 4;
|
||||||
|
default:
|
||||||
|
UNIMPLEMENTED_MSG("Format not implemented");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height,
|
std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height,
|
||||||
u32 block_height) {
|
u32 block_height) {
|
||||||
u8* data = Memory::GetPointer(address);
|
u8* data = Memory::GetPointer(address);
|
||||||
|
@ -110,6 +121,26 @@ std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width,
|
||||||
return unswizzled_data;
|
return unswizzled_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<u8> UnswizzleDepthTexture(VAddr address, DepthFormat format, u32 width, u32 height,
|
||||||
|
u32 block_height) {
|
||||||
|
u8* data = Memory::GetPointer(address);
|
||||||
|
u32 bytes_per_pixel = DepthBytesPerPixel(format);
|
||||||
|
|
||||||
|
std::vector<u8> unswizzled_data(width * height * bytes_per_pixel);
|
||||||
|
|
||||||
|
switch (format) {
|
||||||
|
case DepthFormat::Z24_S8_UNORM:
|
||||||
|
CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
|
||||||
|
unswizzled_data.data(), true, block_height);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNIMPLEMENTED_MSG("Format not implemented");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return unswizzled_data;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat format, u32 width,
|
std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat format, u32 width,
|
||||||
u32 height) {
|
u32 height) {
|
||||||
std::vector<u8> rgba_data;
|
std::vector<u8> rgba_data;
|
||||||
|
|
|
@ -17,6 +17,12 @@ namespace Texture {
|
||||||
std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height,
|
std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height,
|
||||||
u32 block_height = TICEntry::DefaultBlockHeight);
|
u32 block_height = TICEntry::DefaultBlockHeight);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unswizzles a swizzled depth texture without changing its format.
|
||||||
|
*/
|
||||||
|
std::vector<u8> UnswizzleDepthTexture(VAddr address, DepthFormat format, u32 width, u32 height,
|
||||||
|
u32 block_height = TICEntry::DefaultBlockHeight);
|
||||||
|
|
||||||
/// Copies texture data from a buffer and performs swizzling/unswizzling as necessary.
|
/// Copies texture data from a buffer and performs swizzling/unswizzling as necessary.
|
||||||
void CopySwizzledData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_per_pixel,
|
void CopySwizzledData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_per_pixel,
|
||||||
u8* swizzled_data, u8* unswizzled_data, bool unswizzle, u32 block_height);
|
u8* swizzled_data, u8* unswizzled_data, bool unswizzle, u32 block_height);
|
||||||
|
|
Loading…
Reference in a new issue