wined3d: Lookup GLSL float uniform locations only once per program.
This commit is contained in:
parent
efa5f78598
commit
49f4c68e29
|
@ -7,6 +7,7 @@
|
||||||
* Copyright 2004 Christian Costa
|
* Copyright 2004 Christian Costa
|
||||||
* Copyright 2005 Oliver Stieber
|
* Copyright 2005 Oliver Stieber
|
||||||
* Copyright 2006 Stefan Dösinger for CodeWeavers
|
* Copyright 2006 Stefan Dösinger for CodeWeavers
|
||||||
|
* Copyright 2006 Henri Verbeet
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -246,9 +247,9 @@ static void attach_glsl_shader(IWineD3DDevice *iface, IWineD3DBaseShader* shader
|
||||||
|
|
||||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||||
GLhandleARB shaderObj = ((IWineD3DBaseShaderImpl*)shader)->baseShader.prgId;
|
GLhandleARB shaderObj = ((IWineD3DBaseShaderImpl*)shader)->baseShader.prgId;
|
||||||
if (This->stateBlock->shaderPrgId != 0 && shaderObj != 0) {
|
if (This->stateBlock->glsl_program && shaderObj != 0) {
|
||||||
TRACE_(d3d_shader)("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->shaderPrgId);
|
TRACE_(d3d_shader)("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->glsl_program->programId);
|
||||||
GL_EXTCALL(glAttachObjectARB(This->stateBlock->shaderPrgId, shaderObj));
|
GL_EXTCALL(glAttachObjectARB(This->stateBlock->glsl_program->programId, shaderObj));
|
||||||
checkGLcall("glAttachObjectARB");
|
checkGLcall("glAttachObjectARB");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -278,6 +279,8 @@ void set_glsl_shader_program(IWineD3DDevice *iface) {
|
||||||
struct glsl_shader_prog_link *newLink = NULL;
|
struct glsl_shader_prog_link *newLink = NULL;
|
||||||
struct list *ptr = NULL;
|
struct list *ptr = NULL;
|
||||||
GLhandleARB programId = 0;
|
GLhandleARB programId = 0;
|
||||||
|
int i;
|
||||||
|
char glsl_name[8];
|
||||||
|
|
||||||
ptr = list_head( &This->glsl_shader_progs );
|
ptr = list_head( &This->glsl_shader_progs );
|
||||||
while (ptr) {
|
while (ptr) {
|
||||||
|
@ -287,7 +290,7 @@ void set_glsl_shader_program(IWineD3DDevice *iface) {
|
||||||
/* Existing Program found, use it */
|
/* Existing Program found, use it */
|
||||||
TRACE_(d3d_shader)("Found existing program (%u) for this vertex/pixel shader combination\n",
|
TRACE_(d3d_shader)("Found existing program (%u) for this vertex/pixel shader combination\n",
|
||||||
curLink->programId);
|
curLink->programId);
|
||||||
This->stateBlock->shaderPrgId = curLink->programId;
|
This->stateBlock->glsl_program = curLink;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* This isn't the entry we need - try the next one */
|
/* This isn't the entry we need - try the next one */
|
||||||
|
@ -297,11 +300,11 @@ void set_glsl_shader_program(IWineD3DDevice *iface) {
|
||||||
/* If we get to this point, then no matching program exists, so we create one */
|
/* If we get to this point, then no matching program exists, so we create one */
|
||||||
programId = GL_EXTCALL(glCreateProgramObjectARB());
|
programId = GL_EXTCALL(glCreateProgramObjectARB());
|
||||||
TRACE_(d3d_shader)("Created new GLSL shader program %u\n", programId);
|
TRACE_(d3d_shader)("Created new GLSL shader program %u\n", programId);
|
||||||
This->stateBlock->shaderPrgId = programId;
|
|
||||||
|
|
||||||
/* Allocate a new link for the list of programs */
|
/* Allocate a new link for the list of programs */
|
||||||
newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
|
newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
|
||||||
newLink->programId = programId;
|
newLink->programId = programId;
|
||||||
|
This->stateBlock->glsl_program = newLink;
|
||||||
|
|
||||||
/* Attach GLSL vshader */
|
/* Attach GLSL vshader */
|
||||||
if (NULL != vshader && wined3d_settings.vs_selected_mode == SHADER_GLSL) {
|
if (NULL != vshader && wined3d_settings.vs_selected_mode == SHADER_GLSL) {
|
||||||
|
@ -341,6 +344,18 @@ void set_glsl_shader_program(IWineD3DDevice *iface) {
|
||||||
GL_EXTCALL(glLinkProgramARB(programId));
|
GL_EXTCALL(glLinkProgramARB(programId));
|
||||||
print_glsl_info_log(&GLINFO_LOCATION, programId);
|
print_glsl_info_log(&GLINFO_LOCATION, programId);
|
||||||
list_add_head( &This->glsl_shader_progs, &newLink->entry);
|
list_add_head( &This->glsl_shader_progs, &newLink->entry);
|
||||||
|
|
||||||
|
newLink->vuniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(vshader_constantsF));
|
||||||
|
for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) {
|
||||||
|
snprintf(glsl_name, sizeof(glsl_name), "VC[%i]", i);
|
||||||
|
newLink->vuniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
|
||||||
|
}
|
||||||
|
newLink->puniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(pshader_constantsF));
|
||||||
|
for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) {
|
||||||
|
snprintf(glsl_name, sizeof(glsl_name), "PC[%i]", i);
|
||||||
|
newLink->puniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,6 +416,10 @@ static void delete_glsl_shader_list(IWineD3DDevice* iface) {
|
||||||
|
|
||||||
delete_glsl_shader_program(iface, curLink->programId);
|
delete_glsl_shader_program(iface, curLink->programId);
|
||||||
|
|
||||||
|
/* Free the uniform locations */
|
||||||
|
HeapFree(GetProcessHeap(), 0, curLink->vuniformF_locations);
|
||||||
|
HeapFree(GetProcessHeap(), 0, curLink->puniformF_locations);
|
||||||
|
|
||||||
/* Free the memory for this list item */
|
/* Free the memory for this list item */
|
||||||
HeapFree(GetProcessHeap(), 0, curLink);
|
HeapFree(GetProcessHeap(), 0, curLink);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1791,20 +1791,21 @@ inline static void drawPrimitiveDrawStrided(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If GLSL is used for either pixel or vertex shaders, make a GLSL program
|
/* If GLSL is used for either pixel or vertex shaders, make a GLSL program
|
||||||
* Otherwise set 0, which restores fixed function */
|
* Otherwise set NULL, to restore fixed function */
|
||||||
if ((wined3d_settings.vs_selected_mode == SHADER_GLSL && useVertexShaderFunction) ||
|
if ((wined3d_settings.vs_selected_mode == SHADER_GLSL && useVertexShaderFunction) ||
|
||||||
(wined3d_settings.ps_selected_mode == SHADER_GLSL && usePixelShaderFunction))
|
(wined3d_settings.ps_selected_mode == SHADER_GLSL && usePixelShaderFunction))
|
||||||
set_glsl_shader_program(iface);
|
set_glsl_shader_program(iface);
|
||||||
else
|
else
|
||||||
This->stateBlock->shaderPrgId = 0;
|
This->stateBlock->glsl_program = NULL;
|
||||||
|
|
||||||
/* If GLSL is used now, or might have been used before, (re)set the program */
|
/* If GLSL is used now, or might have been used before, (re)set the program */
|
||||||
if (wined3d_settings.vs_selected_mode == SHADER_GLSL ||
|
if (wined3d_settings.vs_selected_mode == SHADER_GLSL ||
|
||||||
wined3d_settings.ps_selected_mode == SHADER_GLSL) {
|
wined3d_settings.ps_selected_mode == SHADER_GLSL) {
|
||||||
|
|
||||||
if (This->stateBlock->shaderPrgId)
|
GLhandleARB progId = This->stateBlock->glsl_program ? This->stateBlock->glsl_program->programId : 0;
|
||||||
TRACE_(d3d_shader)("Using GLSL program %u\n", This->stateBlock->shaderPrgId);
|
if (progId)
|
||||||
GL_EXTCALL(glUseProgramObjectARB(This->stateBlock->shaderPrgId));
|
TRACE_(d3d_shader)("Using GLSL program %u\n", progId);
|
||||||
|
GL_EXTCALL(glUseProgramObjectARB(progId));
|
||||||
checkGLcall("glUseProgramObjectARB");
|
checkGLcall("glUseProgramObjectARB");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* GLSL pixel and vertex shader implementation
|
* GLSL pixel and vertex shader implementation
|
||||||
*
|
*
|
||||||
* Copyright 2006 Jason Green
|
* Copyright 2006 Jason Green
|
||||||
|
* Copyright 2006 Henri Verbeet
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -55,7 +56,7 @@ void shader_glsl_load_psamplers(
|
||||||
IWineD3DStateBlock* iface) {
|
IWineD3DStateBlock* iface) {
|
||||||
|
|
||||||
IWineD3DStateBlockImpl* stateBlock = (IWineD3DStateBlockImpl*) iface;
|
IWineD3DStateBlockImpl* stateBlock = (IWineD3DStateBlockImpl*) iface;
|
||||||
GLhandleARB programId = stateBlock->shaderPrgId;
|
GLhandleARB programId = stateBlock->glsl_program->programId;
|
||||||
GLhandleARB name_loc;
|
GLhandleARB name_loc;
|
||||||
int i;
|
int i;
|
||||||
char sampler_name[20];
|
char sampler_name[20];
|
||||||
|
@ -77,19 +78,11 @@ void shader_glsl_load_psamplers(
|
||||||
* Loads floating point constants (aka uniforms) into the currently set GLSL program.
|
* Loads floating point constants (aka uniforms) into the currently set GLSL program.
|
||||||
* When @constants_set == NULL, it will load all the constants.
|
* When @constants_set == NULL, it will load all the constants.
|
||||||
*/
|
*/
|
||||||
void shader_glsl_load_constantsF(
|
void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_Info *gl_info,
|
||||||
IWineD3DBaseShaderImpl* This,
|
unsigned int max_constants, float* constants, GLhandleARB *constant_locations,
|
||||||
WineD3D_GL_Info *gl_info,
|
BOOL* constants_set) {
|
||||||
GLhandleARB programId,
|
|
||||||
unsigned max_constants,
|
|
||||||
float* constants,
|
|
||||||
BOOL* constants_set) {
|
|
||||||
|
|
||||||
GLhandleARB tmp_loc;
|
GLhandleARB tmp_loc;
|
||||||
int i;
|
int i;
|
||||||
char tmp_name[8];
|
|
||||||
char is_pshader = shader_is_pshader_version(This->baseShader.hex_version);
|
|
||||||
const char* prefix = is_pshader? "PC":"VC";
|
|
||||||
struct list* ptr;
|
struct list* ptr;
|
||||||
|
|
||||||
for (i=0; i<max_constants; ++i) {
|
for (i=0; i<max_constants; ++i) {
|
||||||
|
@ -99,10 +92,7 @@ void shader_glsl_load_constantsF(
|
||||||
constants[i * 4 + 0], constants[i * 4 + 1],
|
constants[i * 4 + 0], constants[i * 4 + 1],
|
||||||
constants[i * 4 + 2], constants[i * 4 + 3]);
|
constants[i * 4 + 2], constants[i * 4 + 3]);
|
||||||
|
|
||||||
/* TODO: Benchmark and see if it would be beneficial to store the
|
tmp_loc = constant_locations[i];
|
||||||
* locations of the constants to avoid looking up each time */
|
|
||||||
snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, i);
|
|
||||||
tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
|
|
||||||
if (tmp_loc != -1) {
|
if (tmp_loc != -1) {
|
||||||
/* We found this uniform name in the program - go ahead and send the data */
|
/* We found this uniform name in the program - go ahead and send the data */
|
||||||
GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, &constants[i * 4]));
|
GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, &constants[i * 4]));
|
||||||
|
@ -121,8 +111,7 @@ void shader_glsl_load_constantsF(
|
||||||
TRACE("Loading local constants %i: %f, %f, %f, %f\n", idx,
|
TRACE("Loading local constants %i: %f, %f, %f, %f\n", idx,
|
||||||
values[0], values[1], values[2], values[3]);
|
values[0], values[1], values[2], values[3]);
|
||||||
|
|
||||||
snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, idx);
|
tmp_loc = constant_locations[idx];
|
||||||
tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
|
|
||||||
if (tmp_loc != -1) {
|
if (tmp_loc != -1) {
|
||||||
/* We found this uniform name in the program - go ahead and send the data */
|
/* We found this uniform name in the program - go ahead and send the data */
|
||||||
GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, values));
|
GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, values));
|
||||||
|
@ -258,12 +247,14 @@ void shader_glsl_load_constants(
|
||||||
|
|
||||||
IWineD3DStateBlockImpl* stateBlock = (IWineD3DStateBlockImpl*) iface;
|
IWineD3DStateBlockImpl* stateBlock = (IWineD3DStateBlockImpl*) iface;
|
||||||
WineD3D_GL_Info *gl_info = &((IWineD3DImpl*)stateBlock->wineD3DDevice->wineD3D)->gl_info;
|
WineD3D_GL_Info *gl_info = &((IWineD3DImpl*)stateBlock->wineD3DDevice->wineD3D)->gl_info;
|
||||||
GLhandleARB programId = stateBlock->shaderPrgId;
|
GLhandleARB *constant_locations;
|
||||||
|
GLhandleARB programId;
|
||||||
|
|
||||||
if (programId == 0) {
|
if (!stateBlock->glsl_program) {
|
||||||
/* No GLSL program set - nothing to do. */
|
/* No GLSL program set - nothing to do. */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
programId = stateBlock->glsl_program->programId;
|
||||||
|
|
||||||
if (useVertexShader) {
|
if (useVertexShader) {
|
||||||
IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader;
|
IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader;
|
||||||
|
@ -272,16 +263,17 @@ void shader_glsl_load_constants(
|
||||||
IWineD3DVertexDeclarationImpl* vertexDeclaration =
|
IWineD3DVertexDeclarationImpl* vertexDeclaration =
|
||||||
(IWineD3DVertexDeclarationImpl*) vshader_impl->vertexDeclaration;
|
(IWineD3DVertexDeclarationImpl*) vshader_impl->vertexDeclaration;
|
||||||
|
|
||||||
|
constant_locations = stateBlock->glsl_program->vuniformF_locations;
|
||||||
|
|
||||||
if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) {
|
if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) {
|
||||||
/* Load DirectX 8 float constants/uniforms for vertex shader */
|
/* Load DirectX 8 float constants/uniforms for vertex shader */
|
||||||
shader_glsl_load_constantsF(vshader, gl_info, programId, GL_LIMITS(vshader_constantsF),
|
shader_glsl_load_constantsF(vshader, gl_info, GL_LIMITS(vshader_constantsF),
|
||||||
vertexDeclaration->constants, NULL);
|
vertexDeclaration->constants, constant_locations, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load DirectX 9 float constants/uniforms for vertex shader */
|
/* Load DirectX 9 float constants/uniforms for vertex shader */
|
||||||
shader_glsl_load_constantsF(vshader, gl_info, programId, GL_LIMITS(vshader_constantsF),
|
shader_glsl_load_constantsF(vshader, gl_info, GL_LIMITS(vshader_constantsF),
|
||||||
stateBlock->vertexShaderConstantF,
|
stateBlock->vertexShaderConstantF, constant_locations, stateBlock->set.vertexShaderConstantsF);
|
||||||
stateBlock->set.vertexShaderConstantsF);
|
|
||||||
|
|
||||||
/* Load DirectX 9 integer constants/uniforms for vertex shader */
|
/* Load DirectX 9 integer constants/uniforms for vertex shader */
|
||||||
shader_glsl_load_constantsI(vshader, gl_info, programId, MAX_CONST_I,
|
shader_glsl_load_constantsI(vshader, gl_info, programId, MAX_CONST_I,
|
||||||
|
@ -298,13 +290,14 @@ void shader_glsl_load_constants(
|
||||||
|
|
||||||
IWineD3DBaseShaderImpl* pshader = (IWineD3DBaseShaderImpl*) stateBlock->pixelShader;
|
IWineD3DBaseShaderImpl* pshader = (IWineD3DBaseShaderImpl*) stateBlock->pixelShader;
|
||||||
|
|
||||||
|
constant_locations = stateBlock->glsl_program->puniformF_locations;
|
||||||
|
|
||||||
/* Load pixel shader samplers */
|
/* Load pixel shader samplers */
|
||||||
shader_glsl_load_psamplers(gl_info, iface);
|
shader_glsl_load_psamplers(gl_info, iface);
|
||||||
|
|
||||||
/* Load DirectX 9 float constants/uniforms for pixel shader */
|
/* Load DirectX 9 float constants/uniforms for pixel shader */
|
||||||
shader_glsl_load_constantsF(pshader, gl_info, programId, GL_LIMITS(pshader_constantsF),
|
shader_glsl_load_constantsF(pshader, gl_info, GL_LIMITS(pshader_constantsF),
|
||||||
stateBlock->pixelShaderConstantF,
|
stateBlock->pixelShaderConstantF, constant_locations, stateBlock->set.pixelShaderConstantsF);
|
||||||
stateBlock->set.pixelShaderConstantsF);
|
|
||||||
|
|
||||||
/* Load DirectX 9 integer constants/uniforms for pixel shader */
|
/* Load DirectX 9 integer constants/uniforms for pixel shader */
|
||||||
shader_glsl_load_constantsI(pshader, gl_info, programId, MAX_CONST_I,
|
shader_glsl_load_constantsI(pshader, gl_info, programId, MAX_CONST_I,
|
||||||
|
|
|
@ -166,7 +166,7 @@ void stateblock_copy(
|
||||||
Dest->pixelShader = This->pixelShader;
|
Dest->pixelShader = This->pixelShader;
|
||||||
Dest->vertex_blend = This->vertex_blend;
|
Dest->vertex_blend = This->vertex_blend;
|
||||||
Dest->tween_factor = This->tween_factor;
|
Dest->tween_factor = This->tween_factor;
|
||||||
Dest->shaderPrgId = This->shaderPrgId;
|
Dest->glsl_program = This->glsl_program;
|
||||||
|
|
||||||
/* Fixed size arrays */
|
/* Fixed size arrays */
|
||||||
memcpy(Dest->vertexShaderConstantB, This->vertexShaderConstantB, sizeof(BOOL) * MAX_CONST_B);
|
memcpy(Dest->vertexShaderConstantB, This->vertexShaderConstantB, sizeof(BOOL) * MAX_CONST_B);
|
||||||
|
@ -1067,9 +1067,9 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat
|
||||||
}
|
}
|
||||||
This->wineD3DDevice->currentPalette = 0;
|
This->wineD3DDevice->currentPalette = 0;
|
||||||
|
|
||||||
/* Set default GLSL program ID to 0. We won't actually create one
|
/* Set default GLSL program to NULL. We won't actually create one
|
||||||
* until the app sets a vertex or pixel shader */
|
* until the app sets a vertex or pixel shader */
|
||||||
This->shaderPrgId = 0;
|
This->glsl_program = NULL;
|
||||||
|
|
||||||
TRACE("-----------------------> Device defaults now set up...\n");
|
TRACE("-----------------------> Device defaults now set up...\n");
|
||||||
return WINED3D_OK;
|
return WINED3D_OK;
|
||||||
|
|
|
@ -1120,7 +1120,7 @@ struct IWineD3DStateBlockImpl
|
||||||
DWORD samplerState[MAX_SAMPLERS][WINED3D_HIGHEST_SAMPLER_STATE + 1];
|
DWORD samplerState[MAX_SAMPLERS][WINED3D_HIGHEST_SAMPLER_STATE + 1];
|
||||||
|
|
||||||
/* Current GLSL Shader Program */
|
/* Current GLSL Shader Program */
|
||||||
GLhandleARB shaderPrgId;
|
struct glsl_shader_prog_link *glsl_program;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void stateblock_savedstates_set(
|
extern void stateblock_savedstates_set(
|
||||||
|
@ -1304,6 +1304,8 @@ typedef void (*SHADER_HANDLER) (struct SHADER_OPCODE_ARG*);
|
||||||
struct glsl_shader_prog_link {
|
struct glsl_shader_prog_link {
|
||||||
struct list entry;
|
struct list entry;
|
||||||
GLhandleARB programId;
|
GLhandleARB programId;
|
||||||
|
GLhandleARB *vuniformF_locations;
|
||||||
|
GLhandleARB *puniformF_locations;
|
||||||
IWineD3DVertexShader* vertexShader;
|
IWineD3DVertexShader* vertexShader;
|
||||||
IWineD3DPixelShader* pixelShader;
|
IWineD3DPixelShader* pixelShader;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue