mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-06 18:13:48 -06:00
feat: add thirty emulator profiles and their data
Thirty profiles from the ES-DE batch, each source-verified by the session that wrote it and passing the schema and semantic checks. Five declare no files at all and say why in notes referenced to the code: NGP.emu, openbor, Plastic, Swan.emu and XeniOS. Twenty-eight files come with them, every one declared by the profile that needs it and matching the hash it declares, with no duplicate of anything already held: the NetherSX2 Turnip Classic assets, the Speccy machine ROMs, the Virtual Boy homebrew the app bundles, Snes9x EX+'s bundled game, and sixtyforce's Overrides.plist, which carries a size and no hash because the binary never checks one. supermodel gains the four data files it reads from its install tree, hakux marks its controller map unsourceable now that the asset manager is known to read inside the package, and nethersx2 sheds the two core aliases that belong to the Turnip profiles.
This commit is contained in:
1 parent
87ff398f9a
commit
e42d0815c1
61 files changed
+154724
-7
No files matched your search
File diff suppressed because it is too large.
Load diff
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,107 @@
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Common Interface Definition
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
#if !pGL_ES
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
float gl_PointSize;
|
||||
#if !pGL_ES
|
||||
float gl_ClipDistance[1];
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef GEOMETRY_SHADER
|
||||
|
||||
#if !pGL_ES
|
||||
in gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
float gl_PointSize;
|
||||
#if !pGL_ES
|
||||
float gl_ClipDistance[1];
|
||||
#endif
|
||||
} gl_in[];
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
float gl_PointSize;
|
||||
#if !pGL_ES
|
||||
float gl_ClipDistance[1];
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Constant Buffer Definition
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Performance note, some drivers (nouveau) will validate all Constant Buffers
|
||||
// even if only one was updated.
|
||||
|
||||
#if defined(VERTEX_SHADER) || defined(GEOMETRY_SHADER)
|
||||
layout(std140, binding = 1) uniform cb20
|
||||
{
|
||||
vec2 VertexScale;
|
||||
vec2 VertexOffset;
|
||||
|
||||
vec2 TextureScale;
|
||||
vec2 TextureOffset;
|
||||
|
||||
vec2 PointSize;
|
||||
uint MaxDepth;
|
||||
uint pad_cb20;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(VERTEX_SHADER) || defined(FRAGMENT_SHADER)
|
||||
layout(std140, binding = 0) uniform cb21
|
||||
{
|
||||
vec3 FogColor;
|
||||
float AREF;
|
||||
|
||||
vec4 WH;
|
||||
|
||||
vec2 TA;
|
||||
float MaxDepthPS;
|
||||
float Af;
|
||||
|
||||
uvec4 MskFix;
|
||||
|
||||
uvec4 FbMask;
|
||||
|
||||
vec4 HalfTexel;
|
||||
|
||||
vec4 MinMax;
|
||||
|
||||
ivec4 ChannelShuffle;
|
||||
|
||||
vec2 TC_OffsetHack;
|
||||
vec2 STScale;
|
||||
|
||||
mat4 DitherMatrix;
|
||||
};
|
||||
#endif
|
||||
|
||||
//layout(std140, binding = 22) uniform cb22
|
||||
//{
|
||||
// vec4 rt_size;
|
||||
//};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Default Sampler
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,387 @@
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec2 POSITION;
|
||||
layout(location = 1) in vec2 TEXCOORD0;
|
||||
layout(location = 7) in vec4 COLOR;
|
||||
|
||||
// FIXME set the interpolation (don't know what dx do)
|
||||
// flat means that there is no interpolation. The value given to the fragment shader is based on the provoking vertex conventions.
|
||||
//
|
||||
// noperspective means that there will be linear interpolation in window-space. This is usually not what you want, but it can have its uses.
|
||||
//
|
||||
// smooth, the default, means to do perspective-correct interpolation.
|
||||
//
|
||||
// The centroid qualifier only matters when multisampling. If this qualifier is not present, then the value is interpolated to the pixel's center, anywhere in the pixel, or to one of the pixel's samples. This sample may lie outside of the actual primitive being rendered, since a primitive can cover only part of a pixel's area. The centroid qualifier is used to prevent this; the interpolation point must fall within both the pixel's area and the primitive's area.
|
||||
out vec4 PSin_p;
|
||||
out vec2 PSin_t;
|
||||
out vec4 PSin_c;
|
||||
|
||||
void vs_main()
|
||||
{
|
||||
PSin_p = vec4(POSITION, 0.5f, 1.0f);
|
||||
PSin_t = TEXCOORD0;
|
||||
PSin_c = COLOR;
|
||||
gl_Position = vec4(POSITION, 0.5f, 1.0f); // NOTE I don't know if it is possible to merge POSITION_OUT and gl_Position
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
in vec4 PSin_p;
|
||||
in vec2 PSin_t;
|
||||
in vec4 PSin_c;
|
||||
|
||||
// Give a different name so I remember there is a special case!
|
||||
#if defined(ps_convert_rgba8_16bits) || defined(ps_convert_float32_32bits)
|
||||
layout(location = 0) out uint SV_Target1;
|
||||
#else
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
#endif
|
||||
|
||||
vec4 sample_c()
|
||||
{
|
||||
return texture(TextureSampler, PSin_t);
|
||||
}
|
||||
|
||||
#ifdef ps_copy
|
||||
void ps_copy()
|
||||
{
|
||||
SV_Target0 = sample_c();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_depth_copy
|
||||
void ps_depth_copy()
|
||||
{
|
||||
gl_FragDepth = sample_c().r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_16bits
|
||||
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
|
||||
void ps_convert_rgba8_16bits()
|
||||
{
|
||||
highp uvec4 i = uvec4(sample_c() * vec4(255.5f, 255.5f, 255.5f, 255.5f));
|
||||
|
||||
SV_Target1 = ((i.x & 0x00F8u) >> 3) | ((i.y & 0x00F8u) << 2) | ((i.z & 0x00f8u) << 7) | ((i.w & 0x80u) << 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_32bits
|
||||
void ps_convert_float32_32bits()
|
||||
{
|
||||
// Convert a GL_FLOAT32 depth texture into a 32 bits UINT texture
|
||||
#if HAS_CLIP_CONTROL
|
||||
SV_Target1 = uint(exp2(32.0f) * sample_c().r);
|
||||
#else
|
||||
SV_Target1 = uint(exp2(24.0f) * sample_c().r);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_rgba8
|
||||
void ps_convert_float32_rgba8()
|
||||
{
|
||||
// Convert a GL_FLOAT32 depth texture into a RGBA color texture
|
||||
#if HAS_CLIP_CONTROL
|
||||
uint d = uint(sample_c().r * exp2(32.0f));
|
||||
#else
|
||||
uint d = uint(sample_c().r * exp2(24.0f));
|
||||
#endif
|
||||
SV_Target0 = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24))) / vec4(255.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float16_rgb5a1
|
||||
void ps_convert_float16_rgb5a1()
|
||||
{
|
||||
// Convert a GL_FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||
#if HAS_CLIP_CONTROL
|
||||
uint d = uint(sample_c().r * exp2(32.0f));
|
||||
#else
|
||||
uint d = uint(sample_c().r * exp2(24.0f));
|
||||
#endif
|
||||
SV_Target0 = vec4(uvec4((d & 0x1Fu), ((d >> 5) & 0x1Fu), ((d >> 10) & 0x1Fu), (d >> 15) & 0x01u)) / vec4(32.0f, 32.0f, 32.0f, 1.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
float rgba8_to_depth32(vec4 unorm)
|
||||
{
|
||||
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||
#if HAS_CLIP_CONTROL
|
||||
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-32.0f);
|
||||
#else
|
||||
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-24.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
float rgba8_to_depth24(vec4 unorm)
|
||||
{
|
||||
uvec3 c = uvec3(unorm.rgb * vec3(255.5f));
|
||||
#if HAS_CLIP_CONTROL
|
||||
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-32.0f);
|
||||
#else
|
||||
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-24.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
float rgba8_to_depth16(vec4 unorm)
|
||||
{
|
||||
uvec2 c = uvec2(unorm.rg * vec2(255.5f));
|
||||
#if HAS_CLIP_CONTROL
|
||||
return float(c.r | (c.g << 8)) * exp2(-32.0f);
|
||||
#else
|
||||
return float(c.r | (c.g << 8)) * exp2(-24.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
float rgb5a1_to_depth16(vec4 unorm)
|
||||
{
|
||||
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||
#if HAS_CLIP_CONTROL
|
||||
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
|
||||
#else
|
||||
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-24.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ps_convert_rgba8_float32
|
||||
void ps_convert_rgba8_float32()
|
||||
{
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth32(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float24
|
||||
void ps_convert_rgba8_float24()
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth24(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float16
|
||||
void ps_convert_rgba8_float16()
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth16(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_float16
|
||||
void ps_convert_rgb5a1_float16()
|
||||
{
|
||||
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
gl_FragDepth = rgb5a1_to_depth16(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SAMPLE_RGBA_DEPTH_BILN(CONVERT_FN) \
|
||||
ivec2 dims = textureSize(TextureSampler, 0); \
|
||||
vec2 top_left_f = PSin_t * vec2(dims) - 0.5f; \
|
||||
ivec2 top_left = ivec2(floor(top_left_f)); \
|
||||
ivec4 coords = clamp(ivec4(top_left, top_left + 1), ivec4(0), dims.xyxy - 1); \
|
||||
vec2 mix_vals = fract(top_left_f); \
|
||||
float depthTL = CONVERT_FN(texelFetch(TextureSampler, coords.xy, 0)); \
|
||||
float depthTR = CONVERT_FN(texelFetch(TextureSampler, coords.zy, 0)); \
|
||||
float depthBL = CONVERT_FN(texelFetch(TextureSampler, coords.xw, 0)); \
|
||||
float depthBR = CONVERT_FN(texelFetch(TextureSampler, coords.zw, 0)); \
|
||||
gl_FragDepth = mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y);
|
||||
|
||||
#ifdef ps_convert_rgba8_float32_biln
|
||||
void ps_convert_rgba8_float32_biln()
|
||||
{
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth32);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float24_biln
|
||||
void ps_convert_rgba8_float24_biln()
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth24);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float16_biln
|
||||
void ps_convert_rgba8_float16_biln()
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth16);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_float16_biln
|
||||
void ps_convert_rgb5a1_float16_biln()
|
||||
{
|
||||
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgb5a1_to_depth16);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba_8i
|
||||
void ps_convert_rgba_8i()
|
||||
{
|
||||
// Convert a RGBA texture into a 8 bits packed texture
|
||||
// Input column: 8x2 RGBA pixels
|
||||
// 0: 8 RGBA
|
||||
// 1: 8 RGBA
|
||||
// Output column: 16x4 Index pixels
|
||||
// 0: 8 R | 8 B
|
||||
// 1: 8 R | 8 B
|
||||
// 2: 8 G | 8 A
|
||||
// 3: 8 G | 8 A
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 block = (pos & ~uvec2(15u, 3u)) >> 1;
|
||||
uvec2 subblock = pos & uvec2(7u, 1u);
|
||||
uvec2 coord = block | subblock;
|
||||
|
||||
// Apply offset to cols 1 and 2
|
||||
uint is_col23 = pos.y & 4u;
|
||||
uint is_col13 = pos.y & 2u;
|
||||
uint is_col12 = is_col23 ^ (is_col13 << 1);
|
||||
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
|
||||
|
||||
if (floor(PS_SCALE_FACTOR) != PS_SCALE_FACTOR)
|
||||
coord = uvec2(vec2(coord) * PS_SCALE_FACTOR);
|
||||
else
|
||||
coord *= uvec2(PS_SCALE_FACTOR);
|
||||
|
||||
vec4 pixel = texelFetch(TextureSampler, ivec2(coord), 0);
|
||||
vec2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
|
||||
float sel1 = (pos.x & 8u) == 0u ? sel0.x : sel0.y;
|
||||
SV_Target0 = vec4(sel1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_transparency
|
||||
void ps_filter_transparency()
|
||||
{
|
||||
vec4 c = sample_c();
|
||||
SV_Target0 = vec4(c.rgb, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Used for DATE (stencil)
|
||||
// DATM == 1
|
||||
#ifdef ps_datm1
|
||||
void ps_datm1()
|
||||
{
|
||||
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Used for DATE (stencil)
|
||||
// DATM == 0
|
||||
#ifdef ps_datm0
|
||||
void ps_datm0()
|
||||
{
|
||||
if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_hdr_init
|
||||
void ps_hdr_init()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
SV_Target0 = vec4(round(value.rgb * 255.0f) / 65535.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_hdr_resolve
|
||||
void ps_hdr_resolve()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
SV_Target0 = vec4(vec3(uvec3(value.rgb * 65535.0f) & 255u) / 255.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_yuv
|
||||
uniform ivec2 EMOD;
|
||||
|
||||
void ps_yuv()
|
||||
{
|
||||
vec4 i = sample_c();
|
||||
vec4 o;
|
||||
|
||||
mat3 rgb2yuv; // Value from GS manual
|
||||
rgb2yuv[0] = vec3(0.587, -0.311, -0.419);
|
||||
rgb2yuv[1] = vec3(0.114, 0.500, -0.081);
|
||||
rgb2yuv[2] = vec3(0.299, -0.169, 0.500);
|
||||
|
||||
vec3 yuv = rgb2yuv * i.gbr;
|
||||
|
||||
float Y = float(0xDB)/255.0f * yuv.x + float(0x10)/255.0f;
|
||||
float Cr = float(0xE0)/255.0f * yuv.y + float(0x80)/255.0f;
|
||||
float Cb = float(0xE0)/255.0f * yuv.z + float(0x80)/255.0f;
|
||||
|
||||
switch(EMOD.x) {
|
||||
case 0:
|
||||
o.a = i.a;
|
||||
break;
|
||||
case 1:
|
||||
o.a = Y;
|
||||
break;
|
||||
case 2:
|
||||
o.a = Y/2.0f;
|
||||
break;
|
||||
case 3:
|
||||
o.a = 0.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(EMOD.y) {
|
||||
case 0:
|
||||
o.rgb = i.rgb;
|
||||
break;
|
||||
case 1:
|
||||
o.rgb = vec3(Y);
|
||||
break;
|
||||
case 2:
|
||||
o.rgb = vec3(Y, Cb, Cr);
|
||||
break;
|
||||
case 3:
|
||||
o.rgb = vec3(i.a);
|
||||
break;
|
||||
}
|
||||
|
||||
SV_Target0 = o;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ps_stencil_image_init_0) || defined(ps_stencil_image_init_1)
|
||||
|
||||
void main()
|
||||
{
|
||||
SV_Target0 = vec4(0x7FFFFFFF);
|
||||
|
||||
#ifdef ps_stencil_image_init_0
|
||||
if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
SV_Target0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_1
|
||||
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
SV_Target0 = vec4(-1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,993 @@
|
||||
//#version 420 // Keep it for text editor detection
|
||||
|
||||
// Require for bit operation
|
||||
//#extension GL_ARB_gpu_shader5 : enable
|
||||
|
||||
#define FMT_32 0
|
||||
#define FMT_24 1
|
||||
#define FMT_16 2
|
||||
|
||||
// APITRACE_DEBUG enables forced pixel output to easily detect
|
||||
// the fragment computed by primitive
|
||||
#define APITRACE_DEBUG 0
|
||||
// TEX_COORD_DEBUG output the uv coordinate as color. It is useful
|
||||
// to detect bad sampling due to upscaling
|
||||
//#define TEX_COORD_DEBUG
|
||||
// Just copy directly the texture coordinate
|
||||
#ifdef TEX_COORD_DEBUG
|
||||
#define PS_TFX 1
|
||||
#define PS_TCC 1
|
||||
#endif
|
||||
|
||||
#define SW_BLEND (PS_BLEND_A || PS_BLEND_B || PS_BLEND_D)
|
||||
#define SW_BLEND_NEEDS_RT (SW_BLEND && (PS_BLEND_A == 1 || PS_BLEND_B == 1 || PS_BLEND_C == 1 || PS_BLEND_D == 1))
|
||||
#define SW_AD_TO_HW (PS_BLEND_C == 1 && PS_CLR_HW > 3)
|
||||
#define PS_PRIMID_INIT (PS_DATE == 1 || PS_DATE == 2)
|
||||
#define NEEDS_RT_EARLY (PS_TEX_IS_FB == 1 || PS_DATE >= 5)
|
||||
#define NEEDS_RT (NEEDS_RT_EARLY || (!PS_PRIMID_INIT && (PS_FBMASK || SW_BLEND_NEEDS_RT || SW_AD_TO_HW)))
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
#if !defined(BROKEN_DRIVER) && (pGL_ES || defined(GL_ARB_enhanced_layouts) && GL_ARB_enhanced_layouts)
|
||||
layout(location = 0)
|
||||
#endif
|
||||
in SHADER
|
||||
{
|
||||
vec4 t_float;
|
||||
vec4 t_int;
|
||||
|
||||
#if PS_IIP != 0
|
||||
vec4 c;
|
||||
#else
|
||||
flat vec4 c;
|
||||
#endif
|
||||
} PSin;
|
||||
|
||||
#define TARGET_0_QUALIFIER out
|
||||
|
||||
// Only enable framebuffer fetch when we actually need it.
|
||||
#if HAS_FRAMEBUFFER_FETCH && NEEDS_RT
|
||||
// We need to force the colour to be defined here, to read from it.
|
||||
// Basically the only scenario where this'll happen is RGBA masked and DATE is active.
|
||||
#undef PS_NO_COLOR
|
||||
#define PS_NO_COLOR 0
|
||||
#if defined(GL_EXT_shader_framebuffer_fetch)
|
||||
#undef TARGET_0_QUALIFIER
|
||||
#define TARGET_0_QUALIFIER inout
|
||||
#define LAST_FRAG_COLOR SV_Target0
|
||||
#elif defined(GL_ARM_shader_framebuffer_fetch)
|
||||
#define LAST_FRAG_COLOR gl_LastFragColorARM
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_DEPTH_FETCH && PS_TEX_IS_DS == 1
|
||||
#if defined(GL_ARM_shader_framebuffer_fetch_depth_stencil)
|
||||
#define LAST_FRAG_DEPTH gl_LastFragDepthARM
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !PS_NO_COLOR
|
||||
#if !defined(DISABLE_DUAL_SOURCE) && !PS_NO_COLOR1
|
||||
// Same buffer but 2 colors for dual source blending
|
||||
layout(location = 0, index = 0) TARGET_0_QUALIFIER vec4 SV_Target0;
|
||||
layout(location = 0, index = 1) out vec4 SV_Target1;
|
||||
#else
|
||||
layout(location = 0) TARGET_0_QUALIFIER vec4 SV_Target0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
layout(binding = 1) uniform sampler2D PaletteSampler;
|
||||
|
||||
#if !HAS_FRAMEBUFFER_FETCH && NEEDS_RT
|
||||
layout(binding = 2) uniform sampler2D RtSampler; // note 2 already use by the image below
|
||||
#endif
|
||||
|
||||
#if PS_DATE == 3
|
||||
layout(binding = 3) uniform sampler2D img_prim_min;
|
||||
|
||||
// I don't remember why I set this parameter but it is surely useless
|
||||
//layout(pixel_center_integer) in vec4 gl_FragCoord;
|
||||
#endif
|
||||
|
||||
vec4 fetch_rt()
|
||||
{
|
||||
#if !NEEDS_RT
|
||||
return vec4(0.0);
|
||||
#elif HAS_FRAMEBUFFER_FETCH
|
||||
return LAST_FRAG_COLOR;
|
||||
#else
|
||||
return texelFetch(RtSampler, ivec2(gl_FragCoord.xy), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
vec4 sample_c(vec2 uv)
|
||||
{
|
||||
#if PS_TEX_IS_FB == 1
|
||||
return fetch_rt();
|
||||
#elif PS_TEX_IS_DS == 1
|
||||
return vec4(LAST_FRAG_DEPTH, 0.0f, 0.0f, 0.0f);
|
||||
#else
|
||||
|
||||
#if PS_POINT_SAMPLER
|
||||
// Weird issue with ATI/AMD cards,
|
||||
// it looks like they add 127/128 of a texel to sampling coordinates
|
||||
// occasionally causing point sampling to erroneously round up.
|
||||
// I'm manually adjusting coordinates to the centre of texels here,
|
||||
// though the centre is just paranoia, the top left corner works fine.
|
||||
// As of 2018 this issue is still present.
|
||||
uv = (trunc(uv * WH.zw) + vec2(0.5, 0.5)) / WH.zw;
|
||||
#endif
|
||||
uv *= STScale;
|
||||
|
||||
#if PS_AUTOMATIC_LOD == 1
|
||||
return texture(TextureSampler, uv);
|
||||
#elif PS_MANUAL_LOD == 1
|
||||
// FIXME add LOD: K - ( LOG2(Q) * (1 << L))
|
||||
float K = MinMax.x;
|
||||
float L = MinMax.y;
|
||||
float bias = MinMax.z;
|
||||
float max_lod = MinMax.w;
|
||||
|
||||
float gs_lod = K - log2(abs(PSin.t_float.w)) * L;
|
||||
// FIXME max useful ?
|
||||
//float lod = max(min(gs_lod, max_lod) - bias, 0.0f);
|
||||
float lod = min(gs_lod, max_lod) - bias;
|
||||
|
||||
return textureLod(TextureSampler, uv, lod);
|
||||
#else
|
||||
return textureLod(TextureSampler, uv, 0.0f); // No lod
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
vec4 sample_p(float idx)
|
||||
{
|
||||
return texture(PaletteSampler, vec2(idx, 0.0f));
|
||||
}
|
||||
|
||||
vec4 clamp_wrap_uv(vec4 uv)
|
||||
{
|
||||
vec4 uv_out = uv;
|
||||
#if PS_INVALID_TEX0 == 1
|
||||
vec4 tex_size = WH.zwzw;
|
||||
#else
|
||||
vec4 tex_size = WH.xyxy;
|
||||
#endif
|
||||
|
||||
#if PS_WMS == PS_WMT
|
||||
|
||||
#if PS_WMS == 2
|
||||
uv_out = clamp(uv, MinMax.xyxy, MinMax.zwzw);
|
||||
#elif PS_WMS == 3
|
||||
#if PS_FST == 0
|
||||
// wrap negative uv coords to avoid an off by one error that shifted
|
||||
// textures. Fixes Xenosaga's hair issue.
|
||||
uv = fract(uv);
|
||||
#endif
|
||||
uv_out = vec4((uvec4(uv * tex_size) & MskFix.xyxy) | MskFix.zwzw) / tex_size;
|
||||
#endif
|
||||
|
||||
#else // PS_WMS != PS_WMT
|
||||
|
||||
#if PS_WMS == 2
|
||||
uv_out.xz = clamp(uv.xz, MinMax.xx, MinMax.zz);
|
||||
|
||||
#elif PS_WMS == 3
|
||||
#if PS_FST == 0
|
||||
uv.xz = fract(uv.xz);
|
||||
#endif
|
||||
uv_out.xz = vec2((uvec2(uv.xz * tex_size.xx) & MskFix.xx) | MskFix.zz) / tex_size.xx;
|
||||
|
||||
#endif
|
||||
|
||||
#if PS_WMT == 2
|
||||
uv_out.yw = clamp(uv.yw, MinMax.yy, MinMax.ww);
|
||||
|
||||
#elif PS_WMT == 3
|
||||
#if PS_FST == 0
|
||||
uv.yw = fract(uv.yw);
|
||||
#endif
|
||||
uv_out.yw = vec2((uvec2(uv.yw * tex_size.yy) & MskFix.yy) | MskFix.ww) / tex_size.yy;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
return uv_out;
|
||||
}
|
||||
|
||||
mat4 sample_4c(vec4 uv)
|
||||
{
|
||||
mat4 c;
|
||||
|
||||
// Note: texture gather can't be used because of special clamping/wrapping
|
||||
// Also it doesn't support lod
|
||||
c[0] = sample_c(uv.xy);
|
||||
c[1] = sample_c(uv.zy);
|
||||
c[2] = sample_c(uv.xw);
|
||||
c[3] = sample_c(uv.zw);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
vec4 sample_4_index(vec4 uv)
|
||||
{
|
||||
vec4 c;
|
||||
|
||||
// Either GS will send a texture that contains a single channel
|
||||
// in this case the red channel is remapped as alpha channel
|
||||
//
|
||||
// Or we have an old RT (ie RGBA8) that contains index (4/8) in the alpha channel
|
||||
|
||||
// Note: texture gather can't be used because of special clamping/wrapping
|
||||
// Also it doesn't support lod
|
||||
c.x = sample_c(uv.xy).a;
|
||||
c.y = sample_c(uv.zy).a;
|
||||
c.z = sample_c(uv.xw).a;
|
||||
c.w = sample_c(uv.zw).a;
|
||||
|
||||
uvec4 i = uvec4(c * 255.0f + 0.5f); // Denormalize value
|
||||
|
||||
#if PS_PAL_FMT == 1
|
||||
// 4HL
|
||||
return vec4(i & 0xFu) / 255.0f;
|
||||
|
||||
#elif PS_PAL_FMT == 2
|
||||
// 4HH
|
||||
return vec4(i >> 4u) / 255.0f;
|
||||
|
||||
#else
|
||||
// Most of texture will hit this code so keep normalized float value
|
||||
|
||||
// 8 bits
|
||||
return c;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
mat4 sample_4p(vec4 u)
|
||||
{
|
||||
mat4 c;
|
||||
|
||||
c[0] = sample_p(u.x);
|
||||
c[1] = sample_p(u.y);
|
||||
c[2] = sample_p(u.z);
|
||||
c[3] = sample_p(u.w);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int fetch_raw_depth()
|
||||
{
|
||||
#if HAS_CLIP_CONTROL
|
||||
float multiplier = exp2(32.0f);
|
||||
#else
|
||||
float multiplier = exp2(24.0f);
|
||||
#endif
|
||||
|
||||
#if PS_TEX_IS_FB == 1
|
||||
return int(fetch_rt().r * multiplier);
|
||||
#elif PS_TEX_IS_DS == 1
|
||||
return int(LAST_FRAG_DEPTH * multiplier);
|
||||
#else
|
||||
return int(texelFetch(TextureSampler, ivec2(gl_FragCoord.xy), 0).r * multiplier);
|
||||
#endif
|
||||
}
|
||||
|
||||
vec4 fetch_raw_color()
|
||||
{
|
||||
#if PS_TEX_IS_FB == 1
|
||||
return fetch_rt();
|
||||
#elif PS_TEX_IS_DS == 1
|
||||
return vec4(LAST_FRAG_DEPTH, 0.0f, 0.0f, 0.0f);
|
||||
#else
|
||||
return texelFetch(TextureSampler, ivec2(gl_FragCoord.xy), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
vec4 fetch_c(ivec2 uv)
|
||||
{
|
||||
#if PS_TEX_IS_DS == 1
|
||||
return vec4(LAST_FRAG_DEPTH, 0.0f, 0.0f, 0.0f);
|
||||
#else
|
||||
return texelFetch(TextureSampler, ivec2(uv), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Depth sampling
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
ivec2 clamp_wrap_uv_depth(ivec2 uv)
|
||||
{
|
||||
ivec2 uv_out = uv;
|
||||
|
||||
// Keep the full precision
|
||||
// It allow to multiply the ScalingFactor before the 1/16 coeff
|
||||
ivec4 mask = ivec4(MskFix) << 4;
|
||||
|
||||
#if PS_WMS == PS_WMT
|
||||
|
||||
#if PS_WMS == 2
|
||||
uv_out = clamp(uv, mask.xy, mask.zw);
|
||||
#elif PS_WMS == 3
|
||||
uv_out = (uv & mask.xy) | mask.zw;
|
||||
#endif
|
||||
|
||||
#else // PS_WMS != PS_WMT
|
||||
|
||||
#if PS_WMS == 2
|
||||
uv_out.x = clamp(uv.x, mask.x, mask.z);
|
||||
#elif PS_WMS == 3
|
||||
uv_out.x = (uv.x & mask.x) | mask.z;
|
||||
#endif
|
||||
|
||||
#if PS_WMT == 2
|
||||
uv_out.y = clamp(uv.y, mask.y, mask.w);
|
||||
#elif PS_WMT == 3
|
||||
uv_out.y = (uv.y & mask.y) | mask.w;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
return uv_out;
|
||||
}
|
||||
|
||||
vec4 sample_depth(vec2 st)
|
||||
{
|
||||
vec2 uv_f = vec2(clamp_wrap_uv_depth(ivec2(st))) * vec2(float(PS_SCALE_FACTOR)) * vec2(1.0f/16.0f);
|
||||
ivec2 uv = ivec2(uv_f);
|
||||
|
||||
vec4 t = vec4(0.0f);
|
||||
#if PS_TALES_OF_ABYSS_HLE == 1
|
||||
// Warning: UV can't be used in channel effect
|
||||
int depth = fetch_raw_depth();
|
||||
|
||||
// Convert msb based on the palette
|
||||
t = texelFetch(PaletteSampler, ivec2((depth >> 8) & 0xFF, 0), 0) * 255.0f;
|
||||
|
||||
#elif PS_URBAN_CHAOS_HLE == 1
|
||||
// Depth buffer is read as a RGB5A1 texture. The game try to extract the green channel.
|
||||
// So it will do a first channel trick to extract lsb, value is right-shifted.
|
||||
// Then a new channel trick to extract msb which will shifted to the left.
|
||||
// OpenGL uses a FLOAT32 format for the depth so it requires a couple of conversion.
|
||||
// To be faster both steps (msb&lsb) are done in a single pass.
|
||||
|
||||
// Warning: UV can't be used in channel effect
|
||||
int depth = fetch_raw_depth();
|
||||
|
||||
// Convert lsb based on the palette
|
||||
t = texelFetch(PaletteSampler, ivec2((depth & 0xFF), 0), 0) * 255.0f;
|
||||
|
||||
// Msb is easier
|
||||
float green = float((depth >> 8) & 0xFF) * 36.0f;
|
||||
green = min(green, 255.0f);
|
||||
|
||||
t.g += green;
|
||||
|
||||
|
||||
#elif PS_DEPTH_FMT == 1
|
||||
// Based on ps_convert_float32_rgba8 of convert
|
||||
// Convert a GL_FLOAT32 depth texture into a RGBA color texture
|
||||
#if HAS_CLIP_CONTROL
|
||||
uint d = uint(fetch_c(uv).r * exp2(32.0f));
|
||||
#else
|
||||
uint d = uint(fetch_c(uv).r * exp2(24.0f));
|
||||
#endif
|
||||
t = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24)));
|
||||
|
||||
#elif PS_DEPTH_FMT == 2
|
||||
// Based on ps_convert_float16_rgb5a1 of convert
|
||||
// Convert a GL_FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||
#if HAS_CLIP_CONTROL
|
||||
uint d = uint(fetch_c(uv).r * exp2(32.0f));
|
||||
#else
|
||||
uint d = uint(fetch_c(uv).r * exp2(24.0f));
|
||||
#endif
|
||||
t = vec4(uvec4((d & 0x1Fu), ((d >> 5) & 0x1Fu), ((d >> 10) & 0x1Fu), (d >> 15) & 0x01u)) * vec4(8.0f, 8.0f, 8.0f, 128.0f);
|
||||
|
||||
#elif PS_DEPTH_FMT == 3
|
||||
// Convert a RGBA/RGB5A1 color texture into a RGBA/RGB5A1 color texture
|
||||
t = fetch_c(uv) * 255.0f;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// warning t ranges from 0 to 255
|
||||
#if (PS_AEM_FMT == FMT_24)
|
||||
t.a = ( (PS_AEM == 0) || any(bvec3(t.rgb)) ) ? 255.0f * TA.x : 0.0f;
|
||||
#elif (PS_AEM_FMT == FMT_16)
|
||||
t.a = t.a >= 128.0f ? 255.0f * TA.y : ( (PS_AEM == 0) || any(bvec3(t.rgb)) ) ? 255.0f * TA.x : 0.0f;
|
||||
#endif
|
||||
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Fetch a Single Channel
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
vec4 fetch_red()
|
||||
{
|
||||
#if PS_DEPTH_FMT == 1 || PS_DEPTH_FMT == 2
|
||||
int depth = (fetch_raw_depth()) & 0xFF;
|
||||
vec4 rt = vec4(depth) / 255.0f;
|
||||
#else
|
||||
vec4 rt = fetch_raw_color();
|
||||
#endif
|
||||
return sample_p(rt.r) * 255.0f;
|
||||
}
|
||||
|
||||
vec4 fetch_green()
|
||||
{
|
||||
#if PS_DEPTH_FMT == 1 || PS_DEPTH_FMT == 2
|
||||
int depth = (fetch_raw_depth() >> 8) & 0xFF;
|
||||
vec4 rt = vec4(depth) / 255.0f;
|
||||
#else
|
||||
vec4 rt = fetch_raw_color();
|
||||
#endif
|
||||
return sample_p(rt.g) * 255.0f;
|
||||
}
|
||||
|
||||
vec4 fetch_blue()
|
||||
{
|
||||
#if PS_DEPTH_FMT == 1 || PS_DEPTH_FMT == 2
|
||||
int depth = (fetch_raw_depth() >> 16) & 0xFF;
|
||||
vec4 rt = vec4(depth) / 255.0f;
|
||||
#else
|
||||
vec4 rt = fetch_raw_color();
|
||||
#endif
|
||||
return sample_p(rt.b) * 255.0f;
|
||||
}
|
||||
|
||||
vec4 fetch_alpha()
|
||||
{
|
||||
vec4 rt = fetch_raw_color();
|
||||
return sample_p(rt.a) * 255.0f;
|
||||
}
|
||||
|
||||
vec4 fetch_rgb()
|
||||
{
|
||||
vec4 rt = fetch_raw_color();
|
||||
vec4 c = vec4(sample_p(rt.r).r, sample_p(rt.g).g, sample_p(rt.b).b, 1.0f);
|
||||
return c * 255.0f;
|
||||
}
|
||||
|
||||
vec4 fetch_gXbY()
|
||||
{
|
||||
#if PS_DEPTH_FMT == 1 || PS_DEPTH_FMT == 2
|
||||
int depth = fetch_raw_depth();
|
||||
int bg = (depth >> (8 + ChannelShuffle.w)) & 0xFF;
|
||||
return vec4(bg);
|
||||
#else
|
||||
ivec4 rt = ivec4(fetch_raw_color() * 255.0f);
|
||||
int green = (rt.g >> ChannelShuffle.w) & ChannelShuffle.z;
|
||||
int blue = (rt.b << ChannelShuffle.y) & ChannelShuffle.x;
|
||||
return vec4(green | blue);
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
vec4 sample_color(vec2 st)
|
||||
{
|
||||
#if (PS_TCOFFSETHACK == 1)
|
||||
st += TC_OffsetHack.xy;
|
||||
#endif
|
||||
|
||||
vec4 t;
|
||||
mat4 c;
|
||||
vec2 dd;
|
||||
|
||||
// FIXME I'm not sure this condition is useful (I think code will be optimized)
|
||||
#if (PS_LTF == 0 && PS_AEM_FMT == FMT_32 && PS_PAL_FMT == 0 && PS_WMS < 2 && PS_WMT < 2)
|
||||
// No software LTF and pure 32 bits RGBA texure without special texture wrapping
|
||||
c[0] = sample_c(st);
|
||||
#ifdef TEX_COORD_DEBUG
|
||||
c[0].rg = st.xy;
|
||||
#endif
|
||||
|
||||
#else
|
||||
vec4 uv;
|
||||
|
||||
if(PS_LTF != 0)
|
||||
{
|
||||
uv = st.xyxy + HalfTexel;
|
||||
dd = fract(uv.xy * WH.zw);
|
||||
#if (PS_FST == 0)
|
||||
// Background in Shin Megami Tensei Lucifers
|
||||
// I suspect that uv isn't a standard number, so fract is outside of the [0;1] range
|
||||
// Note: it is free on GPU but let's do it only for float coordinate
|
||||
dd = clamp(dd, vec2(0.0f), vec2(1.0f));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
uv = st.xyxy;
|
||||
}
|
||||
|
||||
uv = clamp_wrap_uv(uv);
|
||||
|
||||
#if PS_PAL_FMT != 0
|
||||
c = sample_4p(sample_4_index(uv));
|
||||
#else
|
||||
c = sample_4c(uv);
|
||||
#endif
|
||||
|
||||
#ifdef TEX_COORD_DEBUG
|
||||
c[0].rg = uv.xy;
|
||||
c[1].rg = uv.xy;
|
||||
c[2].rg = uv.xy;
|
||||
c[3].rg = uv.xy;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// PERF note: using dot product reduces by 1 the number of instruction
|
||||
// but I'm not sure it is equivalent neither faster.
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
//float sum = dot(c[i].rgb, vec3(1.0f));
|
||||
#if (PS_AEM_FMT == FMT_24)
|
||||
c[i].a = ( (PS_AEM == 0) || any(bvec3(c[i].rgb)) ) ? TA.x : 0.0f;
|
||||
//c[i].a = ( (PS_AEM == 0) || (sum > 0.0f) ) ? TA.x : 0.0f;
|
||||
#elif (PS_AEM_FMT == FMT_16)
|
||||
c[i].a = c[i].a >= 0.5 ? TA.y : ( (PS_AEM == 0) || any(bvec3(c[i].rgb)) ) ? TA.x : 0.0f;
|
||||
//c[i].a = c[i].a >= 0.5 ? TA.y : ( (PS_AEM == 0) || (sum > 0.0f) ) ? TA.x : 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if(PS_LTF != 0)
|
||||
t = mix(mix(c[0], c[1], dd.x), mix(c[2], c[3], dd.x), dd.y);
|
||||
#else
|
||||
t = c[0];
|
||||
#endif
|
||||
|
||||
// The 0.05f helps to fix the overbloom of sotc
|
||||
// I think the issue is related to the rounding of texture coodinate. The linear (from fixed unit)
|
||||
// interpolation could be slightly below the correct one.
|
||||
return trunc(t * 255.0f + 0.05f);
|
||||
}
|
||||
|
||||
vec4 tfx(vec4 T, vec4 C)
|
||||
{
|
||||
vec4 C_out;
|
||||
vec4 FxT = trunc(trunc(C) * T / 128.0f);
|
||||
|
||||
#if (PS_TFX == 0)
|
||||
C_out = FxT;
|
||||
#elif (PS_TFX == 1)
|
||||
C_out = T;
|
||||
#elif (PS_TFX == 2)
|
||||
C_out.rgb = FxT.rgb + C.a;
|
||||
C_out.a = T.a + C.a;
|
||||
#elif (PS_TFX == 3)
|
||||
C_out.rgb = FxT.rgb + C.a;
|
||||
C_out.a = T.a;
|
||||
#else
|
||||
C_out = C;
|
||||
#endif
|
||||
|
||||
#if (PS_TCC == 0)
|
||||
C_out.a = C.a;
|
||||
#endif
|
||||
|
||||
#if (PS_TFX == 0) || (PS_TFX == 2) || (PS_TFX == 3)
|
||||
// Clamp only when it is useful
|
||||
C_out = min(C_out, 255.0f);
|
||||
#endif
|
||||
|
||||
return C_out;
|
||||
}
|
||||
|
||||
void atst(vec4 C)
|
||||
{
|
||||
float a = C.a;
|
||||
|
||||
#if (PS_ATST == 0)
|
||||
// nothing to do
|
||||
#elif (PS_ATST == 1)
|
||||
if (a > AREF) discard;
|
||||
#elif (PS_ATST == 2)
|
||||
if (a < AREF) discard;
|
||||
#elif (PS_ATST == 3)
|
||||
if (abs(a - AREF) > 0.5f) discard;
|
||||
#elif (PS_ATST == 4)
|
||||
if (abs(a - AREF) < 0.5f) discard;
|
||||
#endif
|
||||
}
|
||||
|
||||
void fog(inout vec4 C, float f)
|
||||
{
|
||||
#if PS_FOG != 0
|
||||
C.rgb = trunc(mix(FogColor, C.rgb, f));
|
||||
#endif
|
||||
}
|
||||
|
||||
vec4 ps_color()
|
||||
{
|
||||
//FIXME: maybe we can set gl_Position.w = q in VS
|
||||
#if (PS_FST == 0) && (PS_INVALID_TEX0 == 1)
|
||||
// Re-normalize coordinate from invalid GS to corrected texture size
|
||||
vec2 st = (PSin.t_float.xy * WH.xy) / (vec2(PSin.t_float.w) * WH.zw);
|
||||
vec2 st_int = (PSin.t_int.zw * WH.xy) / (vec2(PSin.t_float.w) * WH.zw);
|
||||
#elif (PS_FST == 0)
|
||||
vec2 st = PSin.t_float.xy / vec2(PSin.t_float.w);
|
||||
vec2 st_int = PSin.t_int.zw / vec2(PSin.t_float.w);
|
||||
#else
|
||||
// Note xy are normalized coordinate
|
||||
vec2 st = PSin.t_int.xy;
|
||||
vec2 st_int = PSin.t_int.zw;
|
||||
#endif
|
||||
|
||||
#if PS_CHANNEL_FETCH == 1
|
||||
vec4 T = fetch_red();
|
||||
#elif PS_CHANNEL_FETCH == 2
|
||||
vec4 T = fetch_green();
|
||||
#elif PS_CHANNEL_FETCH == 3
|
||||
vec4 T = fetch_blue();
|
||||
#elif PS_CHANNEL_FETCH == 4
|
||||
vec4 T = fetch_alpha();
|
||||
#elif PS_CHANNEL_FETCH == 5
|
||||
vec4 T = fetch_rgb();
|
||||
#elif PS_CHANNEL_FETCH == 6
|
||||
vec4 T = fetch_gXbY();
|
||||
#elif PS_DEPTH_FMT > 0
|
||||
// Integral coordinate
|
||||
vec4 T = sample_depth(st_int);
|
||||
#else
|
||||
vec4 T = sample_color(st);
|
||||
#endif
|
||||
|
||||
vec4 C = tfx(T, PSin.c);
|
||||
|
||||
atst(C);
|
||||
|
||||
fog(C, PSin.t_float.z);
|
||||
|
||||
return C;
|
||||
}
|
||||
|
||||
void ps_fbmask(inout vec4 C)
|
||||
{
|
||||
// FIXME do I need special case for 16 bits
|
||||
#if PS_FBMASK
|
||||
vec4 RT = trunc(fetch_rt() * 255.0f + 0.1f);
|
||||
C = vec4((uvec4(C) & ~FbMask) | (uvec4(RT) & FbMask));
|
||||
#endif
|
||||
}
|
||||
|
||||
void ps_dither(inout vec3 C)
|
||||
{
|
||||
#if PS_DITHER
|
||||
#if PS_DITHER == 2
|
||||
ivec2 fpos = ivec2(gl_FragCoord.xy);
|
||||
#else
|
||||
ivec2 fpos = ivec2(gl_FragCoord.xy / float(PS_SCALE_FACTOR));
|
||||
#endif
|
||||
C += DitherMatrix[fpos.y&3][fpos.x&3];
|
||||
#endif
|
||||
}
|
||||
|
||||
void ps_color_clamp_wrap(inout vec3 C)
|
||||
{
|
||||
// When dithering the bottom 3 bits become meaningless and cause lines in the picture
|
||||
// so we need to limit the color depth on dithered items
|
||||
#if SW_BLEND || PS_DITHER || PS_FBMASK
|
||||
|
||||
// Correct the Color value based on the output format
|
||||
#if PS_COLCLIP == 0 && PS_HDR == 0
|
||||
// Standard Clamp
|
||||
C = clamp(C, vec3(0.0f), vec3(255.0f));
|
||||
#endif
|
||||
|
||||
// FIXME rouding of negative float?
|
||||
// compiler uses trunc but it might need floor
|
||||
|
||||
// Warning: normally blending equation is mult(A, B) = A * B >> 7. GPU have the full accuracy
|
||||
// GS: Color = 1, Alpha = 255 => output 1
|
||||
// GPU: Color = 1/255, Alpha = 255/255 * 255/128 => output 1.9921875
|
||||
#if PS_DFMT == FMT_16 && PS_BLEND_MIX == 0
|
||||
// In 16 bits format, only 5 bits of colors are used. It impacts shadows computation of Castlevania
|
||||
C = vec3(ivec3(C) & ivec3(0xF8));
|
||||
#elif PS_COLCLIP == 1 || PS_HDR == 1
|
||||
C = vec3(ivec3(C) & ivec3(0xFF));
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void ps_blend(inout vec4 Color, inout float As)
|
||||
{
|
||||
#if SW_BLEND
|
||||
|
||||
// PABE
|
||||
#if PS_PABE
|
||||
// No blending so early exit
|
||||
if (As < 1.0f)
|
||||
return;
|
||||
#endif
|
||||
|
||||
vec3 Cs = Color.rgb;
|
||||
|
||||
#if SW_BLEND_NEEDS_RT
|
||||
vec4 RT = trunc(fetch_rt() * 255.0f + 0.1f);
|
||||
// FIXME FMT_16 case
|
||||
// FIXME Ad or Ad * 2?
|
||||
float Ad = RT.a / 128.0f;
|
||||
|
||||
// Let the compiler do its jobs !
|
||||
vec3 Cd = RT.rgb;
|
||||
#endif
|
||||
|
||||
#if PS_BLEND_A == 0
|
||||
vec3 A = Cs;
|
||||
#elif PS_BLEND_A == 1
|
||||
vec3 A = Cd;
|
||||
#else
|
||||
vec3 A = vec3(0.0f);
|
||||
#endif
|
||||
|
||||
#if PS_BLEND_B == 0
|
||||
vec3 B = Cs;
|
||||
#elif PS_BLEND_B == 1
|
||||
vec3 B = Cd;
|
||||
#else
|
||||
vec3 B = vec3(0.0f);
|
||||
#endif
|
||||
|
||||
#if PS_BLEND_C == 0
|
||||
float C = As;
|
||||
#elif PS_BLEND_C == 1
|
||||
float C = Ad;
|
||||
#else
|
||||
float C = Af;
|
||||
#endif
|
||||
|
||||
#if PS_BLEND_D == 0
|
||||
vec3 D = Cs;
|
||||
#elif PS_BLEND_D == 1
|
||||
vec3 D = Cd;
|
||||
#else
|
||||
vec3 D = vec3(0.0f);
|
||||
#endif
|
||||
|
||||
// As/Af clamp alpha for Blend mix
|
||||
// We shouldn't clamp blend mix with clr1 as we want alpha higher
|
||||
float C_clamped = C;
|
||||
#if PS_BLEND_MIX > 0 && PS_CLR_HW != 1
|
||||
C_clamped = min(C_clamped, 1.0f);
|
||||
#endif
|
||||
|
||||
#if PS_BLEND_A == PS_BLEND_B
|
||||
Color.rgb = D;
|
||||
// In blend_mix, HW adds on some alpha factor * dst.
|
||||
// Truncating here wouldn't quite get the right result because it prevents the <1 bit here from combining with a <1 bit in dst to form a ≥1 amount that pushes over the truncation.
|
||||
// Instead, apply an offset to convert HW's round to a floor.
|
||||
// Since alpha is in 1/128 increments, subtracting (0.5 - 0.5/128 == 127/256) would get us what we want if GPUs blended in full precision.
|
||||
// But they don't. Details here: https://github.com/PCSX2/pcsx2/pull/6809#issuecomment-1211473399
|
||||
// Based on the scripts at the above link, the ideal choice for Intel GPUs is 126/256, AMD 120/256. Nvidia is a lost cause.
|
||||
// 124/256 seems like a reasonable compromise, providing the correct answer 99.3% of the time on Intel (vs 99.6% for 126/256), and 97% of the time on AMD (vs 97.4% for 120/256).
|
||||
#elif PS_BLEND_MIX == 2
|
||||
Color.rgb = ((A - B) * C_clamped + D) + (124.0f/256.0f);
|
||||
#elif PS_BLEND_MIX == 1
|
||||
Color.rgb = ((A - B) * C_clamped + D) - (124.0f/256.0f);
|
||||
#else
|
||||
Color.rgb = trunc((A - B) * C + D);
|
||||
#endif
|
||||
|
||||
#if PS_CLR_HW == 1
|
||||
// Replace Af with As so we can do proper compensation for Alpha.
|
||||
#if PS_BLEND_C == 2
|
||||
As = Af;
|
||||
#endif
|
||||
// Subtract 1 for alpha to compensate for the changed equation,
|
||||
// if c.rgb > 255.0f then we further need to adjust alpha accordingly,
|
||||
// we pick the lowest overflow from all colors because it's the safest,
|
||||
// we divide by 255 the color because we don't know Cd value,
|
||||
// changed alpha should only be done for hw blend.
|
||||
float min_color = min(min(Color.r, Color.g), Color.b);
|
||||
float alpha_compensate = max(1.0f, min_color / 255.0f);
|
||||
As -= alpha_compensate;
|
||||
#elif PS_CLR_HW == 2
|
||||
// Compensate slightly for Cd*(As + 1) - Cs*As.
|
||||
// The initial factor we chose is 1 (0.00392)
|
||||
// as that is the minimum color Cd can be,
|
||||
// then we multiply by alpha to get the minimum
|
||||
// blended value it can be.
|
||||
float color_compensate = 1.0f * (C + 1.0f);
|
||||
Color.rgb -= vec3(color_compensate);
|
||||
#endif
|
||||
|
||||
#else
|
||||
// Needed for Cd * (As/Ad/F + 1) blending modes
|
||||
#if PS_CLR_HW == 1 || PS_CLR_HW == 5
|
||||
Color.rgb = vec3(255.0f);
|
||||
#elif PS_CLR_HW == 2 || PS_CLR_HW == 4
|
||||
// Cd*As,Cd*Ad or Cd*F
|
||||
|
||||
#if PS_BLEND_C == 2
|
||||
float Alpha = Af;
|
||||
#else
|
||||
float Alpha = As;
|
||||
#endif
|
||||
|
||||
Color.rgb = max(vec3(0.0f), (Alpha - vec3(1.0f)));
|
||||
Color.rgb *= vec3(255.0f);
|
||||
#elif PS_CLR_HW == 3
|
||||
// Needed for Cs*Ad, Cs*Ad + Cd, Cd - Cs*Ad
|
||||
// Multiply Color.rgb by (255/128) to compensate for wrong Ad/255 value
|
||||
|
||||
Color.rgb *= (255.0f / 128.0f);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void ps_main()
|
||||
{
|
||||
#if PS_SCANMSK & 2
|
||||
// fail depth test on prohibited lines
|
||||
if ((int(gl_FragCoord.y) & 1) == (PS_SCANMSK & 1))
|
||||
discard;
|
||||
#endif
|
||||
|
||||
#if PS_DATE >= 5
|
||||
|
||||
#if PS_WRITE_RG == 1
|
||||
// Pseudo 16 bits access.
|
||||
float rt_a = fetch_rt().g;
|
||||
#else
|
||||
float rt_a = fetch_rt().a;
|
||||
#endif
|
||||
|
||||
#if (PS_DATE & 3) == 1
|
||||
// DATM == 0: Pixel with alpha equal to 1 will failed
|
||||
bool bad = (127.5f / 255.0f) < rt_a;
|
||||
#elif (PS_DATE & 3) == 2
|
||||
// DATM == 1: Pixel with alpha equal to 0 will failed
|
||||
bool bad = rt_a < (127.5f / 255.0f);
|
||||
#endif
|
||||
|
||||
if (bad) {
|
||||
discard;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if PS_DATE == 3
|
||||
int stencil_ceil = int(texelFetch(img_prim_min, ivec2(gl_FragCoord.xy), 0).r);
|
||||
// Note gl_PrimitiveID == stencil_ceil will be the primitive that will update
|
||||
// the bad alpha value so we must keep it.
|
||||
|
||||
if (gl_PrimitiveID > stencil_ceil) {
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
vec4 C = ps_color();
|
||||
#if (APITRACE_DEBUG & 1) == 1
|
||||
C.r = 255.0f;
|
||||
#endif
|
||||
#if (APITRACE_DEBUG & 2) == 2
|
||||
C.g = 255.0f;
|
||||
#endif
|
||||
#if (APITRACE_DEBUG & 4) == 4
|
||||
C.b = 255.0f;
|
||||
#endif
|
||||
#if (APITRACE_DEBUG & 8) == 8
|
||||
C.a = 128.0f;
|
||||
#endif
|
||||
|
||||
#if PS_SHUFFLE
|
||||
uvec4 denorm_c = uvec4(C);
|
||||
uvec2 denorm_TA = uvec2(vec2(TA.xy) * 255.0f + 0.5f);
|
||||
|
||||
// Write RB part. Mask will take care of the correct destination
|
||||
#if PS_READ_BA
|
||||
C.rb = C.bb;
|
||||
#else
|
||||
C.rb = C.rr;
|
||||
#endif
|
||||
|
||||
// FIXME precompute my_TA & 0x80
|
||||
|
||||
// Write GA part. Mask will take care of the correct destination
|
||||
// Note: GLSL 4.50/GL_EXT_shader_integer_mix support a mix instruction to select a component\n"
|
||||
// However Nvidia emulate it with an if (at least on kepler arch) ...\n"
|
||||
#if PS_READ_BA
|
||||
// bit field operation requires GL4 HW. Could be nice to merge it with step/mix below
|
||||
// uint my_ta = (bool(bitfieldExtract(denorm_c.a, 7, 1))) ? denorm_TA.y : denorm_TA.x;
|
||||
// denorm_c.a = bitfieldInsert(denorm_c.a, bitfieldExtract(my_ta, 7, 1), 7, 1);
|
||||
// c.ga = vec2(float(denorm_c.a));
|
||||
|
||||
if (bool(denorm_c.a & 0x80u))
|
||||
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
|
||||
#else
|
||||
if (bool(denorm_c.g & 0x80u))
|
||||
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
|
||||
// Nice idea but step/mix requires 4 instructions
|
||||
// set / trunc / I2F / Mad
|
||||
//
|
||||
// float sel = step(128.0f, c.g);
|
||||
// vec2 c_shuffle = vec2((denorm_c.gg & 0x7Fu) | (denorm_TA & 0x80u));
|
||||
// c.ga = mix(c_shuffle.xx, c_shuffle.yy, sel);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Must be done before alpha correction
|
||||
|
||||
// AA (Fixed one) will output a coverage of 1.0 as alpha
|
||||
#if PS_FIXED_ONE_A
|
||||
C.a = 128.0f;
|
||||
#endif
|
||||
|
||||
#if SW_AD_TO_HW
|
||||
vec4 RT = trunc(fetch_rt() * 255.0f + 0.1f);
|
||||
float alpha_blend = RT.a / 128.0f;
|
||||
#else
|
||||
float alpha_blend = C.a / 128.0f;
|
||||
#endif
|
||||
|
||||
// Correct the ALPHA value based on the output format
|
||||
#if (PS_DFMT == FMT_16)
|
||||
float A_one = 128.0f; // alpha output will be 0x80
|
||||
C.a = (PS_FBA != 0) ? A_one : step(128.0f, C.a) * A_one;
|
||||
#elif (PS_DFMT == FMT_32) && (PS_FBA != 0)
|
||||
if(C.a < 128.0f) C.a += 128.0f;
|
||||
#endif
|
||||
|
||||
// Get first primitive that will write a failling alpha value
|
||||
#if PS_DATE == 1
|
||||
// DATM == 0
|
||||
// Pixel with alpha equal to 1 will failed (128-255)
|
||||
SV_Target0 = (C.a > 127.5f) ? vec4(gl_PrimitiveID) : vec4(0x7FFFFFFF);
|
||||
return;
|
||||
#elif PS_DATE == 2
|
||||
// DATM == 1
|
||||
// Pixel with alpha equal to 0 will failed (0-127)
|
||||
SV_Target0 = (C.a < 127.5f) ? vec4(gl_PrimitiveID) : vec4(0x7FFFFFFF);
|
||||
return;
|
||||
#endif
|
||||
|
||||
ps_blend(C, alpha_blend);
|
||||
|
||||
ps_dither(C.rgb);
|
||||
|
||||
// Color clamp/wrap needs to be done after sw blending and dithering
|
||||
ps_color_clamp_wrap(C.rgb);
|
||||
|
||||
ps_fbmask(C);
|
||||
|
||||
#if !PS_NO_COLOR
|
||||
#if PS_HDR == 1
|
||||
SV_Target0 = vec4(C.rgb / 65535.0f, C.a / 255.0f);
|
||||
#else
|
||||
SV_Target0 = C / 255.0f;
|
||||
#endif
|
||||
#if !defined(DISABLE_DUAL_SOURCE) && !PS_NO_COLOR1
|
||||
SV_Target1 = vec4(alpha_blend);
|
||||
#endif
|
||||
|
||||
#if PS_NO_ABLEND
|
||||
// write alpha blend factor into col0
|
||||
SV_Target0.a = alpha_blend;
|
||||
#endif
|
||||
#if PS_ONLY_ALPHA
|
||||
// rgb isn't used
|
||||
SV_Target0.rgb = vec3(0.0f);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PS_ZCLAMP
|
||||
gl_FragDepth = min(gl_FragCoord.z, MaxDepthPS);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,351 @@
|
||||
#ifndef PS_SCALE_FACTOR
|
||||
#define PS_SCALE_FACTOR 1.0
|
||||
#endif
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
layout(location = 1) in vec2 a_tex;
|
||||
|
||||
layout(location = 0) out vec2 v_tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(a_pos.x, -a_pos.y, a_pos.z, a_pos.w);
|
||||
v_tex = a_tex;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(location = 0) in vec2 v_tex;
|
||||
|
||||
#if defined(ps_convert_rgba8_16bits) || defined(ps_convert_float32_32bits)
|
||||
layout(location = 0) out uint o_col0;
|
||||
#else
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
#endif
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D samp0;
|
||||
|
||||
vec4 sample_c(vec2 uv)
|
||||
{
|
||||
return texture(samp0, uv);
|
||||
}
|
||||
|
||||
#ifdef ps_copy
|
||||
void ps_copy()
|
||||
{
|
||||
o_col0 = sample_c(v_tex);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_depth_copy
|
||||
void ps_depth_copy()
|
||||
{
|
||||
gl_FragDepth = sample_c(v_tex).r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_transparency
|
||||
void ps_filter_transparency()
|
||||
{
|
||||
vec4 c = sample_c(v_tex);
|
||||
o_col0 = vec4(c.rgb, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_16bits
|
||||
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
|
||||
void ps_convert_rgba8_16bits()
|
||||
{
|
||||
uvec4 i = uvec4(sample_c(v_tex) * vec4(255.5f, 255.5f, 255.5f, 255.5f));
|
||||
|
||||
o_col0 = ((i.x & 0x00F8u) >> 3) | ((i.y & 0x00F8u) << 2) | ((i.z & 0x00f8u) << 7) | ((i.w & 0x80u) << 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_datm1
|
||||
void ps_datm1()
|
||||
{
|
||||
o_col0 = vec4(0, 0, 0, 0);
|
||||
|
||||
if(sample_c(v_tex).a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
discard;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_datm0
|
||||
void ps_datm0()
|
||||
{
|
||||
o_col0 = vec4(0, 0, 0, 0);
|
||||
|
||||
if((127.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_hdr_init
|
||||
void ps_hdr_init()
|
||||
{
|
||||
vec4 value = sample_c(v_tex);
|
||||
o_col0 = vec4(roundEven(value.rgb * 255.0f) / 65535.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_hdr_resolve
|
||||
void ps_hdr_resolve()
|
||||
{
|
||||
vec4 value = sample_c(v_tex);
|
||||
o_col0 = vec4(vec3(uvec3(value.rgb * 65535.5f) & 255u) / 255.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_32bits
|
||||
void ps_convert_float32_32bits()
|
||||
{
|
||||
// Convert a vec32 depth texture into a 32 bits UINT texture
|
||||
o_col0 = uint(exp2(32.0f) * sample_c(v_tex).r);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_rgba8
|
||||
void ps_convert_float32_rgba8()
|
||||
{
|
||||
// Convert a vec32 depth texture into a RGBA color texture
|
||||
uint d = uint(sample_c(v_tex).r * exp2(32.0f));
|
||||
o_col0 = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24))) / vec4(255.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float16_rgb5a1
|
||||
void ps_convert_float16_rgb5a1()
|
||||
{
|
||||
// Convert a vec32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||
uint d = uint(sample_c(v_tex).r * exp2(32.0f));
|
||||
o_col0 = vec4(uvec4((d & 0x1Fu), ((d >> 5) & 0x1Fu), ((d >> 10) & 0x1Fu), (d >> 15) & 0x01u)) / vec4(32.0f, 32.0f, 32.0f, 1.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
float rgba8_to_depth32(vec4 unorm)
|
||||
{
|
||||
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgba8_to_depth24(vec4 unorm)
|
||||
{
|
||||
uvec3 c = uvec3(unorm.rgb * vec3(255.5f));
|
||||
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgba8_to_depth16(vec4 unorm)
|
||||
{
|
||||
uvec2 c = uvec2(unorm.rg * vec2(255.5f));
|
||||
return float(c.r | (c.g << 8)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgb5a1_to_depth16(vec4 unorm)
|
||||
{
|
||||
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
#ifdef ps_convert_rgba8_float32
|
||||
void ps_convert_rgba8_float32()
|
||||
{
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth32(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float24
|
||||
void ps_convert_rgba8_float24()
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth24(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float16
|
||||
void ps_convert_rgba8_float16()
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth16(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_float16
|
||||
void ps_convert_rgb5a1_float16()
|
||||
{
|
||||
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
gl_FragDepth = rgb5a1_to_depth16(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SAMPLE_RGBA_DEPTH_BILN(CONVERT_FN) \
|
||||
ivec2 dims = textureSize(samp0, 0); \
|
||||
vec2 top_left_f = v_tex * vec2(dims) - 0.5f; \
|
||||
ivec2 top_left = ivec2(floor(top_left_f)); \
|
||||
ivec4 coords = clamp(ivec4(top_left, top_left + 1), ivec4(0), dims.xyxy - 1); \
|
||||
vec2 mix_vals = fract(top_left_f); \
|
||||
float depthTL = CONVERT_FN(texelFetch(samp0, coords.xy, 0)); \
|
||||
float depthTR = CONVERT_FN(texelFetch(samp0, coords.zy, 0)); \
|
||||
float depthBL = CONVERT_FN(texelFetch(samp0, coords.xw, 0)); \
|
||||
float depthBR = CONVERT_FN(texelFetch(samp0, coords.zw, 0)); \
|
||||
gl_FragDepth = mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y);
|
||||
|
||||
#ifdef ps_convert_rgba8_float32_biln
|
||||
void ps_convert_rgba8_float32_biln()
|
||||
{
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth32);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float24_biln
|
||||
void ps_convert_rgba8_float24_biln()
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth24);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float16_biln
|
||||
void ps_convert_rgba8_float16_biln()
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth16);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_float16_biln
|
||||
void ps_convert_rgb5a1_float16_biln()
|
||||
{
|
||||
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgb5a1_to_depth16);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba_8i
|
||||
void ps_convert_rgba_8i()
|
||||
{
|
||||
// Convert a RGBA texture into a 8 bits packed texture
|
||||
// Input column: 8x2 RGBA pixels
|
||||
// 0: 8 RGBA
|
||||
// 1: 8 RGBA
|
||||
// Output column: 16x4 Index pixels
|
||||
// 0: 8 R | 8 B
|
||||
// 1: 8 R | 8 B
|
||||
// 2: 8 G | 8 A
|
||||
// 3: 8 G | 8 A
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 block = (pos & ~uvec2(15u, 3u)) >> 1;
|
||||
uvec2 subblock = pos & uvec2(7u, 1u);
|
||||
uvec2 coord = block | subblock;
|
||||
|
||||
// Apply offset to cols 1 and 2
|
||||
uint is_col23 = pos.y & 4u;
|
||||
uint is_col13 = pos.y & 2u;
|
||||
uint is_col12 = is_col23 ^ (is_col13 << 1);
|
||||
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
|
||||
|
||||
if (floor(PS_SCALE_FACTOR) != PS_SCALE_FACTOR)
|
||||
coord = uvec2(vec2(coord) * PS_SCALE_FACTOR);
|
||||
else
|
||||
coord *= uvec2(PS_SCALE_FACTOR);
|
||||
|
||||
vec4 pixel = texelFetch(samp0, ivec2(coord), 0);
|
||||
vec2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
|
||||
float sel1 = (pos.x & 8u) == 0u ? sel0.x : sel0.y;
|
||||
o_col0 = vec4(sel1); // Divide by something here?
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_yuv
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
int EMODA;
|
||||
int EMODC;
|
||||
};
|
||||
|
||||
void ps_yuv()
|
||||
{
|
||||
vec4 i = sample_c(v_tex);
|
||||
vec4 o;
|
||||
|
||||
mat3 rgb2yuv;
|
||||
rgb2yuv[0] = vec3(0.587, -0.311, -0.419);
|
||||
rgb2yuv[1] = vec3(0.114, 0.500, -0.081);
|
||||
rgb2yuv[2] = vec3(0.299, -0.169, 0.500);
|
||||
|
||||
vec3 yuv = rgb2yuv * i.gbr;
|
||||
|
||||
float Y = float(0xDB)/255.0f * yuv.x + float(0x10)/255.0f;
|
||||
float Cr = float(0xE0)/255.0f * yuv.y + float(0x80)/255.0f;
|
||||
float Cb = float(0xE0)/255.0f * yuv.z + float(0x80)/255.0f;
|
||||
|
||||
switch(EMODA) {
|
||||
case 0:
|
||||
o.a = i.a;
|
||||
break;
|
||||
case 1:
|
||||
o.a = Y;
|
||||
break;
|
||||
case 2:
|
||||
o.a = Y/2.0f;
|
||||
break;
|
||||
case 3:
|
||||
o.a = 0.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(EMODC) {
|
||||
case 0:
|
||||
o.rgb = i.rgb;
|
||||
break;
|
||||
case 1:
|
||||
o.rgb = vec3(Y);
|
||||
break;
|
||||
case 2:
|
||||
o.rgb = vec3(Y, Cb, Cr);
|
||||
break;
|
||||
case 3:
|
||||
o.rgb = vec3(i.a);
|
||||
break;
|
||||
}
|
||||
|
||||
o_col0 = o;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ps_stencil_image_init_0) || defined(ps_stencil_image_init_1)
|
||||
|
||||
void main()
|
||||
{
|
||||
o_col0 = vec4(0x7FFFFFFF);
|
||||
|
||||
#ifdef ps_stencil_image_init_0
|
||||
if((127.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_1
|
||||
if(sample_c(v_tex).a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large.
Load diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 619 B |
Binary file not shown.
|
After Width: | Height: | Size: 620 B |
@@ -0,0 +1,56 @@
|
||||
[
|
||||
{
|
||||
"name": "BLOX",
|
||||
"id": "f82d4c9fdd81518537d88f70c6602bb5",
|
||||
"uri": "content://com.simongellis.vvb.assets/games/BLOX.vb",
|
||||
"authors": ["KR155E"]
|
||||
},
|
||||
{
|
||||
"name": "BLOX 2",
|
||||
"id": "cc91d6389df2c9777919e8e8ab2c0e66",
|
||||
"uri": "content://com.simongellis.vvb.assets/games/BLOX 2.vb",
|
||||
"authors": ["KR155E"]
|
||||
},
|
||||
{
|
||||
"name": "Elevated Speed",
|
||||
"id": "8f7bcfdd0f412d9060b06a97a89fe202",
|
||||
"uri": "content://com.simongellis.vvb.assets/games/Elevated Speed.vb",
|
||||
"authors": ["PizzaRollsRoyce"]
|
||||
},
|
||||
{
|
||||
"name": "Fishbone",
|
||||
"id": "61e38e4e0c43aa8d6274a89ebedd3063",
|
||||
"uri": "content://com.simongellis.vvb.assets/games/Fishbone.vb",
|
||||
"authors": ["thunderstruck"]
|
||||
},
|
||||
{
|
||||
"name": "Formula V Public Demo",
|
||||
"id": "34e9a2ffd60f7ea565caada82d57f29f",
|
||||
"uri": "content://com.simongellis.vvb.assets/games/Formula V Public Demo.vb",
|
||||
"authors": ["KR155E"]
|
||||
},
|
||||
{
|
||||
"name": "Red Square",
|
||||
"id": "9c372321204b9fa65f9324f98aae53ff",
|
||||
"uri": "content://com.simongellis.vvb.assets/games/Red Square.vb",
|
||||
"authors": ["Kresna", "Nyrator"]
|
||||
},
|
||||
{
|
||||
"name": "The Red Castle",
|
||||
"id": "cdb404ff3e1df7b3c13214ac5409d512",
|
||||
"uri": "content://com.simongellis.vvb.assets/games/The Red Castle.vb",
|
||||
"authors": ["Timothy Beck"]
|
||||
},
|
||||
{
|
||||
"name": "VUE Snake",
|
||||
"id": "ccfa400a0ff3d717dad36a3f736fd34d",
|
||||
"uri": "content://com.simongellis.vvb.assets/games/VUE Snake.vb",
|
||||
"authors": ["KR155E"]
|
||||
},
|
||||
{
|
||||
"name": "VUEngine Platformer Demo",
|
||||
"id": "c96d91fb97572a0af7d53f63b292e0f2",
|
||||
"uri": "content://com.simongellis.vvb.assets/games/VUEngine Platformer Demo.vb",
|
||||
"authors": ["KR155E"]
|
||||
}
|
||||
]
|
||||
Reference in new issue
Block a user