wined3d: Manage vs_compile_args in the backends.
This commit is contained in:
parent
814dd42f25
commit
aad92c0780
|
@ -108,6 +108,16 @@ struct arb_pshader_private {
|
||||||
UINT num_gl_shaders, shader_array_size;
|
UINT num_gl_shaders, shader_array_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct arb_vs_compiled_shader {
|
||||||
|
struct vs_compile_args args;
|
||||||
|
GLuint prgId;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct arb_vshader_private {
|
||||||
|
struct arb_vs_compiled_shader *gl_shaders;
|
||||||
|
UINT num_gl_shaders, shader_array_size;
|
||||||
|
};
|
||||||
|
|
||||||
/********************************************************
|
/********************************************************
|
||||||
* ARB_[vertex/fragment]_program helper functions follow
|
* ARB_[vertex/fragment]_program helper functions follow
|
||||||
********************************************************/
|
********************************************************/
|
||||||
|
@ -2220,7 +2230,7 @@ static GLuint find_arb_pshader(IWineD3DPixelShaderImpl *shader, const struct ps_
|
||||||
GLuint ret;
|
GLuint ret;
|
||||||
|
|
||||||
if(!shader->backend_priv) {
|
if(!shader->backend_priv) {
|
||||||
shader->backend_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct arb_pshader_private));
|
shader->backend_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data));
|
||||||
}
|
}
|
||||||
shader_data = shader->backend_priv;
|
shader_data = shader->backend_priv;
|
||||||
|
|
||||||
|
@ -2276,32 +2286,38 @@ static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const str
|
||||||
static GLuint find_arb_vshader(IWineD3DVertexShaderImpl *shader, const struct vs_compile_args *args)
|
static GLuint find_arb_vshader(IWineD3DVertexShaderImpl *shader, const struct vs_compile_args *args)
|
||||||
{
|
{
|
||||||
UINT i;
|
UINT i;
|
||||||
DWORD new_size = shader->shader_array_size;
|
DWORD new_size;
|
||||||
struct vs_compiled_shader *new_array;
|
struct arb_vs_compiled_shader *new_array;
|
||||||
DWORD use_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.use_map;
|
DWORD use_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.use_map;
|
||||||
SHADER_BUFFER buffer;
|
SHADER_BUFFER buffer;
|
||||||
|
struct arb_vshader_private *shader_data;
|
||||||
GLuint ret;
|
GLuint ret;
|
||||||
|
|
||||||
|
if(!shader->backend_priv) {
|
||||||
|
shader->backend_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data));
|
||||||
|
}
|
||||||
|
shader_data = shader->backend_priv;
|
||||||
|
|
||||||
/* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2),
|
/* 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
|
* so a linear search is more performant than a hashmap or a binary search
|
||||||
* (cache coherency etc)
|
* (cache coherency etc)
|
||||||
*/
|
*/
|
||||||
for(i = 0; i < shader->num_gl_shaders; i++) {
|
for(i = 0; i < shader_data->num_gl_shaders; i++) {
|
||||||
if(vs_args_equal(&shader->gl_shaders[i].args, args, use_map)) {
|
if(vs_args_equal(&shader_data->gl_shaders[i].args, args, use_map)) {
|
||||||
return shader->gl_shaders[i].prgId;
|
return shader_data->gl_shaders[i].prgId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("No matching GL shader found, compiling a new shader\n");
|
TRACE("No matching GL shader found, compiling a new shader\n");
|
||||||
|
|
||||||
if(shader->shader_array_size == shader->num_gl_shaders) {
|
if(shader_data->shader_array_size == shader_data->num_gl_shaders) {
|
||||||
if (shader->num_gl_shaders)
|
if (shader_data->num_gl_shaders)
|
||||||
{
|
{
|
||||||
new_size = shader->shader_array_size + max(1, shader->shader_array_size / 2);
|
new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2);
|
||||||
new_array = HeapReAlloc(GetProcessHeap(), 0, shader->gl_shaders,
|
new_array = HeapReAlloc(GetProcessHeap(), 0, shader_data->gl_shaders,
|
||||||
new_size * sizeof(*shader->gl_shaders));
|
new_size * sizeof(*shader_data->gl_shaders));
|
||||||
} else {
|
} else {
|
||||||
new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader->gl_shaders));
|
new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader_data->gl_shaders));
|
||||||
new_size = 1;
|
new_size = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2309,16 +2325,16 @@ static GLuint find_arb_vshader(IWineD3DVertexShaderImpl *shader, const struct vs
|
||||||
ERR("Out of memory\n");
|
ERR("Out of memory\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
shader->gl_shaders = new_array;
|
shader_data->gl_shaders = new_array;
|
||||||
shader->shader_array_size = new_size;
|
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;
|
||||||
|
|
||||||
shader_buffer_init(&buffer);
|
shader_buffer_init(&buffer);
|
||||||
ret = shader_arb_generate_vshader(shader, &buffer, args);
|
ret = shader_arb_generate_vshader(shader, &buffer, args);
|
||||||
shader_buffer_free(&buffer);
|
shader_buffer_free(&buffer);
|
||||||
shader->gl_shaders[shader->num_gl_shaders++].prgId = ret;
|
shader_data->gl_shaders[shader_data->num_gl_shaders++].prgId = ret;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -2451,18 +2467,19 @@ static void shader_arb_destroy(IWineD3DBaseShader *iface) {
|
||||||
This->backend_priv = NULL;
|
This->backend_priv = NULL;
|
||||||
} else {
|
} else {
|
||||||
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *) iface;
|
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *) iface;
|
||||||
|
struct arb_vshader_private *shader_data = This->backend_priv;
|
||||||
UINT i;
|
UINT i;
|
||||||
|
|
||||||
|
if(!shader_data) return; /* This can happen if a shader was never compiled */
|
||||||
ENTER_GL();
|
ENTER_GL();
|
||||||
for(i = 0; i < This->num_gl_shaders; i++) {
|
for(i = 0; i < shader_data->num_gl_shaders; i++) {
|
||||||
GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId));
|
GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->gl_shaders[i].prgId));
|
||||||
checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId))");
|
checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->gl_shaders[i].prgId))");
|
||||||
}
|
}
|
||||||
LEAVE_GL();
|
LEAVE_GL();
|
||||||
HeapFree(GetProcessHeap(), 0, This->gl_shaders);
|
HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders);
|
||||||
This->gl_shaders = NULL;
|
HeapFree(GetProcessHeap(), 0, shader_data);
|
||||||
This->num_gl_shaders = 0;
|
This->backend_priv = NULL;
|
||||||
This->shader_array_size = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,6 +139,18 @@ struct glsl_pshader_private
|
||||||
UINT num_gl_shaders, shader_array_size;
|
UINT num_gl_shaders, shader_array_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct glsl_vs_compiled_shader
|
||||||
|
{
|
||||||
|
struct vs_compile_args args;
|
||||||
|
GLhandleARB prgId;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct glsl_vshader_private
|
||||||
|
{
|
||||||
|
struct glsl_vs_compiled_shader *gl_shaders;
|
||||||
|
UINT num_gl_shaders, shader_array_size;
|
||||||
|
};
|
||||||
|
|
||||||
/* Extract a line from the info log.
|
/* Extract a line from the info log.
|
||||||
* Note that this modifies the source string. */
|
* Note that this modifies the source string. */
|
||||||
static char *get_info_log_line(char **ptr)
|
static char *get_info_log_line(char **ptr)
|
||||||
|
@ -3807,7 +3819,7 @@ static GLhandleARB find_glsl_pshader(IWineD3DPixelShaderImpl *shader, const stru
|
||||||
GLhandleARB ret;
|
GLhandleARB ret;
|
||||||
|
|
||||||
if(!shader->backend_priv) {
|
if(!shader->backend_priv) {
|
||||||
shader->backend_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct glsl_pshader_private));
|
shader->backend_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data));
|
||||||
}
|
}
|
||||||
shader_data = shader->backend_priv;
|
shader_data = shader->backend_priv;
|
||||||
|
|
||||||
|
@ -3863,32 +3875,38 @@ static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const str
|
||||||
static GLhandleARB find_glsl_vshader(IWineD3DVertexShaderImpl *shader, const struct vs_compile_args *args)
|
static GLhandleARB find_glsl_vshader(IWineD3DVertexShaderImpl *shader, const struct vs_compile_args *args)
|
||||||
{
|
{
|
||||||
UINT i;
|
UINT i;
|
||||||
DWORD new_size = shader->shader_array_size;
|
DWORD new_size;
|
||||||
struct vs_compiled_shader *new_array;
|
struct glsl_vs_compiled_shader *new_array;
|
||||||
DWORD use_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.use_map;
|
DWORD use_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.use_map;
|
||||||
SHADER_BUFFER buffer;
|
SHADER_BUFFER buffer;
|
||||||
|
struct glsl_vshader_private *shader_data;
|
||||||
GLhandleARB ret;
|
GLhandleARB ret;
|
||||||
|
|
||||||
|
if(!shader->backend_priv) {
|
||||||
|
shader->backend_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data));
|
||||||
|
}
|
||||||
|
shader_data = shader->backend_priv;
|
||||||
|
|
||||||
/* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2),
|
/* 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
|
* so a linear search is more performant than a hashmap or a binary search
|
||||||
* (cache coherency etc)
|
* (cache coherency etc)
|
||||||
*/
|
*/
|
||||||
for(i = 0; i < shader->num_gl_shaders; i++) {
|
for(i = 0; i < shader_data->num_gl_shaders; i++) {
|
||||||
if(vs_args_equal(&shader->gl_shaders[i].args, args, use_map)) {
|
if(vs_args_equal(&shader_data->gl_shaders[i].args, args, use_map)) {
|
||||||
return shader->gl_shaders[i].prgId;
|
return shader_data->gl_shaders[i].prgId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("No matching GL shader found, compiling a new shader\n");
|
TRACE("No matching GL shader found, compiling a new shader\n");
|
||||||
|
|
||||||
if(shader->shader_array_size == shader->num_gl_shaders) {
|
if(shader_data->shader_array_size == shader_data->num_gl_shaders) {
|
||||||
if (shader->num_gl_shaders)
|
if (shader_data->num_gl_shaders)
|
||||||
{
|
{
|
||||||
new_size = shader->shader_array_size + max(1, shader->shader_array_size / 2);
|
new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2);
|
||||||
new_array = HeapReAlloc(GetProcessHeap(), 0, shader->gl_shaders,
|
new_array = HeapReAlloc(GetProcessHeap(), 0, shader_data->gl_shaders,
|
||||||
new_size * sizeof(*shader->gl_shaders));
|
new_size * sizeof(*shader_data->gl_shaders));
|
||||||
} else {
|
} else {
|
||||||
new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader->gl_shaders));
|
new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader_data->gl_shaders));
|
||||||
new_size = 1;
|
new_size = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3896,16 +3914,16 @@ static GLhandleARB find_glsl_vshader(IWineD3DVertexShaderImpl *shader, const str
|
||||||
ERR("Out of memory\n");
|
ERR("Out of memory\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
shader->gl_shaders = new_array;
|
shader_data->gl_shaders = new_array;
|
||||||
shader->shader_array_size = new_size;
|
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;
|
||||||
|
|
||||||
shader_buffer_init(&buffer);
|
shader_buffer_init(&buffer);
|
||||||
ret = shader_glsl_generate_vshader(shader, &buffer, args);
|
ret = shader_glsl_generate_vshader(shader, &buffer, args);
|
||||||
shader_buffer_free(&buffer);
|
shader_buffer_free(&buffer);
|
||||||
shader->gl_shaders[shader->num_gl_shaders++].prgId = ret;
|
shader_data->gl_shaders[shader_data->num_gl_shaders++].prgId = ret;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -4295,8 +4313,16 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) {
|
||||||
LEAVE_GL();
|
LEAVE_GL();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
struct glsl_vshader_private *shader_data;
|
||||||
vs = (IWineD3DVertexShaderImpl *) This;
|
vs = (IWineD3DVertexShaderImpl *) This;
|
||||||
if(vs->num_gl_shaders == 0) return;
|
shader_data = vs->backend_priv;
|
||||||
|
if(!shader_data || shader_data->num_gl_shaders == 0)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, shader_data);
|
||||||
|
vs->backend_priv = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (priv->glsl_program && (IWineD3DBaseShader *)priv->glsl_program->vshader == iface)
|
if (priv->glsl_program && (IWineD3DBaseShader *)priv->glsl_program->vshader == iface)
|
||||||
{
|
{
|
||||||
ENTER_GL();
|
ENTER_GL();
|
||||||
|
@ -4340,18 +4366,18 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) {
|
||||||
ps->backend_priv = NULL;
|
ps->backend_priv = NULL;
|
||||||
} else {
|
} else {
|
||||||
UINT i;
|
UINT i;
|
||||||
|
struct glsl_vshader_private *shader_data = vs->backend_priv;
|
||||||
|
|
||||||
ENTER_GL();
|
ENTER_GL();
|
||||||
for(i = 0; i < vs->num_gl_shaders; i++) {
|
for(i = 0; i < shader_data->num_gl_shaders; i++) {
|
||||||
TRACE("deleting vshader %u\n", vs->gl_shaders[i].prgId);
|
TRACE("deleting vshader %u\n", shader_data->gl_shaders[i].prgId);
|
||||||
GL_EXTCALL(glDeleteObjectARB(vs->gl_shaders[i].prgId));
|
GL_EXTCALL(glDeleteObjectARB(shader_data->gl_shaders[i].prgId));
|
||||||
checkGLcall("glDeleteObjectARB");
|
checkGLcall("glDeleteObjectARB");
|
||||||
}
|
}
|
||||||
LEAVE_GL();
|
LEAVE_GL();
|
||||||
HeapFree(GetProcessHeap(), 0, vs->gl_shaders);
|
HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders);
|
||||||
vs->gl_shaders = NULL;
|
HeapFree(GetProcessHeap(), 0, shader_data);
|
||||||
vs->num_gl_shaders = 0;
|
vs->backend_priv = NULL;
|
||||||
vs->shader_array_size = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2653,12 +2653,6 @@ static inline BOOL shader_constant_is_local(IWineD3DBaseShaderImpl* This, DWORD
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* IDirect3DVertexShader implementation structures
|
* IDirect3DVertexShader implementation structures
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct vs_compiled_shader {
|
|
||||||
struct vs_compile_args args;
|
|
||||||
GLuint prgId;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct IWineD3DVertexShaderImpl {
|
typedef struct IWineD3DVertexShaderImpl {
|
||||||
/* IUnknown parts*/
|
/* IUnknown parts*/
|
||||||
const IWineD3DVertexShaderVtbl *lpVtbl;
|
const IWineD3DVertexShaderVtbl *lpVtbl;
|
||||||
|
@ -2672,8 +2666,7 @@ typedef struct IWineD3DVertexShaderImpl {
|
||||||
DWORD usage;
|
DWORD usage;
|
||||||
|
|
||||||
/* The GL shader */
|
/* The GL shader */
|
||||||
struct vs_compiled_shader *gl_shaders;
|
void *backend_priv;
|
||||||
UINT num_gl_shaders, shader_array_size;
|
|
||||||
|
|
||||||
/* Vertex shader input and output semantics */
|
/* Vertex shader input and output semantics */
|
||||||
struct wined3d_shader_attribute attributes[MAX_ATTRIBS];
|
struct wined3d_shader_attribute attributes[MAX_ATTRIBS];
|
||||||
|
|
Loading…
Reference in New Issue