[PATCH] WineD3D: Put vertex shader duplication infrastructure =
Stefan Doesinger
stefan at codeweavers.com
Mon Jan 19 12:15:37 CST 2009
in place=0A=
=0A=
It works the same way as the code we already have for pixel shaders=0A=
---=0A=
dlls/wined3d/arb_program_shader.c | 54 +++++++++++--------=0A=
dlls/wined3d/baseshader.c | 3 +-=0A=
dlls/wined3d/glsl_shader.c | 70 ++++++++++++++++---------=0A=
dlls/wined3d/vertexshader.c | 106 =
+++++++++++++++++++++---------------=0A=
dlls/wined3d/wined3d_private.h | 34 +++++++++---=0A=
5 files changed, 167 insertions(+), 100 deletions(-)=0A=
=0A=
diff --git a/dlls/wined3d/arb_program_shader.c =
b/dlls/wined3d/arb_program_shader.c=0A=
index cf434a6..bd70442 100644=0A=
--- a/dlls/wined3d/arb_program_shader.c=0A=
+++ b/dlls/wined3d/arb_program_shader.c=0A=
@@ -510,7 +510,7 @@ static void vshader_program_add_param(const =
SHADER_OPCODE_ARG *arg, const DWORD=0A=
break;=0A=
case WINED3DSPR_INPUT:=0A=
=0A=
- if (This->swizzle_map & (1 << reg)) is_color =3D TRUE;=0A=
+ if (This->cur_args->swizzle_map & (1 << reg)) is_color =3D TRUE;=0A=
=0A=
sprintf(tmpReg, "vertex.attrib[%u]", reg);=0A=
strcat(hwLine, tmpReg);=0A=
@@ -1745,14 +1745,15 @@ static void shader_arb_select(IWineD3DDevice =
*iface, BOOL usePS, BOOL useVS) {=0A=
const WineD3D_GL_Info *gl_info =3D &This->adapter->gl_info;=0A=
=0A=
if (useVS) {=0A=
- TRACE("Using vertex shader\n");=0A=
- =
IWineD3DVertexShaderImpl_CompileShader(This->stateBlock->vertexShader);=0A=
+ struct vs_compile_args compile_args;=0A=
=0A=
- priv->current_vprogram_id =3D ((IWineD3DVertexShaderImpl =
*)This->stateBlock->vertexShader)->prgId;=0A=
+ TRACE("Using vertex shader\n");=0A=
+ find_vs_compile_args((IWineD3DVertexShaderImpl *) =
This->stateBlock->vertexShader, This->stateBlock, &compile_args);=0A=
+ priv->current_vprogram_id =3D =
find_gl_vshader((IWineD3DVertexShaderImpl *) =
This->stateBlock->vertexShader, &compile_args);=0A=
=0A=
/* Bind the vertex program */=0A=
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, =
priv->current_vprogram_id));=0A=
- checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, =
vertexShader->prgId);");=0A=
+ checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, =
priv->current_vprogram_id);");=0A=
=0A=
/* Enable OpenGL vertex programs */=0A=
glEnable(GL_VERTEX_PROGRAM_ARB);=0A=
@@ -1773,7 +1774,7 @@ static void shader_arb_select(IWineD3DDevice =
*iface, BOOL usePS, BOOL useVS) {=0A=
=0A=
/* Bind the fragment program */=0A=
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, =
priv->current_fprogram_id));=0A=
- checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, =
pixelShader->prgId);");=0A=
+ checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, =
priv->current_fprogram_id);");=0A=
=0A=
if(!priv->use_arbfp_fixed_func) {=0A=
/* Enable OpenGL fragment programs */=0A=
@@ -1860,14 +1861,19 @@ static void =
shader_arb_destroy(IWineD3DBaseShader *iface) {=0A=
This->shader_array_size =3D 0;=0A=
} else {=0A=
IWineD3DVertexShaderImpl *This =3D (IWineD3DVertexShaderImpl *) =
iface;=0A=
+ UINT i;=0A=
=0A=
ENTER_GL();=0A=
- GL_EXTCALL(glDeleteProgramsARB(1, &This->prgId));=0A=
- checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &This->prgId))");=0A=
- ((IWineD3DVertexShaderImpl *) This)->prgId =3D 0;=0A=
+ for(i =3D 0; i < This->num_gl_shaders; i++) {=0A=
+ GL_EXTCALL(glDeleteProgramsARB(1, =
&This->gl_shaders[i].prgId));=0A=
+ checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, =
&This->gl_shaders[i].prgId))");=0A=
+ }=0A=
LEAVE_GL();=0A=
+ HeapFree(GetProcessHeap(), 0, This->gl_shaders);=0A=
+ This->gl_shaders =3D NULL;=0A=
+ This->num_gl_shaders =3D 0;=0A=
+ This->shader_array_size =3D 0;=0A=
}=0A=
- baseShader->baseShader.is_compiled =3D FALSE;=0A=
}=0A=
=0A=
static HRESULT shader_arb_alloc(IWineD3DDevice *iface) {=0A=
@@ -2008,13 +2014,14 @@ static GLuint =
shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUF=0A=
return retval;=0A=
}=0A=
=0A=
-static void shader_arb_generate_vshader(IWineD3DVertexShader *iface, =
SHADER_BUFFER *buffer) {=0A=
+static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface, =
SHADER_BUFFER *buffer, const struct vs_compile_args *args) {=0A=
IWineD3DVertexShaderImpl *This =3D (IWineD3DVertexShaderImpl =
*)iface;=0A=
const shader_reg_maps *reg_maps =3D &This->baseShader.reg_maps;=0A=
CONST DWORD *function =3D This->baseShader.function;=0A=
IWineD3DDeviceImpl *device =3D (IWineD3DDeviceImpl =
*)This->baseShader.device;=0A=
const WineD3D_GL_Info *gl_info =3D &device->adapter->gl_info;=0A=
const local_constant *lconst;=0A=
+ GLuint ret;=0A=
=0A=
/* Create the hw ARB shader */=0A=
shader_addline(buffer, "!!ARBvp1.0\n");=0A=
@@ -2086,12 +2093,12 @@ static void =
shader_arb_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUFF=0A=
shader_addline(buffer, "END\n");=0A=
=0A=
/* TODO: change to resource.glObjectHandle or something like that */=0A=
- GL_EXTCALL(glGenProgramsARB(1, &This->prgId));=0A=
+ GL_EXTCALL(glGenProgramsARB(1, &ret));=0A=
=0A=
- TRACE("Creating a hw vertex shader, prg=3D%d\n", This->prgId);=0A=
- GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->prgId));=0A=
+ TRACE("Creating a hw vertex shader, prg=3D%d\n", ret);=0A=
+ GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, ret));=0A=
=0A=
- TRACE("Created hw vertex shader, prg=3D%d\n", This->prgId);=0A=
+ TRACE("Created hw vertex shader, prg=3D%d\n", ret);=0A=
/* Create the program and check for errors */=0A=
GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, =
GL_PROGRAM_FORMAT_ASCII_ARB,=0A=
buffer->bsize, buffer->buffer));=0A=
@@ -2101,16 +2108,17 @@ static void =
shader_arb_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUFF=0A=
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);=0A=
FIXME("HW VertexShader Error at position %d: %s\n",=0A=
errPos, debugstr_a((const char =
*)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));=0A=
- This->prgId =3D -1;=0A=
- }=0A=
-=0A=
- /* Load immediate constants */=0A=
- if(!This->baseShader.load_local_constsF) {=0A=
- LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, =
local_constant, entry) {=0A=
- const float *value =3D (const float *)lconst->value;=0A=
- =
GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, =
lconst->idx, value));=0A=
+ ret =3D -1;=0A=
+ } else {=0A=
+ /* Load immediate constants */=0A=
+ if(!This->baseShader.load_local_constsF) {=0A=
+ LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, =
local_constant, entry) {=0A=
+ const float *value =3D (const float *)lconst->value;=0A=
+ =
GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, =
lconst->idx, value));=0A=
+ }=0A=
}=0A=
}=0A=
+ return ret;=0A=
}=0A=
=0A=
static void shader_arb_get_caps(WINED3DDEVTYPE devtype, const =
WineD3D_GL_Info *gl_info, struct shader_caps *pCaps)=0A=
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c=0A=
index a270b0c..ecbf23e 100644=0A=
--- a/dlls/wined3d/baseshader.c=0A=
+++ b/dlls/wined3d/baseshader.c=0A=
@@ -1135,8 +1135,9 @@ static GLuint =
shader_none_generate_pshader(IWineD3DPixelShader *iface, SHADER_BU=0A=
FIXME("NONE shader backend asked to generate a pixel shader\n");=0A=
return 0;=0A=
}=0A=
-static void shader_none_generate_vshader(IWineD3DVertexShader *iface, =
SHADER_BUFFER *buffer) {=0A=
+static GLuint shader_none_generate_vshader(IWineD3DVertexShader *iface, =
SHADER_BUFFER *buffer, const struct vs_compile_args *args) {=0A=
FIXME("NONE shader backend asked to generate a vertex shader\n");=0A=
+ return 0;=0A=
}=0A=
=0A=
#define GLINFO_LOCATION (*gl_info)=0A=
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c=0A=
index 601d6f6..f0cba39 100644=0A=
--- a/dlls/wined3d/glsl_shader.c=0A=
+++ b/dlls/wined3d/glsl_shader.c=0A=
@@ -101,16 +101,18 @@ struct glsl_shader_prog_link {=0A=
GLhandleARB luminanceoffset_location[MAX_TEXTURES];=0A=
GLhandleARB ycorrection_location;=0A=
GLenum vertex_color_clamp;=0A=
- GLhandleARB vshader;=0A=
+ IWineD3DVertexShader *vshader;=0A=
IWineD3DPixelShader *pshader;=0A=
+ struct vs_compile_args vs_args;=0A=
struct ps_compile_args ps_args;=0A=
UINT constant_version;=0A=
};=0A=
=0A=
typedef struct {=0A=
- GLhandleARB vshader;=0A=
+ IWineD3DVertexShader *vshader;=0A=
IWineD3DPixelShader *pshader;=0A=
struct ps_compile_args ps_args;=0A=
+ struct vs_compile_args vs_args;=0A=
} glsl_program_key_t;=0A=
=0A=
=0A=
@@ -1030,7 +1032,7 @@ static void shader_glsl_get_register_name(const =
DWORD param, const DWORD addr_to=0A=
strcpy(tmpStr, "gl_SecondaryColor");=0A=
}=0A=
} else {=0A=
- if (((IWineD3DVertexShaderImpl *)This)->swizzle_map & (1 << =
reg)) *is_color =3D TRUE;=0A=
+ if (((IWineD3DVertexShaderImpl =
*)This)->cur_args->swizzle_map & (1 << reg)) *is_color =3D TRUE;=0A=
sprintf(tmpStr, "attrib%u", reg);=0A=
} =0A=
break;=0A=
@@ -2918,17 +2920,20 @@ static void add_glsl_program_entry(struct =
shader_glsl_priv *priv, struct glsl_sh=0A=
key =3D HeapAlloc(GetProcessHeap(), 0, sizeof(glsl_program_key_t));=0A=
key->vshader =3D entry->vshader;=0A=
key->pshader =3D entry->pshader;=0A=
+ key->vs_args =3D entry->vs_args;=0A=
key->ps_args =3D entry->ps_args;=0A=
=0A=
hash_table_put(priv->glsl_program_lookup, key, entry);=0A=
}=0A=
=0A=
static struct glsl_shader_prog_link *get_glsl_program_entry(struct =
shader_glsl_priv *priv,=0A=
- GLhandleARB vshader, IWineD3DPixelShader *pshader, struct =
ps_compile_args *ps_args) {=0A=
+ IWineD3DVertexShader *vshader, IWineD3DPixelShader *pshader, =
struct vs_compile_args *vs_args,=0A=
+ struct ps_compile_args *ps_args) {=0A=
glsl_program_key_t key;=0A=
=0A=
key.vshader =3D vshader;=0A=
key.pshader =3D pshader;=0A=
+ key.vs_args =3D *vs_args;=0A=
key.ps_args =3D *ps_args;=0A=
=0A=
return (struct glsl_shader_prog_link =
*)hash_table_get(priv->glsl_program_lookup, &key);=0A=
@@ -2942,6 +2947,7 @@ static void delete_glsl_program_entry(struct =
shader_glsl_priv *priv, const WineD=0A=
key =3D HeapAlloc(GetProcessHeap(), 0, sizeof(glsl_program_key_t));=0A=
key->vshader =3D entry->vshader;=0A=
key->pshader =3D entry->pshader;=0A=
+ key->vs_args =3D entry->vs_args;=0A=
key->ps_args =3D entry->ps_args;=0A=
hash_table_remove(priv->glsl_program_lookup, key);=0A=
=0A=
@@ -3293,21 +3299,22 @@ static void =
set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use=0A=
int i;=0A=
char glsl_name[8];=0A=
GLhandleARB vshader_id, pshader_id;=0A=
- struct ps_compile_args compile_args;=0A=
+ struct ps_compile_args ps_compile_args;=0A=
+ struct vs_compile_args vs_compile_args;=0A=
=0A=
if(use_vs) {=0A=
- IWineD3DVertexShaderImpl_CompileShader(vshader);=0A=
- vshader_id =3D ((IWineD3DVertexShaderImpl*)vshader)->prgId;=0A=
+ =
find_vs_compile_args((IWineD3DVertexShaderImpl*)This->stateBlock->vertexS=
hader, This->stateBlock, &vs_compile_args);=0A=
} else {=0A=
- vshader_id =3D 0;=0A=
+ /* FIXME: Do we really have to spend CPU cycles to generate a =
few zeroed bytes? */=0A=
+ memset(&vs_compile_args, 0, sizeof(vs_compile_args));=0A=
}=0A=
if(use_ps) {=0A=
- =
find_ps_compile_args((IWineD3DPixelShaderImpl*)This->stateBlock->pixelSha=
der, This->stateBlock, &compile_args);=0A=
+ =
find_ps_compile_args((IWineD3DPixelShaderImpl*)This->stateBlock->pixelSha=
der, This->stateBlock, &ps_compile_args);=0A=
} else {=0A=
/* FIXME: Do we really have to spend CPU cycles to generate a =
few zeroed bytes? */=0A=
- memset(&compile_args, 0, sizeof(compile_args));=0A=
+ memset(&ps_compile_args, 0, sizeof(ps_compile_args));=0A=
}=0A=
- entry =3D get_glsl_program_entry(priv, vshader_id, pshader, =
&compile_args);=0A=
+ entry =3D get_glsl_program_entry(priv, vshader, pshader, =
&vs_compile_args, &ps_compile_args);=0A=
if (entry) {=0A=
priv->glsl_program =3D entry;=0A=
return;=0A=
@@ -3320,9 +3327,10 @@ static void =
set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use=0A=
/* Create the entry */=0A=
entry =3D HeapAlloc(GetProcessHeap(), 0, sizeof(struct =
glsl_shader_prog_link));=0A=
entry->programId =3D programId;=0A=
- entry->vshader =3D vshader_id;=0A=
+ entry->vshader =3D vshader;=0A=
entry->pshader =3D pshader;=0A=
- entry->ps_args =3D compile_args;=0A=
+ entry->vs_args =3D vs_compile_args;=0A=
+ entry->ps_args =3D ps_compile_args;=0A=
entry->constant_version =3D 0;=0A=
/* Add the hash table entry */=0A=
add_glsl_program_entry(priv, entry);=0A=
@@ -3330,6 +3338,12 @@ static void =
set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use=0A=
/* Set the current program */=0A=
priv->glsl_program =3D entry;=0A=
=0A=
+ if(use_vs) {=0A=
+ vshader_id =3D find_gl_vshader((IWineD3DVertexShaderImpl *) =
vshader, &vs_compile_args);=0A=
+ } else {=0A=
+ vshader_id =3D 0;=0A=
+ }=0A=
+=0A=
/* Attach GLSL vshader */=0A=
if (vshader_id) {=0A=
int max_attribs =3D 16; /* TODO: Will this always be the =
case? It is at the moment... */=0A=
@@ -3369,7 +3383,7 @@ static void set_glsl_shader_program(IWineD3DDevice =
*iface, BOOL use_ps, BOOL use=0A=
}=0A=
=0A=
if(use_ps) {=0A=
- pshader_id =3D find_gl_pshader((IWineD3DPixelShaderImpl *) =
pshader, &compile_args);=0A=
+ pshader_id =3D find_gl_pshader((IWineD3DPixelShaderImpl *) =
pshader, &ps_compile_args);=0A=
} else {=0A=
pshader_id =3D 0;=0A=
}=0A=
@@ -3619,7 +3633,7 @@ static void shader_glsl_destroy(IWineD3DBaseShader =
*iface) {=0A=
if(ps->num_gl_shaders =3D=3D 0) return;=0A=
} else {=0A=
vs =3D (IWineD3DVertexShaderImpl *) This;=0A=
- if(vs->prgId =3D=3D 0) return;=0A=
+ if(vs->num_gl_shaders =3D=3D 0) return;=0A=
}=0A=
=0A=
linked_programs =3D &This->baseShader.linked_programs;=0A=
@@ -3654,13 +3668,19 @@ static void =
shader_glsl_destroy(IWineD3DBaseShader *iface) {=0A=
ps->num_gl_shaders =3D 0;=0A=
ps->shader_array_size =3D 0;=0A=
} else {=0A=
- TRACE("Deleting shader object %u\n", vs->prgId);=0A=
+ UINT i;=0A=
+=0A=
ENTER_GL();=0A=
- GL_EXTCALL(glDeleteObjectARB(vs->prgId));=0A=
- checkGLcall("glDeleteObjectARB");=0A=
+ for(i =3D 0; i < vs->num_gl_shaders; i++) {=0A=
+ TRACE("deleting vshader %u\n", vs->gl_shaders[i].prgId);=0A=
+ GL_EXTCALL(glDeleteObjectARB(vs->gl_shaders[i].prgId));=0A=
+ checkGLcall("glDeleteObjectARB");=0A=
+ }=0A=
LEAVE_GL();=0A=
- vs->prgId =3D 0;=0A=
- vs->baseShader.is_compiled =3D FALSE;=0A=
+ HeapFree(GetProcessHeap(), 0, vs->gl_shaders);=0A=
+ vs->gl_shaders =3D NULL;=0A=
+ vs->num_gl_shaders =3D 0;=0A=
+ vs->shader_array_size =3D 0;=0A=
}=0A=
}=0A=
=0A=
@@ -3668,7 +3688,7 @@ static unsigned int glsl_program_key_hash(const =
void *key)=0A=
{=0A=
const glsl_program_key_t *k =3D (const glsl_program_key_t *)key;=0A=
=0A=
- unsigned int hash =3D k->vshader | ((DWORD_PTR) k->pshader) << 16;=0A=
+ unsigned int hash =3D ((DWORD_PTR) k->vshader) | ((DWORD_PTR) =
k->pshader) << 16;=0A=
hash +=3D ~(hash << 15);=0A=
hash ^=3D (hash >> 10);=0A=
hash +=3D (hash << 3);=0A=
@@ -3685,7 +3705,8 @@ static BOOL glsl_program_key_compare(const void =
*keya, const void *keyb)=0A=
const glsl_program_key_t *kb =3D (const glsl_program_key_t *)keyb;=0A=
=0A=
return ka->vshader =3D=3D kb->vshader && ka->pshader =3D=3D =
kb->pshader &&=0A=
- (memcmp(&ka->ps_args, &kb->ps_args, sizeof(kb->ps_args)) =
=3D=3D 0);=0A=
+ (memcmp(&ka->ps_args, &kb->ps_args, sizeof(kb->ps_args)) =
=3D=3D 0) &&=0A=
+ (memcmp(&ka->vs_args, &kb->vs_args, sizeof(kb->vs_args)) =
=3D=3D 0);=0A=
}=0A=
=0A=
static BOOL constant_heap_init(struct constant_heap *heap, unsigned int =
constant_count)=0A=
@@ -3870,7 +3891,7 @@ static GLuint =
shader_glsl_generate_pshader(IWineD3DPixelShader *iface, SHADER_BU=0A=
return shader_obj;=0A=
}=0A=
=0A=
-static void shader_glsl_generate_vshader(IWineD3DVertexShader *iface, =
SHADER_BUFFER *buffer) {=0A=
+static GLuint shader_glsl_generate_vshader(IWineD3DVertexShader *iface, =
SHADER_BUFFER *buffer, const struct vs_compile_args *args) {=0A=
IWineD3DVertexShaderImpl *This =3D (IWineD3DVertexShaderImpl =
*)iface;=0A=
const struct shader_reg_maps *reg_maps =3D =
&This->baseShader.reg_maps;=0A=
CONST DWORD *function =3D This->baseShader.function;=0A=
@@ -3920,8 +3941,7 @@ static void =
shader_glsl_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUF=0A=
GL_EXTCALL(glCompileShaderARB(shader_obj));=0A=
print_glsl_info_log(&GLINFO_LOCATION, shader_obj);=0A=
=0A=
- /* Store the shader object */=0A=
- This->prgId =3D shader_obj;=0A=
+ return shader_obj;=0A=
}=0A=
=0A=
static void shader_glsl_get_caps(WINED3DDEVTYPE devtype, const =
WineD3D_GL_Info *gl_info, struct shader_caps *pCaps)=0A=
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c=0A=
index 339d955..3667e86 100644=0A=
--- a/dlls/wined3d/vertexshader.c=0A=
+++ b/dlls/wined3d/vertexshader.c=0A=
@@ -218,21 +218,6 @@ BOOL vshader_get_input(=0A=
return FALSE;=0A=
}=0A=
=0A=
-/** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB=0A=
- or GLSL and send it to the card */=0A=
-static void =
IWineD3DVertexShaderImpl_GenerateShader(IWineD3DVertexShader *iface,=0A=
- const struct shader_reg_maps* reg_maps, const DWORD *pFunction)=0A=
-{=0A=
- IWineD3DVertexShaderImpl *This =3D (IWineD3DVertexShaderImpl =
*)iface;=0A=
- SHADER_BUFFER buffer;=0A=
-=0A=
- This->swizzle_map =3D ((IWineD3DDeviceImpl =
*)This->baseShader.device)->strided_streams.swizzle_map;=0A=
-=0A=
- shader_buffer_init(&buffer);=0A=
- ((IWineD3DDeviceImpl =
*)This->baseShader.device)->shader_backend->shader_generate_vshader(iface=
, &buffer);=0A=
- shader_buffer_free(&buffer);=0A=
-}=0A=
-=0A=
/* *******************************************=0A=
IWineD3DVertexShader IUnknown parts follow=0A=
******************************************* */=0A=
@@ -418,40 +403,20 @@ static HRESULT WINAPI =
IWIneD3DVertexShaderImpl_SetLocalConstantsF(IWineD3DVertex=0A=
return WINED3D_OK;=0A=
}=0A=
=0A=
-HRESULT IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader =
*iface) {=0A=
- IWineD3DVertexShaderImpl *This =3D (IWineD3DVertexShaderImpl =
*)iface;=0A=
- CONST DWORD *function =3D This->baseShader.function;=0A=
+static GLuint vertexshader_compile(IWineD3DVertexShaderImpl *This, =
const struct vs_compile_args *args) {=0A=
IWineD3DDeviceImpl *deviceImpl =3D (IWineD3DDeviceImpl *) =
This->baseShader.device;=0A=
-=0A=
- TRACE("(%p) : function %p\n", iface, function);=0A=
-=0A=
- /* We're already compiled. */=0A=
- if (This->baseShader.is_compiled) {=0A=
- if ((This->swizzle_map & deviceImpl->strided_streams.use_map) =
!=3D deviceImpl->strided_streams.swizzle_map)=0A=
- {=0A=
- WARN("Recompiling vertex shader %p due to D3DCOLOR input =
changes\n", This);=0A=
- goto recompile;=0A=
- }=0A=
-=0A=
- return WINED3D_OK;=0A=
-=0A=
- recompile:=0A=
- if(This->recompile_count < 50) {=0A=
- This->recompile_count++;=0A=
- } else {=0A=
- FIXME("Vertexshader %p recompiled more than 50 times\n", =
This);=0A=
- }=0A=
-=0A=
- deviceImpl->shader_backend->shader_destroy((IWineD3DBaseShader =
*) iface);=0A=
- }=0A=
+ SHADER_BUFFER buffer;=0A=
+ GLuint ret;=0A=
=0A=
/* Generate the HW shader */=0A=
TRACE("(%p) : Generating hardware program\n", This);=0A=
- IWineD3DVertexShaderImpl_GenerateShader(iface, =
&This->baseShader.reg_maps, function);=0A=
-=0A=
- This->baseShader.is_compiled =3D TRUE;=0A=
+ shader_buffer_init(&buffer);=0A=
+ This->cur_args =3D args;=0A=
+ ret =3D =
deviceImpl->shader_backend->shader_generate_vshader((IWineD3DVertexShader=
*)This, &buffer, args);=0A=
+ This->cur_args =3D NULL;=0A=
+ shader_buffer_free(&buffer);=0A=
=0A=
- return WINED3D_OK;=0A=
+ return ret;=0A=
}=0A=
=0A=
const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =3D=0A=
@@ -470,3 +435,56 @@ const IWineD3DVertexShaderVtbl =
IWineD3DVertexShader_Vtbl =3D=0A=
IWineD3DVertexShaderImpl_FakeSemantics,=0A=
IWIneD3DVertexShaderImpl_SetLocalConstantsF=0A=
};=0A=
+=0A=
+void find_vs_compile_args(IWineD3DVertexShaderImpl *shader, =
IWineD3DStateBlockImpl *stateblock, struct vs_compile_args *args) {=0A=
+ args->fog_src =3D stateblock->renderState[WINED3DRS_FOGTABLEMODE] =
=3D=3D WINED3DFOG_NONE ? VS_FOG_COORD : VS_FOG_Z;=0A=
+ args->swizzle_map =3D ((IWineD3DDeviceImpl =
*)shader->baseShader.device)->strided_streams.swizzle_map;=0A=
+}=0A=
+=0A=
+static inline BOOL vs_args_equal(const struct vs_compile_args *stored, =
const struct vs_compile_args *new,=0A=
+ const DWORD use_map) {=0A=
+ if((stored->swizzle_map & use_map) !=3D new->swizzle_map) return =
FALSE;=0A=
+ return stored->fog_src =3D=3D new->fog_src;=0A=
+}=0A=
+=0A=
+GLuint find_gl_vshader(IWineD3DVertexShaderImpl *shader, const struct =
vs_compile_args *args)=0A=
+{=0A=
+ UINT i;=0A=
+ DWORD old_size =3D shader->shader_array_size;=0A=
+ struct vs_compiled_shader *old_array;=0A=
+ DWORD use_map =3D ((IWineD3DDeviceImpl =
*)shader->baseShader.device)->strided_streams.use_map;=0A=
+=0A=
+ /* Usually we have very few GL shaders for each d3d shader(just 1 =
or maybe 2),=0A=
+ * so a linear search is more performant than a hashmap or a binary =
search=0A=
+ * (cache coherency etc)=0A=
+ */=0A=
+ for(i =3D 0; i < shader->num_gl_shaders; i++) {=0A=
+ if(vs_args_equal(&shader->gl_shaders[i].args, args, use_map)) {=0A=
+ return shader->gl_shaders[i].prgId;=0A=
+ }=0A=
+ }=0A=
+=0A=
+ TRACE("No matching GL shader found, compiling a new shader\n");=0A=
+ old_array =3D shader->gl_shaders;=0A=
+=0A=
+ if(old_size <=3D shader->num_gl_shaders) {=0A=
+ if(old_array) {=0A=
+ shader->shader_array_size +=3D max(1, old_size * 0.5);=0A=
+ shader->gl_shaders =3D HeapReAlloc(GetProcessHeap(), 0, =
old_array,=0A=
+ (shader->shader_array_size =
+ 1) * sizeof(*shader->gl_shaders));=0A=
+ } else {=0A=
+ shader->gl_shaders =3D HeapAlloc(GetProcessHeap(), 0, =
sizeof(*shader->gl_shaders));=0A=
+ shader->shader_array_size =3D 1;=0A=
+ }=0A=
+ }=0A=
+=0A=
+ if(!shader->gl_shaders) {=0A=
+ ERR("Out of memory\n");=0A=
+ shader->gl_shaders =3D old_array;=0A=
+ return 0;=0A=
+ }=0A=
+=0A=
+ shader->gl_shaders[shader->num_gl_shaders].args =3D *args;=0A=
+ shader->gl_shaders[shader->num_gl_shaders].prgId =3D =
vertexshader_compile(shader, args);=0A=
+ return shader->gl_shaders[shader->num_gl_shaders++].prgId;=0A=
+}=0A=
diff --git a/dlls/wined3d/wined3d_private.h =
b/dlls/wined3d/wined3d_private.h=0A=
index 26ef4bc..d76988d 100644=0A=
--- a/dlls/wined3d/wined3d_private.h=0A=
+++ b/dlls/wined3d/wined3d_private.h=0A=
@@ -459,6 +459,18 @@ struct ps_compile_args {=0A=
/* Texture types(2D, Cube, 3D) in ps 1.x */=0A=
};=0A=
=0A=
+#define MAX_ATTRIBS 16=0A=
+=0A=
+enum fog_src_type {=0A=
+ VS_FOG_Z =3D 0,=0A=
+ VS_FOG_COORD =3D 1=0A=
+};=0A=
+=0A=
+struct vs_compile_args {=0A=
+ WORD fog_src;=0A=
+ WORD swizzle_map; /* MAX_ATTRIBS, 16 */=0A=
+};=0A=
+=0A=
typedef struct {=0A=
const SHADER_HANDLER *shader_instruction_handler_table;=0A=
void (*shader_select)(IWineD3DDevice *iface, BOOL usePS, BOOL =
useVS);=0A=
@@ -473,7 +485,7 @@ typedef struct {=0A=
void (*shader_free_private)(IWineD3DDevice *iface);=0A=
BOOL (*shader_dirtifyable_constants)(IWineD3DDevice *iface);=0A=
GLuint (*shader_generate_pshader)(IWineD3DPixelShader *iface, =
SHADER_BUFFER *buffer, const struct ps_compile_args *args);=0A=
- void (*shader_generate_vshader)(IWineD3DVertexShader *iface, =
SHADER_BUFFER *buffer);=0A=
+ GLuint (*shader_generate_vshader)(IWineD3DVertexShader *iface, =
SHADER_BUFFER *buffer, const struct vs_compile_args *args);=0A=
void (*shader_get_caps)(WINED3DDEVTYPE devtype, const =
WineD3D_GL_Info *gl_info, struct shader_caps *caps);=0A=
BOOL (*shader_color_fixup_supported)(struct color_fixup_desc fixup);=0A=
} shader_backend_t;=0A=
@@ -2207,7 +2219,6 @@ typedef struct IWineD3DBaseShaderClass=0A=
CONST SHADER_OPCODE *shader_ins;=0A=
DWORD *function;=0A=
UINT functionLength;=0A=
- BOOL is_compiled;=0A=
UINT cur_loop_depth, cur_loop_regno;=0A=
BOOL load_local_constsF;=0A=
BOOL uses_bool_consts, uses_int_consts;=0A=
@@ -2323,8 +2334,14 @@ static inline BOOL =
shader_constant_is_local(IWineD3DBaseShaderImpl* This, DWORD=0A=
}=0A=
=0A=
=
/************************************************************************=
*****=0A=
- * IDirect3DVertexShader implementation structure=0A=
+ * IDirect3DVertexShader implementation structures=0A=
*/=0A=
+=0A=
+struct vs_compiled_shader {=0A=
+ struct vs_compile_args args;=0A=
+ GLuint prgId;=0A=
+};=0A=
+=0A=
typedef struct IWineD3DVertexShaderImpl {=0A=
/* IUnknown parts*/ =0A=
const IWineD3DVertexShaderVtbl *lpVtbl;=0A=
@@ -2338,22 +2355,25 @@ typedef struct IWineD3DVertexShaderImpl {=0A=
DWORD usage;=0A=
=0A=
/* The GL shader */=0A=
- GLuint prgId;=0A=
+ struct vs_compiled_shader *gl_shaders;=0A=
+ UINT num_gl_shaders, shader_array_size;=0A=
=0A=
/* Vertex shader input and output semantics */=0A=
semantic semantics_in [MAX_ATTRIBS];=0A=
semantic semantics_out [MAX_REG_OUTPUT];=0A=
=0A=
- WORD swizzle_map; /* MAX_ATTRIBS, 16 */=0A=
-=0A=
UINT min_rel_offset, max_rel_offset;=0A=
UINT rel_offset;=0A=
=0A=
UINT recompile_count;=0A=
+=0A=
+ const struct vs_compile_args *cur_args;=0A=
} IWineD3DVertexShaderImpl;=0A=
extern const SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[];=0A=
extern const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl;=0A=
-HRESULT IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader =
*iface);=0A=
+=0A=
+void find_vs_compile_args(IWineD3DVertexShaderImpl *shader, =
IWineD3DStateBlockImpl *stateblock, struct vs_compile_args *args);=0A=
+GLuint find_gl_vshader(IWineD3DVertexShaderImpl *shader, const struct =
vs_compile_args *args);=0A=
=0A=
=
/************************************************************************=
*****=0A=
* IDirect3DPixelShader implementation structure=0A=
-- =0A=
1.6.0.6=0A=
=0A=
------=_NextPart_000_0147_01C97A32.A19D8BE0--
More information about the wine-patches
mailing list