wined3d: Lookup GLSL float uniform locations only once per program.

This commit is contained in:
H. Verbeet 2006-08-19 17:23:20 +02:00 committed by Alexandre Julliard
parent efa5f78598
commit 49f4c68e29
5 changed files with 57 additions and 42 deletions

View File

@ -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);
} }

View File

@ -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");
} }

View File

@ -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,

View File

@ -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;

View File

@ -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;
}; };