From b45a0d4f15870868e2c209125cb45f59ae0c7ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zef=20Kucia?= Date: Tue, 16 May 2017 15:00:24 +0200 Subject: [PATCH] wined3d: Generate code for domain shaders. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Józef Kucia Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/context.c | 4 +- dlls/wined3d/glsl_shader.c | 280 +++++++++++++++++++++++++++++++-- dlls/wined3d/shader.c | 39 +++++ dlls/wined3d/wined3d_private.h | 25 +++ 4 files changed, 338 insertions(+), 10 deletions(-) diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 5a899e56d1f..78f8f94ce24 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -2625,7 +2625,8 @@ void context_unmap_bo_address(struct wined3d_context *context, static void context_set_render_offscreen(struct wined3d_context *context, BOOL offscreen) { - if (context->render_offscreen == offscreen) return; + if (context->render_offscreen == offscreen) + return; context_invalidate_state(context, STATE_VIEWPORT); context_invalidate_state(context, STATE_SCISSORRECT); @@ -2634,6 +2635,7 @@ static void context_set_render_offscreen(struct wined3d_context *context, BOOL o context_invalidate_state(context, STATE_FRONTFACE); context_invalidate_state(context, STATE_POINTSPRITECOORDORIGIN); context_invalidate_state(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION)); + context_invalidate_state(context, STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN)); } if (context->gl_info->supported[ARB_FRAGMENT_COORD_CONVENTIONS]) context_invalidate_state(context, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL)); diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 21057646a77..ce960853362 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -177,6 +177,14 @@ struct glsl_vs_program GLint clip_planes_location; }; +struct glsl_ds_program +{ + struct list shader_entry; + GLuint id; + + GLint pos_fixup_location; +}; + struct glsl_gs_program { struct list shader_entry; @@ -220,6 +228,7 @@ struct glsl_shader_prog_link { struct wine_rb_entry program_lookup_entry; struct glsl_vs_program vs; + struct glsl_ds_program ds; struct glsl_gs_program gs; struct glsl_ps_program ps; struct glsl_cs_program cs; @@ -231,6 +240,7 @@ struct glsl_shader_prog_link struct glsl_program_key { GLuint vs_id; + GLuint ds_id; GLuint gs_id; GLuint ps_id; GLuint cs_id; @@ -238,6 +248,7 @@ struct glsl_program_key struct shader_glsl_ctx_priv { const struct vs_compile_args *cur_vs_args; + const struct ds_compile_args *cur_ds_args; const struct ps_compile_args *cur_ps_args; struct ps_np2fixup_info *cur_np2fixup_info; struct wined3d_string_buffer_list *string_buffers; @@ -262,6 +273,12 @@ struct glsl_vs_compiled_shader GLuint id; }; +struct glsl_ds_compiled_shader +{ + struct ds_compile_args args; + GLuint id; +}; + struct glsl_gs_compiled_shader { struct gs_compile_args args; @@ -278,11 +295,12 @@ struct glsl_shader_private union { struct glsl_vs_compiled_shader *vs; + struct glsl_ds_compiled_shader *ds; struct glsl_gs_compiled_shader *gs; struct glsl_ps_compiled_shader *ps; struct glsl_cs_compiled_shader *cs; } gl_shaders; - UINT num_gl_shaders, shader_array_size; + unsigned int num_gl_shaders, shader_array_size; }; struct glsl_ffp_vertex_shader @@ -1731,6 +1749,8 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context shader_get_position_fixup(context, state, position_fixup); if (state->shader[WINED3D_SHADER_TYPE_GEOMETRY]) GL_EXTCALL(glUniform4fv(prog->gs.pos_fixup_location, 1, position_fixup)); + else if (state->shader[WINED3D_SHADER_TYPE_DOMAIN]) + GL_EXTCALL(glUniform4fv(prog->ds.pos_fixup_location, 1, position_fixup)); else GL_EXTCALL(glUniform4fv(prog->vs.pos_fixup_location, 1, position_fixup)); checkGLcall("glUniform4fv"); @@ -6458,6 +6478,7 @@ static void add_glsl_program_entry(struct shader_glsl_priv *priv, struct glsl_sh struct glsl_program_key key; key.vs_id = entry->vs.id; + key.ds_id = entry->ds.id; key.gs_id = entry->gs.id; key.ps_id = entry->ps.id; key.cs_id = entry->cs.id; @@ -6486,6 +6507,8 @@ static void delete_glsl_program_entry(struct shader_glsl_priv *priv, const struc GL_EXTCALL(glDeleteProgram(entry->id)); if (entry->vs.id) list_remove(&entry->vs.shader_entry); + if (entry->ds.id) + list_remove(&entry->ds.shader_entry); if (entry->gs.id) list_remove(&entry->gs.shader_entry); if (entry->ps.id) @@ -7361,6 +7384,105 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context return shader_id; } +static void shader_glsl_generate_ds_epilogue(const struct wined3d_gl_info *gl_info, + struct wined3d_string_buffer *buffer, const struct wined3d_shader *shader, + const struct ds_compile_args *args) +{ + shader_addline(buffer, "setup_ds_output(ds_out);\n"); + + if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL]) + shader_glsl_fixup_position(buffer); +} + +static GLuint shader_glsl_generate_domain_shader(const struct wined3d_context *context, + struct shader_glsl_priv *priv, const struct wined3d_shader *shader, const struct ds_compile_args *args) +{ + struct wined3d_string_buffer_list *string_buffers = &priv->string_buffers; + 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; + struct shader_glsl_ctx_priv priv_ctx; + GLuint shader_id; + + memset(&priv_ctx, 0, sizeof(priv_ctx)); + priv_ctx.cur_ds_args = args; + priv_ctx.string_buffers = string_buffers; + + shader_glsl_add_version_declaration(buffer, gl_info); + + shader_glsl_enable_extensions(buffer, gl_info); + shader_addline(buffer, "#extension GL_ARB_tessellation_shader : enable\n"); + + shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx); + + shader_addline(buffer, "layout("); + switch (shader->u.ds.tessellator_domain) + { + case WINED3D_TESSELLATOR_DOMAIN_LINE: + shader_addline(buffer, "isolines"); + break; + case WINED3D_TESSELLATOR_DOMAIN_QUAD: + shader_addline(buffer, "quads"); + break; + case WINED3D_TESSELLATOR_DOMAIN_TRIANGLE: + shader_addline(buffer, "triangles"); + break; + } + switch (args->tessellator_output_primitive) + { + case WINED3D_TESSELLATOR_OUTPUT_TRIANGLE_CW: + if (args->render_offscreen) + shader_addline(buffer, ", ccw"); + else + shader_addline(buffer, ", cw"); + break; + case WINED3D_TESSELLATOR_OUTPUT_TRIANGLE_CCW: + if (args->render_offscreen) + shader_addline(buffer, ", cw"); + else + shader_addline(buffer, ", ccw"); + break; + case WINED3D_TESSELLATOR_OUTPUT_POINT: + shader_addline(buffer, ", point_mode"); + break; + case WINED3D_TESSELLATOR_OUTPUT_LINE: + break; + } + switch (args->tessellator_partitioning) + { + case WINED3D_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD: + shader_addline(buffer, ", fractional_odd_spacing"); + break; + case WINED3D_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN: + shader_addline(buffer, ", fractional_even_spacing"); + break; + case WINED3D_TESSELLATOR_PARTITIONING_INTEGER: + case WINED3D_TESSELLATOR_PARTITIONING_POW2: + shader_addline(buffer, ", equal_spacing"); + break; + } + shader_addline(buffer, ") in;\n"); + + shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in[];\n", shader->limits->packed_input); + + if (!gl_info->supported[ARB_CLIP_CONTROL]) + shader_addline(buffer, "uniform vec4 pos_fixup;\n"); + + shader_glsl_generate_sm4_output_setup(priv, shader, args->output_count, gl_info, TRUE); + shader_addline(buffer, "void main()\n{\n"); + + if (FAILED(shader_generate_main(shader, buffer, reg_maps, &priv_ctx))) + return 0; + + shader_addline(buffer, "}\n"); + + shader_id = GL_EXTCALL(glCreateShader(GL_TESS_EVALUATION_SHADER)); + TRACE("Compiling shader object %u.\n", shader_id); + shader_glsl_compile(gl_info, shader_id, buffer->buffer); + + return shader_id; +} + /* Context activation is done by the caller. */ static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context *context, struct shader_glsl_priv *priv, const struct wined3d_shader *shader, const struct gs_compile_args *args) @@ -7409,15 +7531,19 @@ static void shader_glsl_generate_shader_epilogue(const struct wined3d_shader_con { const struct shader_glsl_ctx_priv *priv = ctx->backend_data; const struct wined3d_gl_info *gl_info = ctx->gl_info; + struct wined3d_string_buffer *buffer = ctx->buffer; 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); + shader_glsl_generate_ps_epilogue(gl_info, 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); + shader_glsl_generate_vs_epilogue(gl_info, buffer, shader, priv->cur_vs_args); + break; + case WINED3D_SHADER_TYPE_DOMAIN: + shader_glsl_generate_ds_epilogue(gl_info, buffer, shader, priv->cur_ds_args); break; case WINED3D_SHADER_TYPE_GEOMETRY: case WINED3D_SHADER_TYPE_COMPUTE: @@ -7629,6 +7755,62 @@ static GLuint find_glsl_vshader(const struct wined3d_context *context, struct sh return ret; } +static GLuint find_glsl_domain_shader(const struct wined3d_context *context, + struct shader_glsl_priv *priv, struct wined3d_shader *shader, const struct ds_compile_args *args) +{ + struct glsl_ds_compiled_shader *gl_shaders, *new_array; + struct glsl_shader_private *shader_data; + unsigned int i, new_size; + GLuint ret; + + if (!shader->backend_data) + { + if (!(shader->backend_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data)))) + { + ERR("Failed to allocate backend data.\n"); + return 0; + } + } + shader_data = shader->backend_data; + gl_shaders = shader_data->gl_shaders.ds; + + for (i = 0; i < shader_data->num_gl_shaders; ++i) + { + if (!memcmp(&gl_shaders[i].args, args, sizeof(*args))) + return gl_shaders[i].id; + } + + TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader); + + if (shader_data->num_gl_shaders) + { + new_size = shader_data->shader_array_size + 1; + new_array = HeapReAlloc(GetProcessHeap(), 0, shader_data->gl_shaders.ds, + new_size * sizeof(*new_array)); + } + else + { + new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_array)); + new_size = 1; + } + + if (!new_array) + { + ERR("Failed to allocate GL shaders array.\n"); + return 0; + } + shader_data->gl_shaders.ds = new_array; + shader_data->shader_array_size = new_size; + gl_shaders = new_array; + + string_buffer_clear(&priv->shader_buffer); + ret = shader_glsl_generate_domain_shader(context, priv, shader, args); + gl_shaders[shader_data->num_gl_shaders].args = *args; + gl_shaders[shader_data->num_gl_shaders++].id = ret; + + return ret; +} + static GLuint find_glsl_geometry_shader(const struct wined3d_context *context, struct shader_glsl_priv *priv, struct wined3d_shader *shader, const struct gs_compile_args *args) { @@ -8926,6 +9108,12 @@ static void shader_glsl_init_vs_uniform_locations(const struct wined3d_gl_info * string_buffer_release(&priv->string_buffers, name); } +static void shader_glsl_init_ds_uniform_locations(const struct wined3d_gl_info *gl_info, + struct shader_glsl_priv *priv, GLuint program_id, struct glsl_ds_program *ds) +{ + ds->pos_fixup_location = GL_EXTCALL(glGetUniformLocation(program_id, "pos_fixup")); +} + static void shader_glsl_init_gs_uniform_locations(const struct wined3d_gl_info *gl_info, struct shader_glsl_priv *priv, GLuint program_id, struct glsl_gs_program *gs) { @@ -9034,6 +9222,7 @@ static HRESULT shader_glsl_compile_compute_shader(struct shader_glsl_priv *priv, entry->id = program_id; entry->vs.id = 0; + entry->ds.id = 0; entry->gs.id = 0; entry->ps.id = 0; entry->cs.id = shader_id; @@ -9116,14 +9305,15 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const const struct wined3d_d3d_info *d3d_info = context->d3d_info; const struct ps_np2fixup_info *np2fixup_info = NULL; struct glsl_shader_prog_link *entry = NULL; + struct wined3d_shader *dshader, *gshader; struct wined3d_shader *vshader = NULL; - struct wined3d_shader *gshader = NULL; struct wined3d_shader *pshader = NULL; GLuint reorder_shader_id = 0; struct glsl_program_key key; GLuint program_id; unsigned int i; GLuint vs_id = 0; + GLuint ds_id = 0; GLuint gs_id = 0; GLuint ps_id = 0; struct list *ps_list, *vs_list; @@ -9159,6 +9349,19 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const vs_list = &ffp_shader->linked_programs; } + dshader = state->shader[WINED3D_SHADER_TYPE_DOMAIN]; + if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_DOMAIN)) && ctx_data->glsl_program) + { + ds_id = ctx_data->glsl_program->ds.id; + } + else if (dshader) + { + struct ds_compile_args args; + + find_ds_compile_args(state, dshader, &args, context); + ds_id = find_glsl_domain_shader(context, priv, dshader, &args); + } + gshader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY]; if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_GEOMETRY)) && ctx_data->glsl_program) { @@ -9202,10 +9405,11 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const } key.vs_id = vs_id; + key.ds_id = ds_id; key.gs_id = gs_id; key.ps_id = ps_id; key.cs_id = 0; - if ((!vs_id && !gs_id && !ps_id) || (entry = get_glsl_program_entry(priv, &key))) + if ((!vs_id && !ds_id && !gs_id && !ps_id) || (entry = get_glsl_program_entry(priv, &key))) { ctx_data->glsl_program = entry; return; @@ -9219,6 +9423,7 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const entry = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link)); entry->id = program_id; entry->vs.id = vs_id; + entry->ds.id = ds_id; entry->gs.id = gs_id; entry->ps.id = ps_id; entry->cs.id = 0; @@ -9299,6 +9504,15 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const } } + if (dshader) + { + TRACE("Attaching GLSL tessellation evaluation shader object %u to program %u.\n", ds_id, program_id); + GL_EXTCALL(glAttachShader(program_id, ds_id)); + checkGLcall("glAttachShader"); + + list_add_head(&dshader->linked_programs, &entry->ds.shader_entry); + } + if (gshader) { TRACE("Attaching GLSL geometry shader object %u to program %u.\n", gs_id, program_id); @@ -9327,6 +9541,7 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const shader_glsl_init_vs_uniform_locations(gl_info, priv, program_id, &entry->vs, vshader ? vshader->limits->constant_float : 0); + shader_glsl_init_ds_uniform_locations(gl_info, priv, program_id, &entry->ds); shader_glsl_init_gs_uniform_locations(gl_info, priv, program_id, &entry->gs); shader_glsl_init_ps_uniform_locations(gl_info, priv, program_id, &entry->ps, pshader ? pshader->limits->constant_float : 0); @@ -9405,6 +9620,14 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const if (entry->vs.pointsize_min_location != -1) entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_POINTSIZE; + if (dshader) + { + if (entry->ds.pos_fixup_location != -1) + entry->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP; + + shader_glsl_load_program_resources(context, priv, program_id, dshader); + } + if (gshader) { if (entry->gs.pos_fixup_location != -1) @@ -9677,6 +9900,28 @@ static void shader_glsl_destroy(struct wined3d_shader *shader) break; } + case WINED3D_SHADER_TYPE_DOMAIN: + { + struct glsl_ds_compiled_shader *gl_shaders = shader_data->gl_shaders.ds; + + for (i = 0; i < shader_data->num_gl_shaders; ++i) + { + TRACE("Deleting domain shader %u.\n", gl_shaders[i].id); + GL_EXTCALL(glDeleteShader(gl_shaders[i].id)); + checkGLcall("glDeleteShader"); + } + HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders.ds); + + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, + struct glsl_shader_prog_link, ds.shader_entry) + { + shader_glsl_invalidate_contexts_program(device, entry); + delete_glsl_program_entry(priv, gl_info, entry); + } + + break; + } + case WINED3D_SHADER_TYPE_GEOMETRY: { struct glsl_gs_compiled_shader *gl_shaders = shader_data->gl_shaders.gs; @@ -9748,6 +9993,9 @@ static int glsl_program_key_compare(const void *key, const struct wine_rb_entry if (k->ps_id > prog->ps.id) return 1; else if (k->ps_id < prog->ps.id) return -1; + if (k->ds_id > prog->ds.id) return 1; + else if (k->ds_id < prog->ds.id) return -1; + if (k->cs_id > prog->cs.id) return 1; else if (k->cs_id < prog->cs.id) return -1; @@ -10050,9 +10298,9 @@ static const SHADER_HANDLER shader_glsl_instruction_handler_table[WINED3DSIH_TAB /* WINED3DSIH_DCL_SAMPLER */ shader_glsl_nop, /* WINED3DSIH_DCL_STREAM */ NULL, /* WINED3DSIH_DCL_TEMPS */ shader_glsl_nop, - /* WINED3DSIH_DCL_TESSELLATOR_DOMAIN */ NULL, - /* WINED3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE */ NULL, - /* WINED3DSIH_DCL_TESSELLATOR_PARTITIONING */ NULL, + /* WINED3DSIH_DCL_TESSELLATOR_DOMAIN */ shader_glsl_nop, + /* WINED3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE */ shader_glsl_nop, + /* WINED3DSIH_DCL_TESSELLATOR_PARTITIONING */ shader_glsl_nop, /* WINED3DSIH_DCL_TGSM_RAW */ shader_glsl_nop, /* WINED3DSIH_DCL_TGSM_STRUCTURED */ shader_glsl_nop, /* WINED3DSIH_DCL_THREAD_GROUP */ shader_glsl_nop, @@ -10426,10 +10674,21 @@ static void glsl_vertex_pipe_vs(struct wined3d_context *context, context_apply_state(context, state, STATE_VDECL); } +static void glsl_vertex_pipe_hs(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) +{ + /* In Direct3D tessellator options (e.g. output primitive type, primitive + * winding) are defined in Hull Shaders, while in GLSL those are + * specified in Tessellation Evaluation Shaders. */ + context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_DOMAIN; +} + static void glsl_vertex_pipe_geometry_shader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { - if (state->shader[WINED3D_SHADER_TYPE_VERTEX] + if (state->shader[WINED3D_SHADER_TYPE_DOMAIN]) + context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_DOMAIN; + else if (state->shader[WINED3D_SHADER_TYPE_VERTEX] && state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.shader_version.major >= 4) context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; } @@ -10439,6 +10698,8 @@ static void glsl_vertex_pipe_pixel_shader(struct wined3d_context *context, { if (state->shader[WINED3D_SHADER_TYPE_GEOMETRY]) context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_GEOMETRY; + else if (state->shader[WINED3D_SHADER_TYPE_DOMAIN]) + context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_DOMAIN; else if (state->shader[WINED3D_SHADER_TYPE_VERTEX] && state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.shader_version.major >= 4) context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; @@ -10587,6 +10848,7 @@ static const struct StateEntryTemplate glsl_vertex_pipe_vp_states[] = { {STATE_VDECL, {STATE_VDECL, glsl_vertex_pipe_vdecl }, WINED3D_GL_EXT_NONE }, {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), glsl_vertex_pipe_vs }, WINED3D_GL_EXT_NONE }, + {STATE_SHADER(WINED3D_SHADER_TYPE_HULL), {STATE_SHADER(WINED3D_SHADER_TYPE_HULL), glsl_vertex_pipe_hs }, WINED3D_GL_EXT_NONE }, {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), glsl_vertex_pipe_geometry_shader}, WINED3D_GL_EXT_NONE }, {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), glsl_vertex_pipe_pixel_shader}, WINED3D_GL_EXT_NONE }, {STATE_MATERIAL, {STATE_RENDER(WINED3D_RS_SPECULARENABLE), NULL }, WINED3D_GL_EXT_NONE }, diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c index 71a17185c70..1dd8e6d5c34 100644 --- a/dlls/wined3d/shader.c +++ b/dlls/wined3d/shader.c @@ -1095,6 +1095,27 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st { reg_maps->temporary_count = ins.declaration.count; } + else if (ins.handler_idx == WINED3DSIH_DCL_TESSELLATOR_DOMAIN) + { + if (shader_version.type == WINED3D_SHADER_TYPE_DOMAIN) + shader->u.ds.tessellator_domain = ins.declaration.tessellator_domain; + else if (shader_version.type != WINED3D_SHADER_TYPE_HULL) + FIXME("Invalid instruction %#x for shader type %#x.\n", ins.handler_idx, shader_version.type); + } + else if (ins.handler_idx == WINED3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE) + { + if (shader_version.type == WINED3D_SHADER_TYPE_HULL) + shader->u.hs.tessellator_output_primitive = ins.declaration.tessellator_output_primitive; + else + FIXME("Invalid instruction %#x for shader type %#x.\n", ins.handler_idx, shader_version.type); + } + else if (ins.handler_idx == WINED3DSIH_DCL_TESSELLATOR_PARTITIONING) + { + if (shader_version.type == WINED3D_SHADER_TYPE_HULL) + shader->u.hs.tessellator_partitioning = ins.declaration.tessellator_partitioning; + else + FIXME("Invalid instruction %#x for shader type %#x.\n", ins.handler_idx, shader_version.type); + } else if (ins.handler_idx == WINED3DSIH_DCL_TGSM_RAW) { if (FAILED(hr = shader_reg_maps_add_tgsm(reg_maps, ins.declaration.tgsm_raw.reg.reg.idx[0].offset, @@ -3486,6 +3507,24 @@ static HRESULT geometry_shader_init(struct wined3d_shader *shader, struct wined3 return WINED3D_OK; } +void find_ds_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader, + struct ds_compile_args *args, const struct wined3d_context *context) +{ + const struct wined3d_shader *hull_shader = state->shader[WINED3D_SHADER_TYPE_HULL]; + + args->tessellator_output_primitive = hull_shader->u.hs.tessellator_output_primitive; + args->tessellator_partitioning = hull_shader->u.hs.tessellator_partitioning; + + args->output_count = state->shader[WINED3D_SHADER_TYPE_GEOMETRY] ? + state->shader[WINED3D_SHADER_TYPE_GEOMETRY]->limits->packed_input : + state->shader[WINED3D_SHADER_TYPE_PIXEL] ? state->shader[WINED3D_SHADER_TYPE_PIXEL]->limits->packed_input + : shader->limits->packed_output; + args->next_shader_type = state->shader[WINED3D_SHADER_TYPE_GEOMETRY] ? WINED3D_SHADER_TYPE_GEOMETRY + : WINED3D_SHADER_TYPE_PIXEL; + + args->render_offscreen = context->render_offscreen; +} + void find_gs_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader, struct gs_compile_args *args) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 91dd20676b4..f376d4118c6 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1329,6 +1329,15 @@ struct vs_compile_args unsigned int next_shader_input_count; }; +struct ds_compile_args +{ + enum wined3d_tessellator_output_primitive tessellator_output_primitive; + enum wined3d_tessellator_partitioning tessellator_partitioning; + unsigned int output_count : 16; + unsigned int next_shader_type : 3; + unsigned int render_offscreen : 1; +}; + struct gs_compile_args { unsigned int output_count; @@ -3698,6 +3707,17 @@ struct wined3d_vertex_shader struct wined3d_shader_attribute attributes[MAX_ATTRIBS]; }; +struct wined3d_domain_shader +{ + enum wined3d_tessellator_domain tessellator_domain; +}; + +struct wined3d_hull_shader +{ + enum wined3d_tessellator_output_primitive tessellator_output_primitive; + enum wined3d_tessellator_partitioning tessellator_partitioning; +}; + struct wined3d_geometry_shader { enum wined3d_primitive_type input_type; @@ -3761,6 +3781,8 @@ struct wined3d_shader union { struct wined3d_vertex_shader vs; + struct wined3d_domain_shader ds; + struct wined3d_hull_shader hs; struct wined3d_geometry_shader gs; struct wined3d_pixel_shader ps; struct wined3d_compute_shader cs; @@ -3776,6 +3798,9 @@ void find_vs_compile_args(const struct wined3d_state *state, const struct wined3 WORD swizzle_map, struct vs_compile_args *args, const struct wined3d_d3d_info *d3d_info) DECLSPEC_HIDDEN; +void find_ds_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader, + struct ds_compile_args *args, const struct wined3d_context *context) DECLSPEC_HIDDEN; + void find_gs_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader, struct gs_compile_args *args) DECLSPEC_HIDDEN;