|
|
@@ -16,6 +16,7 @@
|
|
|
#include "core/settings.h"
|
|
|
#include "video_core/engines/maxwell_3d.h"
|
|
|
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
|
|
|
+#include "video_core/renderer_opengl/gl_state.h"
|
|
|
#include "video_core/renderer_opengl/utils.h"
|
|
|
#include "video_core/surface.h"
|
|
|
#include "video_core/textures/astc.h"
|
|
|
@@ -58,16 +59,14 @@ void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) {
|
|
|
|
|
|
std::size_t SurfaceParams::InnerMipmapMemorySize(u32 mip_level, bool force_gl, bool layer_only,
|
|
|
bool uncompressed) const {
|
|
|
- const u32 compression_factor{GetCompressionFactor(pixel_format)};
|
|
|
+ const u32 tile_x{GetDefaultBlockWidth(pixel_format)};
|
|
|
+ const u32 tile_y{GetDefaultBlockHeight(pixel_format)};
|
|
|
const u32 bytes_per_pixel{GetBytesPerPixel(pixel_format)};
|
|
|
u32 m_depth = (layer_only ? 1U : depth);
|
|
|
u32 m_width = MipWidth(mip_level);
|
|
|
u32 m_height = MipHeight(mip_level);
|
|
|
- m_width = uncompressed ? m_width
|
|
|
- : std::max(1U, (m_width + compression_factor - 1) / compression_factor);
|
|
|
- m_height = uncompressed
|
|
|
- ? m_height
|
|
|
- : std::max(1U, (m_height + compression_factor - 1) / compression_factor);
|
|
|
+ m_width = uncompressed ? m_width : std::max(1U, (m_width + tile_x - 1) / tile_x);
|
|
|
+ m_height = uncompressed ? m_height : std::max(1U, (m_height + tile_y - 1) / tile_y);
|
|
|
m_depth = std::max(1U, m_depth >> mip_level);
|
|
|
u32 m_block_height = MipBlockHeight(mip_level);
|
|
|
u32 m_block_depth = MipBlockDepth(mip_level);
|
|
|
@@ -128,6 +127,13 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only,
|
|
|
params.target = SurfaceTarget::Texture2D;
|
|
|
}
|
|
|
break;
|
|
|
+ case SurfaceTarget::TextureCubeArray:
|
|
|
+ params.depth = config.tic.Depth() * 6;
|
|
|
+ if (!entry.IsArray()) {
|
|
|
+ ASSERT(params.depth == 6);
|
|
|
+ params.target = SurfaceTarget::TextureCubemap;
|
|
|
+ }
|
|
|
+ break;
|
|
|
default:
|
|
|
LOG_CRITICAL(HW_GPU, "Unknown depth for target={}", static_cast<u32>(params.target));
|
|
|
UNREACHABLE();
|
|
|
@@ -305,6 +311,8 @@ static constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex
|
|
|
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X8_SRGB
|
|
|
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X5_SRGB
|
|
|
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X4_SRGB
|
|
|
+ {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X5
|
|
|
+ {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X5_SRGB
|
|
|
|
|
|
// Depth formats
|
|
|
{GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F
|
|
|
@@ -334,6 +342,8 @@ static GLenum SurfaceTargetToGL(SurfaceTarget target) {
|
|
|
return GL_TEXTURE_2D_ARRAY;
|
|
|
case SurfaceTarget::TextureCubemap:
|
|
|
return GL_TEXTURE_CUBE_MAP;
|
|
|
+ case SurfaceTarget::TextureCubeArray:
|
|
|
+ return GL_TEXTURE_CUBE_MAP_ARRAY_ARB;
|
|
|
}
|
|
|
LOG_CRITICAL(Render_OpenGL, "Unimplemented texture target={}", static_cast<u32>(target));
|
|
|
UNREACHABLE();
|
|
|
@@ -364,15 +374,18 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, u32 block_depth, u32 d
|
|
|
|
|
|
// With the BCn formats (DXT and DXN), each 4x4 tile is swizzled instead of just individual
|
|
|
// pixel values.
|
|
|
- const u32 tile_size{IsFormatBCn(format) ? 4U : 1U};
|
|
|
+ const u32 tile_size_x{GetDefaultBlockWidth(format)};
|
|
|
+ const u32 tile_size_y{GetDefaultBlockHeight(format)};
|
|
|
|
|
|
if (morton_to_gl) {
|
|
|
- const std::vector<u8> data = Tegra::Texture::UnswizzleTexture(
|
|
|
- addr, tile_size, bytes_per_pixel, stride, height, depth, block_height, block_depth);
|
|
|
+ const std::vector<u8> data =
|
|
|
+ Tegra::Texture::UnswizzleTexture(addr, tile_size_x, tile_size_y, bytes_per_pixel,
|
|
|
+ stride, height, depth, block_height, block_depth);
|
|
|
const std::size_t size_to_copy{std::min(gl_buffer_size, data.size())};
|
|
|
memcpy(gl_buffer, data.data(), size_to_copy);
|
|
|
} else {
|
|
|
- Tegra::Texture::CopySwizzledData(stride / tile_size, height / tile_size, depth,
|
|
|
+ Tegra::Texture::CopySwizzledData((stride + tile_size_x - 1) / tile_size_x,
|
|
|
+ (height + tile_size_y - 1) / tile_size_y, depth,
|
|
|
bytes_per_pixel, bytes_per_pixel, Memory::GetPointer(addr),
|
|
|
gl_buffer, false, block_height, block_depth);
|
|
|
}
|
|
|
@@ -440,6 +453,8 @@ static constexpr GLConversionArray morton_to_gl_fns = {
|
|
|
MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>,
|
|
|
MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>,
|
|
|
MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>,
|
|
|
+ MortonCopy<true, PixelFormat::ASTC_2D_5X5>,
|
|
|
+ MortonCopy<true, PixelFormat::ASTC_2D_5X5_SRGB>,
|
|
|
MortonCopy<true, PixelFormat::Z32F>,
|
|
|
MortonCopy<true, PixelFormat::Z16>,
|
|
|
MortonCopy<true, PixelFormat::Z24S8>,
|
|
|
@@ -508,6 +523,8 @@ static constexpr GLConversionArray gl_to_morton_fns = {
|
|
|
nullptr,
|
|
|
nullptr,
|
|
|
nullptr,
|
|
|
+ nullptr,
|
|
|
+ nullptr,
|
|
|
MortonCopy<false, PixelFormat::Z32F>,
|
|
|
MortonCopy<false, PixelFormat::Z16>,
|
|
|
MortonCopy<false, PixelFormat::Z24S8>,
|
|
|
@@ -754,6 +771,7 @@ static void CopySurface(const Surface& src_surface, const Surface& dst_surface,
|
|
|
break;
|
|
|
case SurfaceTarget::Texture3D:
|
|
|
case SurfaceTarget::Texture2DArray:
|
|
|
+ case SurfaceTarget::TextureCubeArray:
|
|
|
glTextureSubImage3D(dst_surface->Texture().handle, 0, 0, 0, 0, width, height,
|
|
|
static_cast<GLsizei>(dst_params.depth), dest_format.format,
|
|
|
dest_format.type, nullptr);
|
|
|
@@ -806,6 +824,7 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
|
|
|
break;
|
|
|
case SurfaceTarget::Texture3D:
|
|
|
case SurfaceTarget::Texture2DArray:
|
|
|
+ case SurfaceTarget::TextureCubeArray:
|
|
|
glTexStorage3D(SurfaceTargetToGL(params.target), params.max_mip_level,
|
|
|
format_tuple.internal_format, rect.GetWidth(), rect.GetHeight(),
|
|
|
params.depth);
|
|
|
@@ -897,21 +916,24 @@ static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) {
|
|
|
* typical desktop GPUs.
|
|
|
*/
|
|
|
static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelFormat pixel_format,
|
|
|
- u32 width, u32 height) {
|
|
|
+ u32 width, u32 height, u32 depth) {
|
|
|
switch (pixel_format) {
|
|
|
case PixelFormat::ASTC_2D_4X4:
|
|
|
case PixelFormat::ASTC_2D_8X8:
|
|
|
case PixelFormat::ASTC_2D_8X5:
|
|
|
case PixelFormat::ASTC_2D_5X4:
|
|
|
+ case PixelFormat::ASTC_2D_5X5:
|
|
|
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_5X4_SRGB:
|
|
|
+ case PixelFormat::ASTC_2D_5X5_SRGB: {
|
|
|
// Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC.
|
|
|
u32 block_width{};
|
|
|
u32 block_height{};
|
|
|
std::tie(block_width, block_height) = GetASTCBlockSize(pixel_format);
|
|
|
- data = Tegra::Texture::ASTC::Decompress(data, width, height, block_width, block_height);
|
|
|
+ data =
|
|
|
+ Tegra::Texture::ASTC::Decompress(data, width, height, depth, block_width, block_height);
|
|
|
break;
|
|
|
}
|
|
|
case PixelFormat::S8Z24:
|
|
|
@@ -971,7 +993,7 @@ void CachedSurface::LoadGLBuffer() {
|
|
|
}
|
|
|
for (u32 i = 0; i < params.max_mip_level; i++)
|
|
|
ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer[i], params.pixel_format, params.MipWidth(i),
|
|
|
- params.MipHeight(i));
|
|
|
+ params.MipHeight(i), params.MipDepth(i));
|
|
|
}
|
|
|
|
|
|
MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64));
|
|
|
@@ -1055,6 +1077,7 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
|
|
|
&gl_buffer[mip_map][buffer_offset]);
|
|
|
break;
|
|
|
case SurfaceTarget::Texture2DArray:
|
|
|
+ case SurfaceTarget::TextureCubeArray:
|
|
|
glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format,
|
|
|
static_cast<GLsizei>(params.MipWidth(mip_map)),
|
|
|
static_cast<GLsizei>(params.MipHeight(mip_map)),
|
|
|
@@ -1104,6 +1127,7 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
|
|
|
tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]);
|
|
|
break;
|
|
|
case SurfaceTarget::Texture2DArray:
|
|
|
+ case SurfaceTarget::TextureCubeArray:
|
|
|
glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0,
|
|
|
static_cast<GLsizei>(rect.GetWidth()),
|
|
|
static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format,
|
|
|
@@ -1307,6 +1331,7 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& old_surface,
|
|
|
case SurfaceTarget::TextureCubemap:
|
|
|
case SurfaceTarget::Texture3D:
|
|
|
case SurfaceTarget::Texture2DArray:
|
|
|
+ case SurfaceTarget::TextureCubeArray:
|
|
|
AccurateCopySurface(old_surface, new_surface);
|
|
|
break;
|
|
|
default:
|