diff options
Diffstat (limited to 'src/video_core/renderer_opengl/gl_rasterizer_cache.cpp')
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 116 |
1 files changed, 76 insertions, 40 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index cfc0dae29..2b9c4628f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -44,6 +44,17 @@ struct FormatTuple { bool compressed; }; +static void ApplyTextureDefaults(GLenum target, u32 max_mip_level) { + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, max_mip_level - 1); + if (max_mip_level == 1) { + glTexParameterf(target, GL_TEXTURE_LOD_BIAS, 1000.0); + } +} + void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) { auto& memory_manager{Core::System::GetInstance().GPU().MemoryManager()}; const auto cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr_)}; @@ -101,8 +112,18 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only, params.srgb_conversion = config.tic.IsSrgbConversionEnabled(); params.pixel_format = PixelFormatFromTextureFormat(config.tic.format, config.tic.r_type.Value(), params.srgb_conversion); + + if (params.pixel_format == PixelFormat::R16U && config.tsc.depth_compare_enabled) { + // Some titles create a 'R16U' (normalized 16-bit) texture with depth_compare enabled, + // then attempt to sample from it via a shadow sampler. Convert format to Z16 (which also + // causes GetFormatType to properly return 'Depth' below). + params.pixel_format = PixelFormat::Z16; + } + params.component_type = ComponentTypeFromTexture(config.tic.r_type.Value()); params.type = GetFormatType(params.pixel_format); + UNIMPLEMENTED_IF(params.type == SurfaceType::ColorTexture && config.tsc.depth_compare_enabled); + params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format)); params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format)); params.unaligned_height = config.tic.Height(); @@ -147,6 +168,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only, } params.is_layered = SurfaceTargetIsLayered(params.target); + params.is_array = SurfaceTargetIsArray(params.target); params.max_mip_level = config.tic.max_mip_level + 1; params.rt = {}; @@ -261,7 +283,7 @@ static constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex {GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, ComponentType::UInt, false}, // R8UI {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, ComponentType::Float, false}, // RGBA16F {GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, ComponentType::UNorm, false}, // RGBA16U - {GL_RGBA16UI, GL_RGBA, GL_UNSIGNED_SHORT, ComponentType::UInt, false}, // RGBA16UI + {GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, ComponentType::UInt, false}, // RGBA16UI {GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, ComponentType::Float, false}, // R11FG11FB10F {GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false}, // RGBA32UI @@ -282,8 +304,6 @@ static constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex {GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, ComponentType::Float, true}, // BC6H_SF16 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4 - {GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // G8R8U - {GL_RG8, GL_RG, GL_BYTE, ComponentType::SNorm, false}, // G8R8S {GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // BGRA8 {GL_RGBA32F, GL_RGBA, GL_FLOAT, ComponentType::Float, false}, // RGBA32F {GL_RG32F, GL_RG, GL_FLOAT, ComponentType::Float, false}, // RG32F @@ -437,7 +457,7 @@ static void CopySurface(const Surface& src_surface, const Surface& dst_surface, const std::size_t buffer_size = std::max(src_params.size_in_bytes, dst_params.size_in_bytes); glBindBuffer(GL_PIXEL_PACK_BUFFER, copy_pbo_handle); - glBufferData(GL_PIXEL_PACK_BUFFER, buffer_size, nullptr, GL_STREAM_DRAW); + glBufferData(GL_PIXEL_PACK_BUFFER, buffer_size, nullptr, GL_STREAM_COPY); if (source_format.compressed) { glGetCompressedTextureImage(src_surface->Texture().handle, src_attachment, static_cast<GLsizei>(src_params.size_in_bytes), nullptr); @@ -526,6 +546,9 @@ CachedSurface::CachedSurface(const SurfaceParams& params) glActiveTexture(GL_TEXTURE0); const auto& format_tuple = GetFormatTuple(params.pixel_format, params.component_type); + gl_internal_format = format_tuple.internal_format; + gl_is_compressed = format_tuple.compressed; + if (!format_tuple.compressed) { // Only pre-create the texture for non-compressed textures. switch (params.target) { @@ -554,15 +577,7 @@ CachedSurface::CachedSurface(const SurfaceParams& params) } } - glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAX_LEVEL, - params.max_mip_level - 1); - if (params.max_mip_level == 1) { - glTexParameterf(SurfaceTargetToGL(params.target), GL_TEXTURE_LOD_BIAS, 1000.0); - } + ApplyTextureDefaults(SurfaceTargetToGL(params.target), params.max_mip_level); OpenGL::LabelGLObject(GL_TEXTURE, texture.handle, params.addr, params.IdentityString()); @@ -613,18 +628,6 @@ static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height, bo } } -static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) { - constexpr auto bpp{GetBytesPerPixel(PixelFormat::G8R8U)}; - for (std::size_t y = 0; y < height; ++y) { - for (std::size_t x = 0; x < width; ++x) { - const std::size_t offset{bpp * (y * width + x)}; - const u8 temp{data[offset]}; - data[offset] = data[offset + 1]; - data[offset + 1] = temp; - } - } -} - /** * Helper function to perform software conversion (as needed) when loading a buffer from Switch * memory. This is for Maxwell pixel formats that cannot be represented as-is in OpenGL or with @@ -657,12 +660,6 @@ static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelForma // Convert the S8Z24 depth format to Z24S8, as OpenGL does not support S8Z24. ConvertS8Z24ToZ24S8(data, width, height, false); break; - - case PixelFormat::G8R8U: - case PixelFormat::G8R8S: - // Convert the G8R8 color format to R8G8, as OpenGL does not support G8R8. - ConvertG8R8ToR8G8(data, width, height); - break; } } @@ -674,8 +671,6 @@ static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelForma static void ConvertFormatAsNeeded_FlushGLBuffer(std::vector<u8>& data, PixelFormat pixel_format, u32 width, u32 height) { switch (pixel_format) { - case PixelFormat::G8R8U: - case PixelFormat::G8R8S: case PixelFormat::ASTC_2D_4X4: case PixelFormat::ASTC_2D_8X8: case PixelFormat::ASTC_2D_4X4_SRGB: @@ -879,6 +874,34 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } +void CachedSurface::EnsureTextureView() { + if (texture_view.handle != 0) + return; + // Compressed texture are not being created with immutable storage + UNIMPLEMENTED_IF(gl_is_compressed); + + const GLenum target{TargetLayer()}; + const GLuint num_layers{target == GL_TEXTURE_CUBE_MAP_ARRAY ? 6u : 1u}; + constexpr GLuint min_layer = 0; + constexpr GLuint min_level = 0; + + texture_view.Create(); + glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, min_level, + params.max_mip_level, min_layer, num_layers); + + OpenGLState cur_state = OpenGLState::GetCurState(); + const auto& old_tex = cur_state.texture_units[0]; + SCOPE_EXIT({ + cur_state.texture_units[0] = old_tex; + cur_state.Apply(); + }); + cur_state.texture_units[0].texture = texture_view.handle; + cur_state.texture_units[0].target = target; + cur_state.Apply(); + + ApplyTextureDefaults(target, params.max_mip_level); +} + MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64)); void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) { if (params.type == SurfaceType::Fill) @@ -903,9 +926,16 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu } Surface RasterizerCacheOpenGL::GetDepthBufferSurface(bool preserve_contents) { - const auto& regs{Core::System::GetInstance().GPU().Maxwell3D().regs}; + auto& gpu{Core::System::GetInstance().GPU().Maxwell3D()}; + const auto& regs{gpu.regs}; + + if (!gpu.dirty_flags.zeta_buffer) { + return last_depth_buffer; + } + gpu.dirty_flags.zeta_buffer = false; + if (!regs.zeta.Address() || !regs.zeta_enable) { - return {}; + return last_depth_buffer = {}; } SurfaceParams depth_params{SurfaceParams::CreateForDepthBuffer( @@ -913,25 +943,31 @@ Surface RasterizerCacheOpenGL::GetDepthBufferSurface(bool preserve_contents) { regs.zeta.memory_layout.block_width, regs.zeta.memory_layout.block_height, regs.zeta.memory_layout.block_depth, regs.zeta.memory_layout.type)}; - return GetSurface(depth_params, preserve_contents); + return last_depth_buffer = GetSurface(depth_params, preserve_contents); } Surface RasterizerCacheOpenGL::GetColorBufferSurface(std::size_t index, bool preserve_contents) { - const auto& regs{Core::System::GetInstance().GPU().Maxwell3D().regs}; + auto& gpu{Core::System::GetInstance().GPU().Maxwell3D()}; + const auto& regs{gpu.regs}; + + if ((gpu.dirty_flags.color_buffer & (1u << static_cast<u32>(index))) == 0) { + return last_color_buffers[index]; + } + gpu.dirty_flags.color_buffer &= ~(1u << static_cast<u32>(index)); ASSERT(index < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets); if (index >= regs.rt_control.count) { - return {}; + return last_color_buffers[index] = {}; } if (regs.rt[index].Address() == 0 || regs.rt[index].format == Tegra::RenderTargetFormat::NONE) { - return {}; + return last_color_buffers[index] = {}; } const SurfaceParams color_params{SurfaceParams::CreateForFramebuffer(index)}; - return GetSurface(color_params, preserve_contents); + return last_color_buffers[index] = GetSurface(color_params, preserve_contents); } void RasterizerCacheOpenGL::LoadSurface(const Surface& surface) { |