mirror of https://github.com/xemu-project/xemu.git
nv2a: Move {Vsh,Psh}State generation into glsl subdir
This commit is contained in:
parent
bebffc7d64
commit
34e8c62a42
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "hw/xbox/nv2a/pgraph/shaders.h"
|
||||
#include "common.h"
|
||||
#include "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;
|
||||
|
|
|
@ -2,6 +2,7 @@ specific_ss.add([files(
|
|||
'common.c',
|
||||
'geom.c',
|
||||
'psh.c',
|
||||
'shaders.c',
|
||||
'vsh.c',
|
||||
'vsh-ff.c',
|
||||
'vsh-prog.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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HW_XBOX_NV2A_PGRAPH_SHADERS_H
|
||||
#define HW_XBOX_NV2A_PGRAPH_SHADERS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#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
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -33,9 +33,8 @@
|
|||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
|
||||
#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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ specific_ss.add(files(
|
|||
'profile.c',
|
||||
'rdi.c',
|
||||
's3tc.c',
|
||||
'shaders.c',
|
||||
'swizzle.c',
|
||||
'texture.c',
|
||||
'vertex.c',
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
|
@ -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 <vulkan/vulkan.h>
|
||||
|
||||
static const VkFilter pgraph_texture_min_filter_vk_map[] = {
|
||||
|
|
|
@ -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 <vulkan/vulkan.h>
|
||||
#include <glslang/Include/glslang_c_interface.h>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue