Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2: Reuse shader_glsl_sprintf_cast() in shader_glsl_generate_color_output(), avoid semantic string comparison.
Let me know if you prefer the old version after all (and the old patch doesn't apply anymore).
dlls/wined3d/glsl_shader.c | 128 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 111 insertions(+), 17 deletions(-)
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index cd4780a6419..d5dc8be136a 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -3318,12 +3318,12 @@ static void shader_glsl_get_swizzle(const struct wined3d_shader_src_param *param shader_glsl_swizzle_to_str(param->swizzle, fixup, mask, swizzle_str); }
-static void shader_glsl_sprintf_cast(struct wined3d_string_buffer *dst_param, const char *src_param, +static void shader_glsl_sprintf_cast(struct wined3d_string_buffer *buffer, const char *arg, enum wined3d_component_type dst_type, enum wined3d_component_type src_type) { if (dst_type == src_type) { - string_buffer_sprintf(dst_param, "%s", src_param); + string_buffer_sprintf(buffer, "%s", arg); return; }
@@ -3332,10 +3332,10 @@ static void shader_glsl_sprintf_cast(struct wined3d_string_buffer *dst_param, co switch (dst_type) { case WINED3D_TYPE_INT: - string_buffer_sprintf(dst_param, "floatBitsToInt(%s)", src_param); + string_buffer_sprintf(buffer, "floatBitsToInt(%s)", arg); return; case WINED3D_TYPE_UINT: - string_buffer_sprintf(dst_param, "floatBitsToUint(%s)", src_param); + string_buffer_sprintf(buffer, "floatBitsToUint(%s)", arg); return; default: break; @@ -3344,18 +3344,18 @@ static void shader_glsl_sprintf_cast(struct wined3d_string_buffer *dst_param, co
if (src_type == WINED3D_TYPE_UINT && dst_type == WINED3D_TYPE_FLOAT) { - string_buffer_sprintf(dst_param, "uintBitsToFloat(%s)", src_param); + string_buffer_sprintf(buffer, "uintBitsToFloat(%s)", arg); return; }
if (src_type == WINED3D_TYPE_INT && dst_type == WINED3D_TYPE_FLOAT) { - string_buffer_sprintf(dst_param, "intBitsToFloat(%s)", src_param); + string_buffer_sprintf(buffer, "intBitsToFloat(%s)", arg); return; }
FIXME("Unhandled cast from %#x to %#x.\n", src_type, dst_type); - string_buffer_sprintf(dst_param, "%s", src_param); + string_buffer_sprintf(buffer, "%s", arg); }
/* From a given parameter token, generate the corresponding GLSL string. @@ -7616,9 +7616,48 @@ 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_color_output(struct wined3d_string_buffer *buffer, + const struct wined3d_gl_info *gl_info, const struct wined3d_shader *shader, + struct wined3d_string_buffer_list *string_buffers) +{ + const struct wined3d_shader_signature *output_signature = &shader->output_signature; + struct wined3d_string_buffer *src, *assignment; + unsigned int i; + + if (output_signature->element_count) + { + src = string_buffer_get(string_buffers); + assignment = string_buffer_get(string_buffers); + for (i = 0; i < output_signature->element_count; ++i) + { + const struct wined3d_shader_signature_element *output = &output_signature->elements[i]; + + /* register_idx is set to ~0u for non-color outputs. */ + if (output->register_idx == ~0u) + continue; + shader_addline(buffer, "color_out%u = ", output->semantic_idx); + string_buffer_sprintf(src, "ps_out[%u]", output->semantic_idx); + shader_glsl_sprintf_cast(assignment, src->buffer, output->component_type, WINED3D_TYPE_FLOAT); + shader_addline(buffer, "%s;\n", assignment->buffer); + } + string_buffer_release(string_buffers, src); + string_buffer_release(string_buffers, assignment); + } + else + { + DWORD mask = shader->reg_maps.rt_mask; + + while (mask) + { + i = wined3d_bit_scan(&mask); + shader_addline(buffer, "color_out%u = ps_out[%u];\n", i, i); + } + } +} + 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 ps_compile_args *args, struct wined3d_string_buffer_list *string_buffers) { const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
@@ -7637,6 +7676,26 @@ static void shader_glsl_generate_ps_epilogue(const struct wined3d_gl_info *gl_in
if (reg_maps->sample_mask) shader_addline(buffer, "gl_SampleMask[0] = floatBitsToInt(sample_mask);\n"); + + if (!needs_legacy_glsl_syntax(gl_info)) + shader_glsl_generate_color_output(buffer, gl_info, shader, string_buffers); +} + +static const char *shader_glsl_get_ps_output_format(enum wined3d_component_type component_type) +{ + static const char formats[][6] = + { + "", /* WINED3D_TYPE_UNKNOWN */ + "uvec4", /* WINED3D_TYPE_UINT */ + "ivec4", /* WINED3D_TYPE_INT */ + "vec4", /* WINED3D_TYPE_FLOAT */ + }; + if (component_type < WINED3D_TYPE_UNKNOWN || component_type > WINED3D_TYPE_FLOAT) + { + WARN("Unexpected component_type %#x.\n", component_type); + return formats[WINED3D_TYPE_FLOAT]; + } + return formats[component_type]; }
/* Context activation is done by the caller. */ @@ -7819,9 +7878,35 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context
if (!needs_legacy_glsl_syntax(gl_info)) { - if (shader_glsl_use_explicit_attrib_location(gl_info)) - shader_addline(buffer, "layout(location = 0) "); - shader_addline(buffer, "out vec4 ps_out[%u];\n", gl_info->limits.buffers); + const struct wined3d_shader_signature *output_signature = &shader->output_signature; + + shader_addline(buffer, "vec4 ps_out[%u];\n", gl_info->limits.buffers); + if (output_signature->element_count) + { + for (i = 0; i < output_signature->element_count; ++i) + { + const struct wined3d_shader_signature_element *output = &output_signature->elements[i]; + + if (output->register_idx == ~0u) + continue; + if (shader_glsl_use_explicit_attrib_location(gl_info)) + shader_addline(buffer, "layout(location = %u) ", output->semantic_idx); + shader_addline(buffer, "out %s color_out%u;\n", + shader_glsl_get_ps_output_format(output->component_type), output->semantic_idx); + } + } + else + { + DWORD mask = reg_maps->rt_mask; + + while (mask) + { + i = wined3d_bit_scan(&mask); + if (shader_glsl_use_explicit_attrib_location(gl_info)) + shader_addline(buffer, "layout(location = %u) ", i); + shader_addline(buffer, "out vec4 color_out%u;\n", i); + } + } }
if (shader->limits->constant_float + extra_constants_needed >= gl_info->limits.glsl_ps_float_constants) @@ -7906,7 +7991,7 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context
/* 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_glsl_generate_ps_epilogue(gl_info, buffer, shader, args, string_buffers);
shader_addline(buffer, "}\n");
@@ -8403,7 +8488,7 @@ static void shader_glsl_generate_shader_epilogue(const struct wined3d_shader_con switch (shader->reg_maps.shader_version.type) { case WINED3D_SHADER_TYPE_PIXEL: - shader_glsl_generate_ps_epilogue(gl_info, buffer, shader, priv->cur_ps_args); + shader_glsl_generate_ps_epilogue(gl_info, buffer, shader, priv->cur_ps_args, priv->string_buffers); break; case WINED3D_SHADER_TYPE_VERTEX: shader_glsl_generate_vs_epilogue(gl_info, buffer, shader, priv->cur_vs_args); @@ -9539,9 +9624,10 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *
if (!needs_legacy_glsl_syntax(gl_info)) { + shader_addline(buffer, "vec4 ps_out[1];\n"); if (shader_glsl_use_explicit_attrib_location(gl_info)) shader_addline(buffer, "layout(location = 0) "); - shader_addline(buffer, "out vec4 ps_out[1];\n"); + shader_addline(buffer, "out vec4 color_out0;\n"); }
shader_addline(buffer, "vec4 tmp0, tmp1;\n"); @@ -9881,6 +9967,8 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv * shader_glsl_generate_fog_code(buffer, gl_info, settings->fog);
shader_glsl_generate_alpha_test(buffer, gl_info, alpha_test_func); + if (!needs_legacy_glsl_syntax(gl_info)) + shader_addline(buffer, "color_out0 = ps_out[0];\n");
shader_addline(buffer, "}\n");
@@ -10422,13 +10510,17 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const } } checkGLcall("glBindAttribLocation"); - string_buffer_release(&priv->string_buffers, tmp_name);
if (!needs_legacy_glsl_syntax(gl_info)) { - GL_EXTCALL(glBindFragDataLocation(program_id, 0, "ps_out")); - checkGLcall("glBindFragDataLocation"); + for (i = 0; i < MAX_RENDER_TARGET_VIEWS; ++i) + { + string_buffer_sprintf(tmp_name, "color_out%u", i); + GL_EXTCALL(glBindFragDataLocation(program_id, i, tmp_name->buffer)); + checkGLcall("glBindFragDataLocation"); + } } + string_buffer_release(&priv->string_buffers, tmp_name); }
if (hshader) @@ -12796,6 +12888,8 @@ static GLuint glsl_blitter_generate_program(struct wined3d_glsl_blitter *blitter shader_glsl_add_version_declaration(buffer, gl_info); shader_addline(buffer, "uniform sampler%s sampler;\n", tex_type); declare_in_varying(gl_info, buffer, FALSE, "vec3 out_texcoord;\n"); + /* TODO: Declare the out variable with the correct type (and put it in the + * blitter args). */ if (!needs_legacy_glsl_syntax(gl_info)) shader_addline(buffer, "out vec4 ps_out[1];\n");