Files
kaizen/parallel-rdp/shaders/vi_fetch.frag
SimoneN64 d94eccab99 Squashed 'external/parallel-rdp/parallel-rdp-standalone/' content from commit 3f59f61f2c
git-subtree-dir: external/parallel-rdp/parallel-rdp-standalone
git-subtree-split: 3f59f61f2c1c56424356003041df5e4a10612049
2024-09-14 16:23:58 +02:00

164 lines
5.9 KiB
GLSL

#version 450
/* Copyright (c) 2020 Themaister
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#extension GL_EXT_samplerless_texture_functions : require
#include "small_types.h"
#include "vi_status.h"
#include "vi_debug.h"
layout(set = 0, binding = 0) uniform mediump utexture2D uAAInput;
layout(location = 0) out uvec4 FragColor;
#if defined(FETCH_BUG) && FETCH_BUG
layout(location = 1) out uvec4 FragColorFetchBug;
#endif
layout(push_constant) uniform Registers
{
ivec2 offset;
} registers;
ivec2 pix;
uvec4 fetch_color_offset(ivec2 offset)
{
return texelFetch(uAAInput, pix + offset, 0);
}
void check_neighbor(uvec4 candidate,
inout uvec3 lo, inout uvec3 hi,
inout uvec3 second_lo, inout uvec3 second_hi)
{
if (candidate.a == 7u)
{
second_lo = min(second_lo, max(candidate.rgb, lo));
second_hi = max(second_hi, min(candidate.rgb, hi));
lo = min(candidate.rgb, lo);
hi = max(candidate.rgb, hi);
}
}
void main()
{
pix = ivec2(gl_FragCoord.xy) + registers.offset;
uvec4 mid_pixel = fetch_color_offset(ivec2(0));
// AA-filter. If coverage is not full, we blend current pixel against background.
uvec3 color;
#if defined(FETCH_BUG) && FETCH_BUG
uvec3 color_bug;
#endif
if (mid_pixel.a != 7u)
{
uvec3 lo = mid_pixel.rgb;
uvec3 hi = lo;
uvec3 second_lo = lo;
uvec3 second_hi = lo;
// Somehow, we're supposed to find the second lowest and second highest neighbor.
uvec4 left_up = fetch_color_offset(ivec2(-1, -1));
uvec4 right_up = fetch_color_offset(ivec2(+1, -1));
uvec4 to_left = fetch_color_offset(ivec2(-2, 0));
uvec4 to_right = fetch_color_offset(ivec2(+2, 0));
uvec4 left_down = fetch_color_offset(ivec2(-1, +1));
uvec4 right_down = fetch_color_offset(ivec2(+1, +1));
check_neighbor(left_up, lo, hi, second_lo, second_hi);
check_neighbor(right_up, lo, hi, second_lo, second_hi);
check_neighbor(to_left, lo, hi, second_lo, second_hi);
check_neighbor(to_right, lo, hi, second_lo, second_hi);
#if defined(FETCH_BUG) && FETCH_BUG
// In the fetch-bug state, we apparently do not read the lower values.
// Instead, the lower values are treated as left and right.
uvec3 lo_bug = lo;
uvec3 hi_bug = hi;
uvec3 second_lo_bug = second_lo;
uvec3 second_hi_bug = second_hi;
#endif
check_neighbor(left_down, lo, hi, second_lo, second_hi);
check_neighbor(right_down, lo, hi, second_lo, second_hi);
#if defined(FETCH_BUG) && FETCH_BUG
check_neighbor(to_left, lo_bug, hi_bug, second_lo_bug, second_hi_bug);
check_neighbor(to_right, lo_bug, hi_bug, second_lo_bug, second_hi_bug);
second_lo = mix(second_lo, lo, equal(mid_pixel.rgb, lo));
second_hi = mix(second_hi, hi, equal(mid_pixel.rgb, hi));
second_lo_bug = mix(second_lo_bug, lo_bug, equal(mid_pixel.rgb, lo_bug));
second_hi_bug = mix(second_hi_bug, hi_bug, equal(mid_pixel.rgb, hi_bug));
#endif
uvec3 offset = second_lo + second_hi - (mid_pixel.rgb << 1u);
uint coeff = 7u - mid_pixel.a;
color = mid_pixel.rgb + (((offset * coeff) + 4u) >> 3u);
color &= 0xffu;
#if defined(FETCH_BUG) && FETCH_BUG
uvec3 offset_bug = second_lo_bug + second_hi_bug - (mid_pixel.rgb << 1u);
color_bug = mid_pixel.rgb + (((offset_bug * coeff) + 4u) >> 3u);
color_bug &= 0xffu;
#endif
}
else if (DITHER_ENABLE)
{
// Dither filter.
ivec3 tmp_color = ivec3(mid_pixel.rgb >> 3u);
ivec3 tmp_accum = ivec3(0);
for (int y = -1; y <= 0; y++)
{
for (int x = -1; x <= 1; x++)
{
ivec3 col = ivec3(fetch_color_offset(ivec2(x, y)).rgb >> 3u);
tmp_accum += clamp(col - tmp_color, ivec3(-1), ivec3(1));
}
}
#if defined(FETCH_BUG) && FETCH_BUG
ivec3 tmp_accum_bug = tmp_accum;
#endif
tmp_accum += clamp(ivec3(fetch_color_offset(ivec2(-1, 1)).rgb >> 3u) - tmp_color, ivec3(-1), ivec3(1));
tmp_accum += clamp(ivec3(fetch_color_offset(ivec2(+1, 1)).rgb >> 3u) - tmp_color, ivec3(-1), ivec3(1));
tmp_accum += clamp(ivec3(fetch_color_offset(ivec2(0, 1)).rgb >> 3u) - tmp_color, ivec3(-1), ivec3(1));
color = (mid_pixel.rgb & 0xf8u) + tmp_accum;
#if defined(FETCH_BUG) && FETCH_BUG
tmp_accum_bug += clamp(ivec3(fetch_color_offset(ivec2(-1, 0)).rgb >> 3u) - tmp_color, ivec3(-1), ivec3(1));
tmp_accum_bug += clamp(ivec3(fetch_color_offset(ivec2(+1, 0)).rgb >> 3u) - tmp_color, ivec3(-1), ivec3(1));
color_bug = (mid_pixel.rgb & 0xf8u) + tmp_accum_bug;
#endif
}
else
{
color = mid_pixel.rgb;
#if defined(FETCH_BUG) && FETCH_BUG
color_bug = mid_pixel.rgb;
#endif
}
FragColor = uvec4(color, mid_pixel.a);
#if defined(FETCH_BUG) && FETCH_BUG
FragColorFetchBug = uvec4(color_bug, mid_pixel.a);
#endif
}