mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	Merge pull request #350 from Subv/tex_components
GPU: Fixed the incorrect component order in ABGR8 textures.
This commit is contained in:
		
						commit
						6a999cf800
					
				| @ -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<u32> src_rect; | ||||
|  | ||||
| @ -36,6 +36,7 @@ | ||||
| 
 | ||||
| using SurfaceType = SurfaceParams::SurfaceType; | ||||
| using PixelFormat = SurfaceParams::PixelFormat; | ||||
| using ComponentType = SurfaceParams::ComponentType; | ||||
| 
 | ||||
| struct FormatTuple { | ||||
|     GLint internal_format; | ||||
| @ -47,26 +48,21 @@ struct FormatTuple { | ||||
|     u32 compression_factor; | ||||
| }; | ||||
| 
 | ||||
| static constexpr std::array<FormatTuple, 1> fb_format_tuples = {{ | ||||
|     {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, false, 1}, // RGBA8
 | ||||
| }}; | ||||
| 
 | ||||
| static constexpr std::array<FormatTuple, 2> 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
 | ||||
| }}; | ||||
| 
 | ||||
| static const FormatTuple& GetFormatTuple(PixelFormat pixel_format) { | ||||
| static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) { | ||||
|     const SurfaceType type = SurfaceParams::GetFormatType(pixel_format); | ||||
|     if (type == SurfaceType::Color) { | ||||
|         ASSERT(static_cast<size_t>(pixel_format) < fb_format_tuples.size()); | ||||
|         return fb_format_tuples[static_cast<unsigned int>(pixel_format)]; | ||||
|     if (type == SurfaceType::ColorTexture) { | ||||
|         ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size()); | ||||
|         // For now only UNORM components are supported
 | ||||
|         ASSERT(component_type == ComponentType::UNorm); | ||||
|         return tex_format_tuples[static_cast<unsigned int>(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<size_t>(pixel_format) < tex_format_tuples.size()); | ||||
|         return tex_format_tuples[static_cast<unsigned int>(pixel_format)]; | ||||
|     } | ||||
| 
 | ||||
|     UNREACHABLE(); | ||||
| @ -123,13 +119,13 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, VAddr b | ||||
| 
 | ||||
| static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr), 2> morton_to_gl_fns = | ||||
|     { | ||||
|         MortonCopy<true, PixelFormat::RGBA8>, | ||||
|         MortonCopy<true, PixelFormat::ABGR8>, | ||||
|         MortonCopy<true, PixelFormat::DXT1>, | ||||
| }; | ||||
| 
 | ||||
| static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr), 2> gl_to_morton_fns = | ||||
|     { | ||||
|         MortonCopy<false, PixelFormat::RGBA8>, | ||||
|         MortonCopy<false, PixelFormat::ABGR8>, | ||||
|         // TODO(Subv): Swizzling the DXT1 format is not yet supported
 | ||||
|         nullptr, | ||||
| }; | ||||
| @ -180,7 +176,7 @@ static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& 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, | ||||
| @ -309,8 +305,9 @@ MathUtil::Rectangle<u32> 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; | ||||
| } | ||||
| 
 | ||||
| @ -318,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; | ||||
| @ -327,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; | ||||
| @ -338,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) { | ||||
| @ -552,7 +551,7 @@ void CachedSurface::UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint | ||||
|     GLint y0 = static_cast<GLint>(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
 | ||||
| @ -625,7 +624,7 @@ void CachedSurface::DownloadGLTexture(const MathUtil::Rectangle<u32>& 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); | ||||
| @ -658,7 +657,7 @@ void CachedSurface::DownloadGLTexture(const MathUtil::Rectangle<u32>& 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, | ||||
| @ -1038,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 { | ||||
| @ -1105,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"); | ||||
| @ -1300,7 +1307,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); | ||||
| @ -1362,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; | ||||
|  | ||||
| @ -52,18 +52,26 @@ enum class ScaleMatch { | ||||
| 
 | ||||
| struct SurfaceParams { | ||||
|     enum class PixelFormat { | ||||
|         RGBA8 = 0, | ||||
|         ABGR8 = 0, | ||||
|         DXT1 = 1, | ||||
|         Invalid = 255, | ||||
|     }; | ||||
| 
 | ||||
|     enum class ComponentType { | ||||
|         Invalid = 0, | ||||
|         SNorm = 1, | ||||
|         UNorm = 2, | ||||
|         SInt = 3, | ||||
|         UInt = 4, | ||||
|         Float = 5, | ||||
|     }; | ||||
| 
 | ||||
|     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) { | ||||
| @ -71,7 +79,7 @@ struct SurfaceParams { | ||||
|             return 0; | ||||
| 
 | ||||
|         constexpr std::array<unsigned int, 2> bpp_table = { | ||||
|             32, // RGBA8
 | ||||
|             32, // ABGR8
 | ||||
|             64, // DXT1
 | ||||
|         }; | ||||
| 
 | ||||
| @ -85,7 +93,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<u32>(format)); | ||||
|             UNREACHABLE(); | ||||
| @ -95,7 +103,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<u32>(format)); | ||||
|             UNREACHABLE(); | ||||
| @ -106,7 +114,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 +126,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; | ||||
| @ -127,12 +135,45 @@ 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<u32>(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<u32>(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<u32>(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); | ||||
| 
 | ||||
|         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 +189,8 @@ struct SurfaceParams { | ||||
|     } | ||||
| 
 | ||||
|     static SurfaceType GetFormatType(PixelFormat pixel_format) { | ||||
|         if ((unsigned int)pixel_format <= static_cast<unsigned int>(PixelFormat::RGBA8)) { | ||||
|             return SurfaceType::Color; | ||||
|         } | ||||
| 
 | ||||
|         if ((unsigned int)pixel_format <= static_cast<unsigned int>(PixelFormat::DXT1)) { | ||||
|             return SurfaceType::Texture; | ||||
|             return SurfaceType::ColorTexture; | ||||
|         } | ||||
| 
 | ||||
|         // TODO(Subv): Implement the other formats
 | ||||
| @ -231,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 { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 bunnei
						bunnei