diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 0e4178355e2..ac03105f379 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -1943,10 +1943,10 @@ static void arbfp_add_sRGB_correction(SHADER_BUFFER *buffer, const char *fragcol shader_addline(buffer, "CMP result.color.xyz, %s, %s, %s;\n", tmp3, tmp2, tmp1); } -static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, +/* GL locking is done by the caller */ +static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This, SHADER_BUFFER *buffer, const struct ps_compile_args *args) { - IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface; const shader_reg_maps* reg_maps = &This->baseShader.reg_maps; CONST DWORD *function = This->baseShader.function; const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info; @@ -2057,10 +2057,9 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, } /* GL locking is done by the caller */ -static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface, +static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This, SHADER_BUFFER *buffer, const struct vs_compile_args *args) { - IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface; const shader_reg_maps *reg_maps = &This->baseShader.reg_maps; CONST DWORD *function = This->baseShader.function; IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)This->baseShader.device; @@ -2086,7 +2085,7 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface, if(need_helper_const(gl_info)) { shader_addline(buffer, "PARAM helper_const = { 2.0, -1.0, %d.0, 0.0 };\n", This->rel_offset); } - if(need_mova_const((IWineD3DBaseShader *) iface, gl_info)) { + if(need_mova_const((IWineD3DBaseShader *) This, gl_info)) { shader_addline(buffer, "PARAM mova_const = { 0.5, 0.0, 2.0, 1.0 };\n"); shader_addline(buffer, "TEMP A0_SHADOW;\n"); } @@ -2245,12 +2244,68 @@ static GLuint find_arb_pshader(IWineD3DPixelShaderImpl *shader, const struct ps_ shader_buffer_init(&buffer); shader->gl_shaders[shader->num_gl_shaders].prgId = - shader_arb_generate_pshader((IWineD3DPixelShader *)shader, &buffer, args); + shader_arb_generate_pshader(shader, &buffer, args); shader_buffer_free(&buffer); return shader->gl_shaders[shader->num_gl_shaders++].prgId; } +static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const struct vs_compile_args *new, + const DWORD use_map) { + if((stored->swizzle_map & use_map) != new->swizzle_map) return FALSE; + return stored->fog_src == new->fog_src; +} + +static GLuint find_arb_vshader(IWineD3DVertexShaderImpl *shader, const struct vs_compile_args *args) +{ + UINT i; + DWORD new_size = shader->shader_array_size; + struct vs_compiled_shader *new_array; + DWORD use_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.use_map; + SHADER_BUFFER buffer; + GLuint ret; + + /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2), + * so a linear search is more performant than a hashmap or a binary search + * (cache coherency etc) + */ + for(i = 0; i < shader->num_gl_shaders; i++) { + if(vs_args_equal(&shader->gl_shaders[i].args, args, use_map)) { + return shader->gl_shaders[i].prgId; + } + } + + TRACE("No matching GL shader found, compiling a new shader\n"); + + if(shader->shader_array_size == shader->num_gl_shaders) { + if (shader->num_gl_shaders) + { + new_size = shader->shader_array_size + max(1, shader->shader_array_size / 2); + new_array = HeapReAlloc(GetProcessHeap(), 0, shader->gl_shaders, + new_size * sizeof(*shader->gl_shaders)); + } else { + new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader->gl_shaders)); + new_size = 1; + } + + if(!new_array) { + ERR("Out of memory\n"); + return 0; + } + shader->gl_shaders = new_array; + shader->shader_array_size = new_size; + } + + shader->gl_shaders[shader->num_gl_shaders].args = *args; + + shader_buffer_init(&buffer); + ret = shader_arb_generate_vshader(shader, &buffer, args); + shader_buffer_free(&buffer); + shader->gl_shaders[shader->num_gl_shaders++].prgId = ret; + + return ret; +} + /* GL locking is done by the caller */ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; @@ -2262,7 +2317,7 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { TRACE("Using vertex shader\n"); find_vs_compile_args((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, This->stateBlock, &compile_args); - priv->current_vprogram_id = find_gl_vshader((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, &compile_args); + priv->current_vprogram_id = find_arb_vshader((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, &compile_args); /* Bind the vertex program */ GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id)); @@ -2589,7 +2644,6 @@ const shader_backend_t arb_program_shader_backend = { shader_arb_alloc, shader_arb_free, shader_arb_dirty_const, - shader_arb_generate_vshader, shader_arb_get_caps, shader_arb_color_fixup_supported, shader_arb_add_instruction_modifiers, diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index d62c91c49bc..0380c33aa54 100644 --- a/dlls/wined3d/baseshader.c +++ b/dlls/wined3d/baseshader.c @@ -1283,12 +1283,6 @@ static void shader_none_destroy(IWineD3DBaseShader *iface) {} static HRESULT shader_none_alloc(IWineD3DDevice *iface) {return WINED3D_OK;} static void shader_none_free(IWineD3DDevice *iface) {} static BOOL shader_none_dirty_const(IWineD3DDevice *iface) {return FALSE;} -static GLuint shader_none_generate_vshader(IWineD3DVertexShader *iface, - SHADER_BUFFER *buffer, const struct vs_compile_args *args) -{ - FIXME("NONE shader backend asked to generate a vertex shader\n"); - return 0; -} static void shader_none_add_instruction_modifiers(const struct wined3d_shader_instruction *ins) {} #define GLINFO_LOCATION (*gl_info) @@ -1332,7 +1326,6 @@ const shader_backend_t none_shader_backend = { shader_none_alloc, shader_none_free, shader_none_dirty_const, - shader_none_generate_vshader, shader_none_get_caps, shader_none_color_fixup_supported, shader_none_add_instruction_modifiers, diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 50df195e231..65c71de09f5 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -3609,10 +3609,9 @@ static void hardcode_local_constants(IWineD3DBaseShaderImpl *shader, const WineD } /* GL locking is done by the caller */ -static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface, +static GLuint shader_glsl_generate_pshader(IWineD3DPixelShaderImpl *This, SHADER_BUFFER *buffer, const struct ps_compile_args *args) { - IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface; const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps; CONST DWORD *function = This->baseShader.function; const char *fragcolor; @@ -3646,7 +3645,7 @@ static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface, /* Pack 3.0 inputs */ if (reg_maps->shader_version.major >= 3 && args->vp_mode != vertexshader) { - pshader_glsl_input_pack(iface, buffer, This->input_signature, reg_maps, args->vp_mode); + pshader_glsl_input_pack((IWineD3DPixelShader *) This, buffer, This->input_signature, reg_maps, args->vp_mode); } /* Base Shader Body */ @@ -3720,11 +3719,9 @@ static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface, } /* GL locking is done by the caller */ -/* GL locking is done by the caller */ -static GLuint shader_glsl_generate_vshader(IWineD3DVertexShader *iface, +static GLuint shader_glsl_generate_vshader(IWineD3DVertexShaderImpl *This, SHADER_BUFFER *buffer, const struct vs_compile_args *args) { - IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface; const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps; CONST DWORD *function = This->baseShader.function; const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info; @@ -3831,12 +3828,68 @@ static GLhandleARB find_glsl_pshader(IWineD3DPixelShaderImpl *shader, const stru ((IWineD3DDeviceImpl *)shader->baseShader.device)->stateBlock->textures); shader_buffer_init(&buffer); shader->gl_shaders[shader->num_gl_shaders].prgId = - shader_glsl_generate_pshader((IWineD3DPixelShader*) shader, &buffer, args); + shader_glsl_generate_pshader(shader, &buffer, args); shader_buffer_free(&buffer); return shader->gl_shaders[shader->num_gl_shaders++].prgId; } +static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const struct vs_compile_args *new, + const DWORD use_map) { + if((stored->swizzle_map & use_map) != new->swizzle_map) return FALSE; + return stored->fog_src == new->fog_src; +} + +static GLhandleARB find_glsl_vshader(IWineD3DVertexShaderImpl *shader, const struct vs_compile_args *args) +{ + UINT i; + DWORD new_size = shader->shader_array_size; + struct vs_compiled_shader *new_array; + DWORD use_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.use_map; + SHADER_BUFFER buffer; + GLhandleARB ret; + + /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2), + * so a linear search is more performant than a hashmap or a binary search + * (cache coherency etc) + */ + for(i = 0; i < shader->num_gl_shaders; i++) { + if(vs_args_equal(&shader->gl_shaders[i].args, args, use_map)) { + return shader->gl_shaders[i].prgId; + } + } + + TRACE("No matching GL shader found, compiling a new shader\n"); + + if(shader->shader_array_size == shader->num_gl_shaders) { + if (shader->num_gl_shaders) + { + new_size = shader->shader_array_size + max(1, shader->shader_array_size / 2); + new_array = HeapReAlloc(GetProcessHeap(), 0, shader->gl_shaders, + new_size * sizeof(*shader->gl_shaders)); + } else { + new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader->gl_shaders)); + new_size = 1; + } + + if(!new_array) { + ERR("Out of memory\n"); + return 0; + } + shader->gl_shaders = new_array; + shader->shader_array_size = new_size; + } + + shader->gl_shaders[shader->num_gl_shaders].args = *args; + + shader_buffer_init(&buffer); + ret = shader_glsl_generate_vshader(shader, &buffer, args); + shader_buffer_free(&buffer); + shader->gl_shaders[shader->num_gl_shaders++].prgId = ret; + + return ret; +} + /** Sets the GLSL program ID for the given pixel and vertex shader combination. * It sets the programId on the current StateBlock (because it should be called * inside of the DrawPrimitive() part of the render loop). @@ -3899,7 +3952,7 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use priv->glsl_program = entry; if(use_vs) { - vshader_id = find_gl_vshader((IWineD3DVertexShaderImpl *) vshader, &vs_compile_args); + vshader_id = find_glsl_vshader((IWineD3DVertexShaderImpl *) vshader, &vs_compile_args); } else { vshader_id = 0; } @@ -4562,7 +4615,6 @@ const shader_backend_t glsl_shader_backend = { shader_glsl_alloc, shader_glsl_free, shader_glsl_dirty_const, - shader_glsl_generate_vshader, shader_glsl_get_caps, shader_glsl_color_fixup_supported, shader_glsl_add_instruction_modifiers, diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c index 9ae52f9e283..6c1440d4c25 100644 --- a/dlls/wined3d/vertexshader.c +++ b/dlls/wined3d/vertexshader.c @@ -332,21 +332,6 @@ static HRESULT WINAPI IWIneD3DVertexShaderImpl_SetLocalConstantsF(IWineD3DVertex return WINED3D_OK; } -/* GL locking is done by the caller */ -static GLuint vertexshader_compile(IWineD3DVertexShaderImpl *This, const struct vs_compile_args *args) { - IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device; - SHADER_BUFFER buffer; - GLuint ret; - - /* Generate the HW shader */ - TRACE("(%p) : Generating hardware program\n", This); - shader_buffer_init(&buffer); - ret = deviceImpl->shader_backend->shader_generate_vshader((IWineD3DVertexShader *)This, &buffer, args); - shader_buffer_free(&buffer); - - return ret; -} - const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl = { /*** IUnknown methods ***/ @@ -367,53 +352,3 @@ void find_vs_compile_args(IWineD3DVertexShaderImpl *shader, IWineD3DStateBlockIm args->fog_src = stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ? VS_FOG_COORD : VS_FOG_Z; args->swizzle_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.swizzle_map; } - -static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const struct vs_compile_args *new, - const DWORD use_map) { - if((stored->swizzle_map & use_map) != new->swizzle_map) return FALSE; - return stored->fog_src == new->fog_src; -} - -/* GL locking is done by the caller */ -GLuint find_gl_vshader(IWineD3DVertexShaderImpl *shader, const struct vs_compile_args *args) -{ - UINT i; - DWORD new_size = shader->shader_array_size; - struct vs_compiled_shader *new_array; - DWORD use_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.use_map; - - /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2), - * so a linear search is more performant than a hashmap or a binary search - * (cache coherency etc) - */ - for(i = 0; i < shader->num_gl_shaders; i++) { - if(vs_args_equal(&shader->gl_shaders[i].args, args, use_map)) { - return shader->gl_shaders[i].prgId; - } - } - - TRACE("No matching GL shader found, compiling a new shader\n"); - - if(shader->shader_array_size == shader->num_gl_shaders) { - if (shader->num_gl_shaders) - { - new_size = shader->shader_array_size + max(1, shader->shader_array_size / 2); - new_array = HeapReAlloc(GetProcessHeap(), 0, shader->gl_shaders, - new_size * sizeof(*shader->gl_shaders)); - } else { - new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader->gl_shaders)); - new_size = 1; - } - - if(!new_array) { - ERR("Out of memory\n"); - return 0; - } - shader->gl_shaders = new_array; - shader->shader_array_size = new_size; - } - - shader->gl_shaders[shader->num_gl_shaders].args = *args; - shader->gl_shaders[shader->num_gl_shaders].prgId = vertexshader_compile(shader, args); - return shader->gl_shaders[shader->num_gl_shaders++].prgId; -} diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index cf9a6ca4fb8..ec18a06f68a 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -809,8 +809,6 @@ typedef struct { HRESULT (*shader_alloc_private)(IWineD3DDevice *iface); void (*shader_free_private)(IWineD3DDevice *iface); BOOL (*shader_dirtifyable_constants)(IWineD3DDevice *iface); - GLuint (*shader_generate_vshader)(IWineD3DVertexShader *iface, - SHADER_BUFFER *buffer, const struct vs_compile_args *args); void (*shader_get_caps)(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct shader_caps *caps); BOOL (*shader_color_fixup_supported)(struct color_fixup_desc fixup); void (*shader_add_instruction_modifiers)(const struct wined3d_shader_instruction *ins); @@ -2689,7 +2687,6 @@ typedef struct IWineD3DVertexShaderImpl { extern const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl; void find_vs_compile_args(IWineD3DVertexShaderImpl *shader, IWineD3DStateBlockImpl *stateblock, struct vs_compile_args *args); -GLuint find_gl_vshader(IWineD3DVertexShaderImpl *shader, const struct vs_compile_args *args); /***************************************************************************** * IDirect3DPixelShader implementation structure