mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Handle signed texture sampler channels in shaders
This commit is contained in:
@@ -701,12 +701,6 @@ void pgraph_gl_bind_textures(NV2AState *d)
|
||||
1 << (GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_TEXCTL0_0 + i*4),
|
||||
NV_PGRAPH_TEXCTL0_0_MAX_ANISOTROPY));
|
||||
|
||||
/* Check for unsupported features */
|
||||
if (filter & NV_PGRAPH_TEXFILTER0_ASIGNED) NV2A_UNIMPLEMENTED("NV_PGRAPH_TEXFILTER0_ASIGNED");
|
||||
if (filter & NV_PGRAPH_TEXFILTER0_RSIGNED) NV2A_UNIMPLEMENTED("NV_PGRAPH_TEXFILTER0_RSIGNED");
|
||||
if (filter & NV_PGRAPH_TEXFILTER0_GSIGNED) NV2A_UNIMPLEMENTED("NV_PGRAPH_TEXFILTER0_GSIGNED");
|
||||
if (filter & NV_PGRAPH_TEXFILTER0_BSIGNED) NV2A_UNIMPLEMENTED("NV_PGRAPH_TEXFILTER0_BSIGNED");
|
||||
|
||||
TextureShape state = pgraph_get_texture_shape(pg, i);
|
||||
hwaddr texture_vram_offset, palette_vram_offset = 0;
|
||||
size_t length, palette_length = 0;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/xbox/nv2a/debug.h"
|
||||
#include "hw/xbox/nv2a/pgraph/pgraph.h"
|
||||
#include "hw/xbox/nv2a/pgraph/texture.h"
|
||||
#include "psh.h"
|
||||
|
||||
DEF_UNIFORM_INFO_ARR(PshUniform, PSH_UNIFORM_DECL_X)
|
||||
@@ -195,6 +196,8 @@ void pgraph_glsl_set_psh_state(PGRAPHState *pg, PshState *state)
|
||||
state->shadow_map[i] = f.depth;
|
||||
|
||||
uint32_t filter = pgraph_reg_r(pg, NV_PGRAPH_TEXFILTER0 + i * 4);
|
||||
state->tex_signed[i] =
|
||||
pgraph_get_texture_signed_component_mask_from_filter(filter);
|
||||
unsigned int min_filter = GET_MASK(filter, NV_PGRAPH_TEXFILTER0_MIN);
|
||||
enum ConvolutionFilter kernel = CONVOLUTION_FILTER_DISABLED;
|
||||
/* FIXME: We do not distinguish between min and mag when
|
||||
@@ -802,6 +805,31 @@ static void define_colorkey_comparator(MString *preflight)
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
static bool texture_channels_are_signed(const struct PixelShader *ps, int tex,
|
||||
uint8_t mask)
|
||||
{
|
||||
return (ps->state->tex_signed[tex] & mask) == mask;
|
||||
}
|
||||
|
||||
static void apply_signed_texture_remap(const struct PixelShader *ps,
|
||||
MString *vars, int tex)
|
||||
{
|
||||
uint8_t mask = ps->state->tex_signed[tex];
|
||||
|
||||
if (mask & PGRAPH_TEXTURE_SIGNED_R) {
|
||||
mstring_append_fmt(vars, "t%d.r = sign3(t%d.r);\n", tex, tex);
|
||||
}
|
||||
if (mask & PGRAPH_TEXTURE_SIGNED_G) {
|
||||
mstring_append_fmt(vars, "t%d.g = sign3(t%d.g);\n", tex, tex);
|
||||
}
|
||||
if (mask & PGRAPH_TEXTURE_SIGNED_B) {
|
||||
mstring_append_fmt(vars, "t%d.b = sign3(t%d.b);\n", tex, tex);
|
||||
}
|
||||
if (mask & PGRAPH_TEXTURE_SIGNED_A) {
|
||||
mstring_append_fmt(vars, "t%d.a = sign3(t%d.a);\n", tex, tex);
|
||||
}
|
||||
}
|
||||
|
||||
static MString* psh_convert(struct PixelShader *ps)
|
||||
{
|
||||
MString *preflight = mstring_new();
|
||||
@@ -1173,7 +1201,10 @@ static MString* psh_convert(struct PixelShader *ps)
|
||||
case PS_TEXTUREMODES_BUMPENVMAP:
|
||||
assert(i >= 1);
|
||||
|
||||
if (ps->state->snorm_tex[ps->input_tex[i]]) {
|
||||
if (ps->state->snorm_tex[ps->input_tex[i]] ||
|
||||
texture_channels_are_signed(
|
||||
ps, ps->input_tex[i],
|
||||
PGRAPH_TEXTURE_SIGNED_G | PGRAPH_TEXTURE_SIGNED_B)) {
|
||||
/* Input color channels already signed (FIXME: May not always want signed textures in this case) */
|
||||
mstring_append_fmt(vars, "vec2 dsdt%d = t%d.bg;\n",
|
||||
i, ps->input_tex[i]);
|
||||
@@ -1199,15 +1230,28 @@ static MString* psh_convert(struct PixelShader *ps)
|
||||
case PS_TEXTUREMODES_BUMPENVMAP_LUM:
|
||||
assert(i >= 1);
|
||||
|
||||
if (ps->state->snorm_tex[ps->input_tex[i]]) {
|
||||
/* Input color channels already signed (FIXME: May not always want signed textures in this case) */
|
||||
mstring_append_fmt(vars, "vec3 dsdtl%d = vec3(t%d.bg, sign3_to_0_to_1(t%d.r));\n",
|
||||
i, ps->input_tex[i], ps->input_tex[i]);
|
||||
} else {
|
||||
/* Convert to signed (FIXME: loss of accuracy due to filtering/interpolation) */
|
||||
mstring_append_fmt(vars, "vec3 dsdtl%d = vec3(sign3(t%d.b), sign3(t%d.g), t%d.r);\n",
|
||||
i, ps->input_tex[i], ps->input_tex[i], ps->input_tex[i]);
|
||||
}
|
||||
{
|
||||
bool bg_signed =
|
||||
ps->state->snorm_tex[ps->input_tex[i]] ||
|
||||
texture_channels_are_signed(
|
||||
ps, ps->input_tex[i],
|
||||
PGRAPH_TEXTURE_SIGNED_G | PGRAPH_TEXTURE_SIGNED_B);
|
||||
bool r_signed =
|
||||
ps->state->snorm_tex[ps->input_tex[i]] ||
|
||||
texture_channels_are_signed(
|
||||
ps, ps->input_tex[i], PGRAPH_TEXTURE_SIGNED_R);
|
||||
g_autofree gchar *b_expr = g_strdup_printf(
|
||||
bg_signed ? "t%d.b" : "sign3(t%d.b)", ps->input_tex[i]);
|
||||
g_autofree gchar *g_expr = g_strdup_printf(
|
||||
bg_signed ? "t%d.g" : "sign3(t%d.g)", ps->input_tex[i]);
|
||||
g_autofree gchar *r_expr = g_strdup_printf(
|
||||
r_signed ? "sign3_to_0_to_1(t%d.r)" : "t%d.r",
|
||||
ps->input_tex[i]);
|
||||
|
||||
mstring_append_fmt(vars,
|
||||
"vec3 dsdtl%d = vec3(%s, %s, %s);\n", i,
|
||||
b_expr, g_expr, r_expr);
|
||||
}
|
||||
|
||||
mstring_append_fmt(vars, "dsdtl%d.st = bumpMat[%d] * dsdtl%d.st;\n",
|
||||
i, i, i);
|
||||
@@ -1403,6 +1447,10 @@ static MString* psh_convert(struct PixelShader *ps)
|
||||
mstring_append(vars, "}\n");
|
||||
}
|
||||
|
||||
if (!ps->state->shadow_map[i] && !ps->state->tex_x8y24[i]) {
|
||||
apply_signed_texture_remap(ps, vars, i);
|
||||
}
|
||||
|
||||
if (ps->state->rect_tex[i]) {
|
||||
mstring_append_fmt(preflight,
|
||||
"vec2 norm%d(vec2 coord) {\n"
|
||||
|
||||
@@ -47,6 +47,7 @@ typedef struct PshState {
|
||||
bool point_sprite;
|
||||
bool rect_tex[4];
|
||||
bool snorm_tex[4];
|
||||
uint8_t tex_signed[4];
|
||||
bool compare_mode[4][4];
|
||||
bool alphakill[4];
|
||||
int colorkey_mode[4];
|
||||
|
||||
@@ -50,8 +50,36 @@ typedef struct BasicColorFormatInfo {
|
||||
bool depth;
|
||||
} BasicColorFormatInfo;
|
||||
|
||||
enum PgraphTextureSignedChannel {
|
||||
PGRAPH_TEXTURE_SIGNED_R = 1 << 0,
|
||||
PGRAPH_TEXTURE_SIGNED_G = 1 << 1,
|
||||
PGRAPH_TEXTURE_SIGNED_B = 1 << 2,
|
||||
PGRAPH_TEXTURE_SIGNED_A = 1 << 3,
|
||||
};
|
||||
|
||||
extern const BasicColorFormatInfo kelvin_color_format_info_map[66];
|
||||
|
||||
static inline uint8_t
|
||||
pgraph_get_texture_signed_component_mask_from_filter(uint32_t filter)
|
||||
{
|
||||
uint8_t mask = 0;
|
||||
|
||||
if (filter & NV_PGRAPH_TEXFILTER0_RSIGNED) {
|
||||
mask |= PGRAPH_TEXTURE_SIGNED_R;
|
||||
}
|
||||
if (filter & NV_PGRAPH_TEXFILTER0_GSIGNED) {
|
||||
mask |= PGRAPH_TEXTURE_SIGNED_G;
|
||||
}
|
||||
if (filter & NV_PGRAPH_TEXFILTER0_BSIGNED) {
|
||||
mask |= PGRAPH_TEXTURE_SIGNED_B;
|
||||
}
|
||||
if (filter & NV_PGRAPH_TEXFILTER0_ASIGNED) {
|
||||
mask |= PGRAPH_TEXTURE_SIGNED_A;
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
uint8_t *pgraph_convert_texture_data(const TextureShape s, const uint8_t *data,
|
||||
const uint8_t *palette_data,
|
||||
unsigned int width, unsigned int height,
|
||||
|
||||
@@ -1703,15 +1703,6 @@ static void create_texture(PGRAPHState *pg, int texture_idx)
|
||||
}
|
||||
}
|
||||
|
||||
if (filter & NV_PGRAPH_TEXFILTER0_ASIGNED)
|
||||
NV2A_UNIMPLEMENTED("NV_PGRAPH_TEXFILTER0_ASIGNED");
|
||||
if (filter & NV_PGRAPH_TEXFILTER0_RSIGNED)
|
||||
NV2A_UNIMPLEMENTED("NV_PGRAPH_TEXFILTER0_RSIGNED");
|
||||
if (filter & NV_PGRAPH_TEXFILTER0_GSIGNED)
|
||||
NV2A_UNIMPLEMENTED("NV_PGRAPH_TEXFILTER0_GSIGNED");
|
||||
if (filter & NV_PGRAPH_TEXFILTER0_BSIGNED)
|
||||
NV2A_UNIMPLEMENTED("NV_PGRAPH_TEXFILTER0_BSIGNED");
|
||||
|
||||
VkFilter vk_min_filter, vk_mag_filter;
|
||||
unsigned int mag_filter = GET_MASK(filter, NV_PGRAPH_TEXFILTER0_MAG);
|
||||
assert(mag_filter < ARRAY_SIZE(pgraph_texture_mag_filter_vk_map));
|
||||
|
||||
Reference in New Issue
Block a user