wined3d: Manage ps_compiled_shader in the backends.
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index ac03105..2c38ab3 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -98,6 +98,16 @@
const struct ps_compile_args *cur_ps_args;
};
+struct arb_ps_compiled_shader {
+ struct ps_compile_args args;
+ GLuint prgId;
+};
+
+struct arb_pshader_private {
+ struct arb_ps_compiled_shader *gl_shaders;
+ UINT num_gl_shaders, shader_array_size;
+};
+
/********************************************************
* ARB_[vertex/fragment]_program helper functions follow
********************************************************/
@@ -2204,28 +2214,35 @@
{
UINT i;
DWORD new_size;
- struct ps_compiled_shader *new_array;
+ struct arb_ps_compiled_shader *new_array;
SHADER_BUFFER buffer;
+ struct arb_pshader_private *shader_data;
+ GLuint ret;
+
+ if(!shader->backend_priv) {
+ shader->backend_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct arb_pshader_private));
+ }
+ shader_data = shader->backend_priv;
/* 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(memcmp(&shader->gl_shaders[i].args, args, sizeof(*args)) == 0) {
- return shader->gl_shaders[i].prgId;
+ for(i = 0; i < shader_data->num_gl_shaders; i++) {
+ if(memcmp(&shader_data->gl_shaders[i].args, args, sizeof(*args)) == 0) {
+ return shader_data->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)
+ if(shader_data->shader_array_size == shader_data->num_gl_shaders) {
+ if (shader_data->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));
+ new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2);
+ new_array = HeapReAlloc(GetProcessHeap(), 0, shader_data->gl_shaders,
+ new_size * sizeof(*shader_data->gl_shaders));
} else {
- new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader->gl_shaders));
+ new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader_data->gl_shaders));
new_size = 1;
}
@@ -2233,21 +2250,21 @@
ERR("Out of memory\n");
return 0;
}
- shader->gl_shaders = new_array;
- shader->shader_array_size = new_size;
+ shader_data->gl_shaders = new_array;
+ shader_data->shader_array_size = new_size;
}
- shader->gl_shaders[shader->num_gl_shaders].args = *args;
+ shader_data->gl_shaders[shader_data->num_gl_shaders].args = *args;
pixelshader_update_samplers(&shader->baseShader.reg_maps,
((IWineD3DDeviceImpl *)shader->baseShader.device)->stateBlock->textures);
shader_buffer_init(&buffer);
- shader->gl_shaders[shader->num_gl_shaders].prgId =
- shader_arb_generate_pshader(shader, &buffer, args);
+ ret = shader_arb_generate_pshader(shader, &buffer, args);
shader_buffer_free(&buffer);
+ shader_data->gl_shaders[shader_data->num_gl_shaders++].prgId = ret;
- return shader->gl_shaders[shader->num_gl_shaders++].prgId;
+ return ret;
}
static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const struct vs_compile_args *new,
@@ -2419,18 +2436,19 @@
if (shader_is_pshader_version(baseShader->baseShader.reg_maps.shader_version.type))
{
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *) iface;
+ struct arb_pshader_private *shader_data = This->backend_priv;
UINT i;
+ if(!shader_data) return; /* This can happen if a shader was never compiled */
ENTER_GL();
- for(i = 0; i < This->num_gl_shaders; i++) {
- GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId));
- checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId))");
+ for(i = 0; i < shader_data->num_gl_shaders; i++) {
+ GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->gl_shaders[i].prgId));
+ checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->gl_shaders[i].prgId))");
}
LEAVE_GL();
- HeapFree(GetProcessHeap(), 0, This->gl_shaders);
- This->gl_shaders = NULL;
- This->num_gl_shaders = 0;
- This->shader_array_size = 0;
+ HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders);
+ HeapFree(GetProcessHeap(), 0, shader_data);
+ This->backend_priv = NULL;
} else {
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *) iface;
UINT i;
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 65c71de..597c7d9 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -127,6 +127,18 @@
const struct ps_compile_args *cur_ps_args;
};
+struct glsl_ps_compiled_shader
+{
+ struct ps_compile_args args;
+ GLhandleARB prgId;
+};
+
+struct glsl_pshader_private
+{
+ struct glsl_ps_compiled_shader *gl_shaders;
+ UINT num_gl_shaders, shader_array_size;
+};
+
/* Extract a line from the info log.
* Note that this modifies the source string. */
static char *get_info_log_line(char **ptr)
@@ -3789,28 +3801,35 @@
{
UINT i;
DWORD new_size;
- struct ps_compiled_shader *new_array;
+ struct glsl_ps_compiled_shader *new_array;
SHADER_BUFFER buffer;
+ struct glsl_pshader_private *shader_data;
+ GLhandleARB ret;
+
+ if(!shader->backend_priv) {
+ shader->backend_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct glsl_pshader_private));
+ }
+ shader_data = shader->backend_priv;
/* 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(memcmp(&shader->gl_shaders[i].args, args, sizeof(*args)) == 0) {
- return shader->gl_shaders[i].prgId;
+ for(i = 0; i < shader_data->num_gl_shaders; i++) {
+ if(memcmp(&shader_data->gl_shaders[i].args, args, sizeof(*args)) == 0) {
+ return shader_data->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)
+ if(shader_data->shader_array_size == shader_data->num_gl_shaders) {
+ if (shader_data->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));
+ new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2);
+ new_array = HeapReAlloc(GetProcessHeap(), 0, shader_data->gl_shaders,
+ new_size * sizeof(*shader_data->gl_shaders));
} else {
- new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader->gl_shaders));
+ new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader_data->gl_shaders));
new_size = 1;
}
@@ -3818,20 +3837,21 @@
ERR("Out of memory\n");
return 0;
}
- shader->gl_shaders = new_array;
- shader->shader_array_size = new_size;
+ shader_data->gl_shaders = new_array;
+ shader_data->shader_array_size = new_size;
}
- shader->gl_shaders[shader->num_gl_shaders].args = *args;
+ shader_data->gl_shaders[shader_data->num_gl_shaders].args = *args;
pixelshader_update_samplers(&shader->baseShader.reg_maps,
((IWineD3DDeviceImpl *)shader->baseShader.device)->stateBlock->textures);
- shader_buffer_init(&buffer);
- shader->gl_shaders[shader->num_gl_shaders].prgId =
- shader_glsl_generate_pshader(shader, &buffer, args);
- shader_buffer_free(&buffer);
- return shader->gl_shaders[shader->num_gl_shaders++].prgId;
+ shader_buffer_init(&buffer);
+ ret = shader_glsl_generate_pshader(shader, &buffer, args);
+ shader_buffer_free(&buffer);
+ shader_data->gl_shaders[shader_data->num_gl_shaders++].prgId = ret;
+
+ return ret;
}
static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const struct vs_compile_args *new,
@@ -4258,8 +4278,16 @@
char pshader = shader_is_pshader_version(This->baseShader.reg_maps.shader_version.type);
if(pshader) {
+ struct glsl_pshader_private *shader_data;
ps = (IWineD3DPixelShaderImpl *) This;
- if(ps->num_gl_shaders == 0) return;
+ shader_data = ps->backend_priv;
+ if(!shader_data || shader_data->num_gl_shaders == 0)
+ {
+ HeapFree(GetProcessHeap(), 0, shader_data);
+ ps->backend_priv = NULL;
+ return;
+ }
+
if (priv->glsl_program && (IWineD3DBaseShader *)priv->glsl_program->pshader == iface)
{
ENTER_GL();
@@ -4298,18 +4326,18 @@
if(pshader) {
UINT i;
+ struct glsl_pshader_private *shader_data = ps->backend_priv;
ENTER_GL();
- for(i = 0; i < ps->num_gl_shaders; i++) {
- TRACE("deleting pshader %u\n", ps->gl_shaders[i].prgId);
- GL_EXTCALL(glDeleteObjectARB(ps->gl_shaders[i].prgId));
+ for(i = 0; i < shader_data->num_gl_shaders; i++) {
+ TRACE("deleting pshader %u\n", shader_data->gl_shaders[i].prgId);
+ GL_EXTCALL(glDeleteObjectARB(shader_data->gl_shaders[i].prgId));
checkGLcall("glDeleteObjectARB");
}
LEAVE_GL();
- HeapFree(GetProcessHeap(), 0, ps->gl_shaders);
- ps->gl_shaders = NULL;
- ps->num_gl_shaders = 0;
- ps->shader_array_size = 0;
+ HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders);
+ HeapFree(GetProcessHeap(), 0, shader_data);
+ ps->backend_priv = NULL;
} else {
UINT i;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index ec18a06..fe48f9f 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2691,11 +2691,6 @@
/*****************************************************************************
* IDirect3DPixelShader implementation structure
*/
-struct ps_compiled_shader {
- struct ps_compile_args args;
- GLuint prgId;
-};
-
typedef struct IWineD3DPixelShaderImpl {
/* IUnknown parts */
const IWineD3DPixelShaderVtbl *lpVtbl;
@@ -2713,8 +2708,7 @@
int declared_in_count;
/* The GL shader */
- struct ps_compiled_shader *gl_shaders;
- UINT num_gl_shaders, shader_array_size;
+ void *backend_priv;
/* Some information about the shader behavior */
struct stb_const_desc bumpenvmatconst[MAX_TEXTURES];