mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 14:49:42 -06:00
Implement EFB copy filter and gamma in hardware backends
Also makes y_scale a dynamic parameter for EFB copies, as it doesn't make sense to keep it as part of the uid, otherwise we're generating redundant shaders.
This commit is contained in:
@ -1365,8 +1365,7 @@ void Renderer::ApplyBlendingState(const BlendingState state, bool force)
|
||||
}
|
||||
|
||||
// This function has the final picture. We adjust the aspect ratio here.
|
||||
void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks,
|
||||
float Gamma)
|
||||
void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks)
|
||||
{
|
||||
if (g_ogl_config.bSupportsDebug)
|
||||
{
|
||||
|
@ -126,7 +126,7 @@ public:
|
||||
|
||||
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
|
||||
|
||||
void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) override;
|
||||
void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks) override;
|
||||
|
||||
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
|
||||
u32 color, u32 z) override;
|
||||
|
@ -68,10 +68,18 @@ constexpr const char* geometry_program = "layout(triangles) in;\n"
|
||||
|
||||
void TextureCache::CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width,
|
||||
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
|
||||
const EFBRectangle& src_rect, bool scale_by_half)
|
||||
const EFBRectangle& src_rect, bool scale_by_half, float y_scale,
|
||||
float gamma, bool clamp_top, bool clamp_bottom,
|
||||
const CopyFilterCoefficientArray& filter_coefficients)
|
||||
{
|
||||
// Flip top/bottom due to lower-left coordinate system.
|
||||
float clamp_top_val =
|
||||
clamp_bottom ? (1.0f - src_rect.bottom / static_cast<float>(EFB_HEIGHT)) : 0.0f;
|
||||
float clamp_bottom_val =
|
||||
clamp_top ? (1.0f - src_rect.top / static_cast<float>(EFB_HEIGHT)) : 0.0f;
|
||||
TextureConverter::EncodeToRamFromTexture(dst, params, native_width, bytes_per_row, num_blocks_y,
|
||||
memory_stride, src_rect, scale_by_half);
|
||||
memory_stride, src_rect, scale_by_half, y_scale, gamma,
|
||||
clamp_top_val, clamp_bottom_val, filter_coefficients);
|
||||
}
|
||||
|
||||
TextureCache::TextureCache()
|
||||
@ -483,7 +491,9 @@ void TextureCache::DecodeTextureOnGPU(TCacheEntry* entry, u32 dst_level, const u
|
||||
|
||||
void TextureCache::CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy,
|
||||
const EFBRectangle& src_rect, bool scale_by_half,
|
||||
EFBCopyFormat dst_format, bool is_intensity)
|
||||
EFBCopyFormat dst_format, bool is_intensity, float gamma,
|
||||
bool clamp_top, bool clamp_bottom,
|
||||
const CopyFilterCoefficientArray& filter_coefficients)
|
||||
{
|
||||
auto* destination_texture = static_cast<OGLTexture*>(entry->texture.get());
|
||||
g_renderer->ResetAPIState(); // reset any game specific settings
|
||||
@ -528,6 +538,11 @@ void TextureCache::CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy,
|
||||
code.GetBuffer(), geo_program);
|
||||
|
||||
shader.position_uniform = glGetUniformLocation(shader.shader.glprogid, "copy_position");
|
||||
shader.pixel_height_uniform = glGetUniformLocation(shader.shader.glprogid, "pixel_height");
|
||||
shader.gamma_rcp_uniform = glGetUniformLocation(shader.shader.glprogid, "gamma_rcp");
|
||||
shader.clamp_tb_uniform = glGetUniformLocation(shader.shader.glprogid, "clamp_tb");
|
||||
shader.filter_coefficients_uniform =
|
||||
glGetUniformLocation(shader.shader.glprogid, "filter_coefficients");
|
||||
}
|
||||
|
||||
shader.shader.Bind();
|
||||
@ -535,6 +550,15 @@ void TextureCache::CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy,
|
||||
TargetRectangle R = g_renderer->ConvertEFBRectangle(src_rect);
|
||||
glUniform4f(shader.position_uniform, static_cast<float>(R.left), static_cast<float>(R.top),
|
||||
static_cast<float>(R.right), static_cast<float>(R.bottom));
|
||||
glUniform1f(shader.pixel_height_uniform, g_ActiveConfig.bCopyEFBScaled ?
|
||||
1.0f / g_renderer->GetTargetHeight() :
|
||||
1.0f / EFB_HEIGHT);
|
||||
glUniform1f(shader.gamma_rcp_uniform, 1.0f / gamma);
|
||||
glUniform2f(shader.clamp_tb_uniform,
|
||||
clamp_bottom ? (1.0f - src_rect.bottom / static_cast<float>(EFB_HEIGHT)) : 0.0f,
|
||||
clamp_top ? (1.0f - src_rect.top / static_cast<float>(EFB_HEIGHT)) : 0.0f);
|
||||
glUniform3f(shader.filter_coefficients_uniform, filter_coefficients[0] / 64.0f,
|
||||
filter_coefficients[1] / 64.0f, filter_coefficients[2] / 64.0f);
|
||||
|
||||
ProgramShaderCache::BindVertexFormat(nullptr);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
@ -65,11 +65,13 @@ private:
|
||||
|
||||
void CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
|
||||
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
|
||||
bool scale_by_half) override;
|
||||
bool scale_by_half, float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
|
||||
const CopyFilterCoefficientArray& filter_coefficients) override;
|
||||
|
||||
void CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy, const EFBRectangle& src_rect,
|
||||
bool scale_by_half, EFBCopyFormat dst_format,
|
||||
bool is_intensity) override;
|
||||
bool scale_by_half, EFBCopyFormat dst_format, bool is_intensity,
|
||||
float gamma, bool clamp_top, bool clamp_bottom,
|
||||
const CopyFilterCoefficientArray& filter_coefficients) override;
|
||||
|
||||
bool CompileShaders() override;
|
||||
void DeleteShaders() override;
|
||||
@ -84,6 +86,10 @@ private:
|
||||
{
|
||||
SHADER shader;
|
||||
GLuint position_uniform;
|
||||
GLuint pixel_height_uniform;
|
||||
GLuint gamma_rcp_uniform;
|
||||
GLuint clamp_tb_uniform;
|
||||
GLuint filter_coefficients_uniform;
|
||||
};
|
||||
|
||||
std::map<TextureConversionShaderGen::TCShaderUid, EFBCopyShader> m_efb_copy_programs;
|
||||
|
@ -39,6 +39,9 @@ struct EncodingProgram
|
||||
SHADER program;
|
||||
GLint copy_position_uniform;
|
||||
GLint y_scale_uniform;
|
||||
GLint gamma_rcp_uniform;
|
||||
GLint clamp_tb_uniform;
|
||||
GLint filter_coefficients_uniform;
|
||||
};
|
||||
|
||||
std::map<EFBCopyParams, EncodingProgram> s_encoding_programs;
|
||||
@ -81,6 +84,10 @@ static EncodingProgram& GetOrCreateEncodingShader(const EFBCopyParams& params)
|
||||
|
||||
program.copy_position_uniform = glGetUniformLocation(program.program.glprogid, "position");
|
||||
program.y_scale_uniform = glGetUniformLocation(program.program.glprogid, "y_scale");
|
||||
program.gamma_rcp_uniform = glGetUniformLocation(program.program.glprogid, "gamma_rcp");
|
||||
program.clamp_tb_uniform = glGetUniformLocation(program.program.glprogid, "clamp_tb");
|
||||
program.filter_coefficients_uniform =
|
||||
glGetUniformLocation(program.program.glprogid, "filter_coefficients");
|
||||
return s_encoding_programs.emplace(params, program).first->second;
|
||||
}
|
||||
|
||||
@ -137,7 +144,9 @@ static void EncodeToRamUsingShader(GLuint srcTexture, u8* destAddr, u32 dst_line
|
||||
|
||||
void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyParams& params, u32 native_width,
|
||||
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
|
||||
const EFBRectangle& src_rect, bool scale_by_half)
|
||||
const EFBRectangle& src_rect, bool scale_by_half, float y_scale,
|
||||
float gamma, float clamp_top, float clamp_bottom,
|
||||
const TextureCacheBase::CopyFilterCoefficientArray& filter_coefficients)
|
||||
{
|
||||
g_renderer->ResetAPIState();
|
||||
|
||||
@ -146,14 +155,18 @@ void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyParams& params, u32 nativ
|
||||
texconv_shader.program.Bind();
|
||||
glUniform4i(texconv_shader.copy_position_uniform, src_rect.left, src_rect.top, native_width,
|
||||
scale_by_half ? 2 : 1);
|
||||
glUniform1f(texconv_shader.y_scale_uniform, params.y_scale);
|
||||
glUniform1f(texconv_shader.y_scale_uniform, y_scale);
|
||||
glUniform1f(texconv_shader.gamma_rcp_uniform, 1.0f / gamma);
|
||||
glUniform2f(texconv_shader.clamp_tb_uniform, clamp_top, clamp_bottom);
|
||||
glUniform3i(texconv_shader.filter_coefficients_uniform, filter_coefficients[0],
|
||||
filter_coefficients[1], filter_coefficients[2]);
|
||||
|
||||
const GLuint read_texture = params.depth ?
|
||||
FramebufferManager::ResolveAndGetDepthTarget(src_rect) :
|
||||
FramebufferManager::ResolveAndGetRenderTarget(src_rect);
|
||||
|
||||
EncodeToRamUsingShader(read_texture, dest_ptr, bytes_per_row, num_blocks_y, memory_stride,
|
||||
scale_by_half && !params.depth, params.y_scale);
|
||||
scale_by_half && !params.depth, y_scale);
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
@ -7,10 +7,9 @@
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/GL/GLUtil.h"
|
||||
|
||||
#include "VideoCommon/TextureCacheBase.h"
|
||||
#include "VideoCommon/VideoCommon.h"
|
||||
|
||||
struct EFBCopyParams;
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
// Converts textures between formats using shaders
|
||||
@ -21,9 +20,11 @@ void Init();
|
||||
void Shutdown();
|
||||
|
||||
// returns size of the encoded data (in bytes)
|
||||
void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyParams& params, u32 native_width,
|
||||
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
|
||||
const EFBRectangle& src_rect, bool scale_by_half);
|
||||
void EncodeToRamFromTexture(
|
||||
u8* dest_ptr, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
|
||||
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect, bool scale_by_half,
|
||||
float y_scale, float gamma, float clamp_top, float clamp_bottom,
|
||||
const TextureCacheBase::CopyFilterCoefficientArray& filter_coefficients);
|
||||
}
|
||||
|
||||
} // namespace OGL
|
||||
|
Reference in New Issue
Block a user