From 884064988795d9da49982a29fdf618f9a6e8074d Mon Sep 17 00:00:00 2001 From: MysterD Date: Wed, 26 Apr 2023 20:37:25 -0700 Subject: [PATCH] Started adding support for advanced materials (2cycle) --- src/pc/gfx/gfx_cc.c | 2 +- src/pc/gfx/gfx_cc.h | 47 +++++- src/pc/gfx/gfx_direct3d_common.cpp | 10 +- src/pc/gfx/gfx_opengl.c | 95 ++++++------ src/pc/gfx/gfx_pc.c | 236 +++++++++++++++++------------ src/pc/gfx/gfx_rendering_api.h | 5 +- 6 files changed, 244 insertions(+), 151 deletions(-) diff --git a/src/pc/gfx/gfx_cc.c b/src/pc/gfx/gfx_cc.c index bfdce3744..408e56f04 100644 --- a/src/pc/gfx/gfx_cc.c +++ b/src/pc/gfx/gfx_cc.c @@ -25,7 +25,7 @@ void gfx_cc_get_features(uint32_t shader_id, struct CCFeatures *cc_features) { if (cc_features->c[i][j] == SHADER_TEXEL0 || cc_features->c[i][j] == SHADER_TEXEL0A) { cc_features->used_textures[0] = true; } - if (cc_features->c[i][j] == SHADER_TEXEL1) { + if (cc_features->c[i][j] == SHADER_TEXEL1 || cc_features->c[i][j] == SHADER_TEXEL1A) { cc_features->used_textures[1] = true; } } diff --git a/src/pc/gfx/gfx_cc.h b/src/pc/gfx/gfx_cc.h index 2840b83ee..1b49e16ce 100644 --- a/src/pc/gfx/gfx_cc.h +++ b/src/pc/gfx/gfx_cc.h @@ -12,7 +12,12 @@ enum { CC_SHADE, CC_ENV, CC_TEXEL0A, - CC_LOD + CC_LOD, + CC_1, + CC_TEXEL1A, + CC_COMBINED, + CC_COMBINEDA, + CC_MAX, }; enum { @@ -23,7 +28,11 @@ enum { SHADER_INPUT_4, SHADER_TEXEL0, SHADER_TEXEL0A, - SHADER_TEXEL1 + SHADER_TEXEL1, + SHADER_TEXEL1A, + SHADER_1, + SHADER_COMBINED, + SHADER_COMBINEDA, }; #define SHADER_OPT_ALPHA (1 << 24) @@ -45,6 +54,40 @@ struct CCFeatures { bool color_alpha_same; }; +#pragma pack(1) +struct CombineMode { + union { + struct { + uint32_t rgb1; + uint32_t alpha1; + uint32_t rgb2; + uint32_t alpha2; + }; + uint8_t all_values[16]; + }; + union { + struct { + uint8_t use_alpha : 1; + uint8_t use_fog : 1; + uint8_t texture_edge : 1; + uint8_t use_noise : 1; + }; + uint32_t flags; + }; + uint64_t hash; +}; +#pragma pack() + +#define SHADER_CMD_LENGTH 16 + +struct ColorCombiner { + struct CombineMode cm; + struct ShaderProgram *prg; + uint8_t shader_input_mapping[16]; + uint8_t shader_commands[16]; + uint64_t hash; +}; + #ifdef __cplusplus extern "C" { #endif diff --git a/src/pc/gfx/gfx_direct3d_common.cpp b/src/pc/gfx/gfx_direct3d_common.cpp index c3249a388..c4e4da6d6 100644 --- a/src/pc/gfx/gfx_direct3d_common.cpp +++ b/src/pc/gfx/gfx_direct3d_common.cpp @@ -30,7 +30,7 @@ void get_cc_features(uint32_t shader_id, CCFeatures *cc_features) { if (cc_features->c[i][j] == SHADER_TEXEL0 || cc_features->c[i][j] == SHADER_TEXEL0A) { cc_features->used_textures[0] = true; } - if (cc_features->c[i][j] == SHADER_TEXEL1) { + if (cc_features->c[i][j] == SHADER_TEXEL1 || cc_features->c[i][j] == SHADER_TEXEL1A) { cc_features->used_textures[1] = true; } } @@ -61,6 +61,8 @@ static const char *shader_item_to_str(int32_t item, bool with_alpha, bool only_a default: case SHADER_0: return with_alpha ? "float4(0.0, 0.0, 0.0, 0.0)" : "float3(0.0, 0.0, 0.0)"; + case SHADER_1: + return with_alpha ? "float4(1.0, 1.0, 1.0, 1.0)" : "float3(1.0, 1.0, 1.0)"; case SHADER_INPUT_1: return with_alpha || !inputs_have_alpha ? "input.input1" : "input.input1.rgb"; case SHADER_INPUT_2: @@ -75,12 +77,16 @@ static const char *shader_item_to_str(int32_t item, bool with_alpha, bool only_a return hint_single_element ? "texVal0.a" : (with_alpha ? "float4(texVal0.a, texVal0.a, texVal0.a, texVal0.a)" : "float3(texVal0.a, texVal0.a, texVal0.a)"); case SHADER_TEXEL1: return with_alpha ? "texVal1" : "texVal1.rgb"; + case SHADER_TEXEL1A: + return hint_single_element ? "texVal1.a" : (with_alpha ? "float4(texVal1.a, texVal1.a, texVal1.a, texVal1.a)" : "float3(texVal1.a, texVal1.a, texVal1.a)"); } } else { switch (item) { default: case SHADER_0: return "0.0"; + case SHADER_1: + return "1.0"; case SHADER_INPUT_1: return "input.input1.a"; case SHADER_INPUT_2: @@ -95,6 +101,8 @@ static const char *shader_item_to_str(int32_t item, bool with_alpha, bool only_a return "texVal0.a"; case SHADER_TEXEL1: return "texVal1.a"; + case SHADER_TEXEL1A: + return "texVal1.a"; } } } diff --git a/src/pc/gfx/gfx_opengl.c b/src/pc/gfx/gfx_opengl.c index 7ae82942e..80dc7ef76 100644 --- a/src/pc/gfx/gfx_opengl.c +++ b/src/pc/gfx/gfx_opengl.c @@ -43,7 +43,7 @@ #define TEX_CACHE_STEP 512 struct ShaderProgram { - uint32_t shader_id; + uint64_t hash; GLuint opengl_program_id; uint8_t num_inputs; bool used_textures[2]; @@ -136,6 +136,8 @@ static const char *shader_item_to_str(uint32_t item, bool with_alpha, bool only_ switch (item) { case SHADER_0: return with_alpha ? "vec4(0.0, 0.0, 0.0, 0.0)" : "vec3(0.0, 0.0, 0.0)"; + case SHADER_1: + return with_alpha ? "vec4(1.0, 1.0, 1.0, 1.0)" : "vec3(1.0, 1.0, 1.0)"; case SHADER_INPUT_1: return with_alpha || !inputs_have_alpha ? "vInput1" : "vInput1.rgb"; case SHADER_INPUT_2: @@ -151,11 +153,16 @@ static const char *shader_item_to_str(uint32_t item, bool with_alpha, bool only_ (with_alpha ? "vec4(texelVal0.a, texelVal0.a, texelVal0.a, texelVal0.a)" : "vec3(texelVal0.a, texelVal0.a, texelVal0.a)"); case SHADER_TEXEL1: return with_alpha ? "texVal1" : "texVal1.rgb"; + case SHADER_TEXEL1A: + return hint_single_element ? "texVal1.a" : + (with_alpha ? "vec4(texelVal1.a, texelVal1.a, texelVal1.a, texelVal1.a)" : "vec3(texelVal1.a, texelVal1.a, texelVal1.a)"); } } else { switch (item) { case SHADER_0: return "0.0"; + case SHADER_1: + return "1.0"; case SHADER_INPUT_1: return "vInput1.a"; case SHADER_INPUT_2: @@ -170,74 +177,66 @@ static const char *shader_item_to_str(uint32_t item, bool with_alpha, bool only_ return "texVal0.a"; case SHADER_TEXEL1: return "texVal1.a"; + case SHADER_TEXEL1A: + return "texVal1.a"; } } return "unknown"; } -static void append_formula(char *buf, size_t *len, uint8_t c[2][4], bool do_single, bool do_multiply, bool do_mix, bool with_alpha, bool only_alpha, bool opt_alpha) { +static void append_formula(char *buf, size_t *len, uint8_t* cmd, bool do_single, bool do_multiply, bool do_mix, bool with_alpha, bool only_alpha, bool opt_alpha) { if (do_single) { - append_str(buf, len, shader_item_to_str(c[only_alpha][3], with_alpha, only_alpha, opt_alpha, false)); + append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 3], with_alpha, only_alpha, opt_alpha, false)); } else if (do_multiply) { - append_str(buf, len, shader_item_to_str(c[only_alpha][0], with_alpha, only_alpha, opt_alpha, false)); + append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 0], with_alpha, only_alpha, opt_alpha, false)); append_str(buf, len, " * "); - append_str(buf, len, shader_item_to_str(c[only_alpha][2], with_alpha, only_alpha, opt_alpha, true)); + append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 2], with_alpha, only_alpha, opt_alpha, true)); } else if (do_mix) { append_str(buf, len, "mix("); - append_str(buf, len, shader_item_to_str(c[only_alpha][1], with_alpha, only_alpha, opt_alpha, false)); + append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 1], with_alpha, only_alpha, opt_alpha, false)); append_str(buf, len, ", "); - append_str(buf, len, shader_item_to_str(c[only_alpha][0], with_alpha, only_alpha, opt_alpha, false)); + append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 0], with_alpha, only_alpha, opt_alpha, false)); append_str(buf, len, ", "); - append_str(buf, len, shader_item_to_str(c[only_alpha][2], with_alpha, only_alpha, opt_alpha, true)); + append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 2], with_alpha, only_alpha, opt_alpha, true)); append_str(buf, len, ")"); } else { append_str(buf, len, "("); - append_str(buf, len, shader_item_to_str(c[only_alpha][0], with_alpha, only_alpha, opt_alpha, false)); + append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 0], with_alpha, only_alpha, opt_alpha, false)); append_str(buf, len, " - "); - append_str(buf, len, shader_item_to_str(c[only_alpha][1], with_alpha, only_alpha, opt_alpha, false)); + append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 1], with_alpha, only_alpha, opt_alpha, false)); append_str(buf, len, ") * "); - append_str(buf, len, shader_item_to_str(c[only_alpha][2], with_alpha, only_alpha, opt_alpha, true)); + append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 2], with_alpha, only_alpha, opt_alpha, true)); append_str(buf, len, " + "); - append_str(buf, len, shader_item_to_str(c[only_alpha][3], with_alpha, only_alpha, opt_alpha, false)); + append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 3], with_alpha, only_alpha, opt_alpha, false)); } } -static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shader_id) { - uint8_t c[2][4]; - for (int i = 0; i < 4; i++) { - c[0][i] = (shader_id >> (i * 3)) & 7; - c[1][i] = (shader_id >> (12 + i * 3)) & 7; - } - bool opt_alpha = (shader_id & SHADER_OPT_ALPHA) != 0; - bool opt_fog = (shader_id & SHADER_OPT_FOG) != 0; - bool opt_texture_edge = (shader_id & SHADER_OPT_TEXTURE_EDGE) != 0; +static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorCombiner* cc) { + bool opt_alpha = cc->cm.use_alpha; + bool opt_fog = cc->cm.use_fog; + bool opt_texture_edge = cc->cm.texture_edge; #ifdef USE_GLES bool opt_noise = false; #else - bool opt_noise = (shader_id & SHADER_OPT_NOISE) != 0; + bool opt_noise = cc->cm.use_noise; #endif - bool used_textures[2] = { 0, 0 }; + u8* cmd = cc->shader_commands; + bool used_textures[2] = { 0 }; int num_inputs = 0; - for (int i = 0; i < 2; i++) { - for (int j = 0; j < 4; j++) { - if (c[i][j] >= SHADER_INPUT_1 && c[i][j] <= SHADER_INPUT_4) { - if (c[i][j] > num_inputs) { - num_inputs = c[i][j]; - } - } - if (c[i][j] == SHADER_TEXEL0 || c[i][j] == SHADER_TEXEL0A) { - used_textures[0] = true; - } - if (c[i][j] == SHADER_TEXEL1) { - used_textures[1] = true; - } + for (int i = 0; i < SHADER_CMD_LENGTH; i++) { + u8 c = cmd[i]; + if (c >= SHADER_INPUT_1 && c <= SHADER_INPUT_4) { + if (c > num_inputs) { num_inputs = c; } } + used_textures[0] = used_textures[0] || c == SHADER_TEXEL0 || c == SHADER_TEXEL0A; + used_textures[1] = used_textures[1] || c == SHADER_TEXEL1 || c == SHADER_TEXEL1A; } - bool do_single[2] = { c[0][2] == 0, c[1][2] == 0 }; - bool do_multiply[2] = { c[0][1] == 0 && c[0][3] == 0, c[1][1] == 0 && c[1][3] == 0 }; - bool do_mix[2] = { c[0][1] == c[0][3], c[1][1] == c[1][3] }; - bool color_alpha_same = (shader_id & 0xfff) == ((shader_id >> 12) & 0xfff); + + bool do_single[2] = { cmd[0 * 4 + 2] == 0, cmd[1 * 4 + 2] == 0 }; + bool do_multiply[2] = { cmd[0 * 4 + 1] == 0 && cmd[0 * 4 + 3] == 0, cmd[1 * 4 + 1] == 0 && cmd[1 * 4 + 3] == 0 }; + bool do_mix[2] = { cmd[0 * 4 + 1] == cmd[0 * 4 + 3], cmd[1 * 4 + 1] == cmd[1 * 4 + 3] }; + bool color_alpha_same = false; // TODO: gotta check shader comamndssadasda char vs_buf[1024]; char fs_buf[2048]; @@ -357,12 +356,12 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shad append_str(fs_buf, &fs_len, opt_alpha ? "vec4 texel = " : "vec3 texel = "); if (!color_alpha_same && opt_alpha) { append_str(fs_buf, &fs_len, "vec4("); - append_formula(fs_buf, &fs_len, c, do_single[0], do_multiply[0], do_mix[0], false, false, true); + append_formula(fs_buf, &fs_len, cmd, do_single[0], do_multiply[0], do_mix[0], false, false, true); append_str(fs_buf, &fs_len, ", "); - append_formula(fs_buf, &fs_len, c, do_single[1], do_multiply[1], do_mix[1], true, true, true); + append_formula(fs_buf, &fs_len, cmd, do_single[1], do_multiply[1], do_mix[1], true, true, true); append_str(fs_buf, &fs_len, ")"); } else { - append_formula(fs_buf, &fs_len, c, do_single[0], do_multiply[0], do_mix[0], opt_alpha, false, opt_alpha); + append_formula(fs_buf, &fs_len, cmd, do_single[0], do_multiply[0], do_mix[0], opt_alpha, false, opt_alpha); } append_line(fs_buf, &fs_len, ";"); @@ -391,11 +390,11 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shad vs_buf[vs_len] = '\0'; fs_buf[fs_len] = '\0'; - /*puts("Vertex shader:"); + puts("Vertex shader:"); puts(vs_buf); puts("Fragment shader:"); puts(fs_buf); - puts("End");*/ + puts("End"); const GLchar *sources[2] = { vs_buf, fs_buf }; const GLint lengths[2] = { vs_len, fs_len }; @@ -461,7 +460,7 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shad ++cnt; } - prg->shader_id = shader_id; + prg->hash = cc->hash; prg->opengl_program_id = shader_program; prg->num_inputs = num_inputs; prg->used_textures[0] = used_textures[0]; @@ -494,9 +493,9 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shad return prg; } -static struct ShaderProgram *gfx_opengl_lookup_shader(uint32_t shader_id) { +static struct ShaderProgram *gfx_opengl_lookup_shader(struct ColorCombiner* cc) { for (size_t i = 0; i < shader_program_pool_size; i++) { - if (shader_program_pool[i].shader_id == shader_id) { + if (shader_program_pool[i].hash == cc->hash) { return &shader_program_pool[i]; } } diff --git a/src/pc/gfx/gfx_pc.c b/src/pc/gfx/gfx_pc.c index 84fad2461..ed27af172 100644 --- a/src/pc/gfx/gfx_pc.c +++ b/src/pc/gfx/gfx_pc.c @@ -94,13 +94,7 @@ static struct { uint32_t pool_pos; } gfx_texture_cache; -struct ColorCombiner { - uint32_t cc_id; - struct ShaderProgram *prg; - uint8_t shader_input_mapping[2][4]; -}; - -static struct ColorCombiner color_combiner_pool[64]; +static struct ColorCombiner color_combiner_pool[64] = { 0 }; static uint8_t color_combiner_pool_size; static struct RSP { @@ -148,7 +142,7 @@ static struct RDP { bool textures_changed[2]; uint32_t other_mode_l, other_mode_h; - uint32_t combine_mode; + struct CombineMode combine_mode; struct RGBA env_color, prim_color, fog_color, fill_color; struct XYWidthHeight viewport, scissor; @@ -234,77 +228,110 @@ static void gfx_flush(void) { } } -static struct ShaderProgram *gfx_lookup_or_create_shader_program(uint32_t shader_id) { - struct ShaderProgram *prg = gfx_rapi->lookup_shader(shader_id); +static void combine_mode_update_hash(struct CombineMode* mode) { + uint64_t hash = 5381; + + hash = (hash << 5) + hash + mode->rgb1; + hash = (hash << 5) + hash + mode->alpha1; + hash = (hash << 5) + hash + mode->rgb2; + hash = (hash << 5) + hash + mode->alpha2; + hash = (hash << 5) + hash + mode->flags; + + mode->hash = hash; +} + +static void color_combiner_update_hash(struct ColorCombiner* cc) { + uint64_t hash = cc->cm.hash; + + for (int i = 0; i < SHADER_CMD_LENGTH; i++) { + hash = (hash << 5) + hash + cc->shader_commands[i]; + } + + cc->hash = hash; +} + +static struct ShaderProgram *gfx_lookup_or_create_shader_program(struct ColorCombiner* cc) { + struct ShaderProgram *prg = gfx_rapi->lookup_shader(cc); if (prg == NULL) { gfx_rapi->unload_shader(rendering_state.shader_program); - prg = gfx_rapi->create_and_load_new_shader(shader_id); + prg = gfx_rapi->create_and_load_new_shader(cc); rendering_state.shader_program = prg; } return prg; } -static void gfx_generate_cc(struct ColorCombiner *comb, uint32_t cc_id) { - uint8_t c[2][4]; - uint32_t shader_id = (cc_id >> 24) << 24; - uint8_t shader_input_mapping[2][4] = {{0}}; - for (int32_t i = 0; i < 4; i++) { - c[0][i] = (cc_id >> (i * 3)) & 7; - c[1][i] = (cc_id >> (12 + i * 3)) & 7; - } - for (int32_t i = 0; i < 2; i++) { - if (c[i][0] == c[i][1] || c[i][2] == CC_0) { - c[i][0] = c[i][1] = c[i][2] = 0; - } - uint8_t input_number[8] = {0}; - int next_input_number = SHADER_INPUT_1; - for (int j = 0; j < 4; j++) { - int val = 0; - switch (c[i][j]) { - case CC_0: - break; - case CC_TEXEL0: - val = SHADER_TEXEL0; - break; - case CC_TEXEL1: - val = SHADER_TEXEL1; - break; - case CC_TEXEL0A: - val = SHADER_TEXEL0A; - break; - case CC_PRIM: - case CC_SHADE: - case CC_ENV: - case CC_LOD: - if (input_number[c[i][j]] == 0) { - shader_input_mapping[i][next_input_number - 1] = c[i][j]; - input_number[c[i][j]] = next_input_number++; - } - val = input_number[c[i][j]]; - break; - } - shader_id |= val << (i * 12 + j * 3); +static void gfx_generate_cc(struct ColorCombiner *cc) { + u8 next_input_number = 0; + u8 input_number[CC_MAX] = { 0 }; + + for (int i = 0; i < SHADER_CMD_LENGTH; i++) { + u8 cm_cmd = cc->cm.all_values[i]; + u8 shader_cmd = 0; + switch (cm_cmd) { + case CC_0: + shader_cmd = SHADER_0; + break; + case CC_1: + shader_cmd = SHADER_1; + break; + case CC_TEXEL0: + shader_cmd = SHADER_TEXEL0; + break; + case CC_TEXEL1: + shader_cmd = SHADER_TEXEL1; + break; + case CC_TEXEL0A: + shader_cmd = SHADER_TEXEL0A; + break; + case CC_TEXEL1A: + shader_cmd = SHADER_TEXEL1A; + break; + case CC_COMBINED: + shader_cmd = SHADER_COMBINED; + break; + case CC_COMBINEDA: + shader_cmd = SHADER_COMBINEDA; + break; + case CC_PRIM: + case CC_SHADE: + case CC_ENV: + case CC_LOD: + if (input_number[cm_cmd] == 0) { + cc->shader_input_mapping[next_input_number] = cm_cmd; + input_number[cm_cmd] = SHADER_INPUT_1 + next_input_number; + next_input_number++; + } + shader_cmd = input_number[cm_cmd]; + break; + default: + shader_cmd = SHADER_0; + break; } + cc->shader_commands[i] = shader_cmd; } - comb->cc_id = cc_id; - comb->prg = gfx_lookup_or_create_shader_program(shader_id); - memcpy(comb->shader_input_mapping, shader_input_mapping, sizeof(shader_input_mapping)); + + color_combiner_update_hash(cc); + cc->prg = gfx_lookup_or_create_shader_program(cc); } -static struct ColorCombiner *gfx_lookup_or_create_color_combiner(uint32_t cc_id) { +static struct ColorCombiner *gfx_lookup_or_create_color_combiner(struct CombineMode* cm) { + combine_mode_update_hash(cm); + static struct ColorCombiner *prev_combiner; - if (prev_combiner != NULL && prev_combiner->cc_id == cc_id) { + if (prev_combiner != NULL && prev_combiner->cm.hash == cm->hash) { return prev_combiner; } for (size_t i = 0; i < color_combiner_pool_size; i++) { - if (color_combiner_pool[i].cc_id == cc_id) { + if (color_combiner_pool[i].cm.hash == cm->hash) { return prev_combiner = &color_combiner_pool[i]; } } gfx_flush(); + struct ColorCombiner *comb = &color_combiner_pool[color_combiner_pool_size++]; - gfx_generate_cc(comb, cc_id); + comb->cm = *cm; + gfx_generate_cc(comb); return prev_combiner = comb; } @@ -979,27 +1006,20 @@ static void OPTIMIZE_O3 gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t rdp.viewport_or_scissor_changed = false; } - uint32_t cc_id = rdp.combine_mode; + struct CombineMode* cm = &rdp.combine_mode; - bool use_alpha = (rdp.other_mode_l & (G_BL_A_MEM << 18)) == 0; - bool use_fog = (rdp.other_mode_l >> 30) == G_BL_CLR_FOG; - bool texture_edge = (rdp.other_mode_l & CVG_X_ALPHA) == CVG_X_ALPHA; - bool use_noise = (rdp.other_mode_l & G_AC_DITHER) == G_AC_DITHER; + cm->use_alpha = (rdp.other_mode_l & (G_BL_A_MEM << 18)) == 0; + cm->texture_edge = (rdp.other_mode_l & CVG_X_ALPHA) == CVG_X_ALPHA; + cm->use_noise = (rdp.other_mode_l & G_AC_DITHER) == G_AC_DITHER; + cm->use_fog = (rdp.other_mode_l >> 30) == G_BL_CLR_FOG; - if (texture_edge) { - use_alpha = true; + if (cm->texture_edge) { + cm->use_alpha = true; } - if (use_alpha) cc_id |= SHADER_OPT_ALPHA; - if (use_fog) cc_id |= SHADER_OPT_FOG; - if (texture_edge) cc_id |= SHADER_OPT_TEXTURE_EDGE; - if (use_noise) cc_id |= SHADER_OPT_NOISE; + struct ColorCombiner *comb = gfx_lookup_or_create_color_combiner(cm); + cm = &comb->cm; - if (!use_alpha) { - cc_id &= ~0xfff000; - } - - struct ColorCombiner *comb = gfx_lookup_or_create_color_combiner(cc_id); struct ShaderProgram *prg = comb->prg; if (prg != rendering_state.shader_program) { gfx_flush(); @@ -1007,10 +1027,10 @@ static void OPTIMIZE_O3 gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t gfx_rapi->load_shader(prg); rendering_state.shader_program = prg; } - if (use_alpha != rendering_state.alpha_blend) { + if (cm->use_alpha != rendering_state.alpha_blend) { gfx_flush(); - gfx_rapi->set_use_alpha(use_alpha); - rendering_state.alpha_blend = use_alpha; + gfx_rapi->set_use_alpha(cm->use_alpha); + rendering_state.alpha_blend = cm->use_alpha; } uint8_t num_inputs; bool used_textures[2]; @@ -1065,7 +1085,7 @@ static void OPTIMIZE_O3 gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t buf_vbo[buf_vbo_len++] = v / tex_height; } - if (use_fog) { + if (cm->use_fog) { buf_vbo[buf_vbo_len++] = rdp.fog_color.r / 255.0f; buf_vbo[buf_vbo_len++] = rdp.fog_color.g / 255.0f; buf_vbo[buf_vbo_len++] = rdp.fog_color.b / 255.0f; @@ -1073,10 +1093,11 @@ static void OPTIMIZE_O3 gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t } for (int j = 0; j < num_inputs; j++) { - struct RGBA *color; - struct RGBA tmp; - for (int k = 0; k < 1 + (use_alpha ? 1 : 0); k++) { - switch (comb->shader_input_mapping[k][j]) { + struct RGBA *color = NULL; + struct RGBA tmp = { 0 }; + for (int a = 0; a < (cm->use_alpha ? 2 : 1 ); a++) { + u8 mapping = comb->shader_input_mapping[j]; + switch (mapping) { case CC_PRIM: color = &rdp.prim_color; break; @@ -1100,12 +1121,12 @@ static void OPTIMIZE_O3 gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t color = &tmp; break; } - if (k == 0) { + if (a == 0) { buf_vbo[buf_vbo_len++] = color->r / 255.0f; buf_vbo[buf_vbo_len++] = color->g / 255.0f; buf_vbo[buf_vbo_len++] = color->b / 255.0f; } else { - if (use_fog && color == &v_arr[i]->color) { + if (cm->use_fog && color == &v_arr[i]->color) { // Shade alpha is 100% for fog buf_vbo[buf_vbo_len++] = 1.0f; } else { @@ -1360,22 +1381,34 @@ static uint8_t color_comb_component(uint32_t v) { return CC_ENV; case G_CCMUX_TEXEL0_ALPHA: return CC_TEXEL0A; + /*case G_CCMUX_TEXEL1_ALPHA: + return CC_TEXEL1A;*/ case G_CCMUX_LOD_FRACTION: return CC_LOD; + /*case G_CCMUX_1: + return CC_1; + case G_CCMUX_COMBINED: + return CC_0; // return CC_COMBINED; TODO + case G_CCMUX_COMBINED_ALPHA: + return CC_0; //return CC_COMBINEDA; TODO*/ default: return CC_0; } } static inline uint32_t color_comb(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { - return color_comb_component(a) | - (color_comb_component(b) << 3) | - (color_comb_component(c) << 6) | - (color_comb_component(d) << 9); + return color_comb_component(a) + | (color_comb_component(b) << 8) + | (color_comb_component(c) << 16) + | (color_comb_component(d) << 24); } -static void gfx_dp_set_combine_mode(uint32_t rgb, uint32_t alpha) { - rdp.combine_mode = rgb | (alpha << 12); +static void gfx_dp_set_combine_mode(uint32_t rgb1, uint32_t alpha1, uint32_t rgb2, uint32_t alpha2) { + rdp.combine_mode.rgb1 = rgb1; + rdp.combine_mode.alpha1 = alpha1; + + rdp.combine_mode.rgb2 = rgb2; + rdp.combine_mode.alpha2 = alpha2; } static void gfx_dp_set_env_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { @@ -1480,14 +1513,14 @@ static void gfx_draw_rectangle(int32_t ulx, int32_t uly, int32_t lrx, int32_t lr } static void gfx_dp_texture_rectangle(int32_t ulx, int32_t uly, int32_t lrx, int32_t lry, UNUSED uint8_t tile, int16_t uls, int16_t ult, int16_t dsdx, int16_t dtdy, bool flip) { - uint32_t saved_combine_mode = rdp.combine_mode; + struct CombineMode saved_combine_mode = rdp.combine_mode; if ((rdp.other_mode_h & (3U << G_MDSFT_CYCLETYPE)) == G_CYC_COPY) { // Per RDP Command Summary Set Tile's shift s and this dsdx should be set to 4 texels // Divide by 4 to get 1 instead dsdx >>= 2; // Color combiner is turned off in copy mode - gfx_dp_set_combine_mode(color_comb(0, 0, 0, G_CCMUX_TEXEL0), color_comb(0, 0, 0, G_ACMUX_TEXEL0)); + gfx_dp_set_combine_mode(color_comb(0, 0, 0, G_CCMUX_TEXEL0), color_comb(0, 0, 0, G_ACMUX_TEXEL0), color_comb(0, 0, 0, G_CCMUX_TEXEL0), color_comb(0, 0, 0, G_ACMUX_TEXEL0)); // Per documentation one extra pixel is added in this modes to each edge lrx += 1 << 2; @@ -1528,7 +1561,10 @@ static void gfx_dp_texture_rectangle(int32_t ulx, int32_t uly, int32_t lrx, int3 } gfx_draw_rectangle(ulx, uly, lrx, lry); + + u32 cflags = rdp.combine_mode.flags; rdp.combine_mode = saved_combine_mode; + rdp.combine_mode.flags = cflags; } static void gfx_dp_fill_rectangle(int32_t ulx, int32_t uly, int32_t lrx, int32_t lry) { @@ -1549,10 +1585,13 @@ static void gfx_dp_fill_rectangle(int32_t ulx, int32_t uly, int32_t lrx, int32_t v->color = rdp.fill_color; } - uint32_t saved_combine_mode = rdp.combine_mode; - gfx_dp_set_combine_mode(color_comb(0, 0, 0, G_CCMUX_SHADE), color_comb(0, 0, 0, G_ACMUX_SHADE)); + struct CombineMode saved_combine_mode = rdp.combine_mode; + gfx_dp_set_combine_mode(color_comb(0, 0, 0, G_CCMUX_SHADE), color_comb(0, 0, 0, G_ACMUX_SHADE), color_comb(0, 0, 0, G_CCMUX_SHADE), color_comb(0, 0, 0, G_ACMUX_SHADE)); gfx_draw_rectangle(ulx, uly, lrx, lry); + + u32 cflags = rdp.combine_mode.flags; rdp.combine_mode = saved_combine_mode; + rdp.combine_mode.flags = cflags; } static void gfx_dp_set_z_image(void *z_buf_address) { @@ -1720,9 +1759,9 @@ static void OPTIMIZE_O3 gfx_run_dl(Gfx* cmd) { case G_SETCOMBINE: gfx_dp_set_combine_mode( color_comb(C0(20, 4), C1(28, 4), C0(15, 5), C1(15, 3)), - color_comb(C0(12, 3), C1(12, 3), C0(9, 3), C1(9, 3))); - /*color_comb(C0(5, 4), C1(24, 4), C0(0, 5), C1(6, 3)), - color_comb(C1(21, 3), C1(3, 3), C1(18, 3), C1(0, 3)));*/ + color_comb(C0(12, 3), C1(12, 3), C0(9, 3), C1(9, 3)), + color_comb(C0(5, 4), C1(24, 4), C0(0, 5), C1(6, 3)), + color_comb(C1(21, 3), C1(3, 3), C1(18, 3), C1(0, 3))); break; // G_SETPRIMCOLOR, G_CCMUX_PRIMITIVE, G_ACMUX_PRIMITIVE, is used by Goddard // G_CCMUX_TEXEL1, LOD_FRACTION is used in Bowser room 1 @@ -1808,6 +1847,8 @@ void gfx_init(struct GfxWindowManagerAPI *wapi, struct GfxRenderingAPI *rapi, co gfx_wapi->init(window_title); gfx_rapi->init(); + // DO NOT COMMIT: must update these! + /* // Used in the 120 star TAS static uint32_t precomp_shaders[] = { 0x01200200, @@ -1840,6 +1881,7 @@ void gfx_init(struct GfxWindowManagerAPI *wapi, struct GfxRenderingAPI *rapi, co for (size_t i = 0; i < sizeof(precomp_shaders) / sizeof(uint32_t); i++) gfx_lookup_or_create_shader_program(precomp_shaders[i]); + */ } #ifdef EXTERNAL_DATA diff --git a/src/pc/gfx/gfx_rendering_api.h b/src/pc/gfx/gfx_rendering_api.h index e76efe74f..064d8de5e 100644 --- a/src/pc/gfx/gfx_rendering_api.h +++ b/src/pc/gfx/gfx_rendering_api.h @@ -6,13 +6,14 @@ #include struct ShaderProgram; +struct ColorCombiner; struct GfxRenderingAPI { bool (*z_is_from_0_to_1)(void); void (*unload_shader)(struct ShaderProgram *old_prg); void (*load_shader)(struct ShaderProgram *new_prg); - struct ShaderProgram *(*create_and_load_new_shader)(uint32_t shader_id); - struct ShaderProgram *(*lookup_shader)(uint32_t shader_id); + struct ShaderProgram *(*create_and_load_new_shader)(struct ColorCombiner* cc); + struct ShaderProgram *(*lookup_shader)(struct ColorCombiner* cc); void (*shader_get_info)(struct ShaderProgram *prg, uint8_t *num_inputs, bool used_textures[2]); uint32_t (*new_texture)(void); void (*select_texture)(int tile, uint32_t texture_id);