diff --git a/hw/xbox/nv2a/pgraph/gl/renderer.h b/hw/xbox/nv2a/pgraph/gl/renderer.h
index f50f592b10..9ad29db4ef 100644
--- a/hw/xbox/nv2a/pgraph/gl/renderer.h
+++ b/hw/xbox/nv2a/pgraph/gl/renderer.h
@@ -33,9 +33,7 @@
#include "hw/xbox/nv2a/nv2a_regs.h"
#include "hw/xbox/nv2a/pgraph/surface.h"
#include "hw/xbox/nv2a/pgraph/texture.h"
-#include "hw/xbox/nv2a/pgraph/shaders.h"
-#include "hw/xbox/nv2a/pgraph/glsl/vsh.h"
-#include "hw/xbox/nv2a/pgraph/glsl/psh.h"
+#include "hw/xbox/nv2a/pgraph/glsl/shaders.h"
#include "gloffscreen.h"
#include "constants.h"
diff --git a/hw/xbox/nv2a/pgraph/gl/shaders.c b/hw/xbox/nv2a/pgraph/gl/shaders.c
index 20314de42d..135238f9ce 100644
--- a/hw/xbox/nv2a/pgraph/gl/shaders.c
+++ b/hw/xbox/nv2a/pgraph/gl/shaders.c
@@ -26,10 +26,6 @@
#include "xemu-version.h"
#include "ui/xemu-settings.h"
-#include "hw/xbox/nv2a/pgraph/glsl/geom.h"
-#include "hw/xbox/nv2a/pgraph/glsl/vsh.h"
-#include "hw/xbox/nv2a/pgraph/glsl/psh.h"
-#include "hw/xbox/nv2a/pgraph/shaders.h"
#include "hw/xbox/nv2a/pgraph/util.h"
#include "debug.h"
#include "renderer.h"
diff --git a/hw/xbox/nv2a/pgraph/glsl/geom.c b/hw/xbox/nv2a/pgraph/glsl/geom.c
index 81451811a1..ebcc678e00 100644
--- a/hw/xbox/nv2a/pgraph/glsl/geom.c
+++ b/hw/xbox/nv2a/pgraph/glsl/geom.c
@@ -19,7 +19,6 @@
* License along with this library; if not, see .
*/
-#include "hw/xbox/nv2a/pgraph/shaders.h"
#include "common.h"
#include "geom.h"
diff --git a/hw/xbox/nv2a/pgraph/glsl/geom.h b/hw/xbox/nv2a/pgraph/glsl/geom.h
index f8050b2176..b2bcfb3ef0 100644
--- a/hw/xbox/nv2a/pgraph/glsl/geom.h
+++ b/hw/xbox/nv2a/pgraph/glsl/geom.h
@@ -23,7 +23,7 @@
#define HW_XBOX_NV2A_PGRAPH_GLSL_GEOM_H
#include "qemu/mstring.h"
-#include "hw/xbox/nv2a/pgraph/vsh.h"
+#include "vsh.h"
typedef struct GenGeomGlslOptions {
bool vulkan;
diff --git a/hw/xbox/nv2a/pgraph/glsl/meson.build b/hw/xbox/nv2a/pgraph/glsl/meson.build
index 82df3f7ede..f8c7e34735 100644
--- a/hw/xbox/nv2a/pgraph/glsl/meson.build
+++ b/hw/xbox/nv2a/pgraph/glsl/meson.build
@@ -2,6 +2,7 @@ specific_ss.add([files(
'common.c',
'geom.c',
'psh.c',
+ 'shaders.c',
'vsh.c',
'vsh-ff.c',
'vsh-prog.c',
diff --git a/hw/xbox/nv2a/pgraph/glsl/psh.c b/hw/xbox/nv2a/pgraph/glsl/psh.c
index df1168fe4a..013b1ca3aa 100644
--- a/hw/xbox/nv2a/pgraph/glsl/psh.c
+++ b/hw/xbox/nv2a/pgraph/glsl/psh.c
@@ -40,6 +40,182 @@
DEF_UNIFORM_INFO_ARR(PshUniform, PSH_UNIFORM_DECL_X)
+// TODO: https://github.com/xemu-project/xemu/issues/2260
+// Investigate how color keying is handled for components with no alpha or
+// only alpha.
+static uint32_t get_colorkey_mask(unsigned int color_format)
+{
+ switch (color_format) {
+ case NV097_SET_TEXTURE_FORMAT_COLOR_SZ_X1R5G5B5:
+ case NV097_SET_TEXTURE_FORMAT_COLOR_SZ_X8R8G8B8:
+ case NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_X1R5G5B5:
+ case NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_X8R8G8B8:
+ return 0x00FFFFFF;
+
+ default:
+ return 0xFFFFFFFF;
+ }
+}
+
+static uint32_t get_color_key_mask_for_texture(PGRAPHState *pg, int i)
+{
+ assert(i < NV2A_MAX_TEXTURES);
+ uint32_t fmt = pgraph_reg_r(pg, NV_PGRAPH_TEXFMT0 + i * 4);
+ unsigned int color_format = GET_MASK(fmt, NV_PGRAPH_TEXFMT0_COLOR);
+ return get_colorkey_mask(color_format);
+}
+
+void pgraph_set_psh_state(PGRAPHState *pg, PshState *psh)
+{
+ psh->window_clip_exclusive = pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER) &
+ NV_PGRAPH_SETUPRASTER_WINDOWCLIPTYPE;
+ psh->combiner_control = pgraph_reg_r(pg, NV_PGRAPH_COMBINECTL);
+ psh->shader_stage_program = pgraph_reg_r(pg, NV_PGRAPH_SHADERPROG);
+ psh->other_stage_input = pgraph_reg_r(pg, NV_PGRAPH_SHADERCTL);
+ psh->final_inputs_0 = pgraph_reg_r(pg, NV_PGRAPH_COMBINESPECFOG0);
+ psh->final_inputs_1 = pgraph_reg_r(pg, NV_PGRAPH_COMBINESPECFOG1);
+
+ psh->alpha_test = pgraph_reg_r(pg, NV_PGRAPH_CONTROL_0) &
+ NV_PGRAPH_CONTROL_0_ALPHATESTENABLE;
+ psh->alpha_func = (enum PshAlphaFunc)GET_MASK(
+ pgraph_reg_r(pg, NV_PGRAPH_CONTROL_0), NV_PGRAPH_CONTROL_0_ALPHAFUNC);
+
+ psh->point_sprite = pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER) &
+ NV_PGRAPH_SETUPRASTER_POINTSMOOTHENABLE;
+
+ psh->shadow_depth_func =
+ (enum PshShadowDepthFunc)GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_SHADOWCTL),
+ NV_PGRAPH_SHADOWCTL_SHADOW_ZFUNC);
+ psh->z_perspective = pgraph_reg_r(pg, NV_PGRAPH_CONTROL_0) &
+ NV_PGRAPH_CONTROL_0_Z_PERSPECTIVE_ENABLE;
+
+ psh->smooth_shading = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CONTROL_3),
+ NV_PGRAPH_CONTROL_3_SHADEMODE) ==
+ NV_PGRAPH_CONTROL_3_SHADEMODE_SMOOTH;
+
+ psh->depth_clipping = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_ZCOMPRESSOCCLUDE),
+ NV_PGRAPH_ZCOMPRESSOCCLUDE_ZCLAMP_EN) ==
+ NV_PGRAPH_ZCOMPRESSOCCLUDE_ZCLAMP_EN_CULL;
+
+ int num_stages = pgraph_reg_r(pg, NV_PGRAPH_COMBINECTL) & 0xFF;
+ for (int i = 0; i < num_stages; i++) {
+ psh->rgb_inputs[i] = pgraph_reg_r(pg, NV_PGRAPH_COMBINECOLORI0 + i * 4);
+ psh->rgb_outputs[i] =
+ pgraph_reg_r(pg, NV_PGRAPH_COMBINECOLORO0 + i * 4);
+ psh->alpha_inputs[i] =
+ pgraph_reg_r(pg, NV_PGRAPH_COMBINEALPHAI0 + i * 4);
+ psh->alpha_outputs[i] =
+ pgraph_reg_r(pg, NV_PGRAPH_COMBINEALPHAO0 + i * 4);
+ }
+
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ psh->compare_mode[i][j] =
+ (pgraph_reg_r(pg, NV_PGRAPH_SHADERCLIPMODE) >> (4 * i + j)) & 1;
+ }
+
+ uint32_t ctl_0 = pgraph_reg_r(pg, NV_PGRAPH_TEXCTL0_0 + i * 4);
+ bool enabled = pgraph_is_texture_stage_active(pg, i) &&
+ (ctl_0 & NV_PGRAPH_TEXCTL0_0_ENABLE);
+ if (!enabled) {
+ continue;
+ }
+
+ psh->alphakill[i] = ctl_0 & NV_PGRAPH_TEXCTL0_0_ALPHAKILLEN;
+ psh->colorkey_mode[i] = ctl_0 & NV_PGRAPH_TEXCTL0_0_COLORKEYMODE;
+
+ uint32_t tex_fmt = pgraph_reg_r(pg, NV_PGRAPH_TEXFMT0 + i * 4);
+ psh->dim_tex[i] = GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_DIMENSIONALITY);
+
+ unsigned int color_format = GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_COLOR);
+ BasicColorFormatInfo f = kelvin_color_format_info_map[color_format];
+ psh->rect_tex[i] = f.linear;
+ psh->tex_x8y24[i] =
+ color_format ==
+ NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_X8_Y24_FIXED ||
+ color_format ==
+ NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_X8_Y24_FLOAT;
+
+ uint32_t border_source =
+ GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_BORDER_SOURCE);
+ bool cubemap = GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_CUBEMAPENABLE);
+ psh->border_logical_size[i][0] = 0.0f;
+ psh->border_logical_size[i][1] = 0.0f;
+ psh->border_logical_size[i][2] = 0.0f;
+ if (border_source != NV_PGRAPH_TEXFMT0_BORDER_SOURCE_COLOR) {
+ if (!f.linear && !cubemap) {
+ // The actual texture will be (at least) double the reported
+ // size and shifted by a 4 texel border but texture coordinates
+ // will still be relative to the reported size.
+ unsigned int reported_width =
+ 1 << GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_BASE_SIZE_U);
+ unsigned int reported_height =
+ 1 << GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_BASE_SIZE_V);
+ unsigned int reported_depth =
+ 1 << GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_BASE_SIZE_P);
+
+ psh->border_logical_size[i][0] = reported_width;
+ psh->border_logical_size[i][1] = reported_height;
+ psh->border_logical_size[i][2] = reported_depth;
+
+ if (reported_width < 8) {
+ psh->border_inv_real_size[i][0] = 0.0625f;
+ } else {
+ psh->border_inv_real_size[i][0] =
+ 1.0f / (reported_width * 2.0f);
+ }
+ if (reported_height < 8) {
+ psh->border_inv_real_size[i][1] = 0.0625f;
+ } else {
+ psh->border_inv_real_size[i][1] =
+ 1.0f / (reported_height * 2.0f);
+ }
+ if (reported_depth < 8) {
+ psh->border_inv_real_size[i][2] = 0.0625f;
+ } else {
+ psh->border_inv_real_size[i][2] =
+ 1.0f / (reported_depth * 2.0f);
+ }
+ } else {
+ NV2A_UNIMPLEMENTED(
+ "Border source texture with linear %d cubemap %d", f.linear,
+ cubemap);
+ }
+ }
+
+ /* Keep track of whether texture data has been loaded as signed
+ * normalized integers or not. This dictates whether or not we will need
+ * to re-map in fragment shader for certain texture modes (e.g.
+ * bumpenvmap).
+ *
+ * FIXME: When signed texture data is loaded as unsigned and remapped in
+ * fragment shader, there may be interpolation artifacts. Fix this to
+ * support signed textures more appropriately.
+ */
+#if 0 // FIXME
+ psh->snorm_tex[i] = (f.gl_internal_format == GL_RGB8_SNORM)
+ || (f.gl_internal_format == GL_RG8_SNORM);
+#endif
+ psh->shadow_map[i] = f.depth;
+
+ uint32_t filter = pgraph_reg_r(pg, NV_PGRAPH_TEXFILTER0 + i * 4);
+ 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
+ * performing convolution. Just use it if specified for min (common AA
+ * case).
+ */
+ if (min_filter == NV_PGRAPH_TEXFILTER0_MIN_CONVOLUTION_2D_LOD0) {
+ int k = GET_MASK(filter, NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL);
+ assert(k == NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL_QUINCUNX ||
+ k == NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL_GAUSSIAN_3);
+ kernel = (enum ConvolutionFilter)k;
+ }
+
+ psh->conv_tex[i] = kernel;
+ }
+}
+
/*
* This implements translation of register combiners into glsl
* fragment shaders, but all terminology is in terms of Xbox DirectX
@@ -1470,7 +1646,7 @@ void pgraph_set_psh_uniform_values(PGRAPHState *pg, const PshUniformLocs locs,
if (locs[PshUniform_colorKeyMask] != -1) {
for (int i = 0; i < NV2A_MAX_TEXTURES; i++) {
values->colorKeyMask[i] =
- pgraph_get_color_key_mask_for_texture(pg, i);
+ get_color_key_mask_for_texture(pg, i);
}
}
diff --git a/hw/xbox/nv2a/pgraph/glsl/psh.h b/hw/xbox/nv2a/pgraph/glsl/psh.h
index fbe2c09786..5f1c141ca8 100644
--- a/hw/xbox/nv2a/pgraph/glsl/psh.h
+++ b/hw/xbox/nv2a/pgraph/glsl/psh.h
@@ -26,6 +26,46 @@
#include "hw/xbox/nv2a/pgraph/psh.h"
#include "common.h"
+typedef struct PGRAPHState PGRAPHState;
+
+typedef struct PshState {
+ uint32_t combiner_control;
+ uint32_t shader_stage_program;
+ uint32_t other_stage_input;
+ uint32_t final_inputs_0;
+ uint32_t final_inputs_1;
+
+ uint32_t rgb_inputs[8], rgb_outputs[8];
+ uint32_t alpha_inputs[8], alpha_outputs[8];
+
+ bool point_sprite;
+ bool rect_tex[4];
+ bool snorm_tex[4];
+ bool compare_mode[4][4];
+ bool alphakill[4];
+ int colorkey_mode[4];
+ enum ConvolutionFilter conv_tex[4];
+ bool tex_x8y24[4];
+ int dim_tex[4];
+
+ float border_logical_size[4][3];
+ float border_inv_real_size[4][3];
+
+ bool shadow_map[4];
+ enum PshShadowDepthFunc shadow_depth_func;
+
+ bool alpha_test;
+ enum PshAlphaFunc alpha_func;
+
+ bool window_clip_exclusive;
+
+ bool smooth_shading;
+ bool depth_clipping;
+ bool z_perspective;
+} PshState;
+
+void pgraph_set_psh_state(PGRAPHState *pg, PshState *psh);
+
#define PSH_UNIFORM_DECL_X(S, DECL) \
DECL(S, alphaRef, int, 1) \
DECL(S, bumpMat, mat2, 4) \
@@ -48,8 +88,6 @@ typedef struct GenPshGlslOptions {
int tex_binding;
} GenPshGlslOptions;
-typedef struct PGRAPHState PGRAPHState;
-
MString *pgraph_gen_psh_glsl(const PshState state, GenPshGlslOptions opts);
void pgraph_set_psh_uniform_values(PGRAPHState *pg,
diff --git a/hw/xbox/nv2a/pgraph/glsl/shaders.c b/hw/xbox/nv2a/pgraph/glsl/shaders.c
new file mode 100644
index 0000000000..9144dd19f2
--- /dev/null
+++ b/hw/xbox/nv2a/pgraph/glsl/shaders.c
@@ -0,0 +1,36 @@
+/*
+ * Geforce NV2A PGRAPH GLSL Shader Generator
+ *
+ * Copyright (c) 2025 Matt Borgerson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#include "hw/xbox/nv2a/pgraph/pgraph.h"
+#include "shaders.h"
+
+ShaderState pgraph_get_shader_state(PGRAPHState *pg)
+{
+ pg->program_data_dirty = false; /* fixme */
+
+ ShaderState state;
+
+ // We will hash it, so make sure any padding is zeroed
+ memset(&state, 0, sizeof(ShaderState));
+
+ pgraph_set_vsh_state(pg, &state.vsh);
+ pgraph_set_psh_state(pg, &state.psh);
+
+ return state;
+}
diff --git a/hw/xbox/nv2a/pgraph/shaders.h b/hw/xbox/nv2a/pgraph/glsl/shaders.h
similarity index 76%
rename from hw/xbox/nv2a/pgraph/shaders.h
rename to hw/xbox/nv2a/pgraph/glsl/shaders.h
index 13dc7cb96d..c6642543c9 100644
--- a/hw/xbox/nv2a/pgraph/shaders.h
+++ b/hw/xbox/nv2a/pgraph/glsl/shaders.h
@@ -1,8 +1,7 @@
/*
- * QEMU Geforce NV2A shader generator
+ * Geforce NV2A PGRAPH GLSL Shader Generator
*
- * Copyright (c) 2015 espes
- * Copyright (c) 2015 Jannik Vogel
+ * Copyright (c) 2025 Matt Borgerson
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -18,11 +17,10 @@
* License along with this library; if not, see .
*/
-#ifndef HW_XBOX_NV2A_PGRAPH_SHADERS_H
-#define HW_XBOX_NV2A_PGRAPH_SHADERS_H
-
-#include
+#ifndef HW_XBOX_NV2A_PGRAPH_GLSL_SHADERS_H
+#define HW_XBOX_NV2A_PGRAPH_GLSL_SHADERS_H
+#include "geom.h"
#include "vsh.h"
#include "psh.h"
@@ -34,6 +32,5 @@ typedef struct ShaderState {
typedef struct PGRAPHState PGRAPHState;
ShaderState pgraph_get_shader_state(PGRAPHState *pg);
-uint32_t pgraph_get_color_key_mask_for_texture(PGRAPHState *pg, int i);
#endif
diff --git a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c
index c970c31761..87f9400108 100644
--- a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c
+++ b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c
@@ -20,8 +20,6 @@
*/
#include "qemu/osdep.h"
-#include "hw/xbox/nv2a/pgraph/glsl/vsh.h"
-#include "hw/xbox/nv2a/pgraph/shaders.h"
#include "common.h"
#include "vsh-ff.h"
diff --git a/hw/xbox/nv2a/pgraph/glsl/vsh-prog.c b/hw/xbox/nv2a/pgraph/glsl/vsh-prog.c
index 7f5a6e4898..e1d6650330 100644
--- a/hw/xbox/nv2a/pgraph/glsl/vsh-prog.c
+++ b/hw/xbox/nv2a/pgraph/glsl/vsh-prog.c
@@ -33,9 +33,8 @@
#include
#include
-#include "hw/xbox/nv2a/pgraph/glsl/vsh.h"
-#include "hw/xbox/nv2a/pgraph/vsh.h"
#include "common.h"
+#include "vsh.h"
#include "vsh-prog.h"
#define VSH_D3DSCM_CORRECTION 96
diff --git a/hw/xbox/nv2a/pgraph/glsl/vsh.c b/hw/xbox/nv2a/pgraph/glsl/vsh.c
index b8074658e6..f3eacf0b5f 100644
--- a/hw/xbox/nv2a/pgraph/glsl/vsh.c
+++ b/hw/xbox/nv2a/pgraph/glsl/vsh.c
@@ -29,6 +29,149 @@
DEF_UNIFORM_INFO_ARR(VshUniform, VSH_UNIFORM_DECL_X)
+static void set_fixed_function_vsh_state(PGRAPHState *pg,
+ FixedFunctionVshState *ff)
+{
+ ff->skinning = (enum VshSkinning)GET_MASK(
+ pgraph_reg_r(pg, NV_PGRAPH_CSV0_D), NV_PGRAPH_CSV0_D_SKIN);
+ ff->normalization = pgraph_reg_r(pg, NV_PGRAPH_CSV0_C) &
+ NV_PGRAPH_CSV0_C_NORMALIZATION_ENABLE;
+ ff->local_eye =
+ GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_LOCALEYE);
+
+ ff->emission_src = (enum MaterialColorSource)GET_MASK(
+ pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_EMISSION);
+ ff->ambient_src = (enum MaterialColorSource)GET_MASK(
+ pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_AMBIENT);
+ ff->diffuse_src = (enum MaterialColorSource)GET_MASK(
+ pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_DIFFUSE);
+ ff->specular_src = (enum MaterialColorSource)GET_MASK(
+ pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_SPECULAR);
+
+ for (int i = 0; i < 4; i++) {
+ ff->texture_matrix_enable[i] = pg->texture_matrix_enable[i];
+ }
+
+ for (int i = 0; i < 4; i++) {
+ unsigned int reg = (i < 2) ? NV_PGRAPH_CSV1_A : NV_PGRAPH_CSV1_B;
+ for (int j = 0; j < 4; j++) {
+ unsigned int masks[] = {
+ (i % 2) ? NV_PGRAPH_CSV1_A_T1_S : NV_PGRAPH_CSV1_A_T0_S,
+ (i % 2) ? NV_PGRAPH_CSV1_A_T1_T : NV_PGRAPH_CSV1_A_T0_T,
+ (i % 2) ? NV_PGRAPH_CSV1_A_T1_R : NV_PGRAPH_CSV1_A_T0_R,
+ (i % 2) ? NV_PGRAPH_CSV1_A_T1_Q : NV_PGRAPH_CSV1_A_T0_Q
+ };
+ ff->texgen[i][j] =
+ (enum VshTexgen)GET_MASK(pgraph_reg_r(pg, reg), masks[j]);
+ }
+ }
+
+ ff->lighting =
+ GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_LIGHTING);
+ if (ff->lighting) {
+ for (int i = 0; i < NV2A_MAX_LIGHTS; i++) {
+ ff->light[i] =
+ (enum VshLight)GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_D),
+ NV_PGRAPH_CSV0_D_LIGHT0 << (i * 2));
+ }
+ }
+
+ if (pgraph_reg_r(pg, NV_PGRAPH_CONTROL_3) & NV_PGRAPH_CONTROL_3_FOGENABLE) {
+ ff->foggen = (enum VshFoggen)GET_MASK(
+ pgraph_reg_r(pg, NV_PGRAPH_CSV0_D), NV_PGRAPH_CSV0_D_FOGGENMODE);
+ }
+}
+
+static void set_programmable_vsh_state(PGRAPHState *pg,
+ ProgrammableVshState *prog)
+{
+ int program_start = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_C),
+ NV_PGRAPH_CSV0_C_CHEOPS_PROGRAM_START);
+
+ // copy in vertex program tokens
+ prog->program_length = 0;
+ for (int i = program_start; i < NV2A_MAX_TRANSFORM_PROGRAM_LENGTH; i++) {
+ uint32_t *cur_token = (uint32_t *)&pg->program_data[i];
+ memcpy(&prog->program_data[prog->program_length], cur_token,
+ VSH_TOKEN_SIZE * sizeof(uint32_t));
+ prog->program_length++;
+
+ if (vsh_get_field(cur_token, FLD_FINAL)) {
+ break;
+ }
+ }
+}
+
+void pgraph_set_vsh_state(PGRAPHState *pg, VshState *vsh)
+{
+ bool vertex_program = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_D),
+ NV_PGRAPH_CSV0_D_MODE) == 2;
+
+ bool fixed_function = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_D),
+ NV_PGRAPH_CSV0_D_MODE) == 0;
+
+ assert(vertex_program || fixed_function);
+
+ vsh->surface_scale_factor = pg->surface_scale_factor; // FIXME
+
+ vsh->compressed_attrs = pg->compressed_attrs;
+ vsh->uniform_attrs = pg->uniform_attrs;
+ vsh->swizzle_attrs = pg->swizzle_attrs;
+
+ vsh->specular_enable = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_C),
+ NV_PGRAPH_CSV0_C_SPECULAR_ENABLE);
+ vsh->separate_specular = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_C),
+ NV_PGRAPH_CSV0_C_SEPARATE_SPECULAR);
+ vsh->ignore_specular_alpha =
+ !GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_C),
+ NV_PGRAPH_CSV0_C_ALPHA_FROM_MATERIAL_SPECULAR);
+ vsh->specular_power = pg->specular_power;
+ vsh->specular_power_back = pg->specular_power_back;
+
+ vsh->z_perspective = pgraph_reg_r(pg, NV_PGRAPH_CONTROL_0) &
+ NV_PGRAPH_CONTROL_0_Z_PERSPECTIVE_ENABLE;
+
+ vsh->point_params_enable = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_D),
+ NV_PGRAPH_CSV0_D_POINTPARAMSENABLE);
+ vsh->point_size = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_POINTSIZE),
+ NV097_SET_POINT_SIZE_V) /
+ 8.0f;
+ if (vsh->point_params_enable) {
+ for (int i = 0; i < 8; i++) {
+ vsh->point_params[i] = pg->point_params[i];
+ }
+ }
+
+ vsh->smooth_shading = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CONTROL_3),
+ NV_PGRAPH_CONTROL_3_SHADEMODE) ==
+ NV_PGRAPH_CONTROL_3_SHADEMODE_SMOOTH;
+
+ vsh->fog_enable =
+ pgraph_reg_r(pg, NV_PGRAPH_CONTROL_3) & NV_PGRAPH_CONTROL_3_FOGENABLE;
+ if (vsh->fog_enable) {
+ /*FIXME: Use CSV0_D? */
+ vsh->fog_mode =
+ (enum VshFogMode)GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CONTROL_3),
+ NV_PGRAPH_CONTROL_3_FOG_MODE);
+ }
+
+ /* geometry shader stuff */
+ vsh->primitive_mode = (enum ShaderPrimitiveMode)pg->primitive_mode;
+ vsh->polygon_front_mode = (enum ShaderPolygonMode)GET_MASK(
+ pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER),
+ NV_PGRAPH_SETUPRASTER_FRONTFACEMODE);
+ vsh->polygon_back_mode = (enum ShaderPolygonMode)GET_MASK(
+ pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER),
+ NV_PGRAPH_SETUPRASTER_BACKFACEMODE);
+
+ vsh->is_fixed_function = fixed_function;
+ if (fixed_function) {
+ set_fixed_function_vsh_state(pg, &vsh->fixed_function);
+ } else {
+ set_programmable_vsh_state(pg, &vsh->programmable);
+ }
+}
+
MString *pgraph_gen_vsh_glsl(const VshState *state,
GenVshGlslOptions opts)
{
diff --git a/hw/xbox/nv2a/pgraph/glsl/vsh.h b/hw/xbox/nv2a/pgraph/glsl/vsh.h
index d5166fb9d3..1b3d420f16 100644
--- a/hw/xbox/nv2a/pgraph/glsl/vsh.h
+++ b/hw/xbox/nv2a/pgraph/glsl/vsh.h
@@ -26,6 +26,63 @@
#include "hw/xbox/nv2a/pgraph/vsh.h"
#include "common.h"
+typedef struct PGRAPHState PGRAPHState;
+
+typedef struct FixedFunctionVshState {
+ bool normalization;
+ bool texture_matrix_enable[4];
+ enum VshTexgen texgen[4][4];
+ enum VshFoggen foggen;
+ enum VshSkinning skinning;
+ bool lighting;
+ enum VshLight light[NV2A_MAX_LIGHTS];
+ enum MaterialColorSource emission_src;
+ enum MaterialColorSource ambient_src;
+ enum MaterialColorSource diffuse_src;
+ enum MaterialColorSource specular_src;
+ bool local_eye;
+} FixedFunctionVshState;
+
+typedef struct ProgrammableVshState {
+ uint32_t program_data[NV2A_MAX_TRANSFORM_PROGRAM_LENGTH][VSH_TOKEN_SIZE];
+ int program_length;
+} ProgrammableVshState;
+
+typedef struct {
+ unsigned int surface_scale_factor; // FIXME: Remove
+
+ uint16_t compressed_attrs;
+ uint16_t uniform_attrs;
+ uint16_t swizzle_attrs;
+
+ /* primitive format for geometry shader */
+ enum ShaderPolygonMode polygon_front_mode;
+ enum ShaderPolygonMode polygon_back_mode;
+ enum ShaderPrimitiveMode primitive_mode;
+
+ bool fog_enable;
+ enum VshFogMode fog_mode;
+
+ bool specular_enable;
+ bool separate_specular;
+ bool ignore_specular_alpha;
+ float specular_power;
+ float specular_power_back;
+
+ bool point_params_enable;
+ float point_size;
+ float point_params[8];
+
+ bool smooth_shading;
+ bool z_perspective;
+
+ bool is_fixed_function;
+ FixedFunctionVshState fixed_function;
+ ProgrammableVshState programmable;
+} VshState;
+
+void pgraph_set_vsh_state(PGRAPHState *pg, VshState *vsh);
+
#define VSH_UNIFORM_DECL_X(S, DECL) \
DECL(S, c, vec4, NV2A_VERTEXSHADER_CONSTANTS) \
DECL(S, clipRange, vec4, 1) \
@@ -52,8 +109,6 @@ typedef struct GenVshGlslOptions {
int ubo_binding;
} GenVshGlslOptions;
-typedef struct PGRAPHState PGRAPHState;
-
MString *pgraph_gen_vsh_glsl(const VshState *state,
GenVshGlslOptions glsl_opts);
diff --git a/hw/xbox/nv2a/pgraph/meson.build b/hw/xbox/nv2a/pgraph/meson.build
index 5b8bc181c3..fc52f609eb 100644
--- a/hw/xbox/nv2a/pgraph/meson.build
+++ b/hw/xbox/nv2a/pgraph/meson.build
@@ -3,7 +3,6 @@ specific_ss.add(files(
'profile.c',
'rdi.c',
's3tc.c',
- 'shaders.c',
'swizzle.c',
'texture.c',
'vertex.c',
diff --git a/hw/xbox/nv2a/pgraph/pgraph.h b/hw/xbox/nv2a/pgraph/pgraph.h
index c74e370bba..1665ce9f19 100644
--- a/hw/xbox/nv2a/pgraph/pgraph.h
+++ b/hw/xbox/nv2a/pgraph/pgraph.h
@@ -29,9 +29,10 @@
#include "qemu/thread.h"
#include "cpu.h"
-#include "shaders.h"
#include "surface.h"
+#include "texture.h"
#include "util.h"
+#include "vsh.h"
typedef struct NV2AState NV2AState;
typedef struct PGRAPHNullState PGRAPHNullState;
diff --git a/hw/xbox/nv2a/pgraph/psh.h b/hw/xbox/nv2a/pgraph/psh.h
index fa207ee079..72a0f2888f 100644
--- a/hw/xbox/nv2a/pgraph/psh.h
+++ b/hw/xbox/nv2a/pgraph/psh.h
@@ -51,40 +51,4 @@ enum ConvolutionFilter {
CONVOLUTION_FILTER_GAUSSIAN,
};
-typedef struct PshState {
- uint32_t combiner_control;
- uint32_t shader_stage_program;
- uint32_t other_stage_input;
- uint32_t final_inputs_0;
- uint32_t final_inputs_1;
-
- uint32_t rgb_inputs[8], rgb_outputs[8];
- uint32_t alpha_inputs[8], alpha_outputs[8];
-
- bool point_sprite;
- bool rect_tex[4];
- bool snorm_tex[4];
- bool compare_mode[4][4];
- bool alphakill[4];
- int colorkey_mode[4];
- enum ConvolutionFilter conv_tex[4];
- bool tex_x8y24[4];
- int dim_tex[4];
-
- float border_logical_size[4][3];
- float border_inv_real_size[4][3];
-
- bool shadow_map[4];
- enum PshShadowDepthFunc shadow_depth_func;
-
- bool alpha_test;
- enum PshAlphaFunc alpha_func;
-
- bool window_clip_exclusive;
-
- bool smooth_shading;
- bool depth_clipping;
- bool z_perspective;
-} PshState;
-
#endif
diff --git a/hw/xbox/nv2a/pgraph/shaders.c b/hw/xbox/nv2a/pgraph/shaders.c
deleted file mode 100644
index 65d396f030..0000000000
--- a/hw/xbox/nv2a/pgraph/shaders.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * Geforce NV2A PGRAPH OpenGL Renderer
- *
- * Copyright (c) 2015 espes
- * Copyright (c) 2015 Jannik Vogel
- * Copyright (c) 2020-2025 Matt Borgerson
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see .
- */
-
-#include "hw/xbox/nv2a/debug.h"
-#include "texture.h"
-#include "pgraph.h"
-#include "shaders.h"
-
-// TODO: https://github.com/xemu-project/xemu/issues/2260
-// Investigate how color keying is handled for components with no alpha or
-// only alpha.
-static uint32_t get_colorkey_mask(unsigned int color_format)
-{
- switch (color_format) {
- case NV097_SET_TEXTURE_FORMAT_COLOR_SZ_X1R5G5B5:
- case NV097_SET_TEXTURE_FORMAT_COLOR_SZ_X8R8G8B8:
- case NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_X1R5G5B5:
- case NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_X8R8G8B8:
- return 0x00FFFFFF;
-
- default:
- return 0xFFFFFFFF;
- }
-}
-
-uint32_t pgraph_get_color_key_mask_for_texture(PGRAPHState *pg, int i)
-{
- assert(i < NV2A_MAX_TEXTURES);
- uint32_t fmt = pgraph_reg_r(pg, NV_PGRAPH_TEXFMT0 + i * 4);
- unsigned int color_format = GET_MASK(fmt, NV_PGRAPH_TEXFMT0_COLOR);
- return get_colorkey_mask(color_format);
-}
-
-static void set_fixed_function_vsh_state(PGRAPHState *pg,
- FixedFunctionVshState *ff)
-{
- ff->skinning = (enum VshSkinning)GET_MASK(
- pgraph_reg_r(pg, NV_PGRAPH_CSV0_D), NV_PGRAPH_CSV0_D_SKIN);
- ff->normalization = pgraph_reg_r(pg, NV_PGRAPH_CSV0_C) &
- NV_PGRAPH_CSV0_C_NORMALIZATION_ENABLE;
- ff->local_eye =
- GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_LOCALEYE);
-
- ff->emission_src = (enum MaterialColorSource)GET_MASK(
- pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_EMISSION);
- ff->ambient_src = (enum MaterialColorSource)GET_MASK(
- pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_AMBIENT);
- ff->diffuse_src = (enum MaterialColorSource)GET_MASK(
- pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_DIFFUSE);
- ff->specular_src = (enum MaterialColorSource)GET_MASK(
- pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_SPECULAR);
-
- for (int i = 0; i < 4; i++) {
- ff->texture_matrix_enable[i] = pg->texture_matrix_enable[i];
- }
-
- for (int i = 0; i < 4; i++) {
- unsigned int reg = (i < 2) ? NV_PGRAPH_CSV1_A : NV_PGRAPH_CSV1_B;
- for (int j = 0; j < 4; j++) {
- unsigned int masks[] = {
- (i % 2) ? NV_PGRAPH_CSV1_A_T1_S : NV_PGRAPH_CSV1_A_T0_S,
- (i % 2) ? NV_PGRAPH_CSV1_A_T1_T : NV_PGRAPH_CSV1_A_T0_T,
- (i % 2) ? NV_PGRAPH_CSV1_A_T1_R : NV_PGRAPH_CSV1_A_T0_R,
- (i % 2) ? NV_PGRAPH_CSV1_A_T1_Q : NV_PGRAPH_CSV1_A_T0_Q
- };
- ff->texgen[i][j] =
- (enum VshTexgen)GET_MASK(pgraph_reg_r(pg, reg), masks[j]);
- }
- }
-
- ff->lighting =
- GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_LIGHTING);
- if (ff->lighting) {
- for (int i = 0; i < NV2A_MAX_LIGHTS; i++) {
- ff->light[i] =
- (enum VshLight)GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_D),
- NV_PGRAPH_CSV0_D_LIGHT0 << (i * 2));
- }
- }
-
- if (pgraph_reg_r(pg, NV_PGRAPH_CONTROL_3) & NV_PGRAPH_CONTROL_3_FOGENABLE) {
- ff->foggen = (enum VshFoggen)GET_MASK(
- pgraph_reg_r(pg, NV_PGRAPH_CSV0_D), NV_PGRAPH_CSV0_D_FOGGENMODE);
- }
-}
-
-static void set_programmable_vsh_state(PGRAPHState *pg,
- ProgrammableVshState *prog)
-{
- int program_start = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_C),
- NV_PGRAPH_CSV0_C_CHEOPS_PROGRAM_START);
-
- // copy in vertex program tokens
- prog->program_length = 0;
- for (int i = program_start; i < NV2A_MAX_TRANSFORM_PROGRAM_LENGTH; i++) {
- uint32_t *cur_token = (uint32_t *)&pg->program_data[i];
- memcpy(&prog->program_data[prog->program_length], cur_token,
- VSH_TOKEN_SIZE * sizeof(uint32_t));
- prog->program_length++;
-
- if (vsh_get_field(cur_token, FLD_FINAL)) {
- break;
- }
- }
-}
-
-static void set_vsh_state(PGRAPHState *pg, VshState *vsh)
-{
- bool vertex_program = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_D),
- NV_PGRAPH_CSV0_D_MODE) == 2;
-
- bool fixed_function = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_D),
- NV_PGRAPH_CSV0_D_MODE) == 0;
-
- assert(vertex_program || fixed_function);
-
- vsh->surface_scale_factor = pg->surface_scale_factor; // FIXME
-
- vsh->compressed_attrs = pg->compressed_attrs;
- vsh->uniform_attrs = pg->uniform_attrs;
- vsh->swizzle_attrs = pg->swizzle_attrs;
-
- vsh->specular_enable = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_C),
- NV_PGRAPH_CSV0_C_SPECULAR_ENABLE);
- vsh->separate_specular = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_C),
- NV_PGRAPH_CSV0_C_SEPARATE_SPECULAR);
- vsh->ignore_specular_alpha =
- !GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_C),
- NV_PGRAPH_CSV0_C_ALPHA_FROM_MATERIAL_SPECULAR);
- vsh->specular_power = pg->specular_power;
- vsh->specular_power_back = pg->specular_power_back;
-
- vsh->z_perspective = pgraph_reg_r(pg, NV_PGRAPH_CONTROL_0) &
- NV_PGRAPH_CONTROL_0_Z_PERSPECTIVE_ENABLE;
-
- vsh->point_params_enable = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_D),
- NV_PGRAPH_CSV0_D_POINTPARAMSENABLE);
- vsh->point_size = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_POINTSIZE),
- NV097_SET_POINT_SIZE_V) /
- 8.0f;
- if (vsh->point_params_enable) {
- for (int i = 0; i < 8; i++) {
- vsh->point_params[i] = pg->point_params[i];
- }
- }
-
- vsh->smooth_shading = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CONTROL_3),
- NV_PGRAPH_CONTROL_3_SHADEMODE) ==
- NV_PGRAPH_CONTROL_3_SHADEMODE_SMOOTH;
-
- vsh->fog_enable =
- pgraph_reg_r(pg, NV_PGRAPH_CONTROL_3) & NV_PGRAPH_CONTROL_3_FOGENABLE;
- if (vsh->fog_enable) {
- /*FIXME: Use CSV0_D? */
- vsh->fog_mode =
- (enum VshFogMode)GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CONTROL_3),
- NV_PGRAPH_CONTROL_3_FOG_MODE);
- }
-
- /* geometry shader stuff */
- vsh->primitive_mode = (enum ShaderPrimitiveMode)pg->primitive_mode;
- vsh->polygon_front_mode = (enum ShaderPolygonMode)GET_MASK(
- pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER),
- NV_PGRAPH_SETUPRASTER_FRONTFACEMODE);
- vsh->polygon_back_mode = (enum ShaderPolygonMode)GET_MASK(
- pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER),
- NV_PGRAPH_SETUPRASTER_BACKFACEMODE);
-
- vsh->is_fixed_function = fixed_function;
- if (fixed_function) {
- set_fixed_function_vsh_state(pg, &vsh->fixed_function);
- } else {
- set_programmable_vsh_state(pg, &vsh->programmable);
- }
-}
-
-static void set_psh_state(PGRAPHState *pg, PshState *psh)
-{
- psh->window_clip_exclusive = pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER) &
- NV_PGRAPH_SETUPRASTER_WINDOWCLIPTYPE;
- psh->combiner_control = pgraph_reg_r(pg, NV_PGRAPH_COMBINECTL);
- psh->shader_stage_program = pgraph_reg_r(pg, NV_PGRAPH_SHADERPROG);
- psh->other_stage_input = pgraph_reg_r(pg, NV_PGRAPH_SHADERCTL);
- psh->final_inputs_0 = pgraph_reg_r(pg, NV_PGRAPH_COMBINESPECFOG0);
- psh->final_inputs_1 = pgraph_reg_r(pg, NV_PGRAPH_COMBINESPECFOG1);
-
- psh->alpha_test = pgraph_reg_r(pg, NV_PGRAPH_CONTROL_0) &
- NV_PGRAPH_CONTROL_0_ALPHATESTENABLE;
- psh->alpha_func = (enum PshAlphaFunc)GET_MASK(
- pgraph_reg_r(pg, NV_PGRAPH_CONTROL_0), NV_PGRAPH_CONTROL_0_ALPHAFUNC);
-
- psh->point_sprite = pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER) &
- NV_PGRAPH_SETUPRASTER_POINTSMOOTHENABLE;
-
- psh->shadow_depth_func =
- (enum PshShadowDepthFunc)GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_SHADOWCTL),
- NV_PGRAPH_SHADOWCTL_SHADOW_ZFUNC);
- psh->z_perspective = pgraph_reg_r(pg, NV_PGRAPH_CONTROL_0) &
- NV_PGRAPH_CONTROL_0_Z_PERSPECTIVE_ENABLE;
-
- psh->smooth_shading = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CONTROL_3),
- NV_PGRAPH_CONTROL_3_SHADEMODE) ==
- NV_PGRAPH_CONTROL_3_SHADEMODE_SMOOTH;
-
- psh->depth_clipping = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_ZCOMPRESSOCCLUDE),
- NV_PGRAPH_ZCOMPRESSOCCLUDE_ZCLAMP_EN) ==
- NV_PGRAPH_ZCOMPRESSOCCLUDE_ZCLAMP_EN_CULL;
-
- int num_stages = pgraph_reg_r(pg, NV_PGRAPH_COMBINECTL) & 0xFF;
- for (int i = 0; i < num_stages; i++) {
- psh->rgb_inputs[i] = pgraph_reg_r(pg, NV_PGRAPH_COMBINECOLORI0 + i * 4);
- psh->rgb_outputs[i] =
- pgraph_reg_r(pg, NV_PGRAPH_COMBINECOLORO0 + i * 4);
- psh->alpha_inputs[i] =
- pgraph_reg_r(pg, NV_PGRAPH_COMBINEALPHAI0 + i * 4);
- psh->alpha_outputs[i] =
- pgraph_reg_r(pg, NV_PGRAPH_COMBINEALPHAO0 + i * 4);
- }
-
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- psh->compare_mode[i][j] =
- (pgraph_reg_r(pg, NV_PGRAPH_SHADERCLIPMODE) >> (4 * i + j)) & 1;
- }
-
- uint32_t ctl_0 = pgraph_reg_r(pg, NV_PGRAPH_TEXCTL0_0 + i * 4);
- bool enabled = pgraph_is_texture_stage_active(pg, i) &&
- (ctl_0 & NV_PGRAPH_TEXCTL0_0_ENABLE);
- if (!enabled) {
- continue;
- }
-
- psh->alphakill[i] = ctl_0 & NV_PGRAPH_TEXCTL0_0_ALPHAKILLEN;
- psh->colorkey_mode[i] = ctl_0 & NV_PGRAPH_TEXCTL0_0_COLORKEYMODE;
-
- uint32_t tex_fmt = pgraph_reg_r(pg, NV_PGRAPH_TEXFMT0 + i * 4);
- psh->dim_tex[i] = GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_DIMENSIONALITY);
-
- unsigned int color_format = GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_COLOR);
- BasicColorFormatInfo f = kelvin_color_format_info_map[color_format];
- psh->rect_tex[i] = f.linear;
- psh->tex_x8y24[i] =
- color_format ==
- NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_X8_Y24_FIXED ||
- color_format ==
- NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_X8_Y24_FLOAT;
-
- uint32_t border_source =
- GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_BORDER_SOURCE);
- bool cubemap = GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_CUBEMAPENABLE);
- psh->border_logical_size[i][0] = 0.0f;
- psh->border_logical_size[i][1] = 0.0f;
- psh->border_logical_size[i][2] = 0.0f;
- if (border_source != NV_PGRAPH_TEXFMT0_BORDER_SOURCE_COLOR) {
- if (!f.linear && !cubemap) {
- // The actual texture will be (at least) double the reported
- // size and shifted by a 4 texel border but texture coordinates
- // will still be relative to the reported size.
- unsigned int reported_width =
- 1 << GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_BASE_SIZE_U);
- unsigned int reported_height =
- 1 << GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_BASE_SIZE_V);
- unsigned int reported_depth =
- 1 << GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_BASE_SIZE_P);
-
- psh->border_logical_size[i][0] = reported_width;
- psh->border_logical_size[i][1] = reported_height;
- psh->border_logical_size[i][2] = reported_depth;
-
- if (reported_width < 8) {
- psh->border_inv_real_size[i][0] = 0.0625f;
- } else {
- psh->border_inv_real_size[i][0] =
- 1.0f / (reported_width * 2.0f);
- }
- if (reported_height < 8) {
- psh->border_inv_real_size[i][1] = 0.0625f;
- } else {
- psh->border_inv_real_size[i][1] =
- 1.0f / (reported_height * 2.0f);
- }
- if (reported_depth < 8) {
- psh->border_inv_real_size[i][2] = 0.0625f;
- } else {
- psh->border_inv_real_size[i][2] =
- 1.0f / (reported_depth * 2.0f);
- }
- } else {
- NV2A_UNIMPLEMENTED(
- "Border source texture with linear %d cubemap %d", f.linear,
- cubemap);
- }
- }
-
- /* Keep track of whether texture data has been loaded as signed
- * normalized integers or not. This dictates whether or not we will need
- * to re-map in fragment shader for certain texture modes (e.g.
- * bumpenvmap).
- *
- * FIXME: When signed texture data is loaded as unsigned and remapped in
- * fragment shader, there may be interpolation artifacts. Fix this to
- * support signed textures more appropriately.
- */
-#if 0 // FIXME
- psh->snorm_tex[i] = (f.gl_internal_format == GL_RGB8_SNORM)
- || (f.gl_internal_format == GL_RG8_SNORM);
-#endif
- psh->shadow_map[i] = f.depth;
-
- uint32_t filter = pgraph_reg_r(pg, NV_PGRAPH_TEXFILTER0 + i * 4);
- 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
- * performing convolution. Just use it if specified for min (common AA
- * case).
- */
- if (min_filter == NV_PGRAPH_TEXFILTER0_MIN_CONVOLUTION_2D_LOD0) {
- int k = GET_MASK(filter, NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL);
- assert(k == NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL_QUINCUNX ||
- k == NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL_GAUSSIAN_3);
- kernel = (enum ConvolutionFilter)k;
- }
-
- psh->conv_tex[i] = kernel;
- }
-}
-
-ShaderState pgraph_get_shader_state(PGRAPHState *pg)
-{
- pg->program_data_dirty = false; /* fixme */
-
- ShaderState state;
-
- // We will hash it, so make sure any padding is zeroed
- memset(&state, 0, sizeof(ShaderState));
-
- set_vsh_state(pg, &state.vsh);
- set_psh_state(pg, &state.psh);
-
- return state;
-}
diff --git a/hw/xbox/nv2a/pgraph/vk/constants.h b/hw/xbox/nv2a/pgraph/vk/constants.h
index eb7e97dbc0..9d2e2f7f88 100644
--- a/hw/xbox/nv2a/pgraph/vk/constants.h
+++ b/hw/xbox/nv2a/pgraph/vk/constants.h
@@ -21,7 +21,7 @@
#define HW_XBOX_NV2A_PGRAPH_VK_CONSTANTS_H
#include "hw/xbox/nv2a/nv2a_regs.h"
-#include "hw/xbox/nv2a/pgraph/shaders.h"
+#include "hw/xbox/nv2a/pgraph/vsh.h"
#include
static const VkFilter pgraph_texture_min_filter_vk_map[] = {
diff --git a/hw/xbox/nv2a/pgraph/vk/renderer.h b/hw/xbox/nv2a/pgraph/vk/renderer.h
index 10a385e147..0d1d588396 100644
--- a/hw/xbox/nv2a/pgraph/vk/renderer.h
+++ b/hw/xbox/nv2a/pgraph/vk/renderer.h
@@ -29,9 +29,7 @@
#include "hw/xbox/nv2a/nv2a_regs.h"
#include "hw/xbox/nv2a/pgraph/surface.h"
#include "hw/xbox/nv2a/pgraph/texture.h"
-#include "hw/xbox/nv2a/pgraph/shaders.h"
-#include "hw/xbox/nv2a/pgraph/glsl/vsh.h"
-#include "hw/xbox/nv2a/pgraph/glsl/psh.h"
+#include "hw/xbox/nv2a/pgraph/glsl/shaders.h"
#include
#include
diff --git a/hw/xbox/nv2a/pgraph/vk/shaders.c b/hw/xbox/nv2a/pgraph/vk/shaders.c
index fe6d6e00dd..c6f56e6597 100644
--- a/hw/xbox/nv2a/pgraph/vk/shaders.c
+++ b/hw/xbox/nv2a/pgraph/vk/shaders.c
@@ -24,11 +24,7 @@
*/
#include "qemu/osdep.h"
-#include "hw/xbox/nv2a/pgraph/shaders.h"
#include "hw/xbox/nv2a/pgraph/util.h"
-#include "hw/xbox/nv2a/pgraph/glsl/geom.h"
-#include "hw/xbox/nv2a/pgraph/glsl/vsh.h"
-#include "hw/xbox/nv2a/pgraph/glsl/psh.h"
#include "qemu/fast-hash.h"
#include "qemu/mstring.h"
#include "renderer.h"
diff --git a/hw/xbox/nv2a/pgraph/vsh.h b/hw/xbox/nv2a/pgraph/vsh.h
index 48a6e9ede1..aba34c5008 100644
--- a/hw/xbox/nv2a/pgraph/vsh.h
+++ b/hw/xbox/nv2a/pgraph/vsh.h
@@ -154,57 +154,4 @@ enum MaterialColorSource {
MATERIAL_COLOR_SRC_SPECULAR,
};
-typedef struct FixedFunctionVshState {
- bool normalization;
- bool texture_matrix_enable[4];
- enum VshTexgen texgen[4][4];
- enum VshFoggen foggen;
- enum VshSkinning skinning;
- bool lighting;
- enum VshLight light[NV2A_MAX_LIGHTS];
- enum MaterialColorSource emission_src;
- enum MaterialColorSource ambient_src;
- enum MaterialColorSource diffuse_src;
- enum MaterialColorSource specular_src;
- bool local_eye;
-} FixedFunctionVshState;
-
-typedef struct ProgrammableVshState {
- uint32_t program_data[NV2A_MAX_TRANSFORM_PROGRAM_LENGTH][VSH_TOKEN_SIZE];
- int program_length;
-} ProgrammableVshState;
-
-typedef struct {
- unsigned int surface_scale_factor; // FIXME: Remove
-
- uint16_t compressed_attrs;
- uint16_t uniform_attrs;
- uint16_t swizzle_attrs;
-
- /* primitive format for geometry shader */
- enum ShaderPolygonMode polygon_front_mode;
- enum ShaderPolygonMode polygon_back_mode;
- enum ShaderPrimitiveMode primitive_mode;
-
- bool fog_enable;
- enum VshFogMode fog_mode;
-
- bool specular_enable;
- bool separate_specular;
- bool ignore_specular_alpha;
- float specular_power;
- float specular_power_back;
-
- bool point_params_enable;
- float point_size;
- float point_params[8];
-
- bool smooth_shading;
- bool z_perspective;
-
- bool is_fixed_function;
- FixedFunctionVshState fixed_function;
- ProgrammableVshState programmable;
-} VshState;
-
#endif