[PATCH] WineD3D: Put vertex shader duplication infrastructure =
Stefan Doesinger
stefan at codeweavers.com
Sat Jan 10 23:53:52 CST 2009
in place=0A=
=0A=
It works the same way as the code we already have for pixel shaders=0A=
---=0A=
dlls/d3d9/tests/visual.c | 2 +-=0A=
dlls/wined3d/arb_program_shader.c | 53 ++++++++++++---------=0A=
dlls/wined3d/baseshader.c | 3 +-=0A=
dlls/wined3d/glsl_shader.c | 69 +++++++++++++++++----------=0A=
dlls/wined3d/pixelshader.c | 2 -=0A=
dlls/wined3d/vertexshader.c | 93 =
+++++++++++++++++++-----------------=0A=
dlls/wined3d/wined3d_private.h | 36 +++++++++++---=0A=
7 files changed, 154 insertions(+), 104 deletions(-)=0A=
=0A=
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c=0A=
index 22035b8..1521a2e 100644=0A=
--- a/dlls/d3d9/tests/visual.c=0A=
+++ b/dlls/d3d9/tests/visual.c=0A=
@@ -1536,7 +1536,7 @@ static void fog_with_shader_test(IDirect3DDevice9 =
*device)=0A=
=0A=
/* As the red and green component are the result of =
blending use 5% tolerance on the expected value */=0A=
color =3D getPixelColor(device, 128, 240);=0A=
- if(test_data[i].vshader =3D=3D 1 && test_data[i].tfog =
=3D=3D 0) {=0A=
+ if(test_data[i].vshader =3D=3D 1 && test_data[i].tfog =
=3D=3D 0 && color !=3D test_data[i].color[j]) {=0A=
todo_wine ok(color_match(color, test_data[i].color[j], =
13),=0A=
"fog vs%i ps%i fvm%i ftm%i %d: got color =
%08x, expected %08x +-5%%(todo)\n",=0A=
test_data[i].vshader, =
test_data[i].pshader, test_data[i].vfog, test_data[i].tfog, j, color, =
test_data[i].color[j]);=0A=
diff --git a/dlls/wined3d/arb_program_shader.c =
b/dlls/wined3d/arb_program_shader.c=0A=
index 4ffa45f..898f2cb 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=
@@ -1859,14 +1860,18 @@ static void =
shader_arb_destroy(IWineD3DBaseShader *iface) {=0A=
This->num_gl_shaders =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=
}=0A=
- baseShader->baseShader.is_compiled =3D FALSE;=0A=
}=0A=
=0A=
static HRESULT shader_arb_alloc(IWineD3DDevice *iface) {=0A=
@@ -2007,13 +2012,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=
@@ -2085,12 +2091,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=
@@ -2100,16 +2106,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 8dfb416..5b5827d 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=
@@ -3653,13 +3667,18 @@ static void =
shader_glsl_destroy(IWineD3DBaseShader *iface) {=0A=
ps->gl_shaders =3D NULL;=0A=
ps->num_gl_shaders =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=
}=0A=
}=0A=
=0A=
@@ -3667,7 +3686,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=
@@ -3684,7 +3703,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=
@@ -3869,7 +3889,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=
@@ -3919,8 +3939,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/pixelshader.c b/dlls/wined3d/pixelshader.c=0A=
index 9f96c59..022ced3 100644=0A=
--- a/dlls/wined3d/pixelshader.c=0A=
+++ b/dlls/wined3d/pixelshader.c=0A=
@@ -439,8 +439,6 @@ static GLuint =
pixelshader_compile(IWineD3DPixelShaderImpl *This, const struct ps=0A=
retval =3D =
device->shader_backend->shader_generate_pshader((IWineD3DPixelShader =
*)This, &buffer, args);=0A=
shader_buffer_free(&buffer);=0A=
=0A=
- This->baseShader.is_compiled =3D TRUE;=0A=
-=0A=
return retval;=0A=
}=0A=
=0A=
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c=0A=
index 339d955..84e415b 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,43 @@ 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=
+GLuint find_gl_vshader(IWineD3DVertexShaderImpl *shader, const struct =
vs_compile_args *args)=0A=
+{=0A=
+ UINT i;=0A=
+ struct vs_compiled_shader *old_array;=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=0A=
+ */=0A=
+ for(i =3D 0; i < shader->num_gl_shaders; i++) {=0A=
+ if(memcmp(&shader->gl_shaders[i].args, args, sizeof(*args)) =
=3D=3D 0) {=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_array) {=0A=
+ shader->gl_shaders =3D HeapReAlloc(GetProcessHeap(), 0, =
old_array,=0A=
+ (shader->num_gl_shaders + 1) * =
sizeof(*shader->gl_shaders));=0A=
+ } else {=0A=
+ shader->gl_shaders =3D HeapAlloc(GetProcessHeap(), 0, =
sizeof(*shader->gl_shaders));=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 ded6d48..ae7aca2 100644=0A=
--- a/dlls/wined3d/wined3d_private.h=0A=
+++ b/dlls/wined3d/wined3d_private.h=0A=
@@ -10,7 +10,7 @@=0A=
* modify it under the terms of the GNU Lesser General Public=0A=
* License as published by the Free Software Foundation; either=0A=
* version 2.1 of the License, or (at your option) any later version.=0A=
- *=0A=
+ * =0A=
* This library is distributed in the hope that it will be useful,=0A=
* but WITHOUT ANY WARRANTY; without even the implied warranty of=0A=
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU=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=
@@ -2201,7 +2213,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=
@@ -2317,8 +2328,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=
@@ -2332,22 +2349,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;=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_000C_01C97515.C4C38240--
More information about the wine-patches
mailing list