From 34e8c62a42343f1781e1266cece646a319a05ef8 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Sat, 28 Jun 2025 00:08:46 -0700 Subject: [PATCH] nv2a: Move {Vsh,Psh}State generation into glsl subdir --- hw/xbox/nv2a/pgraph/gl/renderer.h | 4 +- hw/xbox/nv2a/pgraph/gl/shaders.c | 4 - hw/xbox/nv2a/pgraph/glsl/geom.c | 1 - hw/xbox/nv2a/pgraph/glsl/geom.h | 2 +- hw/xbox/nv2a/pgraph/glsl/meson.build | 1 + hw/xbox/nv2a/pgraph/glsl/psh.c | 178 ++++++++++- hw/xbox/nv2a/pgraph/glsl/psh.h | 42 ++- hw/xbox/nv2a/pgraph/glsl/shaders.c | 36 +++ hw/xbox/nv2a/pgraph/{ => glsl}/shaders.h | 13 +- hw/xbox/nv2a/pgraph/glsl/vsh-ff.c | 2 - hw/xbox/nv2a/pgraph/glsl/vsh-prog.c | 3 +- hw/xbox/nv2a/pgraph/glsl/vsh.c | 143 +++++++++ hw/xbox/nv2a/pgraph/glsl/vsh.h | 59 +++- hw/xbox/nv2a/pgraph/meson.build | 1 - hw/xbox/nv2a/pgraph/pgraph.h | 3 +- hw/xbox/nv2a/pgraph/psh.h | 36 --- hw/xbox/nv2a/pgraph/shaders.c | 359 ----------------------- hw/xbox/nv2a/pgraph/vk/constants.h | 2 +- hw/xbox/nv2a/pgraph/vk/renderer.h | 4 +- hw/xbox/nv2a/pgraph/vk/shaders.c | 4 - hw/xbox/nv2a/pgraph/vsh.h | 53 ---- 21 files changed, 466 insertions(+), 484 deletions(-) create mode 100644 hw/xbox/nv2a/pgraph/glsl/shaders.c rename hw/xbox/nv2a/pgraph/{ => glsl}/shaders.h (76%) delete mode 100644 hw/xbox/nv2a/pgraph/shaders.c 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