From 3aa9fe6bef7a3440845c7410c98e3e98a79eb70f Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Wed, 3 Dec 2014 10:28:11 +0100 Subject: [PATCH] wined3d: Record the data type of shader resources. --- dlls/wined3d/arb_program_shader.c | 2 +- dlls/wined3d/context.c | 32 +++++++++--------- dlls/wined3d/glsl_shader.c | 16 ++++----- dlls/wined3d/shader.c | 56 ++++++++++++++++++++++++------- dlls/wined3d/shader_sm1.c | 1 + dlls/wined3d/shader_sm4.c | 36 ++++++++++++++++++++ dlls/wined3d/wined3d_private.h | 11 +++++- 7 files changed, 115 insertions(+), 39 deletions(-) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index a28b529e14e..bc66c4a9aeb 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -1390,7 +1390,7 @@ static const char *shader_arb_get_modifier(const struct wined3d_shader_instructi static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD sampler_idx, const char *dst_str, const char *coord_reg, WORD flags, const char *dsx, const char *dsy) { - enum wined3d_shader_resource_type resource_type = ins->ctx->reg_maps->resource_type[sampler_idx]; + enum wined3d_shader_resource_type resource_type = ins->ctx->reg_maps->resource_info[sampler_idx].type; struct wined3d_shader_buffer *buffer = ins->ctx->buffer; const char *tex_type; BOOL np2_fixup = FALSE; diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 75161c6ef81..4da8c7dc5e7 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -2585,14 +2585,14 @@ static void context_map_fixed_function_samplers(struct wined3d_context *context, static void context_map_psamplers(struct wined3d_context *context, const struct wined3d_state *state) { - const enum wined3d_shader_resource_type *resource_type = - state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.resource_type; + const struct wined3d_shader_resource_info *resource_info = + state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.resource_info; unsigned int i; const struct wined3d_d3d_info *d3d_info = context->d3d_info; for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) { - if (resource_type[i] && context->tex_unit_map[i] != i) + if (resource_info[i].type && context->tex_unit_map[i] != i) { context_map_stage(context, i, i); context_invalidate_state(context, STATE_SAMPLER(i)); @@ -2603,8 +2603,8 @@ static void context_map_psamplers(struct wined3d_context *context, const struct } static BOOL context_unit_free_for_vs(const struct wined3d_context *context, - const enum wined3d_shader_resource_type *ps_resource_types, - const enum wined3d_shader_resource_type *vs_resource_types, DWORD unit) + const struct wined3d_shader_resource_info *ps_resource_info, + const struct wined3d_shader_resource_info *vs_resource_info, DWORD unit) { DWORD current_mapping = context->rev_tex_unit_map[unit]; @@ -2616,25 +2616,25 @@ static BOOL context_unit_free_for_vs(const struct wined3d_context *context, { /* Used by a fragment sampler */ - if (!ps_resource_types) + if (!ps_resource_info) { /* No pixel shader, check fixed function */ return current_mapping >= MAX_TEXTURES || !(context->fixed_function_usage_map & (1 << current_mapping)); } /* Pixel shader, check the shader's sampler map */ - return !ps_resource_types[current_mapping]; + return !ps_resource_info[current_mapping].type; } /* Used by a vertex sampler */ - return !vs_resource_types[current_mapping - MAX_FRAGMENT_SAMPLERS]; + return !vs_resource_info[current_mapping - MAX_FRAGMENT_SAMPLERS].type; } static void context_map_vsamplers(struct wined3d_context *context, BOOL ps, const struct wined3d_state *state) { - const enum wined3d_shader_resource_type *vs_resource_type = - state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.resource_type; - const enum wined3d_shader_resource_type *ps_resource_type = NULL; + const struct wined3d_shader_resource_info *vs_resource_info = + state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.resource_info; + const struct wined3d_shader_resource_info *ps_resource_info = NULL; const struct wined3d_gl_info *gl_info = context->gl_info; int start = min(MAX_COMBINED_SAMPLERS, gl_info->limits.combined_samplers) - 1; int i; @@ -2643,12 +2643,12 @@ static void context_map_vsamplers(struct wined3d_context *context, BOOL ps, cons * resource's specific type. Otherwise we'd need to call * shader_update_samplers() here for 1.x pixelshaders. */ if (ps) - ps_resource_type = state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.resource_type; + ps_resource_info = state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.resource_info; for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i) { DWORD vsampler_idx = i + MAX_FRAGMENT_SAMPLERS; - if (vs_resource_type[i]) + if (vs_resource_info[i].type) { if (context->tex_unit_map[vsampler_idx] != WINED3D_UNMAPPED_STAGE) { @@ -2658,7 +2658,7 @@ static void context_map_vsamplers(struct wined3d_context *context, BOOL ps, cons while (start >= 0) { - if (context_unit_free_for_vs(context, ps_resource_type, vs_resource_type, start)) + if (context_unit_free_for_vs(context, ps_resource_info, vs_resource_info, start)) { context_map_stage(context, vsampler_idx, start); context_invalidate_state(context, STATE_SAMPLER(vsampler_idx)); @@ -2930,7 +2930,7 @@ static void context_preload_textures(struct wined3d_context *context, const stru { for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i) { - if (state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.resource_type[i]) + if (state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.resource_info[i].type) context_preload_texture(context, state, MAX_FRAGMENT_SAMPLERS + i); } } @@ -2939,7 +2939,7 @@ static void context_preload_textures(struct wined3d_context *context, const stru { for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) { - if (state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.resource_type[i]) + if (state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.resource_info[i].type) context_preload_texture(context, state, i); } } diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index ea6f4c90f2f..a351932b115 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -1066,11 +1066,11 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont { BOOL shadow_sampler, tex_rect; - if (!reg_maps->resource_type[i]) + if (!reg_maps->resource_info[i].type) continue; shadow_sampler = version->type == WINED3D_SHADER_TYPE_PIXEL && (ps_args->shadow & (1 << i)); - switch (reg_maps->resource_type[i]) + switch (reg_maps->resource_info[i].type) { case WINED3D_SHADER_RESOURCE_TEXTURE_1D: if (shadow_sampler) @@ -1112,7 +1112,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont default: shader_addline(buffer, "uniform unsupported_sampler %s_sampler%u;\n", prefix, i); - FIXME("Unhandled resource type %#x.\n", reg_maps->resource_type[i]); + FIXME("Unhandled resource type %#x.\n", reg_maps->resource_info[i].type); break; } } @@ -1134,10 +1134,10 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont for (i = 0; i < shader->limits->sampler; ++i) { - if (!reg_maps->resource_type[i] || !(ps_args->np2_fixup & (1 << i))) + if (!reg_maps->resource_info[i].type || !(ps_args->np2_fixup & (1 << i))) continue; - if (reg_maps->resource_type[i] != WINED3D_SHADER_RESOURCE_TEXTURE_2D) + if (reg_maps->resource_info[i].type != WINED3D_SHADER_RESOURCE_TEXTURE_2D) { FIXME("Non-2D texture is flagged for NP2 texcoord fixup.\n"); continue; @@ -1890,7 +1890,7 @@ static const char *shader_glsl_get_rel_op(enum wined3d_shader_rel_op op) static void shader_glsl_get_sample_function(const struct wined3d_shader_context *ctx, DWORD resource_idx, DWORD flags, struct glsl_sample_function *sample_function) { - enum wined3d_shader_resource_type resource_type = ctx->reg_maps->resource_type[resource_idx]; + enum wined3d_shader_resource_type resource_type = ctx->reg_maps->resource_info[resource_idx].type; const struct wined3d_gl_info *gl_info = ctx->gl_info; BOOL shadow = ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_PIXEL && (((const struct shader_glsl_ctx_priv *)ctx->backend_data)->cur_ps_args->shadow & (1 << resource_idx)); @@ -3468,7 +3468,7 @@ static void shader_glsl_tex(const struct wined3d_shader_instruction *ins) { DWORD flags = (priv->cur_ps_args->tex_transform >> resource_idx * WINED3D_PSARGS_TEXTRANSFORM_SHIFT) & WINED3D_PSARGS_TEXTRANSFORM_MASK; - enum wined3d_shader_resource_type resource_type = ins->ctx->reg_maps->resource_type[resource_idx]; + enum wined3d_shader_resource_type resource_type = ins->ctx->reg_maps->resource_info[resource_idx].type; /* Projected cube textures don't make a lot of sense, the resulting coordinates stay the same. */ if (flags & WINED3D_PSARGS_PROJECTED && resource_type != WINED3D_SHADER_RESOURCE_TEXTURE_CUBE) @@ -3507,7 +3507,7 @@ static void shader_glsl_tex(const struct wined3d_shader_instruction *ins) else { if ((ins->flags & WINED3DSI_TEXLD_PROJECT) - && ins->ctx->reg_maps->resource_type[resource_idx] != WINED3D_SHADER_RESOURCE_TEXTURE_CUBE) + && ins->ctx->reg_maps->resource_info[resource_idx].type != WINED3D_SHADER_RESOURCE_TEXTURE_CUBE) { /* ps 2.0 texldp instruction always divides by the fourth component. */ sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED; diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c index b0aabd90e89..65318036313 100644 --- a/dlls/wined3d/shader.c +++ b/dlls/wined3d/shader.c @@ -664,12 +664,13 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st case WINED3DSPR_SAMPLER: case WINED3DSPR_RESOURCE: - if (reg_idx >= ARRAY_SIZE(reg_maps->resource_type)) + if (reg_idx >= ARRAY_SIZE(reg_maps->resource_info)) { ERR("Invalid resource index %u.\n", reg_idx); break; } - reg_maps->resource_type[reg_idx] = semantic->resource_type; + reg_maps->resource_info[reg_idx].type = semantic->resource_type; + reg_maps->resource_info[reg_idx].data_type = semantic->resource_data_type; break; default: @@ -897,17 +898,20 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st || ins.handler_idx == WINED3DSIH_TEXREG2GB || ins.handler_idx == WINED3DSIH_TEXREG2RGB)) { + unsigned int reg_idx = ins.dst[i].reg.idx[0].offset; + TRACE("Setting fake 2D resource for 1.x pixelshader.\n"); - reg_maps->resource_type[ins.dst[i].reg.idx[0].offset] = WINED3D_SHADER_RESOURCE_TEXTURE_2D; + reg_maps->resource_info[reg_idx].type = WINED3D_SHADER_RESOURCE_TEXTURE_2D; + reg_maps->resource_info[reg_idx].data_type = WINED3D_DATA_FLOAT; /* texbem is only valid with < 1.4 pixel shaders */ if (ins.handler_idx == WINED3DSIH_TEXBEM || ins.handler_idx == WINED3DSIH_TEXBEML) { - reg_maps->bumpmat |= 1 << ins.dst[i].reg.idx[0].offset; + reg_maps->bumpmat |= 1 << reg_idx; if (ins.handler_idx == WINED3DSIH_TEXBEML) { - reg_maps->luminanceparams |= 1 << ins.dst[i].reg.idx[0].offset; + reg_maps->luminanceparams |= 1 << reg_idx; } } } @@ -1063,6 +1067,32 @@ static void shader_dump_decl_usage(const struct wined3d_shader_semantic *semanti TRACE("unknown"); break; } + switch (semantic->resource_data_type) + { + case WINED3D_DATA_FLOAT: + TRACE(" (float)"); + break; + + case WINED3D_DATA_INT: + TRACE(" (int)"); + break; + + case WINED3D_DATA_UINT: + TRACE(" (uint)"); + break; + + case WINED3D_DATA_UNORM: + TRACE(" (unorm)"); + break; + + case WINED3D_DATA_SNORM: + TRACE(" (snorm)"); + break; + + default: + TRACE(" (unknown)"); + break; + } } else { @@ -2179,7 +2209,7 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3 if (!state->shader[WINED3D_SHADER_TYPE_VERTEX]) { - enum wined3d_shader_resource_type resource_type = shader->reg_maps.resource_type[i]; + enum wined3d_shader_resource_type resource_type = shader->reg_maps.resource_info[i].type; unsigned int j; unsigned int index = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX]; DWORD max_valid = WINED3D_TTFF_COUNT4; @@ -2229,7 +2259,7 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3 { const struct wined3d_texture *texture = state->textures[i]; - if (!shader->reg_maps.resource_type[i]) + if (!shader->reg_maps.resource_info[i].type) continue; /* Treat unbound textures as 2D. The dummy texture will provide @@ -2258,7 +2288,7 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3 for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) { - if (!shader->reg_maps.resource_type[i]) + if (!shader->reg_maps.resource_info[i].type) continue; texture = state->textures[i]; @@ -2429,7 +2459,7 @@ static HRESULT pixelshader_init(struct wined3d_shader *shader, struct wined3d_de void pixelshader_update_resource_types(struct wined3d_shader *shader, WORD tex_types) { struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; - enum wined3d_shader_resource_type *resource_type = reg_maps->resource_type; + struct wined3d_shader_resource_info *resource_info = reg_maps->resource_info; unsigned int i; if (reg_maps->shader_version.major != 1) return; @@ -2437,21 +2467,21 @@ void pixelshader_update_resource_types(struct wined3d_shader *shader, WORD tex_t for (i = 0; i < shader->limits->sampler; ++i) { /* We don't sample from this sampler. */ - if (!resource_type[i]) + if (!resource_info[i].type) continue; switch ((tex_types >> i * WINED3D_PSARGS_TEXTYPE_SHIFT) & WINED3D_PSARGS_TEXTYPE_MASK) { case WINED3D_SHADER_TEX_2D: - resource_type[i] = WINED3D_SHADER_RESOURCE_TEXTURE_2D; + resource_info[i].type = WINED3D_SHADER_RESOURCE_TEXTURE_2D; break; case WINED3D_SHADER_TEX_3D: - resource_type[i] = WINED3D_SHADER_RESOURCE_TEXTURE_3D; + resource_info[i].type = WINED3D_SHADER_RESOURCE_TEXTURE_3D; break; case WINED3D_SHADER_TEX_CUBE: - resource_type[i] = WINED3D_SHADER_RESOURCE_TEXTURE_CUBE; + resource_info[i].type = WINED3D_SHADER_RESOURCE_TEXTURE_CUBE; break; } } diff --git a/dlls/wined3d/shader_sm1.c b/dlls/wined3d/shader_sm1.c index 3d9050d7b7e..04650020779 100644 --- a/dlls/wined3d/shader_sm1.c +++ b/dlls/wined3d/shader_sm1.c @@ -646,6 +646,7 @@ static void shader_sm1_read_semantic(const DWORD **ptr, struct wined3d_shader_se { semantic->resource_type = resource_type_table[resource_type]; } + semantic->resource_data_type = WINED3D_DATA_FLOAT; shader_parse_dst_param(dst_token, NULL, &semantic->reg); } diff --git a/dlls/wined3d/shader_sm4.c b/dlls/wined3d/shader_sm4.c index b3bf1562653..046b25292b3 100644 --- a/dlls/wined3d/shader_sm4.c +++ b/dlls/wined3d/shader_sm4.c @@ -185,6 +185,15 @@ enum wined3d_sm4_resource_type WINED3D_SM4_RESOURCE_TEXTURE_2DMSARRAY = 0x9, }; +enum wined3d_sm4_data_type +{ + WINED3D_SM4_DATA_UNORM = 0x1, + WINED3D_SM4_DATA_SNORM = 0x2, + WINED3D_SM4_DATA_INT = 0x3, + WINED3D_SM4_DATA_UINT = 0x4, + WINED3D_SM4_DATA_FLOAT = 0x5, +}; + struct wined3d_shader_src_param_entry { struct list entry; @@ -356,6 +365,16 @@ static const enum wined3d_shader_resource_type resource_type_table[] = /* WINED3D_SM4_RESOURCE_TEXTURE_2DMSARRAY */ WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY, }; +static const enum wined3d_data_type data_type_table[] = +{ + /* 0 */ WINED3D_DATA_FLOAT, + /* WINED3D_SM4_DATA_UNORM */ WINED3D_DATA_UNORM, + /* WINED3D_SM4_DATA_SNORM */ WINED3D_DATA_SNORM, + /* WINED3D_SM4_DATA_INT */ WINED3D_DATA_INT, + /* WINED3D_SM4_DATA_UINT */ WINED3D_DATA_UINT, + /* WINED3D_SM4_DATA_FLOAT */ WINED3D_DATA_FLOAT, +}; + static BOOL shader_sm4_read_src_param(struct wined3d_sm4_data *priv, const DWORD **ptr, enum wined3d_data_type data_type, struct wined3d_shader_src_param *src_param); @@ -779,6 +798,8 @@ static void shader_sm4_read_instruction(void *data, const DWORD **ptr, struct wi if (opcode == WINED3D_SM4_OP_DCL_RESOURCE) { enum wined3d_sm4_resource_type resource_type; + enum wined3d_sm4_data_type data_type; + DWORD components; resource_type = (opcode_token & WINED3D_SM4_RESOURCE_TYPE_MASK) >> WINED3D_SM4_RESOURCE_TYPE_SHIFT; if (!resource_type || (resource_type >= ARRAY_SIZE(resource_type_table))) @@ -791,6 +812,21 @@ static void shader_sm4_read_instruction(void *data, const DWORD **ptr, struct wi ins->declaration.semantic.resource_type = resource_type_table[resource_type]; } shader_sm4_read_dst_param(priv, &p, WINED3D_DATA_RESOURCE, &ins->declaration.semantic.reg); + + components = *p++; + if ((components & 0xfff0) != (components & 0xf) * 0x1110) + FIXME("Components (%#x) have different data types.\n", components); + data_type = components & 0xf; + + if (!data_type || (data_type >= ARRAY_SIZE(data_type_table))) + { + FIXME("Unhandled data type %#x.\n", data_type); + ins->declaration.semantic.resource_data_type = WINED3D_DATA_FLOAT; + } + else + { + ins->declaration.semantic.resource_data_type = data_type_table[data_type]; + } } else if (opcode == WINED3D_SM4_OP_DCL_CONSTANT_BUFFER) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index a1e5dea5016..e8e649a89e4 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -347,6 +347,8 @@ enum wined3d_data_type WINED3D_DATA_RESOURCE, WINED3D_DATA_SAMPLER, WINED3D_DATA_UINT, + WINED3D_DATA_UNORM, + WINED3D_DATA_SNORM, }; enum wined3d_immconst_type @@ -574,6 +576,12 @@ struct wined3d_shader_version BYTE minor; }; +struct wined3d_shader_resource_info +{ + enum wined3d_shader_resource_type type; + enum wined3d_data_type data_type; +}; + #define WINED3D_SHADER_VERSION(major, minor) (((major) << 8) | (minor)) struct wined3d_shader_reg_maps @@ -593,7 +601,7 @@ struct wined3d_shader_reg_maps WORD local_bool_consts; /* MAX_CONST_B, 16 */ UINT cb_sizes[WINED3D_MAX_CBS]; - enum wined3d_shader_resource_type resource_type[max(MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS)]; + struct wined3d_shader_resource_info resource_info[max(MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS)]; BYTE bumpmat; /* MAX_TEXTURES, 8 */ BYTE luminanceparams; /* MAX_TEXTURES, 8 */ @@ -679,6 +687,7 @@ struct wined3d_shader_semantic enum wined3d_decl_usage usage; UINT usage_idx; enum wined3d_shader_resource_type resource_type; + enum wined3d_data_type resource_data_type; struct wined3d_shader_dst_param reg; };