From 9a9a02fafe93b783f065f7bb09500688d5da0e41 Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Sat, 28 May 2016 22:45:59 -0400 Subject: [PATCH] GLSL: Use varyings when usage_str is NULL for vertex/pixel shaders GLSLES: Various fixes from Maik Macho, thanks! Effects: Store parameter staging buffers as vec4 values, per ID3DXEffect spec --- mojoshader.c | 63 ++++++++++++--------- mojoshader_effects.c | 38 ++++++++++--- mojoshader_opengl.c | 131 +++++++++---------------------------------- utils/testparse.c | 61 +++++++++++--------- 4 files changed, 129 insertions(+), 164 deletions(-) diff --git a/mojoshader.c b/mojoshader.c index c131429c..66092ccf 100644 --- a/mojoshader.c +++ b/mojoshader.c @@ -2224,9 +2224,10 @@ static void emit_GLSL_start(Context *ctx, const char *profilestr) else output_line(ctx, "precision mediump float;"); output_line(ctx, "precision mediump int;"); - output_line(ctx, "varying vec4 v_FrontColor;"); - output_line(ctx, "varying vec4 v_FrontSecondaryColor;"); - output_line(ctx, "varying vec4 v_TexCoord[10];"); // 10 according to SM3 + // Some drivers don't like it when the precision varies between shaders. -ade + output_line(ctx, "varying highp vec4 v_FrontColor;"); + output_line(ctx, "varying highp vec4 v_FrontSecondaryColor;"); + output_line(ctx, "varying highp vec4 v_TexCoord[10];"); // 10 according to SM3 pop_output(ctx); } // else if #endif @@ -2344,6 +2345,12 @@ static void emit_GLSL_global(Context *ctx, RegisterType regtype, int regnum) // ps_1_1 TEX opcode expects to overwrite it. if (!shader_version_atleast(ctx, 1, 4)) { +#if SUPPORT_PROFILE_GLSLES + if (support_glsles(ctx)) + output_line(ctx, "vec4 %s = v_TexCoord[%d];", + varname, regnum); + else +#endif output_line(ctx, "vec4 %s = gl_TexCoord[%d];", varname, regnum); } // if @@ -2648,7 +2655,15 @@ static void emit_GLSL_attribute(Context *ctx, RegisterType regtype, int regnum, push_output(ctx, &ctx->globals); // no mapping to built-in var? Just make it a regular global, pray. if (usage_str == NULL) - output_line(ctx, "vec4 %s;", var); + { +#if SUPPORT_PROFILE_GLSLES + if (support_glsles(ctx)) + output_line(ctx, "varying highp vec4 io_%i_%i;", usage, index); + else +#endif + output_line(ctx, "varying vec4 io_%i_%i;", usage, index); + output_line(ctx, "#define %s io_%i_%i", var, usage, index); + } // if else { output_line(ctx, "#define %s %s%s%s%s", var, usage_str, @@ -2731,15 +2746,9 @@ static void emit_GLSL_attribute(Context *ctx, RegisterType regtype, int regnum, #endif usage_str = "gl_SecondaryColor"; } // else if - else - fail(ctx, "unsupported color index"); - } // else if - - else if (usage == MOJOSHADER_USAGE_DEPTH) // !!! FIXME: Possibly more! -flibit - { - push_output(ctx, &ctx->globals); - output_line(ctx, "attribute vec4 %s;", var); - pop_output(ctx); + // FIXME: Does this even matter when we have varyings? -flibit + // else + // fail(ctx, "unsupported color index"); } // else if } // else if @@ -2768,13 +2777,24 @@ static void emit_GLSL_attribute(Context *ctx, RegisterType regtype, int regnum, fail(ctx, "unknown pixel shader attribute register"); } // else - if (usage_str != NULL) + push_output(ctx, &ctx->globals); + // no mapping to built-in var? Just make it a regular global, pray. + if (usage_str == NULL) + { +#if SUPPORT_PROFILE_GLSLES + if (support_glsles(ctx)) + output_line(ctx, "varying highp vec4 io_%i_%i;", usage, index); + else +#endif + output_line(ctx, "varying vec4 io_%i_%i;", usage, index); + output_line(ctx, "#define %s io_%i_%i", var, usage, index); + } // if + else { - push_output(ctx, &ctx->globals); output_line(ctx, "#define %s %s%s%s%s", var, usage_str, arrayleft, index_str, arrayright); - pop_output(ctx); - } // if + } // else + pop_output(ctx); } // else if else @@ -5031,15 +5051,6 @@ static void emit_METAL_attribute(Context *ctx, RegisterType regtype, int regnum, else if (usage == MOJOSHADER_USAGE_FOG) output_line(ctx, "float4 %s [[user(fog)]];", var); - - #if 0 // !!! FIXME: Ethan added this for GLSL, but I don't know what it does. --ryan. - else if (usage == MOJOSHADER_USAGE_DEPTH) // !!! FIXME: Possibly more! -flibit - { - push_output(ctx, &ctx->globals); - output_line(ctx, "attribute vec4 %s;", var); - pop_output(ctx); - } // else if - #endif } // else pop_output(ctx); diff --git a/mojoshader_effects.c b/mojoshader_effects.c index b81c4171..3eb16d9f 100644 --- a/mojoshader_effects.c +++ b/mojoshader_effects.c @@ -251,7 +251,7 @@ static void readvalue(const uint8 *base, MOJOSHADER_malloc m, void *d) { - int i; + int i, j, k; const uint8 *typeptr = base + typeoffset; const uint8 *valptr = base + valoffset; unsigned int typelen = 9999999; // !!! FIXME @@ -284,13 +284,16 @@ static void readvalue(const uint8 *base, value->type.columns = columncount; value->type.rows = rowcount; - uint32 siz = columncount * rowcount; + uint32 siz = 4 * rowcount; if (numelements > 0) siz *= numelements; value->value_count = siz; siz *= 4; value->values = m(siz, d); - memcpy(value->values, valptr, siz); + memset(value->values, '\0', siz); + siz /= 16; + for (i = 0; i < siz; i++) + memcpy(value->valuesF + (i << 2), valptr + ((columncount << 2) * i), columncount << 2); } // if else if (valclass == MOJOSHADER_SYMCLASS_OBJECT) { @@ -376,7 +379,7 @@ static void readvalue(const uint8 *base, mem->info.member_count = 0; mem->info.members = NULL; - uint32 memsize = mem->info.columns * mem->info.rows; + uint32 memsize = 4 * mem->info.rows; if (mem->info.elements > 0) memsize *= mem->info.elements; structsize += memsize; @@ -390,7 +393,24 @@ static void readvalue(const uint8 *base, siz = value->value_count * 4; value->values = m(siz, d); - memcpy(value->values, typeptr, siz); /* Yes, typeptr. -flibit */ + memset(value->values, '\0', siz); + int dst_offset = 0, src_offset = 0; + i = 0; + do + { + for (j = 0; j < value->type.member_count; j++) + { + siz = value->type.members[j].info.rows * value->type.members[j].info.elements; + for (k = 0; k < siz; k++) + { + memcpy(value->valuesF + dst_offset, + typeptr + src_offset, /* Yes, typeptr. -flibit */ + value->type.members[j].info.columns << 2); + dst_offset += 4; + src_offset += value->type.members[j].info.columns << 2; + } // for + } + } while (++i < numelements); } // else if } // readvalue @@ -1639,8 +1659,8 @@ void MOJOSHADER_effectSetRawValueHandle(const MOJOSHADER_effectParam *parameter, const unsigned int offset, const unsigned int len) { - // !!! FIXME: uint32* case is arbitary, for Win32 -flibit - memcpy((uint32 *) parameter->value.values + offset, data, len); + // !!! FIXME: char* case is arbitary, for Win32 -flibit + memcpy((char *) parameter->value.values + offset, data, len); } // MOJOSHADER_effectSetRawValueHandle @@ -1655,8 +1675,8 @@ void MOJOSHADER_effectSetRawValueName(const MOJOSHADER_effect *effect, { if (strcmp(name, effect->params[i].value.name) == 0) { - // !!! FIXME: uint32* case is arbitary, for Win32 -flibit - memcpy((uint32 *) effect->params[i].value.values + offset, data, len); + // !!! FIXME: char* case is arbitary, for Win32 -flibit + memcpy((char *) effect->params[i].value.values + offset, data, len); return; } // if } // for diff --git a/mojoshader_opengl.c b/mojoshader_opengl.c index e8800f93..08b9773f 100644 --- a/mojoshader_opengl.c +++ b/mojoshader_opengl.c @@ -726,7 +726,7 @@ static void impl_ARB1_DeleteShader(const GLuint _shader) static void impl_ARB1_DeleteProgram(const GLuint program) { // no-op. ARB1 doesn't have real linked programs. -} // impl_GLSL_DeleteProgram +} // impl_ARB1_DeleteProgram static GLint impl_ARB1_GetUniformLocation(MOJOSHADER_glProgram *program, MOJOSHADER_glShader *shader, int idx) @@ -1074,8 +1074,10 @@ static void detect_glsl_version(void) const char *str = (const char *) ctx->glGetString(enumval); if (ctx->glGetError() == GL_INVALID_ENUM) str = NULL; - if (strstr(str, "OpenGL ES GLSL ES ")) - str += 18; + if (strstr(str, "OpenGL ES GLSL ")) + str += 15; + if (strstr(str, "ES ")) + str += 3; parse_opengl_version_str(str, &ctx->glsl_major, &ctx->glsl_minor); } // if #endif @@ -1279,7 +1281,7 @@ static int valid_profile(const char *profile) #if SUPPORT_PROFILE_GLSLES else if (strcmp(profile, MOJOSHADER_PROFILE_GLSLES) == 0) { - MUST_HAVE_GLSL(MOJOSHADER_PROFILE_GLSLES, 1, 10); + MUST_HAVE_GLSL(MOJOSHADER_PROFILE_GLSLES, 1, 00); } // else if #endif @@ -2864,116 +2866,44 @@ static inline void copy_parameter_data(MOJOSHADER_effectParam *params, const uint32 start = sym->register_index << 2; if (param->type.parameter_type == MOJOSHADER_SYMTYPE_FLOAT) - { - // Matrices have to be transposed from row-major to column-major! - if (param->type.parameter_class == MOJOSHADER_SYMCLASS_MATRIX_ROWS) - { - if (param->type.elements > 1) - { - const uint32 regcount = sym->register_count / param->type.elements; - j = 0; - do - { - r = 0; - do - { - c = 0; - do - { - const uint32 dest = start + c + - (r << 2) + - ((j << 2) * regcount); - const uint32 src = r + - (c * param->type.rows) + - (j * param->type.rows * param->type.columns); - regf[dest] = param->valuesF[src]; - } while (++c < param->type.columns); - } while (++r < regcount); - } while (++j < param->type.elements); - } // if - else - { - r = 0; - do - { - c = 0; - do - { - regf[start + (r << 2 ) + c] = param->valuesF[r + (c * param->type.rows)]; - } while (++c < param->type.columns); - } while (++r < sym->register_count); - } // else - } // if - else if (sym->register_count > 1) - { - j = 0; - do - { - memcpy(regf + start + (j << 2), - param->valuesF + (j * param->type.columns), - param->type.columns << 2); - } while (++j < sym->register_count); - } // else if - else - memcpy(regf + start, param->valuesF, param->type.columns << 2); - } // if + memcpy(regf + start, param->valuesF, sym->register_count << 4); else if (sym->register_set == MOJOSHADER_SYMREGSET_FLOAT4) { - // Sometimes int/bool parameters get thrown into float registers... + // Structs are a whole different world... if (param->type.parameter_class == MOJOSHADER_SYMCLASS_STRUCT) - { - float *struct_offset = param->valuesF; - r = 0; /* Register offset */ - j = 0; - do - { - c = 0; - do - { - memcpy(regf + start + (r << 2), - struct_offset, - param->type.members[c].info.columns << 2); - struct_offset += param->type.members[c].info.columns; - r++; - } while (++c < param->type.member_count); - } while (++j < param->type.elements); - } // if + memcpy(regf + start, param->valuesF, sym->register_count << 4); else { + // Sometimes int/bool parameters get thrown into float registers... j = 0; do { c = 0; do { - regf[start + (j << 2) + c] = (float) param->valuesI[(j * param->type.columns) + c]; + regf[start + (j << 2) + c] = (float) param->valuesI[(j << 2) + c]; } while (++c < param->type.columns); } while (++j < sym->register_count); } // else } // else if else if (sym->register_set == MOJOSHADER_SYMREGSET_INT4) - { - if (sym->register_count > 1) - { - j = 0; - do - { - memcpy(regi + start + (j << 2), - param->valuesI + (j * param->type.columns), - param->type.columns << 2); - } while (++j < sym->register_count); - } // if - else - memcpy(regi + start, param->valuesI, param->type.columns << 2); - } // else if + memcpy(regi + start, param->valuesI, sym->register_count << 4); else if (sym->register_set == MOJOSHADER_SYMREGSET_BOOL) { j = 0; + r = 0; do { - // regb is not a vec4, enjoy this bitshift! -flibit - regb[(start >> 2) + j] = param->valuesI[j]; - } while (++j < sym->register_count); + c = 0; + do + { + // regb is not a vec4, enjoy that 'start' bitshift! -flibit + regb[(start >> 2) + r + c] = param->valuesI[(j << 2) + c]; + c++; + } while (c < param->type.columns && ((r + c) < sym->register_count)); + r += c; + j++; + } while (r < sym->register_count); } // else if } // for } // copy_parameter_data @@ -2985,7 +2915,7 @@ void MOJOSHADER_glEffectCommitChanges(MOJOSHADER_glEffect *glEffect) MOJOSHADER_effectShader *rawFrag = glEffect->current_frag_raw; /* Used for shader selection from preshaders */ - int i; + int i, j; MOJOSHADER_effectValue *param; float selector; int shader_object; @@ -3003,9 +2933,10 @@ void MOJOSHADER_glEffectCommitChanges(MOJOSHADER_glEffect *glEffect) do \ { \ param = &glEffect->effect->params[raw->preshader_params[i]].value; \ - memcpy(raw->preshader->registers + raw->preshader->symbols[i].register_index, \ - param->values, \ - param->value_count << 2); \ + for (j = 0; j < (param->value_count >> 2); j++) \ + memcpy(raw->preshader->registers + raw->preshader->symbols[i].register_index + j, \ + param->valuesI + (j << 2), \ + param->type.columns << 2); \ } while (++i < raw->preshader->symbol_count); \ MOJOSHADER_runPreshader(raw->preshader, &selector); \ shader_object = glEffect->effect->params[raw->params[0]].value.valuesI[(int) selector]; \ @@ -3051,12 +2982,6 @@ void MOJOSHADER_glEffectCommitChanges(MOJOSHADER_glEffect *glEffect) #define COPY_PARAMETER_DATA(raw, stage) \ if (raw != NULL) \ { \ - if (ctx->bound_program->stage##_float4_loc != -1) \ - memset(ctx->stage##_reg_file_f, '\0', ctx->bound_program->stage##_uniforms_float4_count << 4); \ - if (ctx->bound_program->stage##_int4_loc != -1) \ - memset(ctx->stage##_reg_file_i, '\0', ctx->bound_program->stage##_uniforms_int4_count << 4); \ - if (ctx->bound_program->stage##_bool_loc != -1) \ - memset(ctx->stage##_reg_file_b, '\0', ctx->bound_program->stage##_uniforms_bool_count << 2); \ copy_parameter_data(glEffect->effect->params, raw->params, \ raw->shader->symbols, \ raw->shader->symbol_count, \ diff --git a/utils/testparse.c b/utils/testparse.c index 29853e2d..2de9880e 100644 --- a/utils/testparse.c +++ b/utils/testparse.c @@ -419,7 +419,7 @@ static void print_shader(const char *fname, const MOJOSHADER_parseData *pd, static void print_value(const MOJOSHADER_effectValue *value, const unsigned int indent) { - int i; + int i, r, c; INDENT(); printf("VALUE: %s -> %s\n", value->name, value->semantic); @@ -518,35 +518,44 @@ static void print_value(const MOJOSHADER_effectValue *value, { do_indent(indent + 1); printf("%s VALUES:\n", types[value->type.parameter_type]); - for (i = 0; i < value->value_count; i++) + i = 0; + do { - do_indent(indent + 2); static const char *prints[] = { - "%X\n", - "%d\n", - "%d\n", - "%.2f\n", - "%d\n", - "%d\n", - "%d\n", - "%d\n", - "%d\n", - "%d\n", - "SAMPLER?!\n", - "SAMPLER?!\n", - "SAMPLER?!\n", - "SAMPLER?!\n", - "SAMPLER?!\n", - "%d\n", - "%d\n", - "%X\n" + "%X ", + "%d ", + "%d ", + "%.2f ", + "%d ", + "%d ", + "%d ", + "%d ", + "%d ", + "%d ", + "SAMPLER?! ", + "SAMPLER?! ", + "SAMPLER?! ", + "SAMPLER?! ", + "SAMPLER?! ", + "%d ", + "%d ", + "%X " }; - if (value->type.parameter_type == MOJOSHADER_SYMTYPE_FLOAT) - printf(prints[value->type.parameter_type], value->valuesF[i]); - else - printf(prints[value->type.parameter_type], value->valuesI[i]); - } // for + for (r = 0; r < value->type.rows; r++) + { + do_indent(indent + 2); + for (c = 0; c < value->type.columns; c++) + { + const int offset = (i * value->type.rows * 4) + (r * 4) + c; + if (value->type.parameter_type == MOJOSHADER_SYMTYPE_FLOAT) + printf(prints[value->type.parameter_type], value->valuesF[offset]); + else + printf(prints[value->type.parameter_type], value->valuesI[offset]); + } // for + printf("\n"); + } // for + } while (++i < value->type.elements); } // else } // print_value