From 9fd88f53f365ec6802c81182f6c2d3980a8f6792 Mon Sep 17 00:00:00 2001 From: espes Date: Thu, 4 Feb 2016 02:02:35 +1000 Subject: [PATCH] rework lighting constants to use internal context registers --- hw/xbox/nv2a.c | 664 +++++++++++++++++------------------------ hw/xbox/nv2a_shaders.c | 269 ++++++++++------- hw/xbox/nv2a_shaders.h | 173 +++++++++++ hw/xbox/nv2a_vsh.c | 6 - hw/xbox/nv2a_vsh.h | 1 + 5 files changed, 618 insertions(+), 495 deletions(-) diff --git a/hw/xbox/nv2a.c b/hw/xbox/nv2a.c index bf283d8d52..edf2af619f 100644 --- a/hw/xbox/nv2a.c +++ b/hw/xbox/nv2a.c @@ -1438,11 +1438,6 @@ typedef struct VertexAttribute { GLuint gl_inline_buffer; } VertexAttribute; -typedef struct VertexShaderConstant { - bool dirty; - uint32_t data[4]; -} VertexShaderConstant; - typedef struct Surface { bool draw_dirty; bool buffer_dirty; @@ -1574,38 +1569,7 @@ typedef struct PGRAPHState { GHashTable *shader_cache; ShaderBinding *shader_binding; - float composite_matrix[16]; - - /* FIXME: These are probably stored in the vshader consts */ bool texture_matrix_enable[NV2A_MAX_TEXTURES]; - float texture_matrix[NV2A_MAX_TEXTURES][16]; /* 4 stages with 4x4 matrix each */ - float texture_plane[NV2A_MAX_TEXTURES][4][4]; /* 4 stages, 4 components + plane for each */ - float projection_matrix[16]; - float inverse_model_view_matrix[4][16]; /* 4 weights with 4x4 matrix each */ - float model_view_matrix[4][16]; /* 4 weights with 4x4 matrix each */ - - /* FIXME: Also in vshader consts? */ - float fog_plane[4]; - - /* FIXME: These are probably stored in the vshader consts */ - float scene_ambient_color[3]; - float back_light_ambient_color[NV2A_MAX_LIGHTS][3]; - float back_light_diffuse_color[NV2A_MAX_LIGHTS][3]; - float back_light_specular_color[NV2A_MAX_LIGHTS][3]; - float light_ambient_color[NV2A_MAX_LIGHTS][3]; - float light_diffuse_color[NV2A_MAX_LIGHTS][3]; - float light_specular_color[NV2A_MAX_LIGHTS][3]; - float light_local_range[NV2A_MAX_LIGHTS]; - float light_infinite_half_vector[NV2A_MAX_LIGHTS][3]; - float light_infinite_direction[NV2A_MAX_LIGHTS][3]; - float light_spot_falloff[NV2A_MAX_LIGHTS][3]; - float light_spot_direction[NV2A_MAX_LIGHTS][4]; - float light_local_position[NV2A_MAX_LIGHTS][3]; - float light_local_attenuation[NV2A_MAX_LIGHTS][3]; - - /* FIXME: These are probably stored in the vshader consts */ - float eye_position[4]; - float eye_direction[3]; /* FIXME: Move to NV_PGRAPH_BUMPMAT... */ float bump_env_matrix[NV2A_MAX_TEXTURES-1][4]; /* 3 allowed stages with 2x2 matrix each */ @@ -1630,7 +1594,22 @@ typedef struct PGRAPHState { uint32_t program_data[NV2A_MAX_TRANSFORM_PROGRAM_LENGTH][VSH_TOKEN_SIZE]; - VertexShaderConstant constants[NV2A_VERTEXSHADER_CONSTANTS]; + uint32_t vsh_constants[NV2A_VERTEXSHADER_CONSTANTS][4]; + bool vsh_constants_dirty[NV2A_VERTEXSHADER_CONSTANTS]; + + /* lighting constant arrays */ + uint32_t ltctxa[NV2A_LTCTXA_COUNT][4]; + bool ltctxa_dirty[NV2A_LTCTXA_COUNT]; + uint32_t ltctxb[NV2A_LTCTXB_COUNT][4]; + bool ltctxb_dirty[NV2A_LTCTXB_COUNT]; + uint32_t ltc1[NV2A_LTC1_COUNT][4]; + bool ltc1_dirty[NV2A_LTC1_COUNT]; + + // should figure out where these are in lighting context + float light_infinite_half_vector[NV2A_MAX_LIGHTS][3]; + float light_infinite_direction[NV2A_MAX_LIGHTS][3]; + float light_local_position[NV2A_MAX_LIGHTS][3]; + float light_local_attenuation[NV2A_MAX_LIGHTS][3]; VertexAttribute vertex_attributes[NV2A_VERTEXSHADER_ATTRIBUTES]; @@ -2908,6 +2887,192 @@ static gboolean shader_equal(gconstpointer a, gconstpointer b) return memcmp(as, bs, sizeof(ShaderState)) == 0; } +static void pgraph_shader_update_constants(PGRAPHState *pg, + ShaderBinding *binding, + bool binding_changed, + bool vertex_program, + bool fixed_function) +{ + int i, j; + + /* update combiner constants */ + for (i = 0; i<= 8; i++) { + uint32_t constant[2]; + if (i == 8) { + /* final combiner */ + constant[0] = pg->regs[NV_PGRAPH_SPECFOGFACTOR0]; + constant[1] = pg->regs[NV_PGRAPH_SPECFOGFACTOR1]; + } else { + constant[0] = pg->regs[NV_PGRAPH_COMBINEFACTOR0 + i * 4]; + constant[1] = pg->regs[NV_PGRAPH_COMBINEFACTOR1 + i * 4]; + } + + for (j = 0; j < 2; j++) { + GLint loc = binding->psh_constant_loc[i][j]; + if (loc != -1) { + float value[4]; + value[0] = (float) ((constant[j] >> 16) & 0xFF) / 255.0f; + value[1] = (float) ((constant[j] >> 8) & 0xFF) / 255.0f; + value[2] = (float) (constant[j] & 0xFF) / 255.0f; + value[3] = (float) ((constant[j] >> 24) & 0xFF) / 255.0f; + + glUniform4fv(loc, 1, value); + } + } + } + if (binding->alpha_ref_loc != -1) { + float alpha_ref = GET_MASK(pg->regs[NV_PGRAPH_CONTROL_0], + NV_PGRAPH_CONTROL_0_ALPHAREF) / 255.0; + glUniform1f(binding->alpha_ref_loc, alpha_ref); + } + + + /* For each texture stage */ + for (i = 0; i < NV2A_MAX_TEXTURES; i++) { + // char name[32]; + GLint loc; + + /* Bump luminance only during stages 1 - 3 */ + if (i > 0) { + loc = binding->bump_mat_loc[i]; + if (loc != -1) { + glUniformMatrix2fv(loc, 1, GL_FALSE, pg->bump_env_matrix[i - 1]); + } + loc = binding->bump_scale_loc[i]; + if (loc != -1) { + glUniform1f(loc, *(float*)&pg->regs[ + NV_PGRAPH_BUMPSCALE1 + (i - 1) * 4]); + } + loc = binding->bump_offset_loc[i]; + if (loc != -1) { + glUniform1f(loc, *(float*)&pg->regs[ + NV_PGRAPH_BUMPOFFSET1 + (i - 1) * 4]); + } + } + + } + + if (binding->fog_color_loc != -1) { + uint32_t fog_color = pg->regs[NV_PGRAPH_FOGCOLOR]; + glUniform4f(binding->fog_color_loc, + GET_MASK(fog_color, NV_PGRAPH_FOGCOLOR_RED) / 255.0, + GET_MASK(fog_color, NV_PGRAPH_FOGCOLOR_GREEN) / 255.0, + GET_MASK(fog_color, NV_PGRAPH_FOGCOLOR_BLUE) / 255.0, + GET_MASK(fog_color, NV_PGRAPH_FOGCOLOR_ALPHA) / 255.0); + } + if (binding->fog_param_loc[0] != -1) { + glUniform1f(binding->fog_param_loc[0], + *(float*)&pg->regs[NV_PGRAPH_FOGPARAM0]); + } + if (binding->fog_param_loc[1] != -1) { + glUniform1f(binding->fog_param_loc[1], + *(float*)&pg->regs[NV_PGRAPH_FOGPARAM1]); + } + + + float zclip_max = *(float*)&pg->regs[NV_PGRAPH_ZCLIPMAX]; + float zclip_min = *(float*)&pg->regs[NV_PGRAPH_ZCLIPMIN]; + + if (fixed_function) { + /* update lighting constants */ + struct { + uint32_t* v; + bool* dirty; + GLint* locs; + size_t len; + } lighting_arrays[] = { + {&pg->ltctxa[0][0], &pg->ltctxa_dirty[0], binding->ltctxa_loc, NV2A_LTCTXA_COUNT}, + {&pg->ltctxb[0][0], &pg->ltctxb_dirty[0], binding->ltctxb_loc, NV2A_LTCTXB_COUNT}, + {&pg->ltc1[0][0], &pg->ltc1_dirty[0], binding->ltc1_loc, NV2A_LTC1_COUNT}, + }; + + for (i=0; ilight_infinite_half_vector_loc; + if (loc != -1) { + glUniform3fv(loc, 1, pg->light_infinite_half_vector[i]); + } + loc = binding->light_infinite_direction_loc; + if (loc != -1) { + glUniform3fv(loc, 1, pg->light_infinite_direction[i]); + } + + loc = binding->light_local_position_loc; + if (loc != -1) { + glUniform3fv(loc, 1, pg->light_local_position[i]); + } + loc = binding->light_local_attenuation_loc; + if (loc != -1) { + glUniform3fv(loc, 1, pg->light_local_attenuation[i]); + } + } + + /* estimate the viewport by assuming it matches the surface ... */ + //FIXME: Get surface dimensions? + float m11 = 0.5 * pg->surface_shape.clip_width; + float m22 = -0.5 * pg->surface_shape.clip_height; + float m33 = zclip_max - zclip_min; + //float m41 = m11; + //float m42 = -m22; + float m43 = zclip_min; + //float m44 = 1.0; + + if (m33 == 0.0) { + m33 = 1.0; + } + float invViewport[16] = { + 1.0/m11, 0, 0, 0, + 0, 1.0/m22, 0, 0, + 0, 0, 1.0/m33, 0, + -1.0, 1.0, -m43/m33, 1.0 + }; + + if (binding->inv_viewport_loc != -1) { + glUniformMatrix4fv(binding->inv_viewport_loc, + 1, GL_FALSE, &invViewport[0]); + } + + } + + /* update vertex program constants */ + for (i=0; ivsh_constants_dirty[i] && !binding_changed) continue; + + GLint loc = binding->vsh_constant_loc[i]; + //assert(loc != -1); + if (loc != -1) { + glUniform4fv(loc, 1, (const GLfloat*)pg->vsh_constants[i]); + } + pg->vsh_constants_dirty[i] = false; + } + + if (binding->surface_size_loc != -1) { + glUniform2f(binding->surface_size_loc, pg->surface_shape.clip_width, + pg->surface_shape.clip_height); + } + + if (binding->clip_range_loc != -1) { + glUniform2f(binding->clip_range_loc, zclip_min, zclip_max); + } + +} + static void pgraph_bind_shaders(PGRAPHState *pg) { int i, j; @@ -2926,7 +3091,6 @@ static void pgraph_bind_shaders(PGRAPHState *pg) fixed_function ? "yes" : "no"); ShaderBinding* old_binding = pg->shader_binding; - bool binding_changed = false; ShaderState state = { .psh = (PshState){ @@ -3068,318 +3232,13 @@ static void pgraph_bind_shaders(PGRAPHState *pg) (gpointer)pg->shader_binding); } - binding_changed = (pg->shader_binding != old_binding); + bool binding_changed = (pg->shader_binding != old_binding); glUseProgram(pg->shader_binding->gl_program); + pgraph_shader_update_constants(pg, pg->shader_binding, binding_changed, + vertex_program, fixed_function); - /* update combiner constants */ - for (i = 0; i<= 8; i++) { - uint32_t constant[2]; - if (i == 8) { - /* final combiner */ - constant[0] = pg->regs[NV_PGRAPH_SPECFOGFACTOR0]; - constant[1] = pg->regs[NV_PGRAPH_SPECFOGFACTOR1]; - } else { - constant[0] = pg->regs[NV_PGRAPH_COMBINEFACTOR0 + i * 4]; - constant[1] = pg->regs[NV_PGRAPH_COMBINEFACTOR1 + i * 4]; - } - - for (j = 0; j < 2; j++) { - GLint loc = pg->shader_binding->psh_constant_loc[i][j]; - if (loc != -1) { - float value[4]; - value[0] = (float) ((constant[j] >> 16) & 0xFF) / 255.0f; - value[1] = (float) ((constant[j] >> 8) & 0xFF) / 255.0f; - value[2] = (float) (constant[j] & 0xFF) / 255.0f; - value[3] = (float) ((constant[j] >> 24) & 0xFF) / 255.0f; - - glUniform4fv(loc, 1, value); - } - } - } - GLint alpha_ref_loc = glGetUniformLocation(pg->shader_binding->gl_program, - "alphaRef"); - if (alpha_ref_loc != -1) { - float alpha_ref = GET_MASK(pg->regs[NV_PGRAPH_CONTROL_0], - NV_PGRAPH_CONTROL_0_ALPHAREF) / 255.0; - glUniform1f(alpha_ref_loc, alpha_ref); - } - - /* For each texture stage */ - for (i = 0; i < NV2A_MAX_TEXTURES; i++) { - char name[32]; - GLint loc; - - /* Bump luminance only during stages 1 - 3 */ - if (i > 0) { - - snprintf(name, sizeof(name), "bumpMat%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, name); - if (loc != -1) { - glUniformMatrix2fv(loc, 1, GL_FALSE, pg->bump_env_matrix[i - 1]); - } - - snprintf(name, sizeof(name), "bumpScale%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, name); - if (loc != -1) { - glUniform1f(loc, *(float*)&pg->regs[ - NV_PGRAPH_BUMPSCALE1 + (i - 1) * 4]); - } - - snprintf(name, sizeof(name), "bumpOffset%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, name); - if (loc != -1) { - glUniform1f(loc, *(float*)&pg->regs[ - NV_PGRAPH_BUMPOFFSET1 + (i - 1) * 4]); - } - - } - - /* Texture matrices */ - snprintf(name, sizeof(name), "texMat%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, name); - if (loc != -1) { - glUniformMatrix4fv(loc, 1, GL_FALSE, pg->texture_matrix[i]); - } - - /* TexGen planes */ - for(j = 0; j < 4; j++) { - char cSuffix = "STRQ"[j]; - snprintf(name, sizeof(name), "texPlane%c%d", cSuffix, i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, name); - if (loc != -1) { - glUniform4fv(loc, 1, pg->texture_plane[i][j]); - } - } - - } - - /* Fog */ - { - GLint loc; - uint32_t fog_color = pg->regs[NV_PGRAPH_FOGCOLOR]; - loc = glGetUniformLocation(pg->shader_binding->gl_program, "fogColor"); - if (loc != -1) { - glUniform4f(loc, - GET_MASK(fog_color, NV_PGRAPH_FOGCOLOR_RED) / 255.0, - GET_MASK(fog_color, NV_PGRAPH_FOGCOLOR_GREEN) / 255.0, - GET_MASK(fog_color, NV_PGRAPH_FOGCOLOR_BLUE) / 255.0, - GET_MASK(fog_color, NV_PGRAPH_FOGCOLOR_ALPHA) / 255.0); - } - - /* FIXME: PGRAPH regs have a 16 byte stride in emulation! can't just - * upload this as an array =( - */ - loc = glGetUniformLocation(pg->shader_binding->gl_program, - "fogParam[0]"); - if (loc != -1) { - glUniform1f(loc, *(float*)&pg->regs[NV_PGRAPH_FOGPARAM0]); - } - loc = glGetUniformLocation(pg->shader_binding->gl_program, - "fogParam[1]"); - if (loc != -1) { - glUniform1f(loc, *(float*)&pg->regs[NV_PGRAPH_FOGPARAM1]); - } - - loc = glGetUniformLocation(pg->shader_binding->gl_program, "fogPlane"); - if (loc != -1) { - glUniform4fv(loc, 1, pg->fog_plane); - } - } - - /* For each vertex weight */ - for (i = 0; i < 4; i++) { - char name[32]; - GLint loc; - - snprintf(name, sizeof(name), "modelViewMat%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, name); - if (loc != -1) { - glUniformMatrix4fv(loc, 1, GL_FALSE, - pg->model_view_matrix[i]); - } - - snprintf(name, sizeof(name), "invModelViewMat%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, name); - if (loc != -1) { - glUniformMatrix4fv(loc, 1, GL_FALSE, - pg->inverse_model_view_matrix[i]); - } - - } - - GLint projLoc = glGetUniformLocation(pg->shader_binding->gl_program, - "projectionMat"); - if (projLoc != -1) { - glUniformMatrix4fv(projLoc, 1, GL_FALSE, pg->projection_matrix); - } - - GLint eyeVecLoc = glGetUniformLocation(pg->shader_binding->gl_program, - "eyeVector"); - if (eyeVecLoc != -1) { - glUniform3f(eyeVecLoc, *(float*)&pg->regs[NV_PGRAPH_EYEVEC0], - *(float*)&pg->regs[NV_PGRAPH_EYEVEC1], - *(float*)&pg->regs[NV_PGRAPH_EYEVEC2]); - } - GLint eyePosLoc = glGetUniformLocation(pg->shader_binding->gl_program, - "eyePosition"); - if (eyePosLoc != -1) { - glUniform4fv(eyePosLoc, 1, pg->eye_position); - } - GLint eyeDirLoc = glGetUniformLocation(pg->shader_binding->gl_program, - "eyeDirection"); - if (eyeDirLoc != -1) { - glUniform3fv(eyeDirLoc, 1, pg->eye_direction); - } - - /* FIXME: Only do this if lighting is allowed? I'd believe lighting works - * with both FFP and VPs. - */ - NV2A_GL_DGROUP_BEGIN("Lighting uniforms"); - GLint ambLoc = glGetUniformLocation(pg->shader_binding->gl_program, - "sceneAmbientColor"); - if (ambLoc != -1) { - glUniform3fv(ambLoc, 1, pg->scene_ambient_color); - } - for (i = 0; i < NV2A_MAX_LIGHTS; i++) { - GLint loc; - char tmp[64]; - snprintf(tmp, sizeof(tmp), "backLightAmbientColor%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, tmp); - if (loc != -1) { - glUniform3fv(loc, 1, pg->back_light_ambient_color[i]); - } - snprintf(tmp, sizeof(tmp), "backLightDiffuseColor%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, tmp); - if (loc != -1) { - glUniform3fv(loc, 1, pg->back_light_diffuse_color[i]); - } - snprintf(tmp, sizeof(tmp), "backLightSpecularColor%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, tmp); - if (loc != -1) { - glUniform3fv(loc, 1, pg->back_light_specular_color[i]); - } - snprintf(tmp, sizeof(tmp), "lightAmbientColor%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, tmp); - if (loc != -1) { - glUniform3fv(loc, 1, pg->light_ambient_color[i]); - } - snprintf(tmp, sizeof(tmp), "lightDiffuseColor%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, tmp); - if (loc != -1) { - glUniform3fv(loc, 1, pg->light_diffuse_color[i]); - } - snprintf(tmp, sizeof(tmp), "lightSpecularColor%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, tmp); - if (loc != -1) { - glUniform3fv(loc, 1, pg->light_specular_color[i]); - } - snprintf(tmp, sizeof(tmp), "lightLocalRange%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, tmp); - if (loc != -1) { - glUniform1f(loc, pg->light_local_range[i]); - } - snprintf(tmp, sizeof(tmp), "lightInfiniteHalfVector%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, tmp); - if (loc != -1) { - glUniform3fv(loc, 1, pg->light_infinite_half_vector[i]); - } - snprintf(tmp, sizeof(tmp), "lightInfiniteDirection%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, tmp); - if (loc != -1) { - glUniform3fv(loc, 1, pg->light_infinite_direction[i]); - } - snprintf(tmp, sizeof(tmp), "lightSpotFalloff%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, tmp); - if (loc != -1) { - glUniform3fv(loc, 1, pg->light_spot_falloff[i]); - } - snprintf(tmp, sizeof(tmp), "lightSpotDirection%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, tmp); - if (loc != -1) { - glUniform4fv(loc, 1, pg->light_spot_direction[i]); - } - snprintf(tmp, sizeof(tmp), "lightLocalPosition%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, tmp); - if (loc != -1) { - glUniform3fv(loc, 1, pg->light_local_position[i]); - } - snprintf(tmp, sizeof(tmp), "lightLocalAttenuation%d", i); - loc = glGetUniformLocation(pg->shader_binding->gl_program, tmp); - if (loc != -1) { - glUniform3fv(loc, 1, pg->light_local_attenuation[i]); - } - } - NV2A_GL_DGROUP_END(); - - float zclip_max = *(float*)&pg->regs[NV_PGRAPH_ZCLIPMAX]; - float zclip_min = *(float*)&pg->regs[NV_PGRAPH_ZCLIPMIN]; - - if (fixed_function) { - /* update fixed function composite matrix */ - - GLint comLoc = glGetUniformLocation(pg->shader_binding->gl_program, - "compositeMat"); - if (comLoc != -1) { - glUniformMatrix4fv(comLoc, 1, GL_FALSE, pg->composite_matrix); - } - - /* estimate the viewport by assuming it matches the surface ... */ - //FIXME: Get surface dimensions? - float m11 = 0.5 * pg->surface_shape.clip_width; - float m22 = -0.5 * pg->surface_shape.clip_height; - float m33 = zclip_max - zclip_min; - //float m41 = m11; - //float m42 = -m22; - float m43 = zclip_min; - //float m44 = 1.0; - - if (m33 == 0.0) { - m33 = 1.0; - } - float invViewport[16] = { - 1.0/m11, 0, 0, 0, - 0, 1.0/m22, 0, 0, - 0, 0, 1.0/m33, 0, - -1.0, 1.0, -m43/m33, 1.0 - }; - - GLint view_loc = glGetUniformLocation(pg->shader_binding->gl_program, - "invViewport"); - if (view_loc != -1) { - glUniformMatrix4fv(view_loc, 1, GL_FALSE, &invViewport[0]); - } - - } else if (vertex_program) { - /* update vertex program constants */ - - for (i=0; iconstants[i]; - if (!constant->dirty && !binding_changed) continue; - - GLint loc = pg->shader_binding->vsh_constant_loc[i]; - //assert(loc != -1); - if (loc != -1) { - glUniform4fv(loc, 1, (const GLfloat*)constant->data); - } - constant->dirty = false; - } - - GLint loc = glGetUniformLocation(pg->shader_binding->gl_program, - "surfaceSize"); - if (loc != -1) { - glUniform2f(loc, pg->surface_shape.clip_width, - pg->surface_shape.clip_height); - } - - loc = glGetUniformLocation(pg->shader_binding->gl_program, - "clipRange"); - if (loc != -1) { - glUniform2f(loc, zclip_min, zclip_max); - } - - } NV2A_GL_DGROUP_END(); } @@ -4688,34 +4547,56 @@ static void pgraph_method(NV2AState *d, break; case NV097_SET_PROJECTION_MATRIX ... - NV097_SET_PROJECTION_MATRIX + 0x3c: + NV097_SET_PROJECTION_MATRIX + 0x3c: { slot = (class_method - NV097_SET_PROJECTION_MATRIX) / 4; - pg->projection_matrix[slot] = *(float*)¶meter; + // pg->projection_matrix[slot] = *(float*)¶meter; + unsigned int row = NV_IGRAPH_XF_XFCTX_PMAT0 + slot/4; + pg->vsh_constants[row][slot%4] = parameter; + pg->vsh_constants_dirty[row] = true; break; + } case NV097_SET_MODEL_VIEW_MATRIX ... - NV097_SET_MODEL_VIEW_MATRIX + 0xfc: + NV097_SET_MODEL_VIEW_MATRIX + 0xfc: { slot = (class_method - NV097_SET_MODEL_VIEW_MATRIX) / 4; - pg->model_view_matrix[slot / 16][slot % 16] = *(float*)¶meter; + unsigned int matnum = slot / 16; + unsigned int entry = slot % 16; + unsigned int row = NV_IGRAPH_XF_XFCTX_MMAT0 + matnum*8 + entry/4; + pg->vsh_constants[row][entry % 4] = parameter; + pg->vsh_constants_dirty[row] = true; break; + } case NV097_SET_INVERSE_MODEL_VIEW_MATRIX ... - NV097_SET_INVERSE_MODEL_VIEW_MATRIX + 0xfc: + NV097_SET_INVERSE_MODEL_VIEW_MATRIX + 0xfc: { slot = (class_method - NV097_SET_INVERSE_MODEL_VIEW_MATRIX) / 4; - pg->inverse_model_view_matrix[slot / 16][slot % 16] = *(float*)¶meter; + unsigned int matnum = slot / 16; + unsigned int entry = slot % 16; + unsigned int row = NV_IGRAPH_XF_XFCTX_IMMAT0 + matnum*8 + entry/4; + pg->vsh_constants[row][entry % 4] = parameter; + pg->vsh_constants_dirty[row] = true; break; + } case NV097_SET_COMPOSITE_MATRIX ... - NV097_SET_COMPOSITE_MATRIX + 0x3c: + NV097_SET_COMPOSITE_MATRIX + 0x3c: { slot = (class_method - NV097_SET_COMPOSITE_MATRIX) / 4; - pg->composite_matrix[slot] = *(float*)¶meter; + unsigned int row = NV_IGRAPH_XF_XFCTX_CMAT0 + slot/4; + pg->vsh_constants[row][slot%4] = parameter; + pg->vsh_constants_dirty[row] = true; break; + } case NV097_SET_TEXTURE_MATRIX ... - NV097_SET_TEXTURE_MATRIX + 0xfc: + NV097_SET_TEXTURE_MATRIX + 0xfc: { slot = (class_method - NV097_SET_TEXTURE_MATRIX) / 4; - pg->texture_matrix[slot / 16][slot % 16] = *(float*)¶meter; + unsigned int tex = slot / 16; + unsigned int entry = slot % 16; + unsigned int row = NV_IGRAPH_XF_XFCTX_T0MAT + tex*8 + entry/4; + pg->vsh_constants[row][entry%4] = parameter; + pg->vsh_constants_dirty[row] = true; break; + } case NV097_SET_FOG_PARAMS ... NV097_SET_FOG_PARAMS + 8: @@ -4725,14 +4606,20 @@ static void pgraph_method(NV2AState *d, } else { /* FIXME: No idea where slot = 2 is */ } + + pg->ltctxa[NV_IGRAPH_XF_LTCTXA_FOG_K][slot] = parameter; + pg->ltctxa_dirty[NV_IGRAPH_XF_LTCTXA_FOG_K] = true; break; /* Handles NV097_SET_TEXGEN_PLANE_S,T,R,Q */ case NV097_SET_TEXGEN_PLANE_S ... NV097_SET_TEXGEN_PLANE_S + 0xfc: { slot = (class_method - NV097_SET_TEXGEN_PLANE_S) / 4; - unsigned int part = slot % 16; - pg->texture_plane[slot / 16][part / 4][part % 4] = *(float*)¶meter; + unsigned int tex = slot / 16; + unsigned int entry = slot % 16; + unsigned int row = NV_IGRAPH_XF_XFCTX_TG0MAT + tex*8 + entry/4; + pg->vsh_constants[row][entry%4] = parameter; + pg->vsh_constants_dirty[row] = true; break; } @@ -4744,29 +4631,30 @@ static void pgraph_method(NV2AState *d, case NV097_SET_FOG_PLANE ... NV097_SET_FOG_PLANE + 12: slot = (class_method - NV097_SET_FOG_PLANE) / 4; - pg->fog_plane[slot] = *(float*)¶meter; + pg->vsh_constants[NV_IGRAPH_XF_XFCTX_FOG][slot] = parameter; + pg->vsh_constants_dirty[NV_IGRAPH_XF_XFCTX_FOG] = true; break; case NV097_SET_SCENE_AMBIENT_COLOR ... NV097_SET_SCENE_AMBIENT_COLOR + 8: slot = (class_method - NV097_SET_SCENE_AMBIENT_COLOR) / 4; - pg->scene_ambient_color[slot] = *(float*)¶meter; + // ?? + pg->ltctxa[NV_IGRAPH_XF_LTCTXA_FR_AMB][slot] = parameter; + pg->ltctxa_dirty[NV_IGRAPH_XF_LTCTXA_FR_AMB] = true; break; case NV097_SET_VIEWPORT_OFFSET ... NV097_SET_VIEWPORT_OFFSET + 12: - slot = (class_method - NV097_SET_VIEWPORT_OFFSET) / 4; - - /* populate magic viewport offset constant */ - pg->constants[59].data[slot] = parameter; - pg->constants[59].dirty = true; + pg->vsh_constants[NV_IGRAPH_XF_XFCTX_VPOFF][slot] = parameter; + pg->vsh_constants_dirty[NV_IGRAPH_XF_XFCTX_VPOFF] = true; break; case NV097_SET_EYE_POSITION ... NV097_SET_EYE_POSITION + 12: slot = (class_method - NV097_SET_EYE_POSITION) / 4; - pg->eye_position[slot] = *(float*)¶meter; + pg->vsh_constants[NV_IGRAPH_XF_XFCTX_EYEP][slot] = parameter; + pg->vsh_constants_dirty[NV_IGRAPH_XF_XFCTX_EYEP] = true; break; case NV097_SET_COMBINER_FACTOR0 ... NV097_SET_COMBINER_FACTOR0 + 28: @@ -4794,12 +4682,9 @@ static void pgraph_method(NV2AState *d, case NV097_SET_VIEWPORT_SCALE ... NV097_SET_VIEWPORT_SCALE + 12: - slot = (class_method - NV097_SET_VIEWPORT_SCALE) / 4; - - /* populate magic viewport scale constant */ - pg->constants[58].data[slot] = parameter; - pg->constants[58].dirty = true; + pg->vsh_constants[NV_IGRAPH_XF_XFCTX_VPSCL][slot] = parameter; + pg->vsh_constants_dirty[NV_IGRAPH_XF_XFCTX_VPSCL] = true; break; case NV097_SET_TRANSFORM_PROGRAM ... @@ -4830,9 +4715,10 @@ static void pgraph_method(NV2AState *d, NV_PGRAPH_CHEOPS_OFFSET_CONST_LD_PTR); assert(const_load < NV2A_VERTEXSHADER_CONSTANTS); - VertexShaderConstant *constant = &pg->constants[const_load]; - constant->dirty |= (parameter != constant->data[slot%4]); - constant->data[slot%4] = parameter; + // VertexShaderConstant *constant = &pg->constants[const_load]; + pg->vsh_constants_dirty[const_load] |= + (parameter != pg->vsh_constants[const_load][slot%4]); + pg->vsh_constants[const_load][slot%4] = parameter; if (slot % 4 == 3) { SET_MASK(pg->regs[NV_PGRAPH_CHEOPS_OFFSET], @@ -4866,17 +4752,20 @@ static void pgraph_method(NV2AState *d, case NV097_SET_BACK_LIGHT_AMBIENT_COLOR ... NV097_SET_BACK_LIGHT_AMBIENT_COLOR + 8: part -= NV097_SET_BACK_LIGHT_AMBIENT_COLOR / 4; - pg->back_light_ambient_color[slot][part] = *(float*)¶meter; + pg->ltctxb[NV_IGRAPH_XF_LTCTXB_L0_BAMB + slot*6][part] = parameter; + pg->ltctxb_dirty[NV_IGRAPH_XF_LTCTXB_L0_BAMB + slot*6] = true; break; case NV097_SET_BACK_LIGHT_DIFFUSE_COLOR ... NV097_SET_BACK_LIGHT_DIFFUSE_COLOR + 8: part -= NV097_SET_BACK_LIGHT_DIFFUSE_COLOR / 4; - pg->back_light_diffuse_color[slot][part] = *(float*)¶meter; + pg->ltctxb[NV_IGRAPH_XF_LTCTXB_L0_BDIF + slot*6][part] = parameter; + pg->ltctxb_dirty[NV_IGRAPH_XF_LTCTXB_L0_BDIF + slot*6] = true; break; case NV097_SET_BACK_LIGHT_SPECULAR_COLOR ... NV097_SET_BACK_LIGHT_SPECULAR_COLOR + 8: part -= NV097_SET_BACK_LIGHT_SPECULAR_COLOR / 4; - pg->back_light_specular_color[slot][part] = *(float*)¶meter; + pg->ltctxb[NV_IGRAPH_XF_LTCTXB_L0_BSPC + slot*6][part] = parameter; + pg->ltctxb_dirty[NV_IGRAPH_XF_LTCTXB_L0_BSPC + slot*6] = true; break; default: assert(false); @@ -4895,20 +4784,24 @@ static void pgraph_method(NV2AState *d, case NV097_SET_LIGHT_AMBIENT_COLOR ... NV097_SET_LIGHT_AMBIENT_COLOR + 8: part -= NV097_SET_LIGHT_AMBIENT_COLOR / 4; - pg->light_ambient_color[slot][part] = *(float*)¶meter; + pg->ltctxb[NV_IGRAPH_XF_LTCTXB_L0_AMB + slot*6][part] = parameter; + pg->ltctxb_dirty[NV_IGRAPH_XF_LTCTXB_L0_AMB + slot*6] = true; break; case NV097_SET_LIGHT_DIFFUSE_COLOR ... NV097_SET_LIGHT_DIFFUSE_COLOR + 8: part -= NV097_SET_LIGHT_DIFFUSE_COLOR / 4; - pg->light_diffuse_color[slot][part] = *(float*)¶meter; + pg->ltctxb[NV_IGRAPH_XF_LTCTXB_L0_DIF + slot*6][part] = parameter; + pg->ltctxb_dirty[NV_IGRAPH_XF_LTCTXB_L0_DIF + slot*6] = true; break; case NV097_SET_LIGHT_SPECULAR_COLOR ... NV097_SET_LIGHT_SPECULAR_COLOR + 8: part -= NV097_SET_LIGHT_SPECULAR_COLOR / 4; - pg->light_specular_color[slot][part] = *(float*)¶meter; + pg->ltctxb[NV_IGRAPH_XF_LTCTXB_L0_SPC + slot*6][part] = parameter; + pg->ltctxb_dirty[NV_IGRAPH_XF_LTCTXB_L0_SPC + slot*6] = true; break; case NV097_SET_LIGHT_LOCAL_RANGE: - pg->light_local_range[slot] = *(float*)¶meter; + pg->ltc1[NV_IGRAPH_XF_LTC1_r0 + slot][0] = parameter; + pg->ltc1_dirty[NV_IGRAPH_XF_LTC1_r0 + slot] = true; break; case NV097_SET_LIGHT_INFINITE_HALF_VECTOR ... NV097_SET_LIGHT_INFINITE_HALF_VECTOR + 8: @@ -4923,12 +4816,14 @@ static void pgraph_method(NV2AState *d, case NV097_SET_LIGHT_SPOT_FALLOFF ... NV097_SET_LIGHT_SPOT_FALLOFF + 8: part -= NV097_SET_LIGHT_SPOT_FALLOFF / 4; - pg->light_spot_falloff[slot][part] = *(float*)¶meter; + pg->ltctxa[NV_IGRAPH_XF_LTCTXA_L0_K + slot*2][part] = parameter; + pg->ltctxa_dirty[NV_IGRAPH_XF_LTCTXA_L0_K + slot*2] = true; break; case NV097_SET_LIGHT_SPOT_DIRECTION ... NV097_SET_LIGHT_SPOT_DIRECTION + 12: part -= NV097_SET_LIGHT_SPOT_DIRECTION / 4; - pg->light_spot_direction[slot][part] = *(float*)¶meter; + pg->ltctxa[NV_IGRAPH_XF_LTCTXA_L0_SPT + slot*2][part] = parameter; + pg->ltctxa_dirty[NV_IGRAPH_XF_LTCTXA_L0_SPT + slot*2] = true; break; case NV097_SET_LIGHT_LOCAL_POSITION ... NV097_SET_LIGHT_LOCAL_POSITION + 8: @@ -5126,7 +5021,8 @@ static void pgraph_method(NV2AState *d, case NV097_SET_EYE_DIRECTION ... NV097_SET_EYE_DIRECTION + 8: slot = (class_method - NV097_SET_EYE_DIRECTION) / 4; - pg->eye_direction[slot] = *(float*)¶meter; + pg->ltctxa[NV_IGRAPH_XF_LTCTXA_EYED][slot] = parameter; + pg->ltctxa_dirty[NV_IGRAPH_XF_LTCTXA_EYED] = true; break; case NV097_SET_BEGIN_END: { diff --git a/hw/xbox/nv2a_shaders.c b/hw/xbox/nv2a_shaders.c index 8f358f1eef..a4f2526dae 100644 --- a/hw/xbox/nv2a_shaders.c +++ b/hw/xbox/nv2a_shaders.c @@ -226,6 +226,15 @@ static void append_skinning_code(QString* str, bool mix, } } +#define GLSL_C(idx) "c[" stringify(idx) "]" +#define GLSL_LTCTXA(idx) "ltctxa[" stringify(idx) "]" + +#define GLSL_C_MAT4(idx) \ + "mat4(" GLSL_C(idx) ", " GLSL_C(idx+1) ", " \ + GLSL_C(idx+2) ", " GLSL_C(idx+3) ")" + +#define GLSL_DEFINE(a, b) "#define " stringify(a) " " b "\n" + static void generate_fixed_function(const ShaderState state, QString *header, QString *body) { @@ -249,40 +258,63 @@ static void generate_fixed_function(const ShaderState state, "#define reserved1 v13\n" "#define reserved2 v14\n" "#define reserved3 v15\n" -"\n"); - - qstring_append(header, -/* FIXME: Add these uniforms using code when they are used */ -"uniform vec4 texPlaneS0;\n" -"uniform vec4 texPlaneT0;\n" -"uniform vec4 texPlaneQ0;\n" -"uniform vec4 texPlaneR0;\n" -"uniform vec4 texPlaneS1;\n" -"uniform vec4 texPlaneT1;\n" -"uniform vec4 texPlaneQ1;\n" -"uniform vec4 texPlaneR1;\n" -"uniform vec4 texPlaneS2;\n" -"uniform vec4 texPlaneT2;\n" -"uniform vec4 texPlaneQ2;\n" -"uniform vec4 texPlaneR2;\n" -"uniform vec4 texPlaneS3;\n" -"uniform vec4 texPlaneT3;\n" -"uniform vec4 texPlaneQ3;\n" -"uniform vec4 texPlaneR3;\n" -"uniform mat4 texMat0;\n" -"uniform mat4 texMat1;\n" -"uniform mat4 texMat2;\n" -"uniform mat4 texMat3;\n" -"uniform mat4 modelViewMat0;\n" -"uniform mat4 modelViewMat1;\n" -"uniform mat4 modelViewMat2;\n" -"uniform mat4 modelViewMat3;\n" -"uniform mat4 invModelViewMat0;\n" -"uniform mat4 invModelViewMat1;\n" -"uniform mat4 invModelViewMat2;\n" -"uniform mat4 invModelViewMat3;\n" -"uniform mat4 projectionMat; /* FIXME: when is this used? */\n" -"uniform mat4 compositeMat;\n" +"\n" +"uniform vec4 ltctxa[" stringify(NV2A_LTCTXA_COUNT) "];\n" +"uniform vec4 ltctxb[" stringify(NV2A_LTCTXB_COUNT) "];\n" +"uniform vec4 ltc1[" stringify(NV2A_LTC1_COUNT) "];\n" +"\n" +GLSL_DEFINE(projectionMat, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_PMAT0)) +GLSL_DEFINE(compositeMat, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_CMAT0)) +"\n" +GLSL_DEFINE(texPlaneS0, GLSL_C(NV_IGRAPH_XF_XFCTX_TG0MAT + 0)) +GLSL_DEFINE(texPlaneT0, GLSL_C(NV_IGRAPH_XF_XFCTX_TG0MAT + 1)) +GLSL_DEFINE(texPlaneQ0, GLSL_C(NV_IGRAPH_XF_XFCTX_TG0MAT + 2)) +GLSL_DEFINE(texPlaneR0, GLSL_C(NV_IGRAPH_XF_XFCTX_TG0MAT + 3)) +"\n" +GLSL_DEFINE(texPlaneS1, GLSL_C(NV_IGRAPH_XF_XFCTX_TG1MAT + 0)) +GLSL_DEFINE(texPlaneT1, GLSL_C(NV_IGRAPH_XF_XFCTX_TG1MAT + 1)) +GLSL_DEFINE(texPlaneQ1, GLSL_C(NV_IGRAPH_XF_XFCTX_TG1MAT + 2)) +GLSL_DEFINE(texPlaneR1, GLSL_C(NV_IGRAPH_XF_XFCTX_TG1MAT + 3)) +"\n" +GLSL_DEFINE(texPlaneS2, GLSL_C(NV_IGRAPH_XF_XFCTX_TG2MAT + 0)) +GLSL_DEFINE(texPlaneT2, GLSL_C(NV_IGRAPH_XF_XFCTX_TG2MAT + 1)) +GLSL_DEFINE(texPlaneQ2, GLSL_C(NV_IGRAPH_XF_XFCTX_TG2MAT + 2)) +GLSL_DEFINE(texPlaneR2, GLSL_C(NV_IGRAPH_XF_XFCTX_TG2MAT + 3)) +"\n" +GLSL_DEFINE(texPlaneS3, GLSL_C(NV_IGRAPH_XF_XFCTX_TG3MAT + 0)) +GLSL_DEFINE(texPlaneT3, GLSL_C(NV_IGRAPH_XF_XFCTX_TG3MAT + 1)) +GLSL_DEFINE(texPlaneQ3, GLSL_C(NV_IGRAPH_XF_XFCTX_TG3MAT + 2)) +GLSL_DEFINE(texPlaneR3, GLSL_C(NV_IGRAPH_XF_XFCTX_TG3MAT + 3)) +"\n" +GLSL_DEFINE(modelViewMat0, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_MMAT0)) +GLSL_DEFINE(modelViewMat1, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_MMAT1)) +GLSL_DEFINE(modelViewMat2, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_MMAT2)) +GLSL_DEFINE(modelViewMat3, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_MMAT3)) +"\n" +GLSL_DEFINE(invModelViewMat0, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_IMMAT0)) +GLSL_DEFINE(invModelViewMat1, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_IMMAT1)) +GLSL_DEFINE(invModelViewMat2, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_IMMAT2)) +GLSL_DEFINE(invModelViewMat3, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_IMMAT3)) +"\n" +GLSL_DEFINE(eyePosition, GLSL_C(NV_IGRAPH_XF_XFCTX_EYEP)) +"\n" +"#define lightAmbientColor(i) " + "ltctxb[" stringify(NV_IGRAPH_XF_LTCTXB_L0_AMB) " + (i)*6].xyz\n" +"#define lightDiffuseColor(i) " + "ltctxb[" stringify(NV_IGRAPH_XF_LTCTXB_L0_DIF) " + (i)*6].xyz\n" +"#define lightSpecularColor(i) " + "ltctxb[" stringify(NV_IGRAPH_XF_LTCTXB_L0_SPC) " + (i)*6].xyz\n" +"\n" +"#define lightSpotFalloff(i) " + "ltctxa[" stringify(NV_IGRAPH_XF_LTCTXA_L0_K) " + (i)*2].xyz\n" +"#define lightSpotDirection(i) " + "ltctxa[" stringify(NV_IGRAPH_XF_LTCTXA_L0_SPT) " + (i)*2]\n" +"\n" +"#define lightLocalRange(i) " + "ltc1[" stringify(NV_IGRAPH_XF_LTC1_r0) " + (i)].x\n" +"\n" +GLSL_DEFINE(sceneAmbientColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_FR_AMB) ".xyz") +"\n" "uniform mat4 invViewport;\n" "\n"); @@ -403,25 +435,14 @@ static void generate_fixed_function(const ShaderState state, if (state.lighting) { //FIXME: Do 2 passes if we want 2 sided-lighting? - qstring_append_fmt(header, "uniform vec3 sceneAmbientColor;\n"); qstring_append(body, "oD0 = vec4(sceneAmbientColor, diffuse.a);\n"); qstring_append(body, "oD1 = vec4(0.0, 0.0, 0.0, specular.a);\n"); - /* FIXME: Only add if necessary */ - qstring_append(header, - "uniform vec4 eyePosition;\n"); - for (i = 0; i < NV2A_MAX_LIGHTS; i++) { if (state.light[i] == LIGHT_OFF) { continue; } - qstring_append_fmt(header, - "uniform vec3 lightAmbientColor%d;\n" - "uniform vec3 lightDiffuseColor%d;\n" - "uniform vec3 lightSpecularColor%d;\n", - i, i, i); - /* FIXME: It seems that we only have to handle the surface colors if * they are not part of the material [= vertex colors]. * If they are material the cpu will premultiply light @@ -430,9 +451,6 @@ static void generate_fixed_function(const ShaderState state, qstring_append_fmt(body, "/* Light %d */ {\n", i); - qstring_append_fmt(header, - "uniform float lightLocalRange%d;\n", i); - if (state.light[i] == LIGHT_LOCAL || state.light[i] == LIGHT_SPOT) { @@ -479,10 +497,6 @@ static void generate_fixed_function(const ShaderState state, /* Everything done already */ break; case LIGHT_SPOT: - qstring_append_fmt(header, - "uniform vec3 lightSpotFalloff%d;\n" - "uniform vec4 lightSpotDirection%d;\n", - i, i); assert(false); /*FIXME: calculate falloff */ break; @@ -498,9 +512,9 @@ static void generate_fixed_function(const ShaderState state, " } else {\n" " pf = pow(nDotHV, /* specular(l, m, n, l1, m1, n1) */ 0.001);\n" " }\n" - " vec3 lightAmbient = lightAmbientColor%d * attenuation;\n" - " vec3 lightDiffuse = lightDiffuseColor%d * attenuation * nDotVP;\n" - " vec3 lightSpecular = lightSpecularColor%d * pf;\n", + " vec3 lightAmbient = lightAmbientColor(%d) * attenuation;\n" + " vec3 lightDiffuse = lightDiffuseColor(%d) * attenuation * nDotVP;\n" + " vec3 lightSpecular = lightSpecularColor(%d) * pf;\n", i, i, i); qstring_append(body, @@ -567,46 +581,54 @@ static QString *generate_vertex_shader(const ShaderState state, char vtx_prefix) { int i; - QString *header = qstring_from_str("#version 330\n" - "\n" - "uniform vec2 clipRange;\n" - "uniform vec2 surfaceSize;\n" - "\n" - /* All constants in 1 array declaration */ - "uniform vec4 c[192];\n" - "\n" - /* FIXME: Most [all?] of these are probably part of the constant space */ - "uniform vec4 fogColor;\n" - "uniform vec4 fogPlane;\n" - "uniform float fogParam[2];\n" - "\n" - "vec4 oPos = vec4(0.0,0.0,0.0,1.0);\n" - "vec4 oD0 = vec4(0.0,0.0,0.0,1.0);\n" - "vec4 oD1 = vec4(0.0,0.0,0.0,1.0);\n" - "vec4 oB0 = vec4(0.0,0.0,0.0,1.0);\n" - "vec4 oB1 = vec4(0.0,0.0,0.0,1.0);\n" - "vec4 oPts = vec4(0.0,0.0,0.0,1.0);\n" - /* FIXME: NV_vertex_program says: "FOGC is the transformed vertex's fog - * coordinate. The register's first floating-point component is interpolated - * across the assembled primitive during rasterization and used as the fog - * distance to compute per-fragment the fog factor when fog is enabled. - * However, if both fog and vertex program mode are enabled, but the FOGC - * vertex result register is not written, the fog factor is overridden to - * 1.0. The register's other three components are ignored." - * - * That probably means it will read back as vec4(0.0, 0.0, 0.0, 1.0) but - * will be set to 1.0 AFTER the VP if it was never written? - * We should test on real hardware.. - * - * We'll force 1.0 for oFog.x for now. - */ - "vec4 oFog = vec4(1.0,0.0,0.0,1.0);\n" - "vec4 oT0 = vec4(0.0,0.0,0.0,1.0);\n" - "vec4 oT1 = vec4(0.0,0.0,0.0,1.0);\n" - "vec4 oT2 = vec4(0.0,0.0,0.0,1.0);\n" - "vec4 oT3 = vec4(0.0,0.0,0.0,1.0);\n" - "\n" - STRUCT_VERTEX_DATA); + QString *header = qstring_from_str( +"#version 330\n" +"\n" +"uniform vec2 clipRange;\n" +"uniform vec2 surfaceSize;\n" +"\n" +/* All constants in 1 array declaration */ +"uniform vec4 c[" stringify(NV2A_VERTEXSHADER_CONSTANTS) "];\n" +"\n" +"uniform vec4 fogColor;\n" +"uniform float fogParam[2];\n" +"\n" + +GLSL_DEFINE(fogPlane, GLSL_C(NV_IGRAPH_XF_XFCTX_FOG)) +GLSL_DEFINE(texMat0, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T0MAT)) +GLSL_DEFINE(texMat1, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T1MAT)) +GLSL_DEFINE(texMat2, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T2MAT)) +GLSL_DEFINE(texMat3, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T3MAT)) + +"\n" +"vec4 oPos = vec4(0.0,0.0,0.0,1.0);\n" +"vec4 oD0 = vec4(0.0,0.0,0.0,1.0);\n" +"vec4 oD1 = vec4(0.0,0.0,0.0,1.0);\n" +"vec4 oB0 = vec4(0.0,0.0,0.0,1.0);\n" +"vec4 oB1 = vec4(0.0,0.0,0.0,1.0);\n" +"vec4 oPts = vec4(0.0,0.0,0.0,1.0);\n" +/* FIXME: NV_vertex_program says: "FOGC is the transformed vertex's fog + * coordinate. The register's first floating-point component is interpolated + * across the assembled primitive during rasterization and used as the fog + * distance to compute per-fragment the fog factor when fog is enabled. + * However, if both fog and vertex program mode are enabled, but the FOGC + * vertex result register is not written, the fog factor is overridden to + * 1.0. The register's other three components are ignored." + * + * That probably means it will read back as vec4(0.0, 0.0, 0.0, 1.0) but + * will be set to 1.0 AFTER the VP if it was never written? + * We should test on real hardware.. + * + * We'll force 1.0 for oFog.x for now. + */ +"vec4 oFog = vec4(1.0,0.0,0.0,1.0);\n" +"vec4 oT0 = vec4(0.0,0.0,0.0,1.0);\n" +"vec4 oT1 = vec4(0.0,0.0,0.0,1.0);\n" +"vec4 oT2 = vec4(0.0,0.0,0.0,1.0);\n" +"vec4 oT3 = vec4(0.0,0.0,0.0,1.0);\n" +"\n" +STRUCT_VERTEX_DATA); + qstring_append_fmt(header, "noperspective out VertexData %c_vtx;\n", vtx_prefix); qstring_append_fmt(header, "#define vtx %c_vtx\n", @@ -767,6 +789,8 @@ static GLuint create_gl_shader(GLenum gl_shader_type, ShaderBinding* generate_shaders(const ShaderState state) { int i, j; + char tmp[64]; + char vtx_prefix; GLuint program = glCreateProgram(); @@ -805,7 +829,6 @@ ShaderBinding* generate_shaders(const ShaderState state) /* Bind attributes for vertices */ - char tmp[8]; for(i = 0; i < 16; i++) { snprintf(tmp, sizeof(tmp), "v%d", i); glBindAttribLocation(program, i, tmp); @@ -864,21 +887,57 @@ ShaderBinding* generate_shaders(const ShaderState state) ret->gl_program = program; ret->gl_primitive_mode = gl_primitive_mode; - /* lookup fragment shader locations */ + /* lookup fragment shader uniforms */ for (i=0; i<=8; i++) { for (j=0; j<2; j++) { - char tmp[8]; snprintf(tmp, sizeof(tmp), "c_%d_%d", i, j); ret->psh_constant_loc[i][j] = glGetUniformLocation(program, tmp); } } - if (state.vertex_program) { - /* lookup vertex shader bindings */ - for(i = 0; i < NV2A_VERTEXSHADER_CONSTANTS; i++) { - char tmp[8]; - snprintf(tmp, sizeof(tmp), "c[%d]", i); - ret->vsh_constant_loc[i] = glGetUniformLocation(program, tmp); - } + ret->alpha_ref_loc = glGetUniformLocation(program, "alphaRef"); + for (i = 1; i < 4; i++) { + snprintf(tmp, sizeof(tmp), "bumpMat%d", i); + ret->bump_mat_loc[i] = glGetUniformLocation(program, tmp); + snprintf(tmp, sizeof(tmp), "bumpScale%d", i); + ret->bump_scale_loc[i] = glGetUniformLocation(program, tmp); + snprintf(tmp, sizeof(tmp), "bumpOffset%d", i); + ret->bump_offset_loc[i] = glGetUniformLocation(program, tmp); + } + + /* lookup vertex shader uniforms */ + for(i = 0; i < NV2A_VERTEXSHADER_CONSTANTS; i++) { + snprintf(tmp, sizeof(tmp), "c[%d]", i); + ret->vsh_constant_loc[i] = glGetUniformLocation(program, tmp); + } + ret->surface_size_loc = glGetUniformLocation(program, "surfaceSize"); + ret->clip_range_loc = glGetUniformLocation(program, "clipRange"); + ret->fog_color_loc = glGetUniformLocation(program, "fogColor"); + ret->fog_param_loc[0] = glGetUniformLocation(program, "fogParam[0]"); + ret->fog_param_loc[1] = glGetUniformLocation(program, "fogParam[1]"); + + ret->inv_viewport_loc = glGetUniformLocation(program, "invViewport"); + for (i = 0; i < NV2A_LTCTXA_COUNT; i++) { + snprintf(tmp, sizeof(tmp), "ltctxa[%d]", i); + ret->ltctxa_loc[i] = glGetUniformLocation(program, tmp); + } + for (i = 0; i < NV2A_LTCTXB_COUNT; i++) { + snprintf(tmp, sizeof(tmp), "ltctxb[%d]", i); + ret->ltctxb_loc[i] = glGetUniformLocation(program, tmp); + } + for (i = 0; i < NV2A_LTC1_COUNT; i++) { + snprintf(tmp, sizeof(tmp), "ltc1[%d]", i); + ret->ltc1_loc[i] = glGetUniformLocation(program, tmp); + } + for (i = 0; i < NV2A_MAX_LIGHTS; i++) { + snprintf(tmp, sizeof(tmp), "lightInfiniteHalfVector%d", i); + ret->light_infinite_half_vector_loc = glGetUniformLocation(program, tmp); + snprintf(tmp, sizeof(tmp), "lightInfiniteDirection%d", i); + ret->light_infinite_direction_loc = glGetUniformLocation(program, tmp); + + snprintf(tmp, sizeof(tmp), "lightLocalPosition%d", i); + ret->light_local_position_loc = glGetUniformLocation(program, tmp); + snprintf(tmp, sizeof(tmp), "lightLocalAttenuation%d", i); + ret->light_local_attenuation_loc = glGetUniformLocation(program, tmp); } return ret; diff --git a/hw/xbox/nv2a_shaders.h b/hw/xbox/nv2a_shaders.h index 9d4928985f..85bd01fde2 100644 --- a/hw/xbox/nv2a_shaders.h +++ b/hw/xbox/nv2a_shaders.h @@ -31,6 +31,156 @@ #define NV2A_VERTEXSHADER_CONSTANTS 192 #define NV2A_MAX_LIGHTS 8 +#define NV2A_LTCTXA_COUNT 26 +#define NV2A_LTCTXB_COUNT 52 +#define NV2A_LTC1_COUNT 20 + +/* vertex processing (cheops) context layout */ +#define NV_IGRAPH_XF_XFCTX_CMAT0 0x00 +#define NV_IGRAPH_XF_XFCTX_PMAT0 0x04 +#define NV_IGRAPH_XF_XFCTX_MMAT0 0x08 +#define NV_IGRAPH_XF_XFCTX_IMMAT0 0x0c +#define NV_IGRAPH_XF_XFCTX_MMAT1 0x10 +#define NV_IGRAPH_XF_XFCTX_IMMAT1 0x14 +#define NV_IGRAPH_XF_XFCTX_MMAT2 0x18 +#define NV_IGRAPH_XF_XFCTX_IMMAT2 0x1c +#define NV_IGRAPH_XF_XFCTX_MMAT3 0x20 +#define NV_IGRAPH_XF_XFCTX_IMMAT3 0x24 +#define NV_IGRAPH_XF_XFCTX_LIT0 0x28 +#define NV_IGRAPH_XF_XFCTX_LIT1 0x29 +#define NV_IGRAPH_XF_XFCTX_LIT2 0x2a +#define NV_IGRAPH_XF_XFCTX_LIT3 0x2b +#define NV_IGRAPH_XF_XFCTX_LIT4 0x2c +#define NV_IGRAPH_XF_XFCTX_LIT5 0x2d +#define NV_IGRAPH_XF_XFCTX_LIT6 0x2e +#define NV_IGRAPH_XF_XFCTX_LIT7 0x2f +#define NV_IGRAPH_XF_XFCTX_SPOT0 0x30 +#define NV_IGRAPH_XF_XFCTX_SPOT1 0x31 +#define NV_IGRAPH_XF_XFCTX_SPOT2 0x32 +#define NV_IGRAPH_XF_XFCTX_SPOT3 0x33 +#define NV_IGRAPH_XF_XFCTX_SPOT4 0x34 +#define NV_IGRAPH_XF_XFCTX_SPOT5 0x35 +#define NV_IGRAPH_XF_XFCTX_SPOT6 0x36 +#define NV_IGRAPH_XF_XFCTX_SPOT7 0x37 +#define NV_IGRAPH_XF_XFCTX_EYEP 0x38 +#define NV_IGRAPH_XF_XFCTX_FOG 0x39 +#define NV_IGRAPH_XF_XFCTX_VPSCL 0x3a +#define NV_IGRAPH_XF_XFCTX_VPOFF 0x3b +#define NV_IGRAPH_XF_XFCTX_CONS0 0x3c +#define NV_IGRAPH_XF_XFCTX_CONS1 0x3d +#define NV_IGRAPH_XF_XFCTX_CONS2 0x3e +#define NV_IGRAPH_XF_XFCTX_CONS3 0x3f +#define NV_IGRAPH_XF_XFCTX_TG0MAT 0x40 +#define NV_IGRAPH_XF_XFCTX_T0MAT 0x44 +#define NV_IGRAPH_XF_XFCTX_TG1MAT 0x48 +#define NV_IGRAPH_XF_XFCTX_T1MAT 0x4c +#define NV_IGRAPH_XF_XFCTX_TG2MAT 0x50 +#define NV_IGRAPH_XF_XFCTX_T2MAT 0x54 +#define NV_IGRAPH_XF_XFCTX_TG3MAT 0x58 +#define NV_IGRAPH_XF_XFCTX_T3MAT 0x5c +#define NV_IGRAPH_XF_XFCTX_PRSPACE 0x60 + +/* lighting (zoser) context layout */ +#define NV_IGRAPH_XF_LTCTXA_L0_K 0x00 +#define NV_IGRAPH_XF_LTCTXA_L0_SPT 0x01 +#define NV_IGRAPH_XF_LTCTXA_L1_K 0x02 +#define NV_IGRAPH_XF_LTCTXA_L1_SPT 0x03 +#define NV_IGRAPH_XF_LTCTXA_L2_K 0x04 +#define NV_IGRAPH_XF_LTCTXA_L2_SPT 0x05 +#define NV_IGRAPH_XF_LTCTXA_L3_K 0x06 +#define NV_IGRAPH_XF_LTCTXA_L3_SPT 0x07 +#define NV_IGRAPH_XF_LTCTXA_L4_K 0x08 +#define NV_IGRAPH_XF_LTCTXA_L4_SPT 0x09 +#define NV_IGRAPH_XF_LTCTXA_L5_K 0x0a +#define NV_IGRAPH_XF_LTCTXA_L5_SPT 0x0b +#define NV_IGRAPH_XF_LTCTXA_L6_K 0x0c +#define NV_IGRAPH_XF_LTCTXA_L6_SPT 0x0d +#define NV_IGRAPH_XF_LTCTXA_L7_K 0x0e +#define NV_IGRAPH_XF_LTCTXA_L7_SPT 0x0f +#define NV_IGRAPH_XF_LTCTXA_EYED 0x10 +#define NV_IGRAPH_XF_LTCTXA_FR_AMB 0x11 +#define NV_IGRAPH_XF_LTCTXA_BR_AMB 0x12 +#define NV_IGRAPH_XF_LTCTXA_CM_COL 0x13 +#define NV_IGRAPH_XF_LTCTXA_BCM_COL 0x14 +#define NV_IGRAPH_XF_LTCTXA_FOG_K 0x15 +#define NV_IGRAPH_XF_LTCTXA_ZERO 0x16 +#define NV_IGRAPH_XF_LTCTXA_PT0 0x17 +#define NV_IGRAPH_XF_LTCTXA_FOGLIN 0x18 + +#define NV_IGRAPH_XF_LTCTXB_L0_AMB 0x00 +#define NV_IGRAPH_XF_LTCTXB_L0_DIF 0x01 +#define NV_IGRAPH_XF_LTCTXB_L0_SPC 0x02 +#define NV_IGRAPH_XF_LTCTXB_L0_BAMB 0x03 +#define NV_IGRAPH_XF_LTCTXB_L0_BDIF 0x04 +#define NV_IGRAPH_XF_LTCTXB_L0_BSPC 0x05 +#define NV_IGRAPH_XF_LTCTXB_L1_AMB 0x06 +#define NV_IGRAPH_XF_LTCTXB_L1_DIF 0x07 +#define NV_IGRAPH_XF_LTCTXB_L1_SPC 0x08 +#define NV_IGRAPH_XF_LTCTXB_L1_BAMB 0x09 +#define NV_IGRAPH_XF_LTCTXB_L1_BDIF 0x0a +#define NV_IGRAPH_XF_LTCTXB_L1_BSPC 0x0b +#define NV_IGRAPH_XF_LTCTXB_L2_AMB 0x0c +#define NV_IGRAPH_XF_LTCTXB_L2_DIF 0x0d +#define NV_IGRAPH_XF_LTCTXB_L2_SPC 0x0e +#define NV_IGRAPH_XF_LTCTXB_L2_BAMB 0x0f +#define NV_IGRAPH_XF_LTCTXB_L2_BDIF 0x10 +#define NV_IGRAPH_XF_LTCTXB_L2_BSPC 0x11 +#define NV_IGRAPH_XF_LTCTXB_L3_AMB 0x12 +#define NV_IGRAPH_XF_LTCTXB_L3_DIF 0x13 +#define NV_IGRAPH_XF_LTCTXB_L3_SPC 0x14 +#define NV_IGRAPH_XF_LTCTXB_L3_BAMB 0x15 +#define NV_IGRAPH_XF_LTCTXB_L3_BDIF 0x16 +#define NV_IGRAPH_XF_LTCTXB_L3_BSPC 0x17 +#define NV_IGRAPH_XF_LTCTXB_L4_AMB 0x18 +#define NV_IGRAPH_XF_LTCTXB_L4_DIF 0x19 +#define NV_IGRAPH_XF_LTCTXB_L4_SPC 0x1a +#define NV_IGRAPH_XF_LTCTXB_L4_BAMB 0x1b +#define NV_IGRAPH_XF_LTCTXB_L4_BDIF 0x1c +#define NV_IGRAPH_XF_LTCTXB_L4_BSPC 0x1d +#define NV_IGRAPH_XF_LTCTXB_L5_AMB 0x1e +#define NV_IGRAPH_XF_LTCTXB_L5_DIF 0x1f +#define NV_IGRAPH_XF_LTCTXB_L5_SPC 0x20 +#define NV_IGRAPH_XF_LTCTXB_L5_BAMB 0x21 +#define NV_IGRAPH_XF_LTCTXB_L5_BDIF 0x22 +#define NV_IGRAPH_XF_LTCTXB_L5_BSPC 0x23 +#define NV_IGRAPH_XF_LTCTXB_L6_AMB 0x24 +#define NV_IGRAPH_XF_LTCTXB_L6_DIF 0x25 +#define NV_IGRAPH_XF_LTCTXB_L6_SPC 0x26 +#define NV_IGRAPH_XF_LTCTXB_L6_BAMB 0x27 +#define NV_IGRAPH_XF_LTCTXB_L6_BDIF 0x28 +#define NV_IGRAPH_XF_LTCTXB_L6_BSPC 0x29 +#define NV_IGRAPH_XF_LTCTXB_L7_AMB 0x2a +#define NV_IGRAPH_XF_LTCTXB_L7_DIF 0x2b +#define NV_IGRAPH_XF_LTCTXB_L7_SPC 0x2c +#define NV_IGRAPH_XF_LTCTXB_L7_BAMB 0x2d +#define NV_IGRAPH_XF_LTCTXB_L7_BDIF 0x2e +#define NV_IGRAPH_XF_LTCTXB_L7_BSPC 0x2f +#define NV_IGRAPH_XF_LTCTXB_PT1 0x30 +#define NV_IGRAPH_XF_LTCTXB_ONE 0x31 +#define NV_IGRAPH_XF_LTCTXB_VPOFFSET 0x32 + +#define NV_IGRAPH_XF_LTC1_ZERO1 0x00 +#define NV_IGRAPH_XF_LTC1_l0 0x01 +#define NV_IGRAPH_XF_LTC1_Bl0 0x02 +#define NV_IGRAPH_XF_LTC1_PP 0x03 +#define NV_IGRAPH_XF_LTC1_r0 0x04 +#define NV_IGRAPH_XF_LTC1_r1 0x05 +#define NV_IGRAPH_XF_LTC1_r2 0x06 +#define NV_IGRAPH_XF_LTC1_r3 0x07 +#define NV_IGRAPH_XF_LTC1_r4 0x08 +#define NV_IGRAPH_XF_LTC1_r5 0x09 +#define NV_IGRAPH_XF_LTC1_r6 0x0a +#define NV_IGRAPH_XF_LTC1_r7 0x0b +#define NV_IGRAPH_XF_LTC1_L0 0x0c +#define NV_IGRAPH_XF_LTC1_L1 0x0d +#define NV_IGRAPH_XF_LTC1_L2 0x0e +#define NV_IGRAPH_XF_LTC1_L3 0x0f +#define NV_IGRAPH_XF_LTC1_L4 0x10 +#define NV_IGRAPH_XF_LTC1_L5 0x11 +#define NV_IGRAPH_XF_LTC1_L6 0x12 +#define NV_IGRAPH_XF_LTC1_L7 0x13 + + enum ShaderPrimitiveMode { PRIM_TYPE_NONE, PRIM_TYPE_POINTS, @@ -85,8 +235,31 @@ typedef struct ShaderState { typedef struct ShaderBinding { GLuint gl_program; GLenum gl_primitive_mode; + GLint psh_constant_loc[9][2]; + GLint alpha_ref_loc; + + GLint bump_mat_loc[4]; + GLint bump_scale_loc[4]; + GLint bump_offset_loc[4]; + + GLint surface_size_loc; + GLint clip_range_loc; + GLint vsh_constant_loc[NV2A_VERTEXSHADER_CONSTANTS]; + + GLint inv_viewport_loc; + GLint ltctxa_loc[NV2A_LTCTXA_COUNT]; + GLint ltctxb_loc[NV2A_LTCTXB_COUNT]; + GLint ltc1_loc[NV2A_LTC1_COUNT]; + + GLint fog_color_loc; + GLint fog_param_loc[2]; + GLint light_infinite_half_vector_loc; + GLint light_infinite_direction_loc; + GLint light_local_position_loc; + GLint light_local_attenuation_loc; + } ShaderBinding; ShaderBinding* generate_shaders(const ShaderState state); diff --git a/hw/xbox/nv2a_vsh.c b/hw/xbox/nv2a_vsh.c index 38de2a4263..8de65963cc 100644 --- a/hw/xbox/nv2a_vsh.c +++ b/hw/xbox/nv2a_vsh.c @@ -696,12 +696,6 @@ void vsh_translate(uint16_t version, QString *header, QString *body) { - - qstring_append(header, "\n" - "uniform mat4 texMat0;\n" - "uniform mat4 texMat1;\n" - "uniform mat4 texMat2;\n" - "uniform mat4 texMat3;\n"); qstring_append(header, vsh_header); bool has_final = false; diff --git a/hw/xbox/nv2a_vsh.h b/hw/xbox/nv2a_vsh.h index 7ebfdb10cd..f3a9e662d2 100644 --- a/hw/xbox/nv2a_vsh.h +++ b/hw/xbox/nv2a_vsh.h @@ -22,6 +22,7 @@ #ifndef HW_NV2A_VSH_H #define HW_NV2A_VSH_H +#include #include "qapi/qmp/qstring.h" enum VshLight {