From 3ef5ab73232c3084d432c7f74a6dec63361ac2c8 Mon Sep 17 00:00:00 2001 From: GPUCode Date: Wed, 21 Dec 2022 23:02:22 +0200 Subject: [PATCH] video_core: Move pixel format functions to cpp file --- src/video_core/CMakeLists.txt | 8 +- .../rasterizer_cache/pixel_format.cpp | 98 +++++++ .../rasterizer_cache/pixel_format.h | 208 +++++---------- .../rasterizer_cache/surface_params.h | 2 - .../renderer_opengl/depth_to_color.frag | 10 - .../renderer_opengl/depth_to_color.vert | 8 - .../renderer_opengl/ds_to_color.frag | 9 - .../renderer_opengl/gl_texture_runtime.cpp | 8 +- .../renderer_opengl/gl_texture_runtime.h | 7 - .../renderer_opengl/texture_downloader_es.cpp | 250 ------------------ .../renderer_opengl/texture_downloader_es.h | 57 ---- 11 files changed, 173 insertions(+), 492 deletions(-) create mode 100644 src/video_core/rasterizer_cache/pixel_format.cpp delete mode 100644 src/video_core/renderer_opengl/depth_to_color.frag delete mode 100644 src/video_core/renderer_opengl/depth_to_color.vert delete mode 100644 src/video_core/renderer_opengl/ds_to_color.frag delete mode 100644 src/video_core/renderer_opengl/texture_downloader_es.cpp delete mode 100644 src/video_core/renderer_opengl/texture_downloader_es.h diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 474aec6e1..7ad420dae 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -29,6 +29,7 @@ add_library(video_core STATIC renderer_base.cpp renderer_base.h rasterizer_cache/morton_swizzle.h + rasterizer_cache/pixel_format.cpp rasterizer_cache/pixel_format.h rasterizer_cache/rasterizer_cache.cpp rasterizer_cache/rasterizer_cache.h @@ -41,6 +42,8 @@ add_library(video_core STATIC renderer_opengl/frame_dumper_opengl.h renderer_opengl/gl_driver.cpp renderer_opengl/gl_driver.h + renderer_opengl/gl_format_reinterpreter.cpp + renderer_opengl/gl_format_reinterpreter.h renderer_opengl/gl_rasterizer.cpp renderer_opengl/gl_rasterizer.h renderer_opengl/gl_resource_manager.cpp @@ -68,8 +71,6 @@ add_library(video_core STATIC renderer_opengl/post_processing_opengl.h renderer_opengl/renderer_opengl.cpp renderer_opengl/renderer_opengl.h - renderer_opengl/texture_downloader_es.cpp - renderer_opengl/texture_downloader_es.h renderer_opengl/texture_filters/anime4k/anime4k_ultrafast.cpp renderer_opengl/texture_filters/anime4k/anime4k_ultrafast.h renderer_opengl/texture_filters/bicubic/bicubic.cpp @@ -83,9 +84,6 @@ add_library(video_core STATIC renderer_opengl/texture_filters/texture_filterer.h renderer_opengl/texture_filters/xbrz/xbrz_freescale.cpp renderer_opengl/texture_filters/xbrz/xbrz_freescale.h - #temporary, move these back in alphabetical order before merging - renderer_opengl/gl_format_reinterpreter.cpp - renderer_opengl/gl_format_reinterpreter.h renderer_vulkan/pica_to_vk.h renderer_vulkan/renderer_vulkan.cpp renderer_vulkan/renderer_vulkan.h diff --git a/src/video_core/rasterizer_cache/pixel_format.cpp b/src/video_core/rasterizer_cache/pixel_format.cpp new file mode 100644 index 000000000..7f8eb43bf --- /dev/null +++ b/src/video_core/rasterizer_cache/pixel_format.cpp @@ -0,0 +1,98 @@ +// Copyright 2022 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "video_core/rasterizer_cache/pixel_format.h" + +namespace VideoCore { + +std::string_view PixelFormatAsString(PixelFormat format) { + switch (format) { + case PixelFormat::RGBA8: + return "RGBA8"; + case PixelFormat::RGB8: + return "RGB8"; + case PixelFormat::RGB5A1: + return "RGB5A1"; + case PixelFormat::RGB565: + return "RGB565"; + case PixelFormat::RGBA4: + return "RGBA4"; + case PixelFormat::IA8: + return "IA8"; + case PixelFormat::RG8: + return "RG8"; + case PixelFormat::I8: + return "I8"; + case PixelFormat::A8: + return "A8"; + case PixelFormat::IA4: + return "IA4"; + case PixelFormat::I4: + return "I4"; + case PixelFormat::A4: + return "A4"; + case PixelFormat::ETC1: + return "ETC1"; + case PixelFormat::ETC1A4: + return "ETC1A4"; + case PixelFormat::D16: + return "D16"; + case PixelFormat::D24: + return "D24"; + case PixelFormat::D24S8: + return "D24S8"; + default: + return "NotReal"; + } +} + +bool CheckFormatsBlittable(PixelFormat source_format, PixelFormat dest_format) { + SurfaceType source_type = GetFormatType(source_format); + SurfaceType dest_type = GetFormatType(dest_format); + + if ((source_type == SurfaceType::Color || source_type == SurfaceType::Texture) && + (dest_type == SurfaceType::Color || dest_type == SurfaceType::Texture)) { + return true; + } + + if (source_type == SurfaceType::Depth && dest_type == SurfaceType::Depth) { + return true; + } + + if (source_type == SurfaceType::DepthStencil && dest_type == SurfaceType::DepthStencil) { + return true; + } + + return false; +} + +PixelFormat PixelFormatFromTextureFormat(Pica::TexturingRegs::TextureFormat format) { + const u32 format_index = static_cast(format); + return (format_index < 14) ? static_cast(format) : PixelFormat::Invalid; +} + +PixelFormat PixelFormatFromColorFormat(Pica::FramebufferRegs::ColorFormat format) { + const u32 format_index = static_cast(format); + return (format_index < 5) ? static_cast(format) : PixelFormat::Invalid; +} + +PixelFormat PixelFormatFromDepthFormat(Pica::FramebufferRegs::DepthFormat format) { + const u32 format_index = static_cast(format); + return (format_index < 4) ? static_cast(format_index + 14) : PixelFormat::Invalid; +} + +PixelFormat PixelFormatFromGPUPixelFormat(GPU::Regs::PixelFormat format) { + const u32 format_index = static_cast(format); + switch (format) { + // RGB565 and RGB5A1 are switched in PixelFormat compared to ColorFormat + case GPU::Regs::PixelFormat::RGB565: + return PixelFormat::RGB565; + case GPU::Regs::PixelFormat::RGB5A1: + return PixelFormat::RGB5A1; + default: + return (format_index < 5) ? static_cast(format) : PixelFormat::Invalid; + } +} + +} // namespace VideoCore diff --git a/src/video_core/rasterizer_cache/pixel_format.h b/src/video_core/rasterizer_cache/pixel_format.h index 50f1bcfaf..7aa57bebc 100644 --- a/src/video_core/rasterizer_cache/pixel_format.h +++ b/src/video_core/rasterizer_cache/pixel_format.h @@ -11,16 +11,14 @@ namespace VideoCore { -constexpr u32 PIXEL_FORMAT_COUNT = 18; +constexpr std::size_t PIXEL_FORMAT_COUNT = 18; enum class PixelFormat : u32 { - // First 5 formats are shared between textures and color buffers RGBA8 = 0, RGB8 = 1, RGB5A1 = 2, RGB565 = 3, RGBA4 = 4, - // Texture-only formats IA8 = 5, RG8 = 6, I8 = 7, @@ -30,159 +28,77 @@ enum class PixelFormat : u32 { A4 = 11, ETC1 = 12, ETC1A4 = 13, - // Depth buffer-only formats D16 = 14, D24 = 16, D24S8 = 17, + Max = 18, Invalid = 255, }; -enum class SurfaceType { +enum class SurfaceType : u32 { Color = 0, Texture = 1, Depth = 2, DepthStencil = 3, Fill = 4, - Invalid = 5 + Invalid = 5, }; -constexpr std::string_view PixelFormatAsString(PixelFormat format) { - switch (format) { - case PixelFormat::RGBA8: - return "RGBA8"; - case PixelFormat::RGB8: - return "RGB8"; - case PixelFormat::RGB5A1: - return "RGB5A1"; - case PixelFormat::RGB565: - return "RGB565"; - case PixelFormat::RGBA4: - return "RGBA4"; - case PixelFormat::IA8: - return "IA8"; - case PixelFormat::RG8: - return "RG8"; - case PixelFormat::I8: - return "I8"; - case PixelFormat::A8: - return "A8"; - case PixelFormat::IA4: - return "IA4"; - case PixelFormat::I4: - return "I4"; - case PixelFormat::A4: - return "A4"; - case PixelFormat::ETC1: - return "ETC1"; - case PixelFormat::ETC1A4: - return "ETC1A4"; - case PixelFormat::D16: - return "D16"; - case PixelFormat::D24: - return "D24"; - case PixelFormat::D24S8: - return "D24S8"; - default: - return "NotReal"; - } -} +enum class TextureType : u32 { + Texture2D = 0, + CubeMap = 1, +}; -constexpr PixelFormat PixelFormatFromTextureFormat(Pica::TexturingRegs::TextureFormat format) { - const u32 format_index = static_cast(format); - return (format_index < 14) ? static_cast(format) : PixelFormat::Invalid; -} - -constexpr PixelFormat PixelFormatFromColorFormat(Pica::FramebufferRegs::ColorFormat format) { - const u32 format_index = static_cast(format); - return (format_index < 5) ? static_cast(format) : PixelFormat::Invalid; -} - -constexpr PixelFormat PixelFormatFromDepthFormat(Pica::FramebufferRegs::DepthFormat format) { - const u32 format_index = static_cast(format); - return (format_index < 4) ? static_cast(format_index + 14) : PixelFormat::Invalid; -} - -constexpr PixelFormat PixelFormatFromGPUPixelFormat(GPU::Regs::PixelFormat format) { - const u32 format_index = static_cast(format); - switch (format) { - // RGB565 and RGB5A1 are switched in PixelFormat compared to ColorFormat - case GPU::Regs::PixelFormat::RGB565: - return PixelFormat::RGB565; - case GPU::Regs::PixelFormat::RGB5A1: - return PixelFormat::RGB5A1; - default: - return (format_index < 5) ? static_cast(format) : PixelFormat::Invalid; - } -} - -constexpr SurfaceType GetFormatType(PixelFormat pixel_format) { - const u32 format_index = static_cast(pixel_format); - if (format_index < 5) { - return SurfaceType::Color; - } - - if (format_index < 14) { - return SurfaceType::Texture; - } - - if (pixel_format == PixelFormat::D16 || pixel_format == PixelFormat::D24) { - return SurfaceType::Depth; - } - - if (pixel_format == PixelFormat::D24S8) { - return SurfaceType::DepthStencil; - } - - return SurfaceType::Invalid; -} - -constexpr bool CheckFormatsBlittable(PixelFormat source_format, PixelFormat dest_format) { - SurfaceType source_type = GetFormatType(source_format); - SurfaceType dest_type = GetFormatType(dest_format); - - if ((source_type == SurfaceType::Color || source_type == SurfaceType::Texture) && - (dest_type == SurfaceType::Color || dest_type == SurfaceType::Texture)) { - return true; - } - - if (source_type == SurfaceType::Depth && dest_type == SurfaceType::Depth) { - return true; - } - - if (source_type == SurfaceType::DepthStencil && dest_type == SurfaceType::DepthStencil) { - return true; - } - - return false; -} +constexpr std::array BITS_PER_BLOCK_TABLE = {{ + 32, // RGBA8 + 24, // RGB8 + 16, // RGB5A1 + 16, // RGB565 + 16, // RGBA4 + 16, // IA8 + 16, // RG8 + 8, // I8 + 8, // A8 + 8, // IA4 + 4, // I4 + 4, // A4 + 4, // ETC1 + 8, // ETC1A4 + 16, // D16 + 0, + 24, // D24 + 32, // D24S8 +}}; constexpr u32 GetFormatBpp(PixelFormat format) { - switch (format) { - case PixelFormat::RGBA8: - case PixelFormat::D24S8: - return 32; - case PixelFormat::RGB8: - case PixelFormat::D24: - return 24; - case PixelFormat::RGB5A1: - case PixelFormat::RGB565: - case PixelFormat::RGBA4: - case PixelFormat::IA8: - case PixelFormat::RG8: - case PixelFormat::D16: - return 16; - case PixelFormat::I8: - case PixelFormat::A8: - case PixelFormat::IA4: - case PixelFormat::ETC1A4: - return 8; - case PixelFormat::I4: - case PixelFormat::A4: - case PixelFormat::ETC1: - return 4; - default: - return 1; - } + ASSERT(static_cast(format) < BITS_PER_BLOCK_TABLE.size()); + return BITS_PER_BLOCK_TABLE[static_cast(format)]; +} + +constexpr std::array FORMAT_TYPE_TABLE = {{ + SurfaceType::Color, // RGBA8 + SurfaceType::Color, // RGB8 + SurfaceType::Color, // RGB5A1 + SurfaceType::Color, // RGB565 + SurfaceType::Color, // RGBA4 + SurfaceType::Texture, // IA8 + SurfaceType::Texture, // RG8 + SurfaceType::Texture, // I8 + SurfaceType::Texture, // A8 + SurfaceType::Texture, // IA4 + SurfaceType::Texture, // I4 + SurfaceType::Texture, // A4 + SurfaceType::Texture, // ETC1 + SurfaceType::Texture, // ETC1A4 + SurfaceType::Depth, // D16 + SurfaceType::Invalid, + SurfaceType::Depth, // D24 + SurfaceType::DepthStencil, // D24S8 +}}; + +constexpr SurfaceType GetFormatType(PixelFormat format) { + ASSERT(static_cast(format) < FORMAT_TYPE_TABLE.size()); + return FORMAT_TYPE_TABLE[static_cast(format)]; } constexpr u32 GetBytesPerPixel(PixelFormat format) { @@ -194,4 +110,16 @@ constexpr u32 GetBytesPerPixel(PixelFormat format) { return GetFormatBpp(format) / 8; } +std::string_view PixelFormatAsString(PixelFormat format); + +bool CheckFormatsBlittable(PixelFormat source_format, PixelFormat dest_format); + +PixelFormat PixelFormatFromTextureFormat(Pica::TexturingRegs::TextureFormat format); + +PixelFormat PixelFormatFromColorFormat(Pica::FramebufferRegs::ColorFormat format); + +PixelFormat PixelFormatFromDepthFormat(Pica::FramebufferRegs::DepthFormat format); + +PixelFormat PixelFormatFromGPUPixelFormat(GPU::Regs::PixelFormat format); + } // namespace VideoCore diff --git a/src/video_core/rasterizer_cache/surface_params.h b/src/video_core/rasterizer_cache/surface_params.h index 39fe30579..a89f888e9 100644 --- a/src/video_core/rasterizer_cache/surface_params.h +++ b/src/video_core/rasterizer_cache/surface_params.h @@ -15,8 +15,6 @@ namespace VideoCore { using SurfaceInterval = boost::icl::right_open_interval; -enum class TextureType { Texture2D = 0, CubeMap = 1 }; - class SurfaceParams { public: /// Surface match traits diff --git a/src/video_core/renderer_opengl/depth_to_color.frag b/src/video_core/renderer_opengl/depth_to_color.frag deleted file mode 100644 index e69bed890..000000000 --- a/src/video_core/renderer_opengl/depth_to_color.frag +++ /dev/null @@ -1,10 +0,0 @@ -//? #version 320 es - -out highp uint color; - -uniform highp sampler2D depth; -uniform int lod; - -void main() { - color = uint(texelFetch(depth, ivec2(gl_FragCoord.xy), lod).x * (exp2(32.0) - 1.0)); -} diff --git a/src/video_core/renderer_opengl/depth_to_color.vert b/src/video_core/renderer_opengl/depth_to_color.vert deleted file mode 100644 index 866d43b46..000000000 --- a/src/video_core/renderer_opengl/depth_to_color.vert +++ /dev/null @@ -1,8 +0,0 @@ -//? #version 320 es - -const vec2 vertices[4] = - vec2[4](vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0)); - -void main() { - gl_Position = vec4(vertices[gl_VertexID], 0.0, 1.0); -} diff --git a/src/video_core/renderer_opengl/ds_to_color.frag b/src/video_core/renderer_opengl/ds_to_color.frag deleted file mode 100644 index 954217064..000000000 --- a/src/video_core/renderer_opengl/ds_to_color.frag +++ /dev/null @@ -1,9 +0,0 @@ -//? #version 320 es -#extension GL_ARM_shader_framebuffer_fetch_depth_stencil : enable - -out highp uint color; - -void main() { - color = uint(gl_LastFragDepthARM * (exp2(24.0) - 1.0)) << 8; - color |= uint(gl_LastFragStencilARM); -} diff --git a/src/video_core/renderer_opengl/gl_texture_runtime.cpp b/src/video_core/renderer_opengl/gl_texture_runtime.cpp index 2687a4857..e1bb54149 100644 --- a/src/video_core/renderer_opengl/gl_texture_runtime.cpp +++ b/src/video_core/renderer_opengl/gl_texture_runtime.cpp @@ -59,7 +59,7 @@ constexpr u32 DOWNLOAD_BUFFER_SIZE = 32 * 1024 * 1024; TextureRuntime::TextureRuntime(Driver& driver) : driver{driver}, filterer{Settings::values.texture_filter_name.GetValue(), VideoCore::GetResolutionScaleFactor()}, - downloader_es{false}, upload_buffer{GL_PIXEL_UNPACK_BUFFER, UPLOAD_BUFFER_SIZE}, + upload_buffer{GL_PIXEL_UNPACK_BUFFER, UPLOAD_BUFFER_SIZE}, download_buffer{GL_PIXEL_PACK_BUFFER, DOWNLOAD_BUFFER_SIZE, true} { read_fbo.Create(); @@ -466,9 +466,9 @@ void Surface::ScaledDownload(const VideoCore::BufferTextureCopy& download, const auto& tuple = runtime.GetFormatTuple(pixel_format); if (driver.IsOpenGLES()) { - const auto& downloader_es = runtime.GetDownloaderES(); - downloader_es.GetTexImage(GL_TEXTURE_2D, 0, tuple.format, tuple.type, rect_height, - rect_width, reinterpret_cast(staging.buffer_offset)); + runtime.BindFramebuffer(GL_READ_FRAMEBUFFER, 0, GL_TEXTURE_2D, type, unscaled_surface.texture); + glReadPixels(0, 0, rect_width, rect_height, tuple.format, tuple.type, + reinterpret_cast(staging.buffer_offset)); } else { glGetTexImage(GL_TEXTURE_2D, 0, tuple.format, tuple.type, reinterpret_cast(staging.buffer_offset)); diff --git a/src/video_core/renderer_opengl/gl_texture_runtime.h b/src/video_core/renderer_opengl/gl_texture_runtime.h index eb89c164e..f2e8bb9cf 100644 --- a/src/video_core/renderer_opengl/gl_texture_runtime.h +++ b/src/video_core/renderer_opengl/gl_texture_runtime.h @@ -9,7 +9,6 @@ #include "video_core/rasterizer_cache/surface_base.h" #include "video_core/renderer_opengl/gl_format_reinterpreter.h" #include "video_core/renderer_opengl/gl_stream_buffer.h" -#include "video_core/renderer_opengl/texture_downloader_es.h" #include "video_core/renderer_opengl/texture_filters/texture_filterer.h" namespace OpenGL { @@ -87,11 +86,6 @@ private: return driver; } - /// Returns the class that handles texture downloads for OpenGL ES - const TextureDownloaderES& GetDownloaderES() const { - return downloader_es; - } - /// Returns the class that handles texture filtering const TextureFilterer& GetFilterer() const { return filterer; @@ -100,7 +94,6 @@ private: private: Driver& driver; TextureFilterer filterer; - TextureDownloaderES downloader_es; std::array reinterpreters; std::unordered_multimap texture_recycler; OGLStreamBuffer upload_buffer, download_buffer; diff --git a/src/video_core/renderer_opengl/texture_downloader_es.cpp b/src/video_core/renderer_opengl/texture_downloader_es.cpp deleted file mode 100644 index cc3722379..000000000 --- a/src/video_core/renderer_opengl/texture_downloader_es.cpp +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright 2020 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include -#include -#include "common/logging/log.h" -#include "video_core/rasterizer_cache/utils.h" -#include "video_core/renderer_opengl/gl_state.h" -#include "video_core/renderer_opengl/gl_texture_runtime.h" -#include "video_core/renderer_opengl/texture_downloader_es.h" - -#include "shaders/depth_to_color.frag" -#include "shaders/depth_to_color.vert" -#include "shaders/ds_to_color.frag" - -namespace OpenGL { - -static constexpr std::array DEPTH_TUPLES_HACK = { - FormatTuple{GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // D16 - FormatTuple{}, FormatTuple{GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT}, // D24 - FormatTuple{GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // D24S8 -}; - -const FormatTuple& GetFormatTuple(VideoCore::PixelFormat format) { - return DEPTH_TUPLES_HACK[static_cast(format)]; -} - -void TextureDownloaderES::Test() { - auto cur_state = OpenGLState::GetCurState(); - OpenGLState state; - - { - GLint range[2]; - GLint precision; -#define PRECISION_TEST(type) \ - glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, type, range, &precision); \ - LOG_INFO(Render_OpenGL, #type " range: [{}, {}], precision: {}", range[0], range[1], precision); - PRECISION_TEST(GL_LOW_INT); - PRECISION_TEST(GL_MEDIUM_INT); - PRECISION_TEST(GL_HIGH_INT); - PRECISION_TEST(GL_LOW_FLOAT); - PRECISION_TEST(GL_MEDIUM_FLOAT); - PRECISION_TEST(GL_HIGH_FLOAT); -#undef PRECISION_TEST - } - glActiveTexture(GL_TEXTURE0); - - const auto test = [this, &state](FormatTuple tuple, std::vector original_data, - std::size_t tex_size, auto data_generator) { - OGLTexture texture; - texture.Create(); - state.texture_units[0].texture_2d = texture.handle; - state.Apply(); - - original_data.resize(tex_size * tex_size); - for (std::size_t idx = 0; idx < original_data.size(); ++idx) { - original_data[idx] = data_generator(idx); - } - GLsizei tex_sizei = static_cast(tex_size); - glTexStorage2D(GL_TEXTURE_2D, 1, tuple.internal_format, tex_sizei, tex_sizei); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tex_sizei, tex_sizei, tuple.format, tuple.type, - original_data.data()); - - std::vector new_data(original_data.size()); - glFinish(); - auto start = std::chrono::high_resolution_clock::now(); - GetTexImage(GL_TEXTURE_2D, 0, tuple.format, tuple.type, tex_sizei, tex_sizei, - new_data.data()); - glFinish(); - auto time = std::chrono::high_resolution_clock::now() - start; - LOG_INFO(Render_OpenGL, "test took {}", std::chrono::duration(time)); - - int diff = 0; - for (std::size_t idx = 0; idx < original_data.size(); ++idx) - if (new_data[idx] - original_data[idx] != diff) { - diff = new_data[idx] - original_data[idx]; - // every time the error between the real and expected value changes, log it - // some error is expected in D24 due to floating point precision - LOG_WARNING(Render_OpenGL, "difference changed at {:#X}: {:#X} -> {:#X}", idx, - original_data[idx], new_data[idx]); - } - }; - LOG_INFO(Render_OpenGL, "GL_DEPTH24_STENCIL8 download test starting"); - test(GetFormatTuple(VideoCore::PixelFormat::D24S8), std::vector{}, 4096, - [](std::size_t idx) { return static_cast((idx << 8) | (idx & 0xFF)); }); - LOG_INFO(Render_OpenGL, "GL_DEPTH_COMPONENT24 download test starting"); - test(GetFormatTuple(VideoCore::PixelFormat::D24), std::vector{}, 4096, - [](std::size_t idx) { return static_cast(idx << 8); }); - LOG_INFO(Render_OpenGL, "GL_DEPTH_COMPONENT16 download test starting"); - test(GetFormatTuple(VideoCore::PixelFormat::D16), std::vector{}, 256, - [](std::size_t idx) { return static_cast(idx); }); - - cur_state.Apply(); -} - -TextureDownloaderES::TextureDownloaderES(bool enable_depth_stencil) { - vao.Create(); - read_fbo_generic.Create(); - - depth32_fbo.Create(); - r32ui_renderbuffer.Create(); - depth16_fbo.Create(); - r16_renderbuffer.Create(); - - const auto init_program = [](ConversionShader& converter, std::string_view frag) { - converter.program.Create(depth_to_color_vert.data(), frag.data()); - converter.lod_location = glGetUniformLocation(converter.program.handle, "lod"); - }; - - // xperia64: The depth stencil shader currently uses a GLES extension that is not supported - // across all devices Reportedly broken on Tegra devices and the Nexus 6P, so enabling it can be - // toggled - if (enable_depth_stencil) { - init_program(d24s8_r32ui_conversion_shader, ds_to_color_frag); - } - - init_program(d24_r32ui_conversion_shader, depth_to_color_frag); - init_program(d16_r16_conversion_shader, R"( -out highp float color; - -uniform highp sampler2D depth; -uniform int lod; - -void main(){ - color = texelFetch(depth, ivec2(gl_FragCoord.xy), lod).x; -} -)"); - - sampler.Create(); - glSamplerParameteri(sampler.handle, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glSamplerParameteri(sampler.handle, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - auto cur_state = OpenGLState::GetCurState(); - auto state = cur_state; - - state.draw.shader_program = d24s8_r32ui_conversion_shader.program.handle; - state.draw.draw_framebuffer = depth32_fbo.handle; - state.renderbuffer = r32ui_renderbuffer.handle; - state.Apply(); - glRenderbufferStorage(GL_RENDERBUFFER, GL_R32UI, MAX_SIZE, MAX_SIZE); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - r32ui_renderbuffer.handle); - - state.draw.draw_framebuffer = depth16_fbo.handle; - state.renderbuffer = r16_renderbuffer.handle; - state.Apply(); - glRenderbufferStorage(GL_RENDERBUFFER, GL_R16, MAX_SIZE, MAX_SIZE); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, - r16_renderbuffer.handle); - - cur_state.Apply(); -} - -GLuint TextureDownloaderES::ConvertDepthToColor(GLuint level, GLenum& format, GLenum& type, - GLint height, GLint width) const { - ASSERT(width <= MAX_SIZE && height <= MAX_SIZE); - const OpenGLState cur_state = OpenGLState::GetCurState(); - OpenGLState state; - state.texture_units[0] = {cur_state.texture_units[0].texture_2d, sampler.handle}; - state.draw.vertex_array = vao.handle; - - OGLTexture texture_view; - const ConversionShader* converter = nullptr; - switch (type) { - case GL_UNSIGNED_SHORT: - state.draw.draw_framebuffer = depth16_fbo.handle; - converter = &d16_r16_conversion_shader; - format = GL_RED; - break; - case GL_UNSIGNED_INT: - state.draw.draw_framebuffer = depth32_fbo.handle; - converter = &d24_r32ui_conversion_shader; - format = GL_RED_INTEGER; - break; - case GL_UNSIGNED_INT_24_8: - state.draw.draw_framebuffer = depth32_fbo.handle; - converter = &d24s8_r32ui_conversion_shader; - format = GL_RED_INTEGER; - type = GL_UNSIGNED_INT; - break; - default: - UNREACHABLE_MSG("Destination type not recognized"); - } - - state.draw.shader_program = converter->program.handle; - state.viewport = {0, 0, width, height}; - state.Apply(); - if (converter->program.handle == d24s8_r32ui_conversion_shader.program.handle) { - // TODO BreadFish64: the ARM framebuffer reading extension is probably not the most optimal - // way to do this, search for another solution - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, - state.texture_units[0].texture_2d, level); - } - - glUniform1i(converter->lod_location, level); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - if (texture_view.handle) { - glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT); - } - return state.draw.draw_framebuffer; -} - -void TextureDownloaderES::GetTexImage(GLenum target, GLuint level, GLenum format, GLenum type, - GLint height, GLint width, void* pixels) const { - OpenGLState state = OpenGLState::GetCurState(); - GLuint texture{}; - const GLuint old_read_buffer = state.draw.read_framebuffer; - switch (target) { - case GL_TEXTURE_2D: - texture = state.texture_units[0].texture_2d; - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - texture = state.texture_cube_unit.texture_cube; - break; - default: - UNIMPLEMENTED_MSG("Unexpected target {:x}", target); - } - - switch (format) { - case GL_DEPTH_COMPONENT: - case GL_DEPTH_STENCIL: - // unfortunately, the accurate way is too slow for release - return; - state.draw.read_framebuffer = ConvertDepthToColor(level, format, type, height, width); - state.Apply(); - break; - default: - state.draw.read_framebuffer = read_fbo_generic.handle; - state.Apply(); - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, - level); - } - GLenum status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - LOG_DEBUG(Render_OpenGL, "Framebuffer is incomplete, status: {:X}", status); - } - glReadPixels(0, 0, width, height, format, type, pixels); - - state.draw.read_framebuffer = old_read_buffer; - state.Apply(); -} - -} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/texture_downloader_es.h b/src/video_core/renderer_opengl/texture_downloader_es.h deleted file mode 100644 index c5c3d9a5a..000000000 --- a/src/video_core/renderer_opengl/texture_downloader_es.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2020 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once -#include "common/common_types.h" -#include "video_core/renderer_opengl/gl_resource_manager.h" - -namespace OpenGL { - -class OpenGLState; - -class TextureDownloaderES { - static constexpr u16 MAX_SIZE = 1024; - -public: - TextureDownloaderES(bool enable_depth_stencil); - - /** - * OpenGL ES does not support glGetTexImage. Obtain the pixels by attaching the - * texture to a framebuffer. - * Originally from https://github.com/apitrace/apitrace/blob/master/retrace/glstate_images.cpp - * Depth texture download assumes that the texture's format tuple matches what is found - * OpenGL::depth_format_tuples - */ - void GetTexImage(GLenum target, GLuint level, GLenum format, const GLenum type, GLint height, - GLint width, void* pixels) const; - -private: - /** - * OpenGL ES does not support glReadBuffer for depth/stencil formats. - * This gets around it by converting to a Red surface before downloading - */ - GLuint ConvertDepthToColor(GLuint level, GLenum& format, GLenum& type, GLint height, - GLint width) const; - - /// Self tests for the texture downloader - void Test(); - -private: - struct ConversionShader { - OGLProgram program; - GLint lod_location{-1}; - }; - - OGLVertexArray vao; - OGLFramebuffer read_fbo_generic; - OGLFramebuffer depth32_fbo, depth16_fbo; - OGLRenderbuffer r32ui_renderbuffer, r16_renderbuffer; - - ConversionShader d24_r32ui_conversion_shader; - ConversionShader d16_r16_conversion_shader; - ConversionShader d24s8_r32ui_conversion_shader; - OGLSampler sampler; -}; - -} // namespace OpenGL