nv2a: Implement shadow samplers

This commit is contained in:
Erik Abair 2022-04-12 15:01:56 -07:00 committed by mborgerson
parent b9aef0c57c
commit c33d96127c
6 changed files with 137 additions and 22 deletions

View File

@ -304,6 +304,8 @@ typedef struct PGRAPHState {
bool texture_matrix_enable[NV2A_MAX_TEXTURES];
enum PshShadowDepthFunc shadow_depth_func;
GLuint gl_framebuffer;
GLuint gl_display_buffer;

View File

@ -1218,6 +1218,15 @@
# define NV097_SET_COMBINER_COLOR_OCW 0x00001E40
# define NV097_SET_COMBINER_CONTROL 0x00001E60
# define NV097_SET_SHADOW_ZSLOPE_THRESHOLD 0x00001E68
# define NV097_SET_SHADOW_DEPTH_FUNC 0x00001E6C
# define NV097_SET_SHADOW_DEPTH_FUNC_NEVER 0x00000000
# define NV097_SET_SHADOW_DEPTH_FUNC_LESS 0x00000001
# define NV097_SET_SHADOW_DEPTH_FUNC_EQUAL 0x00000002
# define NV097_SET_SHADOW_DEPTH_FUNC_LEQUAL 0x00000003
# define NV097_SET_SHADOW_DEPTH_FUNC_GREATER 0x00000004
# define NV097_SET_SHADOW_DEPTH_FUNC_NOTEQUAL 0x00000005
# define NV097_SET_SHADOW_DEPTH_FUNC_GEQUAL 0x00000006
# define NV097_SET_SHADOW_DEPTH_FUNC_ALWAYS 0x00000007
# define NV097_SET_SHADER_STAGE_PROGRAM 0x00001E70
# define NV097_SET_DOT_RGBMAPPING 0X00001E74
# define NV097_SET_SHADER_OTHER_STAGE_INPUT 0x00001E78

View File

@ -219,6 +219,7 @@ typedef struct ColorFormatInfo {
GLenum gl_format;
GLenum gl_type;
GLenum gl_swizzle_mask[4];
bool depth;
} ColorFormatInfo;
static const ColorFormatInfo kelvin_color_format_map[66] = {
@ -300,14 +301,20 @@ static const ColorFormatInfo kelvin_color_format_map[66] = {
{2, true, GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV},
[NV097_SET_TEXTURE_FORMAT_COLOR_LC_IMAGE_YB8CR8YA8CB8] =
{2, true, GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV},
[NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_X8_Y24_FIXED] =
{4, true, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8},
[NV097_SET_TEXTURE_FORMAT_COLOR_SZ_DEPTH_Y16_FIXED] =
{2, false, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT},
{2, false, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,
{GL_RED, GL_ZERO, GL_ZERO, GL_ZERO}, true},
[NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_X8_Y24_FIXED] =
{4, true, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8,
{GL_RED, GL_ONE, GL_ZERO, GL_ZERO}, true},
[NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_Y16_FIXED] =
{2, true, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT},
{2, true, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,
{GL_RED, GL_ZERO, GL_ZERO, GL_ZERO}, true},
[NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_Y16_FLOAT] =
{2, true, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_FLOAT},
{2, true, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_FLOAT,
{GL_RED, GL_ZERO, GL_ZERO, GL_ZERO}, true},
[NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_Y16] =
{2, true, GL_R16, GL_RED, GL_UNSIGNED_SHORT,
{GL_RED, GL_RED, GL_RED, GL_ONE}},
@ -3545,6 +3552,11 @@ DEF_METHOD(NV097, SET_SHADOW_ZSLOPE_THRESHOLD)
assert(parameter == 0x7F800000); /* FIXME: Unimplemented */
}
DEF_METHOD(NV097, SET_SHADOW_DEPTH_FUNC)
{
pg->shadow_depth_func = parameter;
}
DEF_METHOD(NV097, SET_SHADER_STAGE_PROGRAM)
{
pg->regs[NV_PGRAPH_SHADERPROG] = parameter;
@ -3845,6 +3857,7 @@ void pgraph_init(NV2AState *d)
pg->shader_cache = g_hash_table_new(shader_hash, shader_equal);
pg->shadow_depth_func = SHADOW_DEPTH_FUNC_NEVER;
pg->material_alpha = 0.0f;
for (i=0; i<NV2A_VERTEXSHADER_ATTRIBUTES; i++) {
@ -4242,6 +4255,8 @@ static void pgraph_bind_shaders(PGRAPHState *pg)
state.psh.point_sprite = pg->regs[NV_PGRAPH_SETUPRASTER] &
NV_PGRAPH_SETUPRASTER_POINTSMOOTHENABLE;
state.psh.shadow_depth_func = pg->shadow_depth_func;
state.fixed_function = fixed_function;
/* fixed function stuff */
@ -4385,6 +4400,8 @@ static void pgraph_bind_shaders(PGRAPHState *pg)
state.psh.snorm_tex[i] = (f.gl_internal_format == GL_RGB8_SNORM)
|| (f.gl_internal_format == GL_RG8_SNORM);
state.psh.shadow_map[i] = f.depth;
uint32_t filter = pg->regs[NV_PGRAPH_TEXFILTER0 + i*4];
unsigned int min_filter = GET_MASK(filter, NV_PGRAPH_TEXFILTER0_MIN);
enum ConvolutionFilter kernel = CONVOLUTION_FILTER_DISABLED;

View File

@ -177,6 +177,7 @@ DEF_METHOD(NV097, SET_SHADER_CLIP_PLANE_MODE)
DEF_METHOD_RANGE(NV097, SET_COMBINER_COLOR_OCW, 8)
DEF_METHOD(NV097, SET_COMBINER_CONTROL)
DEF_METHOD(NV097, SET_SHADOW_ZSLOPE_THRESHOLD)
DEF_METHOD(NV097, SET_SHADOW_DEPTH_FUNC)
DEF_METHOD(NV097, SET_SHADER_STAGE_PROGRAM)
DEF_METHOD(NV097, SET_DOT_RGBMAPPING)
DEF_METHOD(NV097, SET_SHADER_OTHER_STAGE_INPUT)

View File

@ -558,6 +558,64 @@ static void add_final_stage_code(struct PixelShader *ps, struct FCInputInfo fina
ps->varE = ps->varF = NULL;
}
static const char sampler2D[] = "sampler2D";
static const char sampler3D[] = "sampler3D";
static const char samplerCube[] = "samplerCube";
static const char sampler2DRect[] = "sampler2DRect";
static const char* get_sampler_type(enum PS_TEXTUREMODES mode, const PshState *state, int i)
{
switch (mode) {
default:
case PS_TEXTUREMODES_NONE:
return NULL;
case PS_TEXTUREMODES_PROJECT2D:
case PS_TEXTUREMODES_BUMPENVMAP:
case PS_TEXTUREMODES_BUMPENVMAP_LUM:
case PS_TEXTUREMODES_DOT_ST:
if (state->shadow_map[i]) {
fprintf(stderr, "Shadow map support not implemented for mode %d\n", mode);
assert(!"Shadow map support not implemented for this mode");
}
return state->rect_tex[i] ? sampler2DRect : sampler2D;
case PS_TEXTUREMODES_PROJECT3D:
case PS_TEXTUREMODES_DOT_STR_3D:
if (state->shadow_map[i]) {
return state->rect_tex[i] ? sampler2DRect : sampler2D;
}
return sampler3D;
case PS_TEXTUREMODES_CUBEMAP:
case PS_TEXTUREMODES_DOT_RFLCT_DIFF:
case PS_TEXTUREMODES_DOT_RFLCT_SPEC:
case PS_TEXTUREMODES_DOT_STR_CUBE:
if (state->shadow_map[i]) {
fprintf(stderr, "Shadow map support not implemented for mode %d\n", mode);
assert(!"Shadow map support not implemented for this mode");
}
return samplerCube;
case PS_TEXTUREMODES_DPNDNT_AR:
case PS_TEXTUREMODES_DPNDNT_GB:
if (state->shadow_map[i]) {
fprintf(stderr, "Shadow map support not implemented for mode %d\n", mode);
assert(!"Shadow map support not implemented for this mode");
}
return sampler2D;
}
}
static const char *shadow_comparison_map[] = {
[SHADOW_DEPTH_FUNC_LESS] = "<",
[SHADOW_DEPTH_FUNC_EQUAL] = "==",
[SHADOW_DEPTH_FUNC_LEQUAL] = "<=",
[SHADOW_DEPTH_FUNC_GREATER] = ">",
[SHADOW_DEPTH_FUNC_NOTEQUAL] = "!=",
[SHADOW_DEPTH_FUNC_GEQUAL] = ">=",
};
static MString* psh_convert(struct PixelShader *ps)
{
int i;
@ -699,7 +757,7 @@ static MString* psh_convert(struct PixelShader *ps)
for (i = 0; i < 4; i++) {
const char *sampler_type = NULL;
const char *sampler_type = get_sampler_type(ps->tex_modes[i], &ps->state, i);
assert(ps->dot_map[i] < 8);
const char *dotmap_func = dotmap_funcs[ps->dot_map[i]];
@ -713,7 +771,6 @@ static MString* psh_convert(struct PixelShader *ps)
i);
break;
case PS_TEXTUREMODES_PROJECT2D: {
sampler_type = ps->state.rect_tex[i] ? "sampler2DRect" : "sampler2D";
const char *lookup = "textureProj";
if ((ps->state.conv_tex[i] == CONVOLUTION_FILTER_GAUSSIAN)
|| (ps->state.conv_tex[i] == CONVOLUTION_FILTER_QUINCUNX)) {
@ -733,12 +790,38 @@ static MString* psh_convert(struct PixelShader *ps)
break;
}
case PS_TEXTUREMODES_PROJECT3D:
sampler_type = "sampler3D";
mstring_append_fmt(vars, "vec4 t%d = textureProj(texSamp%d, pT%d.xyzw);\n",
i, i, i);
if (ps->state.shadow_map[i]) {
if (ps->state.shadow_depth_func == SHADOW_DEPTH_FUNC_NEVER) {
mstring_append_fmt(vars, "vec4 t%d = vec4(0.0);\n", i);
} else if (ps->state.shadow_depth_func == SHADOW_DEPTH_FUNC_ALWAYS) {
mstring_append_fmt(vars, "vec4 t%d = vec4(1.0);\n", i);
} else {
mstring_append_fmt(vars,
"pT%d.xy *= texScale%d;\n"
"vec4 t%d_depth = textureProj(texSamp%d, pT%d.xyw);\n"
"float t%d_max_depth;\n"
"if (t%d_depth.y > 0) {\n"
" t%d_max_depth = 0xFFFFFF;\n"
"} else {\n"
" t%d_max_depth = 0xFFFF; // TODO: Support float max.\n"
"}\n"
"t%d_depth.x *= t%d_max_depth;\n"
"pT%d.z = clamp(pT%d.z / pT%d.w, 0, t%d_max_depth);\n",
i, i, i, i, i,
i, i, i, i, i,
i, i, i, i, i);
const char *comparison = shadow_comparison_map[ps->state.shadow_depth_func];
mstring_append_fmt(vars,
"vec4 t%d = vec4(t%d_depth.x %s pT%d.z ? 1.0 : 0.0);\n",
i, i, comparison, i);
}
} else {
mstring_append_fmt(vars, "vec4 t%d = textureProj(texSamp%d, pT%d.xyzw);\n",
i, i, i);
}
break;
case PS_TEXTUREMODES_CUBEMAP:
sampler_type = "samplerCube";
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, pT%d.xyz / pT%d.w);\n",
i, i, i, i);
break;
@ -758,7 +841,6 @@ static MString* psh_convert(struct PixelShader *ps)
}
case PS_TEXTUREMODES_BUMPENVMAP:
assert(i >= 1);
sampler_type = ps->state.rect_tex[i] ? "sampler2DRect" : "sampler2D";
mstring_append_fmt(preflight, "uniform mat2 bumpMat%d;\n", i);
if (ps->state.snorm_tex[ps->input_tex[i]]) {
@ -778,7 +860,6 @@ static MString* psh_convert(struct PixelShader *ps)
break;
case PS_TEXTUREMODES_BUMPENVMAP_LUM:
assert(i >= 1);
sampler_type = ps->state.rect_tex[i] ? "sampler2DRect" : "sampler2D";
mstring_append_fmt(preflight, "uniform float bumpScale%d;\n", i);
mstring_append_fmt(preflight, "uniform float bumpOffset%d;\n", i);
mstring_append_fmt(preflight, "uniform mat2 bumpMat%d;\n", i);
@ -808,7 +889,6 @@ static MString* psh_convert(struct PixelShader *ps)
break;
case PS_TEXTUREMODES_DOT_ST:
assert(i >= 2);
sampler_type = ps->state.rect_tex[i] ? "sampler2DRect" : "sampler2D";
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_ST */\n");
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
i, i, dotmap_func, ps->input_tex[i]);
@ -825,7 +905,6 @@ static MString* psh_convert(struct PixelShader *ps)
break;
case PS_TEXTUREMODES_DOT_RFLCT_DIFF:
assert(i == 2);
sampler_type = "samplerCube";
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_RFLCT_DIFF */\n");
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
i, i, dotmap_func, ps->input_tex[i]);
@ -839,7 +918,6 @@ static MString* psh_convert(struct PixelShader *ps)
break;
case PS_TEXTUREMODES_DOT_RFLCT_SPEC:
assert(i == 3);
sampler_type = "samplerCube";
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_RFLCT_SPEC */\n");
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
i, i, dotmap_func, ps->input_tex[i]);
@ -854,7 +932,6 @@ static MString* psh_convert(struct PixelShader *ps)
break;
case PS_TEXTUREMODES_DOT_STR_3D:
assert(i == 3);
sampler_type = "sampler3D";
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_STR_3D */\n");
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
i, i, dotmap_func, ps->input_tex[i]);
@ -863,7 +940,6 @@ static MString* psh_convert(struct PixelShader *ps)
break;
case PS_TEXTUREMODES_DOT_STR_CUBE:
assert(i == 3);
sampler_type = "samplerCube";
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_STR_CUBE */\n");
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
i, i, dotmap_func, ps->input_tex[i]);
@ -873,14 +949,12 @@ static MString* psh_convert(struct PixelShader *ps)
case PS_TEXTUREMODES_DPNDNT_AR:
assert(i >= 1);
assert(!ps->state.rect_tex[i]);
sampler_type = "sampler2D";
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, t%d.ar);\n",
i, i, ps->input_tex[i]);
break;
case PS_TEXTUREMODES_DPNDNT_GB:
assert(i >= 1);
assert(!ps->state.rect_tex[i]);
sampler_type = "sampler2D";
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, t%d.gb);\n",
i, i, ps->input_tex[i]);
break;
@ -1063,7 +1137,5 @@ MString *psh_translate(const PshState state)
ps.final_input.inv_r0 = flags & PS_FINALCOMBINERSETTING_COMPLEMENT_R0;
}
return psh_convert(&ps);
}

View File

@ -33,6 +33,17 @@ enum PshAlphaFunc {
ALPHA_FUNC_ALWAYS,
};
enum PshShadowDepthFunc {
SHADOW_DEPTH_FUNC_NEVER,
SHADOW_DEPTH_FUNC_LESS,
SHADOW_DEPTH_FUNC_EQUAL,
SHADOW_DEPTH_FUNC_LEQUAL,
SHADOW_DEPTH_FUNC_GREATER,
SHADOW_DEPTH_FUNC_NOTEQUAL,
SHADOW_DEPTH_FUNC_GEQUAL,
SHADOW_DEPTH_FUNC_ALWAYS,
};
enum ConvolutionFilter {
CONVOLUTION_FILTER_DISABLED,
CONVOLUTION_FILTER_QUINCUNX,
@ -57,6 +68,9 @@ typedef struct PshState {
bool alphakill[4];
enum ConvolutionFilter conv_tex[4];
bool shadow_map[4];
enum PshShadowDepthFunc shadow_depth_func;
bool alpha_test;
enum PshAlphaFunc alpha_func;