Skip to content

Instantly share code, notes, and snippets.

@esiqveland
Created September 5, 2015 13:03
Show Gist options
  • Save esiqveland/086167c9803f64b6e128 to your computer and use it in GitHub Desktop.
Save esiqveland/086167c9803f64b6e128 to your computer and use it in GitHub Desktop.
From ee32bf843b1c50bfcb5563a8c87b1d7f440e6c45 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Fri, 27 Feb 2015 12:25:39 +0100
Subject: [PATCH 7/7] wined3d: Reorder shader constants.
Reply-To: wine-devel <wine-devel@winehq.org>
This attempts to fix bug 34052 without requiring a range check for every
indirect constant read. GL_ARB_robust_buffer_access_behavior would be an
OpenGL extension to reliably give us what we need, but I haven't tested
its performance impact yet.
---
dlls/wined3d/arb_program_shader.c | 7 +++----
dlls/wined3d/glsl_shader.c | 36 ++++++++++++++++++++++++++----------
2 files changed, 29 insertions(+), 14 deletions(-)
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 688bdb7..130293f 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -4209,10 +4209,6 @@ static GLuint shader_arb_generate_vshader(const struct wined3d_shader *shader,
shader_addline(buffer, "TEMP TA;\n");
shader_addline(buffer, "TEMP TB;\n");
- /* Base Declarations */
- shader_generate_arb_declarations(shader, reg_maps, buffer, gl_info,
- &priv_ctx.vs_clipplanes, &priv_ctx);
-
for(i = 0; i < MAX_CONST_I; i++)
{
compiled->int_consts[i] = WINED3D_CONST_NUM_UNUSED;
@@ -4238,6 +4234,9 @@ static GLuint shader_arb_generate_vshader(const struct wined3d_shader *shader,
shader_addline(buffer, "PARAM posFixup = program.local[%u];\n", next_local);
compiled->pos_fixup = next_local++;
+ shader_generate_arb_declarations(shader, reg_maps, buffer, gl_info,
+ &priv_ctx.vs_clipplanes, &priv_ctx);
+
/* Initialize output parameters. GL_ARB_vertex_program does not require special initialization values
* for output parameters. D3D in theory does not do that either, but some applications depend on a
* proper initialization of the secondary color, and programs using the fixed function pipeline without
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 0804997..b51a9a2 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -967,7 +967,32 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
if (map & 1) shader_addline(buffer, "void subroutine%u();\n", i);
}
- /* Declare the constants (aka uniforms) */
+ /* Always declare the full set of constants, the compiler can remove the
+ * unused ones because d3d doesn't (yet) support indirect int and bool
+ * constant addressing. This avoids problems if the app uses e.g. i0 and i9. */
+ if (shader->limits->constant_int > 0 && reg_maps->integer_constants)
+ shader_addline(buffer, "uniform ivec4 %s_i[%u];\n", prefix, shader->limits->constant_int);
+
+ if (shader->limits->constant_bool > 0 && reg_maps->boolean_constants)
+ shader_addline(buffer, "uniform bool %s_b[%u];\n", prefix, shader->limits->constant_bool);
+
+ /* The game The Witcher reads beyond the 256 constants supported in
+ * d3d9 and expects vec4(0.0) to be returned.
+ *
+ * Declare the float constants last to get an on-GPU memory layout
+ * similar to what Windows drivers create. Reading outside the valid
+ * constant range is supposed to return vec4(0.0) on Windows. On dx10
+ * cards the drivers load int and bool constants into the same memory,
+ * but they happen to be placed in front of the float array. E.g.
+ * on Nvidia GPUs the int consts are at c[-40] to c[-25]. Reading
+ * indices > 255 reliably returns 0.0 on Windows, except dx9 Radeon
+ * cards, which return c[255].
+ *
+ * If the read location is outside the memory area defined by the
+ * driver, the hardware will return 0.0 in GL, presumably because
+ * it is built to conform to the d3d requirement. Problems happen
+ * if the read location is valid from the GPU's point of view but
+ * outside the declared float uniform array. */
if (shader->limits->constant_float > 0)
{
unsigned max_constantsF;
@@ -1042,15 +1067,6 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
shader_addline(buffer, "uniform vec4 %s_c[%u];\n", prefix, max_constantsF);
}
- /* Always declare the full set of constants, the compiler can remove the
- * unused ones because d3d doesn't (yet) support indirect int and bool
- * constant addressing. This avoids problems if the app uses e.g. i0 and i9. */
- if (shader->limits->constant_int > 0 && reg_maps->integer_constants)
- shader_addline(buffer, "uniform ivec4 %s_i[%u];\n", prefix, shader->limits->constant_int);
-
- if (shader->limits->constant_bool > 0 && reg_maps->boolean_constants)
- shader_addline(buffer, "uniform bool %s_b[%u];\n", prefix, shader->limits->constant_bool);
-
for (i = 0; i < WINED3D_MAX_CBS; ++i)
{
if (reg_maps->cb_sizes[i])
--
2.3.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment