From b2c1672e108333bb38ae15f6c6677a0f3719896a Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 18 Apr 2018 13:51:09 -0500 Subject: GPU: Texture format 8 and framebuffer format 0xD5 are actually ABGR8. --- src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 6 +++--- src/video_core/renderer_opengl/gl_rasterizer_cache.h | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index a92773f11..d54ddf643 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -52,7 +52,7 @@ static constexpr std::array fb_format_tuples = {{ }}; static constexpr std::array tex_format_tuples = {{ - {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, false, 1}, // RGBA8 + {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false, 1}, // ABGR8 {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT1 }}; @@ -123,13 +123,13 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, VAddr b static constexpr std::array morton_to_gl_fns = { - MortonCopy, + MortonCopy, MortonCopy, }; static constexpr std::array gl_to_morton_fns = { - MortonCopy, + MortonCopy, // TODO(Subv): Swizzling the DXT1 format is not yet supported nullptr, }; diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 26d6c3061..0f8f14404 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -52,7 +52,7 @@ enum class ScaleMatch { struct SurfaceParams { enum class PixelFormat { - RGBA8 = 0, + ABGR8 = 0, DXT1 = 1, Invalid = 255, }; @@ -71,7 +71,7 @@ struct SurfaceParams { return 0; constexpr std::array bpp_table = { - 32, // RGBA8 + 32, // ABGR8 64, // DXT1 }; @@ -85,7 +85,7 @@ struct SurfaceParams { static PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) { switch (format) { case Tegra::RenderTargetFormat::RGBA8_UNORM: - return PixelFormat::RGBA8; + return PixelFormat::ABGR8; default: NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast(format)); UNREACHABLE(); @@ -95,7 +95,7 @@ struct SurfaceParams { static PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) { switch (format) { case Tegra::FramebufferConfig::PixelFormat::ABGR8: - return PixelFormat::RGBA8; + return PixelFormat::ABGR8; default: NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast(format)); UNREACHABLE(); @@ -106,7 +106,7 @@ struct SurfaceParams { // TODO(Subv): Properly implement this switch (format) { case Tegra::Texture::TextureFormat::A8R8G8B8: - return PixelFormat::RGBA8; + return PixelFormat::ABGR8; case Tegra::Texture::TextureFormat::DXT1: return PixelFormat::DXT1; default: @@ -118,7 +118,7 @@ struct SurfaceParams { static Tegra::Texture::TextureFormat TextureFormatFromPixelFormat(PixelFormat format) { // TODO(Subv): Properly implement this switch (format) { - case PixelFormat::RGBA8: + case PixelFormat::ABGR8: return Tegra::Texture::TextureFormat::A8R8G8B8; case PixelFormat::DXT1: return Tegra::Texture::TextureFormat::DXT1; @@ -148,7 +148,7 @@ struct SurfaceParams { } static SurfaceType GetFormatType(PixelFormat pixel_format) { - if ((unsigned int)pixel_format <= static_cast(PixelFormat::RGBA8)) { + if ((unsigned int)pixel_format <= static_cast(PixelFormat::ABGR8)) { return SurfaceType::Color; } -- cgit v1.2.3 From 5b3fab6766d68ddc00fc342fde3c32d449e82535 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 18 Apr 2018 13:54:10 -0500 Subject: GLCache: Unify texture and framebuffer formats when converting to OpenGL. --- .../renderer_opengl/gl_rasterizer_cache.cpp | 19 ++++++------------- src/video_core/renderer_opengl/gl_rasterizer_cache.h | 20 +++++++------------- 2 files changed, 13 insertions(+), 26 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index d54ddf643..10e9dc5c2 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -47,26 +47,20 @@ struct FormatTuple { u32 compression_factor; }; -static constexpr std::array fb_format_tuples = {{ - {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, false, 1}, // RGBA8 -}}; - static constexpr std::array tex_format_tuples = {{ {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false, 1}, // ABGR8 {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT1 }}; static const FormatTuple& GetFormatTuple(PixelFormat pixel_format) { + using Tegra::Texture::ComponentType; const SurfaceType type = SurfaceParams::GetFormatType(pixel_format); - if (type == SurfaceType::Color) { - ASSERT(static_cast(pixel_format) < fb_format_tuples.size()); - return fb_format_tuples[static_cast(pixel_format)]; + if (type == SurfaceType::ColorTexture) { + ASSERT(static_cast(pixel_format) < tex_format_tuples.size()); + return tex_format_tuples[static_cast(pixel_format)]; } else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) { // TODO(Subv): Implement depth formats ASSERT_MSG(false, "Unimplemented"); - } else if (type == SurfaceType::Texture) { - ASSERT(static_cast(pixel_format) < tex_format_tuples.size()); - return tex_format_tuples[static_cast(pixel_format)]; } UNREACHABLE(); @@ -180,7 +174,7 @@ static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle& src_rec u32 buffers = 0; - if (type == SurfaceType::Color || type == SurfaceType::Texture) { + if (type == SurfaceType::ColorTexture) { glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src_tex, 0); glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, @@ -658,7 +652,7 @@ void CachedSurface::DownloadGLTexture(const MathUtil::Rectangle& rect, GLui state.draw.read_framebuffer = read_fb_handle; state.Apply(); - if (type == SurfaceType::Color || type == SurfaceType::Texture) { + if (type == SurfaceType::ColorTexture) { glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.handle, 0); glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, @@ -1300,7 +1294,6 @@ void RasterizerCacheOpenGL::InvalidateRegion(VAddr addr, u64 size, const Surface const SurfaceInterval invalid_interval(addr, addr + size); if (region_owner != nullptr) { - ASSERT(region_owner->type != SurfaceType::Texture); ASSERT(addr >= region_owner->addr && addr + size <= region_owner->end); // Surfaces can't have a gap ASSERT(region_owner->width == region_owner->stride); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 0f8f14404..434cd2277 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -58,12 +58,11 @@ struct SurfaceParams { }; enum class SurfaceType { - Color = 0, - Texture = 1, - Depth = 2, - DepthStencil = 3, - Fill = 4, - Invalid = 5 + ColorTexture = 0, + Depth = 1, + DepthStencil = 2, + Fill = 3, + Invalid = 4, }; static constexpr unsigned int GetFormatBpp(PixelFormat format) { @@ -131,8 +130,7 @@ struct SurfaceParams { SurfaceType a_type = GetFormatType(pixel_format_a); SurfaceType b_type = GetFormatType(pixel_format_b); - if ((a_type == SurfaceType::Color || a_type == SurfaceType::Texture) && - (b_type == SurfaceType::Color || b_type == SurfaceType::Texture)) { + if (a_type == SurfaceType::ColorTexture && b_type == SurfaceType::ColorTexture) { return true; } @@ -148,12 +146,8 @@ struct SurfaceParams { } static SurfaceType GetFormatType(PixelFormat pixel_format) { - if ((unsigned int)pixel_format <= static_cast(PixelFormat::ABGR8)) { - return SurfaceType::Color; - } - if ((unsigned int)pixel_format <= static_cast(PixelFormat::DXT1)) { - return SurfaceType::Texture; + return SurfaceType::ColorTexture; } // TODO(Subv): Implement the other formats -- cgit v1.2.3 From 43d98ca8fee384c5aef462dd37200477e9de2013 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 18 Apr 2018 14:17:05 -0500 Subject: GLCache: Added boilerplate code to make supporting configurable texture component types. For now only the UNORM type is supported. --- src/video_core/renderer_opengl/gl_rasterizer.cpp | 2 + .../renderer_opengl/gl_rasterizer_cache.cpp | 32 +++++++++++----- .../renderer_opengl/gl_rasterizer_cache.h | 44 ++++++++++++++++++++++ 3 files changed, 69 insertions(+), 9 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 9522a35ea..13e2a77ce 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -527,6 +527,8 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& framebu src_params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight; src_params.pixel_format = SurfaceParams::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format); + src_params.component_type = + SurfaceParams::ComponentTypeFromGPUPixelFormat(framebuffer.pixel_format); src_params.UpdateParams(); MathUtil::Rectangle src_rect; diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 10e9dc5c2..9ccc63090 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -36,6 +36,7 @@ using SurfaceType = SurfaceParams::SurfaceType; using PixelFormat = SurfaceParams::PixelFormat; +using ComponentType = SurfaceParams::ComponentType; struct FormatTuple { GLint internal_format; @@ -52,11 +53,12 @@ static constexpr std::array tex_format_tuples = {{ {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT1 }}; -static const FormatTuple& GetFormatTuple(PixelFormat pixel_format) { - using Tegra::Texture::ComponentType; +static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) { const SurfaceType type = SurfaceParams::GetFormatType(pixel_format); if (type == SurfaceType::ColorTexture) { ASSERT(static_cast(pixel_format) < tex_format_tuples.size()); + // For now only UNORM components are supported + ASSERT(component_type == ComponentType::UNorm); return tex_format_tuples[static_cast(pixel_format)]; } else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) { // TODO(Subv): Implement depth formats @@ -303,8 +305,9 @@ MathUtil::Rectangle SurfaceParams::GetScaledSubRect(const SurfaceParams& su bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const { return std::tie(other_surface.addr, other_surface.width, other_surface.height, other_surface.stride, other_surface.block_height, other_surface.pixel_format, - other_surface.is_tiled) == - std::tie(addr, width, height, stride, block_height, pixel_format, is_tiled) && + other_surface.component_type, + other_surface.is_tiled) == std::tie(addr, width, height, stride, block_height, + pixel_format, component_type, is_tiled) && pixel_format != PixelFormat::Invalid; } @@ -312,6 +315,7 @@ bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const { return sub_surface.addr >= addr && sub_surface.end <= end && sub_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid && sub_surface.is_tiled == is_tiled && sub_surface.block_height == block_height && + sub_surface.component_type == component_type && (sub_surface.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 && (sub_surface.stride == stride || sub_surface.height <= (is_tiled ? 8u : 1u)) && GetSubRect(sub_surface).left + sub_surface.width <= stride; @@ -321,7 +325,7 @@ bool SurfaceParams::CanExpand(const SurfaceParams& expanded_surface) const { return pixel_format != PixelFormat::Invalid && pixel_format == expanded_surface.pixel_format && addr <= expanded_surface.end && expanded_surface.addr <= end && is_tiled == expanded_surface.is_tiled && block_height == expanded_surface.block_height && - stride == expanded_surface.stride && + component_type == expanded_surface.component_type && stride == expanded_surface.stride && (std::max(expanded_surface.addr, addr) - std::min(expanded_surface.addr, addr)) % BytesInPixels(stride * (is_tiled ? 8 : 1)) == 0; @@ -332,7 +336,8 @@ bool SurfaceParams::CanTexCopy(const SurfaceParams& texcopy_params) const { end < texcopy_params.end) { return false; } - if (texcopy_params.block_height != block_height) + if (texcopy_params.block_height != block_height || + texcopy_params.component_type != component_type) return false; if (texcopy_params.width != texcopy_params.stride) { @@ -546,7 +551,7 @@ void CachedSurface::UploadGLTexture(const MathUtil::Rectangle& rect, GLuint GLint y0 = static_cast(rect.bottom); size_t buffer_offset = (y0 * stride + x0) * GetGLBytesPerPixel(pixel_format); - const FormatTuple& tuple = GetFormatTuple(pixel_format); + const FormatTuple& tuple = GetFormatTuple(pixel_format, component_type); GLuint target_tex = texture.handle; // If not 1x scale, create 1x texture that we will blit from to replace texture subrect in @@ -619,7 +624,7 @@ void CachedSurface::DownloadGLTexture(const MathUtil::Rectangle& rect, GLui OpenGLState prev_state = state; SCOPE_EXIT({ prev_state.Apply(); }); - const FormatTuple& tuple = GetFormatTuple(pixel_format); + const FormatTuple& tuple = GetFormatTuple(pixel_format, component_type); // Ensure no bad interactions with GL_PACK_ALIGNMENT ASSERT(stride * GetGLBytesPerPixel(pixel_format) % 4 == 0); @@ -1032,6 +1037,13 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu params.is_tiled = config.tic.IsTiled(); params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format); + // TODO(Subv): Different types per component are not supported. + ASSERT(config.tic.r_type.Value() == config.tic.g_type.Value() && + config.tic.r_type.Value() == config.tic.b_type.Value() && + config.tic.r_type.Value() == config.tic.a_type.Value()); + + params.component_type = SurfaceParams::ComponentTypeFromTexture(config.tic.r_type.Value()); + if (config.tic.IsTiled()) { params.block_height = config.tic.BlockHeight(); } else { @@ -1099,6 +1111,7 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( color_params.addr = memory_manager->PhysicalToVirtualAddress(config.Address()); color_params.pixel_format = SurfaceParams::PixelFormatFromRenderTargetFormat(config.format); + color_params.component_type = SurfaceParams::ComponentTypeFromRenderTarget(config.format); color_params.UpdateParams(); ASSERT_MSG(!using_depth_fb, "depth buffer is unimplemented"); @@ -1355,7 +1368,8 @@ Surface RasterizerCacheOpenGL::CreateSurface(const SurfaceParams& params) { surface->gl_buffer_size = 0; surface->invalid_regions.insert(surface->GetInterval()); - AllocateSurfaceTexture(surface->texture.handle, GetFormatTuple(surface->pixel_format), + AllocateSurfaceTexture(surface->texture.handle, + GetFormatTuple(surface->pixel_format, surface->component_type), surface->GetScaledWidth(), surface->GetScaledHeight()); return surface; diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 434cd2277..0ff0ce90f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -57,6 +57,15 @@ struct SurfaceParams { Invalid = 255, }; + enum class ComponentType { + Invalid = 0, + SNorm = 1, + UNorm = 2, + SInt = 3, + UInt = 4, + Float = 5, + }; + enum class SurfaceType { ColorTexture = 0, Depth = 1, @@ -126,6 +135,40 @@ struct SurfaceParams { } } + static ComponentType ComponentTypeFromTexture(Tegra::Texture::ComponentType type) { + // TODO(Subv): Implement more component types + switch (type) { + case Tegra::Texture::ComponentType::UNORM: + return ComponentType::UNorm; + default: + NGLOG_CRITICAL(HW_GPU, "Unimplemented component type={}", static_cast(type)); + UNREACHABLE(); + } + } + + static ComponentType ComponentTypeFromRenderTarget(Tegra::RenderTargetFormat format) { + // TODO(Subv): Implement more render targets + switch (format) { + case Tegra::RenderTargetFormat::RGBA8_UNORM: + case Tegra::RenderTargetFormat::RGB10_A2_UNORM: + return ComponentType::UNorm; + default: + NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast(format)); + UNREACHABLE(); + } + } + + static ComponentType ComponentTypeFromGPUPixelFormat( + Tegra::FramebufferConfig::PixelFormat format) { + switch (format) { + case Tegra::FramebufferConfig::PixelFormat::ABGR8: + return ComponentType::UNorm; + default: + NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast(format)); + UNREACHABLE(); + } + } + static bool CheckFormatsBlittable(PixelFormat pixel_format_a, PixelFormat pixel_format_b) { SurfaceType a_type = GetFormatType(pixel_format_a); SurfaceType b_type = GetFormatType(pixel_format_b); @@ -225,6 +268,7 @@ struct SurfaceParams { bool is_tiled = false; PixelFormat pixel_format = PixelFormat::Invalid; SurfaceType type = SurfaceType::Invalid; + ComponentType component_type = ComponentType::Invalid; }; struct CachedSurface : SurfaceParams { -- cgit v1.2.3