diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 7d98487d4be..a840a5d810f 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -1253,15 +1253,14 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont shader_addline(buffer, "vec4 tmp0;\n"); shader_addline(buffer, "vec4 tmp1;\n"); - /* Local constants use a different name so they can be loaded once at shader link time - * They can't be hardcoded into the shader text via LC = {x, y, z, w}; because the - * float -> string conversion can cause precision loss. - */ if (!shader->load_local_constsF) { LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry) { - shader_addline(buffer, "uniform vec4 %s_lc%u;\n", prefix, lconst->idx); + const float *value; + value = (const float *)lconst->value; + shader_addline(buffer, "const vec4 %s_lc%u = vec4(%.8e, %.8e, %.8e, %.8e);\n", + prefix, lconst->idx, value[0], value[1], value[2], value[3]); } } @@ -4456,25 +4455,6 @@ static void shader_glsl_generate_fog_code(struct wined3d_shader_buffer *buffer, shader_addline(buffer, "gl_FragData[0].xyz = mix(gl_Fog.color.xyz, gl_FragData[0].xyz, clamp(Fog, 0.0, 1.0));\n"); } -/* Context activation is done by the caller. */ -static void hardcode_local_constants(const struct wined3d_shader *shader, - const struct wined3d_gl_info *gl_info, GLhandleARB programId, const char *prefix) -{ - const struct wined3d_shader_lconst *lconst; - GLint tmp_loc; - const float *value; - char glsl_name[10]; - - LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry) - { - value = (const float *)lconst->value; - snprintf(glsl_name, sizeof(glsl_name), "%s_lc%u", prefix, lconst->idx); - tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name)); - GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, value)); - } - checkGLcall("Hardcoding local constants"); -} - /* Context activation is done by the caller. */ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context, struct wined3d_shader_buffer *buffer, const struct wined3d_shader *shader, @@ -5705,15 +5685,6 @@ static void set_glsl_shader_program(const struct wined3d_context *context, struc */ shader_glsl_load_vsamplers(gl_info, device->texUnitMap, programId); shader_glsl_load_psamplers(gl_info, device->texUnitMap, programId); - - /* If the local constants do not have to be loaded with the environment constants, - * load them now to have them hardcoded in the GLSL program. This saves some CPU cycles - * later - */ - if (pshader && !pshader->load_local_constsF) - hardcode_local_constants(pshader, gl_info, programId, "ps"); - if (vshader && !vshader->load_local_constsF) - hardcode_local_constants(vshader, gl_info, programId, "vs"); } /* Context activation is done by the caller. */ diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c index 6444896594c..692e5b2f24a 100644 --- a/dlls/wined3d/shader.c +++ b/dlls/wined3d/shader.c @@ -584,15 +584,16 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st else if (ins.handler_idx == WINED3DSIH_DEF) { struct wined3d_shader_lconst *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(*lconst)); + float *value; if (!lconst) return E_OUTOFMEMORY; lconst->idx = ins.dst[0].reg.idx[0].offset; memcpy(lconst->value, ins.src[0].reg.immconst_data, 4 * sizeof(DWORD)); + value = (float *)lconst->value; /* In pixel shader 1.X shaders, the constants are clamped between [-1;1] */ if (shader_version.major == 1 && shader_version.type == WINED3D_SHADER_TYPE_PIXEL) { - float *value = (float *)lconst->value; if (value[0] < -1.0f) value[0] = -1.0f; else if (value[0] > 1.0f) value[0] = 1.0f; if (value[1] < -1.0f) value[1] = -1.0f; @@ -604,6 +605,12 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st } list_add_head(&shader->constantsF, &lconst->entry); + + if (isinf(value[0]) || isnan(value[0]) || isinf(value[1]) || isnan(value[1]) + || isinf(value[2]) || isnan(value[2]) || isinf(value[3]) || isnan(value[3])) + { + shader->lconst_inf_or_nan = TRUE; + } } else if (ins.handler_idx == WINED3DSIH_DEFI) { @@ -1629,6 +1636,7 @@ static HRESULT shader_set_function(struct wined3d_shader *shader, const DWORD *b list_init(&shader->constantsF); list_init(&shader->constantsB); list_init(&shader->constantsI); + shader->lconst_inf_or_nan = FALSE; /* Second pass: figure out which registers are used, what the semantics are, etc. */ hr = shader_get_registers_used(shader, fe, @@ -1752,12 +1760,20 @@ HRESULT CDECL wined3d_shader_set_local_constants_float(struct wined3d_shader *sh for (i = start_idx; i < end_idx; ++i) { struct wined3d_shader_lconst *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(*lconst)); + float *value; if (!lconst) return E_OUTOFMEMORY; lconst->idx = i; - memcpy(lconst->value, src_data + (i - start_idx) * 4 /* 4 components */, 4 * sizeof(float)); + value = (float *)lconst->value; + memcpy(value, src_data + (i - start_idx) * 4 /* 4 components */, 4 * sizeof(float)); list_add_head(&shader->constantsF, &lconst->entry); + + if (isinf(value[0]) || isnan(value[0]) || isinf(value[1]) || isnan(value[1]) + || isinf(value[2]) || isnan(value[2]) || isinf(value[3]) || isnan(value[3])) + { + shader->lconst_inf_or_nan = TRUE; + } } return WINED3D_OK; @@ -1916,8 +1932,8 @@ static HRESULT vertexshader_init(struct wined3d_shader *shader, struct wined3d_d vertexshader_set_limits(shader); - shader->load_local_constsF = reg_maps->usesrelconstF - && !list_empty(&shader->constantsF); + shader->load_local_constsF = (reg_maps->usesrelconstF && !list_empty(&shader->constantsF)) || + shader->lconst_inf_or_nan; return WINED3D_OK; } @@ -1964,7 +1980,7 @@ static HRESULT geometryshader_init(struct wined3d_shader *shader, struct wined3d geometryshader_set_limits(shader); - shader->load_local_constsF = FALSE; + shader->load_local_constsF = shader->lconst_inf_or_nan; return WINED3D_OK; } @@ -2253,7 +2269,7 @@ static HRESULT pixelshader_init(struct wined3d_shader *shader, struct wined3d_de } } - shader->load_local_constsF = FALSE; + shader->load_local_constsF = shader->lconst_inf_or_nan; return WINED3D_OK; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 2a112863403..bdba525e06d 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2618,6 +2618,7 @@ struct wined3d_shader struct list constantsF; struct list constantsI; struct wined3d_shader_reg_maps reg_maps; + BOOL lconst_inf_or_nan; struct wined3d_shader_signature_element input_signature[max(MAX_ATTRIBS, MAX_REG_INPUT)]; struct wined3d_shader_signature_element output_signature[MAX_REG_OUTPUT];