From: Józef Kucia Subject: [PATCH 01/11] wined3d: Implement return instruction. Message-Id: <1481110985-1006-1-git-send-email-jkucia@codeweavers.com> Date: Wed, 7 Dec 2016 12:42:55 +0100 Based on a patch by Andrew Wesie. Signed-off-by: Józef Kucia --- dlls/d3d10core/tests/device.c | 6 +- dlls/d3d11/tests/d3d11.c | 6 +- dlls/wined3d/glsl_shader.c | 150 ++++++++++++++++++++++++++++-------------- 3 files changed, 106 insertions(+), 56 deletions(-) diff --git a/dlls/d3d10core/tests/device.c b/dlls/d3d10core/tests/device.c index aad9184..f278f42 100644 --- a/dlls/d3d10core/tests/device.c +++ b/dlls/d3d10core/tests/device.c @@ -7643,7 +7643,7 @@ static void test_swapchain_flip(void) ID3D10Device_Draw(device, 4, 0); color = get_texture_color(offscreen, 120, 240); - todo_wine ok(compare_color(color, 0x7f0000ff, 1), "Got unexpected color 0x%08x.\n", color); + ok(compare_color(color, 0x7f0000ff, 1), "Got unexpected color 0x%08x.\n", color); /* DXGI moves buffers in the same direction as earlier versions. Buffer 2 becomes buffer 1, * buffer 1 becomes the new buffer 0, and buffer 0 becomes buffer n - 1. However, only buffer @@ -7660,7 +7660,7 @@ static void test_swapchain_flip(void) ID3D10Device_Draw(device, 4, 0); color = get_texture_color(offscreen, 120, 240); /* green, buf 0 */ - todo_wine ok(compare_color(color, 0x7f00ff00, 1), "Got unexpected color 0x%08x.\n", color); + ok(compare_color(color, 0x7f00ff00, 1), "Got unexpected color 0x%08x.\n", color); /* Buffer 1 is still untouched. */ color = get_texture_color(backbuffer_0, 320, 240); /* green */ @@ -7674,7 +7674,7 @@ static void test_swapchain_flip(void) ID3D10Device_Draw(device, 4, 0); color = get_texture_color(offscreen, 120, 240); /* blue, buf 0 */ - todo_wine ok(compare_color(color, 0x7fff0000, 1), "Got unexpected color 0x%08x.\n", color); + ok(compare_color(color, 0x7fff0000, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(offscreen, 360, 240); /* red, buf 1 */ ok(compare_color(color, 0x7f0000ff, 1), "Got unexpected color 0x%08x.\n", color); diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index bad38d3..d8fc21e 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -7962,7 +7962,7 @@ static void test_swapchain_flip(void) ID3D11DeviceContext_Draw(context, 4, 0); color = get_texture_color(offscreen, 120, 240); - todo_wine ok(compare_color(color, 0x7f0000ff, 1), "Got unexpected color 0x%08x.\n", color); + ok(compare_color(color, 0x7f0000ff, 1), "Got unexpected color 0x%08x.\n", color); /* DXGI moves buffers in the same direction as earlier versions. Buffer 2 * becomes buffer 1, buffer 1 becomes the new buffer 0, and buffer 0 @@ -7980,7 +7980,7 @@ static void test_swapchain_flip(void) ID3D11DeviceContext_Draw(context, 4, 0); color = get_texture_color(offscreen, 120, 240); /* green, buf 0 */ - todo_wine ok(compare_color(color, 0x7f00ff00, 1), "Got unexpected color 0x%08x.\n", color); + ok(compare_color(color, 0x7f00ff00, 1), "Got unexpected color 0x%08x.\n", color); /* Buffer 1 is still untouched. */ color = get_texture_color(backbuffer_0, 320, 240); /* green */ @@ -7994,7 +7994,7 @@ static void test_swapchain_flip(void) ID3D11DeviceContext_Draw(context, 4, 0); color = get_texture_color(offscreen, 120, 240); /* blue, buf 0 */ - todo_wine ok(compare_color(color, 0x7fff0000, 1), "Got unexpected color 0x%08x.\n", color); + ok(compare_color(color, 0x7fff0000, 1), "Got unexpected color 0x%08x.\n", color); color = get_texture_color(offscreen, 360, 240); /* red, buf 1 */ ok(compare_color(color, 0x7f0000ff, 1), "Got unexpected color 0x%08x.\n", color); diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 434444a..b3e7607 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -290,6 +290,8 @@ struct glsl_ffp_destroy_ctx const struct wined3d_gl_info *gl_info; }; +static void shader_glsl_generate_shader_epilogue(const struct wined3d_shader_context *ctx); + static const char *debug_gl_shader_type(GLenum type) { switch (type) @@ -4553,9 +4555,13 @@ static void shader_glsl_callnz(const struct wined3d_shader_instruction *ins) static void shader_glsl_ret(const struct wined3d_shader_instruction *ins) { - /* No-op. The closing } is written when a new function is started, and at the end of the shader. This - * function only suppresses the unhandled instruction warning - */ + const struct wined3d_shader_version *version = &ins->ctx->shader->reg_maps.shader_version; + + if (version->major >= 4) + { + shader_glsl_generate_shader_epilogue(ins->ctx); + shader_addline(ins->ctx->buffer, "return;\n"); + } } /********************************************* @@ -6065,6 +6071,26 @@ static void shader_glsl_enable_extensions(struct wined3d_string_buffer *buffer, shader_addline(buffer, "#extension GL_EXT_texture_array : enable\n"); } +static void shader_glsl_generate_ps_epilogue(const struct wined3d_gl_info *gl_info, + struct wined3d_string_buffer *buffer, const struct wined3d_shader *shader, + const struct ps_compile_args *args) +{ + const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; + + /* Pixel shaders < 2.0 place the resulting color in R0 implicitly. */ + if (reg_maps->shader_version.major < 2) + shader_addline(buffer, "%s[0] = R0;\n", get_fragment_output(gl_info)); + + if (args->srgb_correction) + shader_glsl_generate_srgb_write_correction(buffer, gl_info); + + /* SM < 3 does not replace the fog stage. */ + if (reg_maps->shader_version.major < 3) + shader_glsl_generate_fog_code(buffer, gl_info, args->fog); + + shader_glsl_generate_alpha_test(buffer, gl_info, args->alpha_test_func + 1); +} + /* Context activation is done by the caller. */ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context, struct wined3d_string_buffer *buffer, struct wined3d_string_buffer_list *string_buffers, @@ -6171,18 +6197,9 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context /* Base Shader Body */ shader_generate_main(shader, buffer, reg_maps, function, &priv_ctx); - /* Pixel shaders < 2.0 place the resulting color in R0 implicitly */ - if (reg_maps->shader_version.major < 2) - shader_addline(buffer, "%s[0] = R0;\n", get_fragment_output(gl_info)); - - if (args->srgb_correction) - shader_glsl_generate_srgb_write_correction(buffer, gl_info); - - /* SM < 3 does not replace the fog stage. */ - if (reg_maps->shader_version.major < 3) - shader_glsl_generate_fog_code(buffer, gl_info, args->fog); - - shader_glsl_generate_alpha_test(buffer, gl_info, args->alpha_test_func + 1); + /* In SM4+ the shader epilogue is generated by the "ret" instruction. */ + if (reg_maps->shader_version.major < 4) + shader_glsl_generate_ps_epilogue(gl_info, buffer, shader, args); shader_addline(buffer, "}\n"); @@ -6192,6 +6209,49 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context return shader_id; } +static void shader_glsl_generate_vs_epilogue(const struct wined3d_gl_info *gl_info, + struct wined3d_string_buffer *buffer, const struct wined3d_shader *shader, + const struct vs_compile_args *args) +{ + const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; + BOOL legacy_context = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]; + unsigned int i; + + /* Unpack outputs. */ + shader_addline(buffer, "setup_vs_output(vs_out);\n"); + + /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used + * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE), + * the fog frag coord is thrown away. If the fog frag coord is used, but not written by + * the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0). + */ + if (reg_maps->shader_version.major < 3) + { + if (args->fog_src == VS_FOG_Z) + shader_addline(buffer, "%s = gl_Position.z;\n", + legacy_context ? "gl_FogFragCoord" : "ffp_varying_fogcoord"); + else if (!reg_maps->fog) + shader_addline(buffer, "%s = 0.0;\n", + legacy_context ? "gl_FogFragCoord" : "ffp_varying_fogcoord"); + } + + /* We always store the clipplanes without y inversion. */ + if (args->clip_enabled) + { + if (legacy_context) + shader_addline(buffer, "gl_ClipVertex = gl_Position;\n"); + else + for (i = 0; i < gl_info->limits.user_clip_distances; ++i) + shader_addline(buffer, "gl_ClipDistance[%u] = dot(gl_Position, clip_planes[%u]);\n", i, i); + } + + if (args->point_size && !args->per_vertex_point_size) + shader_addline(buffer, "gl_PointSize = clamp(ffp_point.size, ffp_point.size_min, ffp_point.size_max);\n"); + + if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL]) + shader_glsl_fixup_position(buffer); +} + /* Context activation is done by the caller. */ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context, struct shader_glsl_priv *priv, const struct wined3d_shader *shader, const struct vs_compile_args *args) @@ -6200,10 +6260,8 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; struct wined3d_string_buffer *buffer = &priv->shader_buffer; const struct wined3d_gl_info *gl_info = context->gl_info; - BOOL legacy_context = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]; const DWORD *function = shader->function; struct shader_glsl_ctx_priv priv_ctx; - unsigned int i; /* Create the hw GLSL shader program and assign it as the shader->prgId */ GLuint shader_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER)); @@ -6239,39 +6297,9 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context /* Base Shader Body */ shader_generate_main(shader, buffer, reg_maps, function, &priv_ctx); - /* Unpack outputs */ - shader_addline(buffer, "setup_vs_output(vs_out);\n"); - - /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used - * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE), - * the fog frag coord is thrown away. If the fog frag coord is used, but not written by - * the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0) - */ - if (reg_maps->shader_version.major < 3) - { - if (args->fog_src == VS_FOG_Z) - shader_addline(buffer, "%s = gl_Position.z;\n", - legacy_context ? "gl_FogFragCoord" : "ffp_varying_fogcoord"); - else if (!reg_maps->fog) - shader_addline(buffer, "%s = 0.0;\n", - legacy_context ? "gl_FogFragCoord" : "ffp_varying_fogcoord"); - } - - /* We always store the clipplanes without y inversion */ - if (args->clip_enabled) - { - if (legacy_context) - shader_addline(buffer, "gl_ClipVertex = gl_Position;\n"); - else - for (i = 0; i < gl_info->limits.user_clip_distances; ++i) - shader_addline(buffer, "gl_ClipDistance[%u] = dot(gl_Position, clip_planes[%u]);\n", i, i); - } - - if (args->point_size && !args->per_vertex_point_size) - shader_addline(buffer, "gl_PointSize = clamp(ffp_point.size, ffp_point.size_min, ffp_point.size_max);\n"); - - if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL]) - shader_glsl_fixup_position(buffer); + /* In SM4+ the shader epilogue is generated by the "ret" instruction. */ + if (reg_maps->shader_version.major < 4) + shader_glsl_generate_vs_epilogue(gl_info, buffer, shader, args); shader_addline(buffer, "}\n"); @@ -6317,6 +6345,28 @@ static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context return shader_id; } +static void shader_glsl_generate_shader_epilogue(const struct wined3d_shader_context *ctx) +{ + const struct shader_glsl_ctx_priv *priv = ctx->backend_data; + const struct wined3d_gl_info *gl_info = ctx->gl_info; + const struct wined3d_shader *shader = ctx->shader; + + switch (shader->reg_maps.shader_version.type) + { + case WINED3D_SHADER_TYPE_PIXEL: + shader_glsl_generate_ps_epilogue(gl_info, ctx->buffer, shader, priv->cur_ps_args); + break; + case WINED3D_SHADER_TYPE_VERTEX: + shader_glsl_generate_vs_epilogue(gl_info, ctx->buffer, shader, priv->cur_vs_args); + break; + case WINED3D_SHADER_TYPE_GEOMETRY: + break; + default: + FIXME("Unhandled shader type %#x.\n", shader->reg_maps.shader_version.type); + break; + } +} + static GLuint find_glsl_pshader(const struct wined3d_context *context, struct wined3d_string_buffer *buffer, struct wined3d_string_buffer_list *string_buffers, struct wined3d_shader *shader, -- 2.7.3