Skip to content

Commit e6e8283

Browse files
abairemborgerson
authored andcommitted
nv2a: Handle 2D textures given to 3D texture modes
Hardware transparently supports passing 2D textures to operations that are intended to operate on cubemaps. This change introduces a remapping function to mimic the hardware behavior in cases where the texture sampler does not match the expectations of the texture mode. Fixes #1622 Tests: https://github.com/abaire/nxdk_pgraph_tests/blob/4a1fde90854f318a4725178c9c6a7f1fcd016d05/src/tests/texture_2d_as_cubemap_tests.cpp#L79 HW results: https://abaire.github.io/nxdk_pgraph_tests_golden_results/results/Texture_2D_as_cubemap/index.html
1 parent a4b8caf commit e6e8283

File tree

2 files changed

+79
-16
lines changed

2 files changed

+79
-16
lines changed

hw/xbox/nv2a/pgraph/glsl/psh.c

Lines changed: 78 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ void pgraph_glsl_set_psh_state(PGRAPHState *pg, PshState *state)
134134
uint32_t border_source =
135135
GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_BORDER_SOURCE);
136136
bool cubemap = GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_CUBEMAPENABLE);
137+
state->tex_cubemap[i] = cubemap;
137138
state->border_logical_size[i][0] = 0.0f;
138139
state->border_logical_size[i][1] = 0.0f;
139140
state->border_logical_size[i][2] = 0.0f;
@@ -627,13 +628,13 @@ static const char *get_sampler_type(struct PixelShader *ps, enum PS_TEXTUREMODES
627628
return NULL;
628629

629630
case PS_TEXTUREMODES_PROJECT2D:
630-
if (state->dim_tex[i] == 2) {
631+
if (dim == 2) {
631632
if (state->tex_x8y24[i] && ps->opts.vulkan) {
632633
return "usampler2D";
633634
}
634635
return sampler2D;
635636
}
636-
if (state->dim_tex[i] == 3) return sampler3D;
637+
if (dim == 3) return sampler3D;
637638
assert(!"Unhandled texture dimensions");
638639
return NULL;
639640

@@ -644,8 +645,8 @@ static const char *get_sampler_type(struct PixelShader *ps, enum PS_TEXTUREMODES
644645
fprintf(stderr, "Shadow map support not implemented for mode %d\n", mode);
645646
assert(!"Shadow map support not implemented for this mode");
646647
}
647-
if (state->dim_tex[i] == 2) return sampler2D;
648-
if (state->dim_tex[i] == 3 && mode != PS_TEXTUREMODES_DOT_ST) return sampler3D;
648+
if (dim == 2) return sampler2D;
649+
if (dim == 3 && mode != PS_TEXTUREMODES_DOT_ST) return sampler3D;
649650
assert(!"Unhandled texture dimensions");
650651
return NULL;
651652

@@ -667,16 +668,19 @@ static const char *get_sampler_type(struct PixelShader *ps, enum PS_TEXTUREMODES
667668
fprintf(stderr, "Shadow map support not implemented for mode %d\n", mode);
668669
assert(!"Shadow map support not implemented for this mode");
669670
}
670-
assert(state->dim_tex[i] == 2);
671-
return samplerCube;
671+
assert(dim == 2);
672+
if (state->tex_cubemap[i]) {
673+
return samplerCube;
674+
}
675+
return sampler2D;
672676

673677
case PS_TEXTUREMODES_DPNDNT_AR:
674678
case PS_TEXTUREMODES_DPNDNT_GB:
675679
if (state->shadow_map[i]) {
676680
fprintf(stderr, "Shadow map support not implemented for mode %d\n", mode);
677681
assert(!"Shadow map support not implemented for this mode");
678682
}
679-
assert(state->dim_tex[i] == 2);
683+
assert(dim == 2);
680684
return sampler2D;
681685
}
682686
}
@@ -920,6 +924,41 @@ static MString* psh_convert(struct PixelShader *ps)
920924
" vec2(-1.0,-1.0),vec2(0.0,-1.0),vec2(1.0,-1.0),\n"
921925
" vec2(-1.0, 0.0),vec2(0.0, 0.0),vec2(1.0, 0.0),\n"
922926
" vec2(-1.0, 1.0),vec2(0.0, 1.0),vec2(1.0, 1.0));\n"
927+
"vec2 remapCubeTo2D(vec3 texCoord) {\n"
928+
" vec2 uv;\n"
929+
" vec3 absTexCoord = abs(texCoord);\n"
930+
" if (absTexCoord.x > absTexCoord.y && absTexCoord.x > absTexCoord.z) {\n"
931+
" if (texCoord.x > 0.0) {\n"
932+
" // +X: Right\n"
933+
" uv = vec2(-texCoord.z, texCoord.y);\n"
934+
" } else {\n"
935+
" // -X: Left\n"
936+
" uv = vec2(texCoord.z, texCoord.y);\n"
937+
" }\n"
938+
" uv /= absTexCoord.x;\n"
939+
" }\n"
940+
" else if (absTexCoord.y > absTexCoord.x && absTexCoord.y > absTexCoord.z) {\n"
941+
" if (texCoord.y > 0.0) {\n"
942+
" // +Y: Top\n"
943+
" uv = vec2(texCoord.x, -texCoord.z);\n"
944+
" } else {\n"
945+
" // -Y: Bottom\n"
946+
" uv = vec2(texCoord.x, texCoord.z);\n"
947+
" }\n"
948+
" uv /= absTexCoord.y;\n"
949+
" }\n"
950+
" else {\n"
951+
" if (texCoord.z > 0.0) {\n"
952+
" // +Z: Front\n"
953+
" uv = vec2(texCoord.x, texCoord.y);\n"
954+
" } else {\n"
955+
" // -Z: Back\n"
956+
" uv = vec2(-texCoord.x, texCoord.y);\n"
957+
" }\n"
958+
" uv /= absTexCoord.z;\n"
959+
" }\n"
960+
" return uv;\n"
961+
"}\n"
923962
);
924963

925964
MString *clip = mstring_new();
@@ -1089,8 +1128,14 @@ static MString* psh_convert(struct PixelShader *ps)
10891128
}
10901129
break;
10911130
case PS_TEXTUREMODES_CUBEMAP:
1092-
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, pT%d.xyz);\n",
1093-
i, i, i);
1131+
if (!ps->state->tex_cubemap[i]) {
1132+
mstring_append_fmt(vars,
1133+
"pT%d.xy = remapCubeTo2D(pT%d.xyz);\n",
1134+
i, i);
1135+
}
1136+
mstring_append_fmt(vars,
1137+
"vec4 t%d = texture(texSamp%d, pT%d.xy%s);\n",
1138+
i, i, i, ps->state->tex_cubemap[i] ? "z" : "");
10941139
break;
10951140
case PS_TEXTUREMODES_PASSTHRU:
10961141
assert(ps->state->border_logical_size[i][0] == 0.0f && "Unexpected border texture on passthru");
@@ -1200,8 +1245,13 @@ static MString* psh_convert(struct PixelShader *ps)
12001245
mstring_append_fmt(vars, "vec3 n_%d = vec3(dot%d, dot%d, dot%d_n);\n",
12011246
i, i-1, i, i);
12021247
apply_border_adjustment(ps, vars, i, "n_%d");
1203-
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, n_%d);\n",
1204-
i, i, i);
1248+
if (!ps->state->tex_cubemap[i]) {
1249+
mstring_append_fmt(vars,
1250+
"n_%d.xy = remapCubeTo2D(n_%d);\n", i, i);
1251+
}
1252+
mstring_append_fmt(vars,
1253+
"vec4 t%d = texture(texSamp%d, n_%d%s);\n",
1254+
i, i, i, ps->state->tex_cubemap[i] ? "" : ".xy");
12051255
break;
12061256
case PS_TEXTUREMODES_DOT_RFLCT_SPEC:
12071257
assert(i == 3);
@@ -1215,8 +1265,13 @@ static MString* psh_convert(struct PixelShader *ps)
12151265
mstring_append_fmt(vars, "vec3 rv_%d = 2*n_%d*dot(n_%d,e_%d)/dot(n_%d,n_%d) - e_%d;\n",
12161266
i, i, i, i, i, i, i);
12171267
apply_border_adjustment(ps, vars, i, "rv_%d");
1218-
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, rv_%d);\n",
1219-
i, i, i);
1268+
if (!ps->state->tex_cubemap[i]) {
1269+
mstring_append_fmt(vars,
1270+
"rv_%d.xy = remapCubeTo2D(rv_%d);\n", i, i);
1271+
}
1272+
mstring_append_fmt(vars,
1273+
"vec4 t%d = texture(texSamp%d, rv_%d%s);\n",
1274+
i, i, i, ps->state->tex_cubemap[i] ? "" : ".xy");
12201275
break;
12211276
case PS_TEXTUREMODES_DOT_STR_3D:
12221277
assert(i == 3);
@@ -1228,7 +1283,8 @@ static MString* psh_convert(struct PixelShader *ps)
12281283
i, i-2, i-1, i);
12291284

12301285
apply_border_adjustment(ps, vars, i, "dotSTR%d");
1231-
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, %s(dotSTR%d%s));\n",
1286+
mstring_append_fmt(vars,
1287+
"vec4 t%d = texture(texSamp%d, %s(dotSTR%d%s));\n",
12321288
i, i, tex_remap, i, ps->state->dim_tex[i] == 2 ? ".xy" : "");
12331289
break;
12341290
case PS_TEXTUREMODES_DOT_STR_CUBE:
@@ -1239,8 +1295,14 @@ static MString* psh_convert(struct PixelShader *ps)
12391295
mstring_append_fmt(vars, "vec3 dotSTR%dCube = vec3(dot%d, dot%d, dot%d);\n",
12401296
i, i-2, i-1, i);
12411297
apply_border_adjustment(ps, vars, i, "dotSTR%dCube");
1242-
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, dotSTR%dCube);\n",
1243-
i, i, i);
1298+
if (!ps->state->tex_cubemap[i]) {
1299+
mstring_append_fmt(vars,
1300+
"dotSTR%dCube.xy = remapCubeTo2D(dotSTR%dCube);\n",
1301+
i, i);
1302+
}
1303+
mstring_append_fmt(vars,
1304+
"vec4 t%d = texture(texSamp%d, dotSTR%dCube%s);\n",
1305+
i, i, i, ps->state->tex_cubemap[i] ? "" : ".xy");
12441306
break;
12451307
case PS_TEXTUREMODES_DPNDNT_AR:
12461308
assert(i >= 1);

hw/xbox/nv2a/pgraph/glsl/psh.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ typedef struct PshState {
5353
enum ConvolutionFilter conv_tex[4];
5454
bool tex_x8y24[4];
5555
int dim_tex[4];
56+
bool tex_cubemap[4];
5657

5758
float border_logical_size[4][3];
5859
float border_inv_real_size[4][3];

0 commit comments

Comments
 (0)