From: Józef Kucia Subject: [PATCH 2/4] wined3d: Implement vertex blending in glsl_vertex_pipe. Message-Id: <1435818408-9494-2-git-send-email-joseph.kucia@gmail.com> Date: Thu, 2 Jul 2015 08:26:46 +0200 --- dlls/wined3d/cs.c | 2 +- dlls/wined3d/directx.c | 3 +- dlls/wined3d/glsl_shader.c | 79 +++++++++++++++++++++++++++++++----------- dlls/wined3d/state.c | 4 +-- dlls/wined3d/utils.c | 20 +++++++++-- dlls/wined3d/wined3d_private.h | 46 +++++++++++++----------- 6 files changed, 106 insertions(+), 48 deletions(-) diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 874129a..39e78e1 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -858,7 +858,7 @@ static void wined3d_cs_exec_set_transform(struct wined3d_cs *cs, const void *dat const struct wined3d_cs_set_transform *op = data; cs->state.transforms[op->state] = *op->matrix; - if (op->state < WINED3D_TS_WORLD_MATRIX(cs->device->adapter->gl_info.limits.blends)) + if (op->state < WINED3D_TS_WORLD_MATRIX(cs->device->adapter->d3d_info.limits.ffp_vertex_blend_matrices)) device_invalidate_state(cs->device, STATE_TRANSFORM(op->state)); } diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 243f5ae..146b544 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -3564,7 +3564,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter) adapter->fragment_pipe = select_fragment_implementation(gl_info, adapter->shader_backend); adapter->blitter = select_blit_implementation(gl_info, adapter->shader_backend); - adapter->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps); + adapter->shader_backend->shader_get_caps(gl_info, &shader_caps); adapter->d3d_info.vs_clipping = shader_caps.wined3d_caps & WINED3D_SHADER_CAP_VS_CLIPPING; adapter->d3d_info.limits.vs_version = shader_caps.vs_version; adapter->d3d_info.limits.gs_version = shader_caps.gs_version; @@ -3575,6 +3575,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter) adapter->vertex_pipe->vp_get_caps(gl_info, &vertex_caps); adapter->d3d_info.xyzrhw = vertex_caps.xyzrhw; adapter->d3d_info.ffp_generic_attributes = vertex_caps.ffp_generic_attributes; + adapter->d3d_info.limits.ffp_vertex_blend_matrices = vertex_caps.max_vertex_blend_matrices; adapter->fragment_pipe->get_caps(gl_info, &fragment_caps); adapter->d3d_info.limits.ffp_blend_stages = fragment_caps.MaxTextureBlendStages; diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 1f6ce09..c3ecb77 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -119,7 +119,7 @@ struct glsl_vs_program GLint uniform_b_locations[MAX_CONST_B]; GLint pos_fixup_location; - GLint modelview_matrix_location; + GLint modelview_matrix_location[MAX_VERTEX_BLENDS]; GLint projection_matrix_location; GLint normal_matrix_location; GLint texture_matrix_location[MAX_TEXTURES]; @@ -1072,7 +1072,7 @@ static void shader_glsl_ffp_vertex_normalmatrix_uniform(const struct wined3d_con struct wined3d_matrix mv; unsigned int i, j; - get_modelview_matrix(context, state, &mv); + get_modelview_matrix(context, state, 0, &mv); if (context->swapchain->device->wined3d->flags & WINED3D_LEGACY_FFP_LIGHTING) invert_matrix_3d(&mv, &mv); else @@ -1318,13 +1318,28 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context { struct wined3d_matrix mat; - get_modelview_matrix(context, state, &mat); - GL_EXTCALL(glUniformMatrix4fv(prog->vs.modelview_matrix_location, 1, FALSE, &mat._11)); + get_modelview_matrix(context, state, 0, &mat); + GL_EXTCALL(glUniformMatrix4fv(prog->vs.modelview_matrix_location[0], 1, FALSE, &mat._11)); checkGLcall("glUniformMatrix4fv"); shader_glsl_ffp_vertex_normalmatrix_uniform(context, state, prog); } + if (update_mask & WINED3D_SHADER_CONST_FFP_VERTEXBLEND) + { + struct wined3d_matrix mat; + + for (i = 1; i < MAX_VERTEX_BLENDS; ++i) + { + if (prog->vs.modelview_matrix_location[i] == -1) + break; + + get_modelview_matrix(context, state, i, &mat); + GL_EXTCALL(glUniformMatrix4fv(prog->vs.modelview_matrix_location[i], 1, FALSE, &mat._11)); + checkGLcall("glUniformMatrix4fv"); + } + } + if (update_mask & WINED3D_SHADER_CONST_FFP_PROJ) { struct wined3d_matrix projection; @@ -5554,13 +5569,13 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct wined3d_string_buffe static const struct attrib_info { const char type[6]; - const char name[20]; + const char name[24]; } attrib_info[] = { {"vec4", "ffp_attrib_position"}, /* WINED3D_FFP_POSITION */ - /* TODO: Vertex blending */ - {"vec4", ""}, /* WINED3D_FFP_BLENDWEIGHT */ + {"vec4", "ffp_attrib_blendweight"}, /* WINED3D_FFP_BLENDWEIGHT */ + /* TODO: Indexed vertex blending */ {"float", ""}, /* WINED3D_FFP_BLENDINDICES */ {"vec3", "ffp_attrib_normal"}, /* WINED3D_FFP_NORMAL */ {"float", "ffp_attrib_psize"}, /* WINED3D_FFP_PSIZE */ @@ -5583,7 +5598,7 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct wined3d_string_buffe } shader_addline(buffer, "\n"); - shader_addline(buffer, "uniform mat4 ffp_modelview_matrix;\n"); + shader_addline(buffer, "uniform mat4 ffp_modelview_matrix[%u];\n", MAX_VERTEX_BLENDS); shader_addline(buffer, "uniform mat4 ffp_projection_matrix;\n"); shader_addline(buffer, "uniform mat3 ffp_normal_matrix;\n"); shader_addline(buffer, "uniform mat4 ffp_texture_matrix[%u];\n", MAX_TEXTURES); @@ -5651,7 +5666,14 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct wined3d_string_buffe } else { - shader_addline(buffer, "vec4 ec_pos = ffp_modelview_matrix * ffp_attrib_position;\n"); + shader_addline(buffer, "ffp_attrib_blendweight[%u] = 1.0;\n", settings->vertexblends); + for (i = 0; i < settings->vertexblends; ++i) + shader_addline(buffer, "ffp_attrib_blendweight[%u] -= ffp_attrib_blendweight[%u];\n", settings->vertexblends, i); + + shader_addline(buffer, "vec4 ec_pos = vec4(0.0);\n"); + for (i = 0; i < settings->vertexblends + 1; ++i) + shader_addline(buffer, "ec_pos += ffp_attrib_blendweight[%u] * (ffp_modelview_matrix[%u] * ffp_attrib_position);\n", i, i); + shader_addline(buffer, "gl_Position = ffp_projection_matrix * ec_pos;\n"); if (settings->clipping) shader_addline(buffer, "gl_ClipVertex = ec_pos;\n"); @@ -6436,7 +6458,11 @@ static void shader_glsl_init_vs_uniform_locations(const struct wined3d_gl_info * vs->pos_fixup_location = GL_EXTCALL(glGetUniformLocation(program_id, "posFixup")); - vs->modelview_matrix_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_modelview_matrix")); + for (i = 0; i < MAX_VERTEX_BLENDS; ++i) + { + string_buffer_sprintf(name, "ffp_modelview_matrix[%u]", i); + vs->modelview_matrix_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); + } vs->projection_matrix_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_projection_matrix")); vs->normal_matrix_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_normal_matrix")); for (i = 0; i < MAX_TEXTURES; ++i) @@ -6809,6 +6835,15 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MODELVIEW | WINED3D_SHADER_CONST_FFP_PROJ; + for (i = 1; i < MAX_VERTEX_BLENDS; ++i) + { + if (entry->vs.modelview_matrix_location[i] != -1) + { + entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_VERTEXBLEND; + break; + } + } + for (i = 0; i < MAX_TEXTURES; ++i) { if (entry->vs.texture_matrix_location[i] != -1) @@ -7674,7 +7709,7 @@ static void glsl_vertex_pipe_vp_get_caps(const struct wined3d_gl_info *gl_info, caps->xyzrhw = TRUE; caps->ffp_generic_attributes = TRUE; caps->max_active_lights = MAX_ACTIVE_LIGHTS; - caps->max_vertex_blend_matrices = 1; + caps->max_vertex_blend_matrices = MAX_VERTEX_BLENDS; caps->max_vertex_blend_matrix_index = 0; caps->vertex_processing_caps = WINED3DVTXPCAPS_TEXGEN | WINED3DVTXPCAPS_MATERIALSOURCE7 @@ -7808,27 +7843,26 @@ static void glsl_vertex_pipe_world(struct wined3d_context *context, context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MODELVIEW; } +static void glsl_vertex_pipe_vertexblend(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) +{ + context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_VERTEXBLEND; +} + static void glsl_vertex_pipe_view(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; unsigned int k; context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MODELVIEW - | WINED3D_SHADER_CONST_FFP_LIGHTS; + | WINED3D_SHADER_CONST_FFP_LIGHTS + | WINED3D_SHADER_CONST_FFP_VERTEXBLEND; for (k = 0; k < gl_info->limits.clipplanes; ++k) { if (!isStateDirty(context, STATE_CLIPPLANE(k))) clipplane(context, state, STATE_CLIPPLANE(k)); } - - if (context->swapchain->device->vertexBlendUsed) - { - static int warned; - - if (!warned++) - FIXME("Vertex blending emulation.\n"); - } } static void glsl_vertex_pipe_projection(struct wined3d_context *context, @@ -7946,6 +7980,9 @@ static const struct StateEntryTemplate glsl_vertex_pipe_vp_states[] = {STATE_TRANSFORM(WINED3D_TS_TEXTURE6), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TRANSFORM(WINED3D_TS_TEXTURE7), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)), glsl_vertex_pipe_world }, WINED3D_GL_EXT_NONE }, + {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(1)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(1)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, + {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(2)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(2)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, + {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(3)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(3)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, @@ -8032,7 +8069,7 @@ static const struct StateEntryTemplate glsl_vertex_pipe_vp_states[] = * instead of using the immediate mode fallback. * - Similarly, we don't need the fallback for certain combinations of * material sources anymore. - * - Implement vertex blending and vertex tweening. + * - Implement vertex tweening. * - Handle WINED3D_TSS_TEXCOORD_INDEX in the shader, instead of duplicating * attribute arrays in load_tex_coords(). * - Per-vertex point sizes. */ diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 1a95161..4751b37 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -3686,7 +3686,7 @@ static void transform_world(struct wined3d_context *context, const struct wined3 gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW); checkGLcall("glMatrixMode"); - get_modelview_matrix(context, state, &mat); + get_modelview_matrix(context, state, 0, &mat); gl_info->gl_ops.gl.p_glLoadMatrixf((GLfloat *)&mat); checkGLcall("glLoadMatrixf"); @@ -5757,7 +5757,7 @@ static void prune_invalid_states(struct StateEntry *state_table, const struct wi state_table[i].apply = state_undefined; } - start = STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(gl_info->limits.blends)); + start = STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(d3d_info->limits.ffp_vertex_blend_matrices)); last = STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(255)); for (i = start; i <= last; ++i) { diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index a9231a8..b035fd8 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -3247,6 +3247,9 @@ const char *debug_d3dtstype(enum wined3d_transform_state tstype) TSTYPE_TO_STR(WINED3D_TS_TEXTURE6); TSTYPE_TO_STR(WINED3D_TS_TEXTURE7); TSTYPE_TO_STR(WINED3D_TS_WORLD_MATRIX(0)); + TSTYPE_TO_STR(WINED3D_TS_WORLD_MATRIX(1)); + TSTYPE_TO_STR(WINED3D_TS_WORLD_MATRIX(2)); + TSTYPE_TO_STR(WINED3D_TS_WORLD_MATRIX(3)); #undef TSTYPE_TO_STR default: if (tstype > 256 && tstype < 512) @@ -3468,12 +3471,12 @@ void get_identity_matrix(struct wined3d_matrix *mat) *mat = identity; } -void get_modelview_matrix(const struct wined3d_context *context, const struct wined3d_state *state, struct wined3d_matrix *mat) +void get_modelview_matrix(const struct wined3d_context *context, const struct wined3d_state *state, int i, struct wined3d_matrix *mat) { if (context->last_was_rhw) get_identity_matrix(mat); else - multiply_matrix(mat, &state->transforms[WINED3D_TS_VIEW], &state->transforms[WINED3D_TS_WORLD_MATRIX(0)]); + multiply_matrix(mat, &state->transforms[WINED3D_TS_VIEW], &state->transforms[WINED3D_TS_WORLD_MATRIX(i)]); } void get_projection_matrix(const struct wined3d_context *context, const struct wined3d_state *state, @@ -4532,6 +4535,19 @@ void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct return; } + switch (state->render_states[WINED3D_RS_VERTEXBLEND]) + { + case WINED3D_VBF_DISABLE: + case WINED3D_VBF_1WEIGHTS: + case WINED3D_VBF_2WEIGHTS: + case WINED3D_VBF_3WEIGHTS: + settings->vertexblends = state->render_states[WINED3D_RS_VERTEXBLEND]; + break; + default: + FIXME("Unsupported vertex blending: %d\n", state->render_states[WINED3D_RS_VERTEXBLEND]); + break; + } + settings->transformed = 0; settings->clipping = state->render_states[WINED3D_RS_CLIPPING] && state->render_states[WINED3D_RS_CLIPPLANEENABLE]; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index c184b72..2772a85 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -179,6 +179,7 @@ void wined3d_rb_free(void *ptr) DECLSPEC_HIDDEN; #define MAX_CONSTANT_BUFFERS 15 #define MAX_SAMPLER_OBJECTS 16 #define MAX_SHADER_RESOURCE_VIEWS 128 +#define MAX_VERTEX_BLENDS 4 struct min_lookup { @@ -296,25 +297,26 @@ enum wined3d_shader_resource_type WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY, }; -#define WINED3D_SHADER_CONST_VS_F 0x00000001 -#define WINED3D_SHADER_CONST_VS_I 0x00000002 -#define WINED3D_SHADER_CONST_VS_B 0x00000004 -#define WINED3D_SHADER_CONST_VS_POINTSIZE 0x00000008 -#define WINED3D_SHADER_CONST_VS_POS_FIXUP 0x00000010 -#define WINED3D_SHADER_CONST_PS_F 0x00000020 -#define WINED3D_SHADER_CONST_PS_I 0x00000040 -#define WINED3D_SHADER_CONST_PS_B 0x00000080 -#define WINED3D_SHADER_CONST_PS_BUMP_ENV 0x00000100 -#define WINED3D_SHADER_CONST_PS_FOG 0x00000200 -#define WINED3D_SHADER_CONST_PS_Y_CORR 0x00000400 -#define WINED3D_SHADER_CONST_PS_NP2_FIXUP 0x00000800 -#define WINED3D_SHADER_CONST_FFP_MODELVIEW 0x00001000 -#define WINED3D_SHADER_CONST_FFP_PROJ 0x00002000 -#define WINED3D_SHADER_CONST_FFP_TEXMATRIX 0x00004000 -#define WINED3D_SHADER_CONST_FFP_MATERIAL 0x00008000 -#define WINED3D_SHADER_CONST_FFP_LIGHTS 0x00010000 -#define WINED3D_SHADER_CONST_FFP_PS 0x00020000 -#define WINED3D_SHADER_CONST_FFP_COLOR_KEY 0x00040000 +#define WINED3D_SHADER_CONST_VS_F 0x00000001 +#define WINED3D_SHADER_CONST_VS_I 0x00000002 +#define WINED3D_SHADER_CONST_VS_B 0x00000004 +#define WINED3D_SHADER_CONST_VS_POINTSIZE 0x00000008 +#define WINED3D_SHADER_CONST_VS_POS_FIXUP 0x00000010 +#define WINED3D_SHADER_CONST_PS_F 0x00000020 +#define WINED3D_SHADER_CONST_PS_I 0x00000040 +#define WINED3D_SHADER_CONST_PS_B 0x00000080 +#define WINED3D_SHADER_CONST_PS_BUMP_ENV 0x00000100 +#define WINED3D_SHADER_CONST_PS_FOG 0x00000200 +#define WINED3D_SHADER_CONST_PS_Y_CORR 0x00000400 +#define WINED3D_SHADER_CONST_PS_NP2_FIXUP 0x00000800 +#define WINED3D_SHADER_CONST_FFP_MODELVIEW 0x00001000 +#define WINED3D_SHADER_CONST_FFP_VERTEXBLEND 0x00002000 +#define WINED3D_SHADER_CONST_FFP_PROJ 0x00004000 +#define WINED3D_SHADER_CONST_FFP_TEXMATRIX 0x00008000 +#define WINED3D_SHADER_CONST_FFP_MATERIAL 0x00010000 +#define WINED3D_SHADER_CONST_FFP_LIGHTS 0x00020000 +#define WINED3D_SHADER_CONST_FFP_PS 0x00040000 +#define WINED3D_SHADER_CONST_FFP_COLOR_KEY 0x00080000 enum wined3d_shader_register_type { @@ -1743,6 +1745,7 @@ struct wined3d_d3d_limits DWORD ps_uniform_count; UINT ffp_textures; UINT ffp_blend_stages; + UINT ffp_vertex_blend_matrices; }; typedef void (WINE_GLAPI *wined3d_ffp_attrib_func)(const void *data); @@ -1888,6 +1891,7 @@ struct wined3d_ffp_vs_settings DWORD specular_source : 2; DWORD transformed : 1; + DWORD vertexblends : 2; DWORD clipping : 1; DWORD normal : 1; DWORD normalize : 1; @@ -1898,7 +1902,7 @@ struct wined3d_ffp_vs_settings DWORD fog_mode : 2; DWORD texcoords : 8; /* MAX_TEXTURES */ DWORD ortho_fog : 1; - DWORD padding : 13; + DWORD padding : 11; DWORD texgen[MAX_TEXTURES]; }; @@ -3071,7 +3075,7 @@ static inline BOOL shader_constant_is_local(const struct wined3d_shader *shader, void get_identity_matrix(struct wined3d_matrix *mat) DECLSPEC_HIDDEN; void get_modelview_matrix(const struct wined3d_context *context, const struct wined3d_state *state, - struct wined3d_matrix *mat) DECLSPEC_HIDDEN; + int i, struct wined3d_matrix *mat) DECLSPEC_HIDDEN; void get_projection_matrix(const struct wined3d_context *context, const struct wined3d_state *state, struct wined3d_matrix *mat) DECLSPEC_HIDDEN; void get_texture_matrix(const struct wined3d_context *context, const struct wined3d_state *state, -- 2.3.6