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 2005 Oliver Stieber
|
||||
* Copyright 2006 Stefan Dösinger for CodeWeavers
|
||||
* Copyright 2006 Henri Verbeet
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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;
|
||||
GLhandleARB shaderObj = ((IWineD3DBaseShaderImpl*)shader)->baseShader.prgId;
|
||||
if (This->stateBlock->shaderPrgId != 0 && shaderObj != 0) {
|
||||
TRACE_(d3d_shader)("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->shaderPrgId);
|
||||
GL_EXTCALL(glAttachObjectARB(This->stateBlock->shaderPrgId, shaderObj));
|
||||
if (This->stateBlock->glsl_program && shaderObj != 0) {
|
||||
TRACE_(d3d_shader)("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->glsl_program->programId);
|
||||
GL_EXTCALL(glAttachObjectARB(This->stateBlock->glsl_program->programId, shaderObj));
|
||||
checkGLcall("glAttachObjectARB");
|
||||
}
|
||||
}
|
||||
|
@ -278,6 +279,8 @@ void set_glsl_shader_program(IWineD3DDevice *iface) {
|
|||
struct glsl_shader_prog_link *newLink = NULL;
|
||||
struct list *ptr = NULL;
|
||||
GLhandleARB programId = 0;
|
||||
int i;
|
||||
char glsl_name[8];
|
||||
|
||||
ptr = list_head( &This->glsl_shader_progs );
|
||||
while (ptr) {
|
||||
|
@ -287,7 +290,7 @@ void set_glsl_shader_program(IWineD3DDevice *iface) {
|
|||
/* Existing Program found, use it */
|
||||
TRACE_(d3d_shader)("Found existing program (%u) for this vertex/pixel shader combination\n",
|
||||
curLink->programId);
|
||||
This->stateBlock->shaderPrgId = curLink->programId;
|
||||
This->stateBlock->glsl_program = curLink;
|
||||
return;
|
||||
}
|
||||
/* 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 */
|
||||
programId = GL_EXTCALL(glCreateProgramObjectARB());
|
||||
TRACE_(d3d_shader)("Created new GLSL shader program %u\n", programId);
|
||||
This->stateBlock->shaderPrgId = programId;
|
||||
|
||||
/* Allocate a new link for the list of programs */
|
||||
newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
|
||||
newLink->programId = programId;
|
||||
This->stateBlock->glsl_program = newLink;
|
||||
|
||||
/* Attach GLSL vshader */
|
||||
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));
|
||||
print_glsl_info_log(&GLINFO_LOCATION, programId);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -401,6 +416,10 @@ static void delete_glsl_shader_list(IWineD3DDevice* iface) {
|
|||
|
||||
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 */
|
||||
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
|
||||
* Otherwise set 0, which restores fixed function */
|
||||
* Otherwise set NULL, to restore fixed function */
|
||||
if ((wined3d_settings.vs_selected_mode == SHADER_GLSL && useVertexShaderFunction) ||
|
||||
(wined3d_settings.ps_selected_mode == SHADER_GLSL && usePixelShaderFunction))
|
||||
set_glsl_shader_program(iface);
|
||||
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 (wined3d_settings.vs_selected_mode == SHADER_GLSL ||
|
||||
wined3d_settings.ps_selected_mode == SHADER_GLSL) {
|
||||
|
||||
if (This->stateBlock->shaderPrgId)
|
||||
TRACE_(d3d_shader)("Using GLSL program %u\n", This->stateBlock->shaderPrgId);
|
||||
GL_EXTCALL(glUseProgramObjectARB(This->stateBlock->shaderPrgId));
|
||||
GLhandleARB progId = This->stateBlock->glsl_program ? This->stateBlock->glsl_program->programId : 0;
|
||||
if (progId)
|
||||
TRACE_(d3d_shader)("Using GLSL program %u\n", progId);
|
||||
GL_EXTCALL(glUseProgramObjectARB(progId));
|
||||
checkGLcall("glUseProgramObjectARB");
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* GLSL pixel and vertex shader implementation
|
||||
*
|
||||
* Copyright 2006 Jason Green
|
||||
* Copyright 2006 Henri Verbeet
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -55,7 +56,7 @@ void shader_glsl_load_psamplers(
|
|||
IWineD3DStateBlock* iface) {
|
||||
|
||||
IWineD3DStateBlockImpl* stateBlock = (IWineD3DStateBlockImpl*) iface;
|
||||
GLhandleARB programId = stateBlock->shaderPrgId;
|
||||
GLhandleARB programId = stateBlock->glsl_program->programId;
|
||||
GLhandleARB name_loc;
|
||||
int i;
|
||||
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.
|
||||
* When @constants_set == NULL, it will load all the constants.
|
||||
*/
|
||||
void shader_glsl_load_constantsF(
|
||||
IWineD3DBaseShaderImpl* This,
|
||||
WineD3D_GL_Info *gl_info,
|
||||
GLhandleARB programId,
|
||||
unsigned max_constants,
|
||||
float* constants,
|
||||
BOOL* constants_set) {
|
||||
|
||||
void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_Info *gl_info,
|
||||
unsigned int max_constants, float* constants, GLhandleARB *constant_locations,
|
||||
BOOL* constants_set) {
|
||||
GLhandleARB tmp_loc;
|
||||
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;
|
||||
|
||||
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 + 2], constants[i * 4 + 3]);
|
||||
|
||||
/* TODO: Benchmark and see if it would be beneficial to store the
|
||||
* 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));
|
||||
tmp_loc = constant_locations[i];
|
||||
if (tmp_loc != -1) {
|
||||
/* We found this uniform name in the program - go ahead and send the data */
|
||||
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,
|
||||
values[0], values[1], values[2], values[3]);
|
||||
|
||||
snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, idx);
|
||||
tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
|
||||
tmp_loc = constant_locations[idx];
|
||||
if (tmp_loc != -1) {
|
||||
/* We found this uniform name in the program - go ahead and send the data */
|
||||
GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, values));
|
||||
|
@ -258,12 +247,14 @@ void shader_glsl_load_constants(
|
|||
|
||||
IWineD3DStateBlockImpl* stateBlock = (IWineD3DStateBlockImpl*) iface;
|
||||
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. */
|
||||
return;
|
||||
}
|
||||
programId = stateBlock->glsl_program->programId;
|
||||
|
||||
if (useVertexShader) {
|
||||
IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader;
|
||||
|
@ -272,16 +263,17 @@ void shader_glsl_load_constants(
|
|||
IWineD3DVertexDeclarationImpl* vertexDeclaration =
|
||||
(IWineD3DVertexDeclarationImpl*) vshader_impl->vertexDeclaration;
|
||||
|
||||
constant_locations = stateBlock->glsl_program->vuniformF_locations;
|
||||
|
||||
if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) {
|
||||
/* Load DirectX 8 float constants/uniforms for vertex shader */
|
||||
shader_glsl_load_constantsF(vshader, gl_info, programId, GL_LIMITS(vshader_constantsF),
|
||||
vertexDeclaration->constants, NULL);
|
||||
shader_glsl_load_constantsF(vshader, gl_info, GL_LIMITS(vshader_constantsF),
|
||||
vertexDeclaration->constants, constant_locations, NULL);
|
||||
}
|
||||
|
||||
/* Load DirectX 9 float constants/uniforms for vertex shader */
|
||||
shader_glsl_load_constantsF(vshader, gl_info, programId, GL_LIMITS(vshader_constantsF),
|
||||
stateBlock->vertexShaderConstantF,
|
||||
stateBlock->set.vertexShaderConstantsF);
|
||||
shader_glsl_load_constantsF(vshader, gl_info, GL_LIMITS(vshader_constantsF),
|
||||
stateBlock->vertexShaderConstantF, constant_locations, stateBlock->set.vertexShaderConstantsF);
|
||||
|
||||
/* Load DirectX 9 integer constants/uniforms for vertex shader */
|
||||
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;
|
||||
|
||||
constant_locations = stateBlock->glsl_program->puniformF_locations;
|
||||
|
||||
/* Load pixel shader samplers */
|
||||
shader_glsl_load_psamplers(gl_info, iface);
|
||||
|
||||
/* Load DirectX 9 float constants/uniforms for pixel shader */
|
||||
shader_glsl_load_constantsF(pshader, gl_info, programId, GL_LIMITS(pshader_constantsF),
|
||||
stateBlock->pixelShaderConstantF,
|
||||
stateBlock->set.pixelShaderConstantsF);
|
||||
shader_glsl_load_constantsF(pshader, gl_info, GL_LIMITS(pshader_constantsF),
|
||||
stateBlock->pixelShaderConstantF, constant_locations, stateBlock->set.pixelShaderConstantsF);
|
||||
|
||||
/* Load DirectX 9 integer constants/uniforms for pixel shader */
|
||||
shader_glsl_load_constantsI(pshader, gl_info, programId, MAX_CONST_I,
|
||||
|
|
|
@ -166,7 +166,7 @@ void stateblock_copy(
|
|||
Dest->pixelShader = This->pixelShader;
|
||||
Dest->vertex_blend = This->vertex_blend;
|
||||
Dest->tween_factor = This->tween_factor;
|
||||
Dest->shaderPrgId = This->shaderPrgId;
|
||||
Dest->glsl_program = This->glsl_program;
|
||||
|
||||
/* Fixed size arrays */
|
||||
memcpy(Dest->vertexShaderConstantB, This->vertexShaderConstantB, sizeof(BOOL) * MAX_CONST_B);
|
||||
|
@ -1067,9 +1067,9 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat
|
|||
}
|
||||
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 */
|
||||
This->shaderPrgId = 0;
|
||||
This->glsl_program = NULL;
|
||||
|
||||
TRACE("-----------------------> Device defaults now set up...\n");
|
||||
return WINED3D_OK;
|
||||
|
|
|
@ -1120,7 +1120,7 @@ struct IWineD3DStateBlockImpl
|
|||
DWORD samplerState[MAX_SAMPLERS][WINED3D_HIGHEST_SAMPLER_STATE + 1];
|
||||
|
||||
/* Current GLSL Shader Program */
|
||||
GLhandleARB shaderPrgId;
|
||||
struct glsl_shader_prog_link *glsl_program;
|
||||
};
|
||||
|
||||
extern void stateblock_savedstates_set(
|
||||
|
@ -1304,6 +1304,8 @@ typedef void (*SHADER_HANDLER) (struct SHADER_OPCODE_ARG*);
|
|||
struct glsl_shader_prog_link {
|
||||
struct list entry;
|
||||
GLhandleARB programId;
|
||||
GLhandleARB *vuniformF_locations;
|
||||
GLhandleARB *puniformF_locations;
|
||||
IWineD3DVertexShader* vertexShader;
|
||||
IWineD3DPixelShader* pixelShader;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue