mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -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:
@ -502,6 +502,23 @@ static u32 VerticalFilter(const std::array<u32, 3>& colors,
|
||||
return out_color32;
|
||||
}
|
||||
|
||||
static u32 GammaCorrection(u32 color, const float gamma_rcp)
|
||||
{
|
||||
u8 in_colors[4];
|
||||
std::memcpy(&in_colors, &color, sizeof(in_colors));
|
||||
|
||||
u8 out_color[4];
|
||||
for (int i = BLU_C; i <= RED_C; i++)
|
||||
{
|
||||
out_color[i] = static_cast<u8>(
|
||||
MathUtil::Clamp(std::pow(in_colors[i] / 255.0f, gamma_rcp) * 255.0f, 0.0f, 255.0f));
|
||||
}
|
||||
|
||||
u32 out_color32;
|
||||
std::memcpy(&out_color32, out_color, sizeof(out_color32));
|
||||
return out_color32;
|
||||
}
|
||||
|
||||
// For internal used only, return a non-normalized value, which saves work later.
|
||||
static yuv444 ConvertColorToYUV(u32 color)
|
||||
{
|
||||
@ -530,8 +547,7 @@ u8* GetPixelPointer(u16 x, u16 y, bool depth)
|
||||
}
|
||||
|
||||
void EncodeXFB(u8* xfb_in_ram, u32 memory_stride, const EFBRectangle& source_rect, float y_scale,
|
||||
bool clamp_top, bool clamp_bottom, float Gamma,
|
||||
const std::array<u8, 7>& filterCoefficients)
|
||||
float gamma)
|
||||
{
|
||||
if (!xfb_in_ram)
|
||||
{
|
||||
@ -539,8 +555,12 @@ void EncodeXFB(u8* xfb_in_ram, u32 memory_stride, const EFBRectangle& source_rec
|
||||
return;
|
||||
}
|
||||
|
||||
int left = source_rect.left;
|
||||
int right = source_rect.right;
|
||||
const int left = source_rect.left;
|
||||
const int right = source_rect.right;
|
||||
const bool clamp_top = bpmem.triggerEFBCopy.clamp_top;
|
||||
const bool clamp_bottom = bpmem.triggerEFBCopy.clamp_bottom;
|
||||
const float gamma_rcp = 1.0f / gamma;
|
||||
const auto filter_coefficients = bpmem.copyfilter.GetCoefficients();
|
||||
|
||||
// this assumes copies will always start on an even (YU) pixel and the
|
||||
// copy always has an even width, which might not be true.
|
||||
@ -575,9 +595,10 @@ void EncodeXFB(u8* xfb_in_ram, u32 memory_stride, const EFBRectangle& source_rec
|
||||
std::array<u32, 3> colors = {{GetColor(x, y_prev), GetColor(x, y), GetColor(x, y_next)}};
|
||||
|
||||
// Vertical Filter (Multisampling resolve, deflicker, brightness)
|
||||
u32 filtered = VerticalFilter(colors, filterCoefficients);
|
||||
u32 filtered = VerticalFilter(colors, filter_coefficients);
|
||||
|
||||
// TODO: Gamma correction happens here.
|
||||
// Gamma correction happens here.
|
||||
filtered = GammaCorrection(filtered, gamma_rcp);
|
||||
|
||||
scanline[i] = ConvertColorToYUV(filtered);
|
||||
}
|
||||
|
@ -59,8 +59,7 @@ u32 GetDepth(u16 x, u16 y);
|
||||
u8* GetPixelPointer(u16 x, u16 y, bool depth);
|
||||
|
||||
void EncodeXFB(u8* xfb_in_ram, u32 memory_stride, const EFBRectangle& source_rect, float y_scale,
|
||||
bool clamp_top, bool clamp_bottom, float Gamma,
|
||||
const std::array<u8, 7>& filterCoefficients);
|
||||
float gamma);
|
||||
|
||||
extern u32 perf_values[PQ_NUM_MEMBERS];
|
||||
inline void IncPerfCounterQuadCount(PerfQueryType type)
|
||||
|
@ -87,8 +87,7 @@ std::unique_ptr<AbstractPipeline> SWRenderer::CreatePipeline(const AbstractPipel
|
||||
}
|
||||
|
||||
// Called on the GPU thread
|
||||
void SWRenderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks,
|
||||
float Gamma)
|
||||
void SWRenderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks)
|
||||
{
|
||||
OSD::DoCallbacks(OSD::CallbackType::OnFrame);
|
||||
|
||||
|
@ -34,7 +34,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;
|
||||
|
@ -18,15 +18,18 @@ public:
|
||||
}
|
||||
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
|
||||
{
|
||||
TextureEncoder::Encode(dst, params, native_width, bytes_per_row, num_blocks_y, memory_stride,
|
||||
src_rect, scale_by_half);
|
||||
src_rect, scale_by_half, y_scale, gamma);
|
||||
}
|
||||
|
||||
private:
|
||||
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
|
||||
{
|
||||
// TODO: If we ever want to "fake" vram textures, we would need to implement this
|
||||
}
|
||||
|
@ -1469,15 +1469,12 @@ void EncodeEfbCopy(u8* dst, const EFBCopyParams& params, u32 native_width, u32 b
|
||||
}
|
||||
|
||||
void Encode(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)
|
||||
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect, bool scale_by_half,
|
||||
float y_scale, float gamma)
|
||||
{
|
||||
if (params.copy_format == EFBCopyFormat::XFB)
|
||||
{
|
||||
static constexpr std::array<float, 4> gamma_LUT = {1.0f, 1.7f, 2.2f, 1.0f};
|
||||
EfbInterface::EncodeXFB(dst, native_width, src_rect, params.y_scale,
|
||||
!!bpmem.triggerEFBCopy.clamp_top, !!bpmem.triggerEFBCopy.clamp_bottom,
|
||||
gamma_LUT[bpmem.triggerEFBCopy.gamma],
|
||||
bpmem.copyfilter.GetCoefficients());
|
||||
EfbInterface::EncodeXFB(dst, native_width, src_rect, y_scale, gamma);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -5,12 +5,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "VideoCommon/TextureCacheBase.h"
|
||||
#include "VideoCommon/VideoCommon.h"
|
||||
|
||||
struct EFBCopyParams;
|
||||
|
||||
namespace TextureEncoder
|
||||
{
|
||||
void Encode(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);
|
||||
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect, bool scale_by_half,
|
||||
float y_scale, float gamma);
|
||||
}
|
||||
|
Reference in New Issue
Block a user