From 09eb0c40a63a09150c1c70308864017c27f72fbc Mon Sep 17 00:00:00 2001 From: "H. Verbeet" Date: Sat, 19 Aug 2006 17:24:02 +0200 Subject: [PATCH] wined3d: Improve float constant loading a bit. - Use a list to keep track of what constants are set. - Move TRACEs and checkGLcall calls out of the main constant loading loop. --- dlls/wined3d/arb_program_shader.c | 76 +++++++++++++++------------ dlls/wined3d/device.c | 14 ++++- dlls/wined3d/glsl_shader.c | 87 +++++++++++++++++++++---------- dlls/wined3d/stateblock.c | 13 +++++ dlls/wined3d/wined3d_private.h | 7 +++ 5 files changed, 134 insertions(+), 63 deletions(-) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 7aa6691da1b..7a3fb7056ee 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -8,6 +8,7 @@ * Copyright 2005 Oliver Stieber * Copyright 2006 Ivan Gyurdiev * 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 @@ -41,48 +42,57 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); /** * Loads floating point constants into the currently set ARB_vertex/fragment_program. - * When @constants_set == NULL, it will load all the constants. + * When constant_list == NULL, it will load all the constants. * * @target_type should be either GL_VERTEX_PROGRAM_ARB (for vertex shaders) * or GL_FRAGMENT_PROGRAM_ARB (for pixel shaders) */ -void shader_arb_load_constantsF( - IWineD3DBaseShaderImpl* This, - WineD3D_GL_Info *gl_info, - GLuint target_type, - unsigned max_constants, - float* constants, - BOOL* constants_set) { - +static void shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_Info *gl_info, GLuint target_type, + unsigned int max_constants, float* constants, struct list *constant_list) { + constant_entry *constant; + local_constant* lconst; int i; - struct list* ptr; - - for (i=0; iidx; + TRACE("Loading constants %i: %f, %f, %f, %f\n", i, + constants[i * 4 + 0], constants[i * 4 + 1], + constants[i * 4 + 2], constants[i * 4 + 3]); + } + } + LIST_FOR_EACH_ENTRY(constant, constant_list, constant_entry, entry) { + i = constant->idx; + GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, constants + (i * 4))); + } + checkGLcall("glProgramEnvParameter4fvARB()"); } /* Load immediate constants */ - ptr = list_head(&This->baseShader.constantsF); - while (ptr) { - - local_constant* lconst = LIST_ENTRY(ptr, struct local_constant, entry); - unsigned int idx = lconst->idx; - GLfloat* values = (GLfloat*) lconst->value; - - TRACE("Loading local constants %i: %f, %f, %f, %f\n", idx, - values[0], values[1], values[2], values[3]); - - GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, idx, values)); - checkGLcall("glProgramEnvParameter4fvARB"); - ptr = list_next(&This->baseShader.constantsF, ptr); + if (TRACE_ON(d3d_shader)) { + LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { + GLfloat* values = (GLfloat*)lconst->value; + TRACE("Loading local constants %i: %f, %f, %f, %f\n", lconst->idx, + values[0], values[1], values[2], values[3]); + } } + LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { + GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, lconst->idx, (GLfloat*)lconst->value)); + } + checkGLcall("glProgramEnvParameter4fvARB()"); } /** @@ -116,7 +126,7 @@ void shader_arb_load_constants( shader_arb_load_constantsF(vshader, gl_info, GL_VERTEX_PROGRAM_ARB, GL_LIMITS(vshader_constantsF), stateBlock->vertexShaderConstantF, - stateBlock->set.vertexShaderConstantsF); + &stateBlock->set_vconstantsF); } if (usePixelShader) { @@ -127,7 +137,7 @@ void shader_arb_load_constants( shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB, GL_LIMITS(pshader_constantsF), stateBlock->pixelShaderConstantF, - stateBlock->set.pixelShaderConstantsF); + &stateBlock->set_pconstantsF); } } diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 75c8a6d4bc7..5e303a254ba 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4882,8 +4882,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF( srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]); for (i = start; i < cnt + start; ++i) { + if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) { + constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry)); + ptr->idx = i; + list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry); + This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE; + } This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE; - This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE; } return WINED3D_OK; @@ -5064,8 +5069,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF( srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]); for (i = start; i < cnt + start; ++i) { + if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) { + constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry)); + ptr->idx = i; + list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry); + This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE; + } This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE; - This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE; } return WINED3D_OK; diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 3c1d9ad2111..2ff147cd7c3 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -76,49 +76,77 @@ 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. + * When constant_list == NULL, it will load all the constants. */ -void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_Info *gl_info, +static void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_Info *gl_info, unsigned int max_constants, float* constants, GLhandleARB *constant_locations, - BOOL* constants_set) { + struct list *constant_list) { + local_constant* lconst; GLhandleARB tmp_loc; int i; - struct list* ptr; - - for (i=0; iidx; + tmp_loc = constant_locations[i]; + if (tmp_loc != -1) { + TRACE("Loading constants %i: %f, %f, %f, %f\n", i, + constants[i * 4 + 0], constants[i * 4 + 1], + constants[i * 4 + 2], constants[i * 4 + 3]); + } + } + } + LIST_FOR_EACH_ENTRY(constant, constant_list, constant_entry, entry) { + i = constant->idx; + 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))); + } + } + checkGLcall("glUniform4fvARB()"); } /* Load immediate constants */ - ptr = list_head(&This->baseShader.constantsF); - while (ptr) { - local_constant* lconst = LIST_ENTRY(ptr, struct local_constant, entry); - unsigned int idx = lconst->idx; - GLfloat* values = (GLfloat*) lconst->value; - - TRACE("Loading local constants %i: %f, %f, %f, %f\n", idx, - values[0], values[1], values[2], values[3]); - - tmp_loc = constant_locations[idx]; + if (TRACE_ON(d3d_shader)) { + LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { + tmp_loc = constant_locations[lconst->idx]; + if (tmp_loc != -1) { + GLfloat* values = (GLfloat*)lconst->value; + TRACE("Loading local constants %i: %f, %f, %f, %f\n", lconst->idx, + values[0], values[1], values[2], values[3]); + } + } + } + LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { + tmp_loc = constant_locations[lconst->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)); - checkGLcall("glUniform4fvARB"); + GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, (GLfloat*)lconst->value)); } - ptr = list_next(&This->baseShader.constantsF, ptr); } + checkGLcall("glUniform4fvARB()"); } /** @@ -248,6 +276,7 @@ void shader_glsl_load_constants( IWineD3DStateBlockImpl* stateBlock = (IWineD3DStateBlockImpl*) iface; WineD3D_GL_Info *gl_info = &((IWineD3DImpl*)stateBlock->wineD3DDevice->wineD3D)->gl_info; GLhandleARB *constant_locations; + struct list *constant_list; GLhandleARB programId; if (!stateBlock->glsl_program) { @@ -264,6 +293,7 @@ void shader_glsl_load_constants( (IWineD3DVertexDeclarationImpl*) vshader_impl->vertexDeclaration; constant_locations = stateBlock->glsl_program->vuniformF_locations; + constant_list = &stateBlock->set_vconstantsF; if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) { /* Load DirectX 8 float constants/uniforms for vertex shader */ @@ -273,7 +303,7 @@ void shader_glsl_load_constants( /* Load DirectX 9 float constants/uniforms for vertex shader */ shader_glsl_load_constantsF(vshader, gl_info, GL_LIMITS(vshader_constantsF), - stateBlock->vertexShaderConstantF, constant_locations, stateBlock->set.vertexShaderConstantsF); + stateBlock->vertexShaderConstantF, constant_locations, constant_list); /* Load DirectX 9 integer constants/uniforms for vertex shader */ shader_glsl_load_constantsI(vshader, gl_info, programId, MAX_CONST_I, @@ -291,13 +321,14 @@ void shader_glsl_load_constants( IWineD3DBaseShaderImpl* pshader = (IWineD3DBaseShaderImpl*) stateBlock->pixelShader; constant_locations = stateBlock->glsl_program->puniformF_locations; + constant_list = &stateBlock->set_pconstantsF; /* 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, GL_LIMITS(pshader_constantsF), - stateBlock->pixelShaderConstantF, constant_locations, stateBlock->set.pixelShaderConstantsF); + stateBlock->pixelShaderConstantF, constant_locations, constant_list); /* Load DirectX 9 integer constants/uniforms for pixel shader */ shader_glsl_load_constantsI(pshader, gl_info, programId, MAX_CONST_I, diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index 6dde42972fb..823bc7a12e5 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -53,6 +53,9 @@ HRESULT allocate_shader_constants(IWineD3DStateBlockImpl* object) { object->changed.vertexShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BOOL) * GL_LIMITS(vshader_constantsF)); WINED3D_MEMCHECK(object->changed.vertexShaderConstantsF); + list_init(&object->set_vconstantsF); + list_init(&object->set_pconstantsF); + #undef WINED3D_MEMCHECK return WINED3D_OK; @@ -225,6 +228,8 @@ static ULONG WINAPI IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) { TRACE("(%p) : Releasing from %ld\n", This, refCount + 1); if (!refCount) { + constant_entry *constant, *constant2; + /* type 0 represents the primary stateblock, so free all the resources */ if (This->blockType == WINED3DSBT_INIT) { int counter; @@ -274,6 +279,14 @@ static ULONG WINAPI IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) { HeapFree(GetProcessHeap(), 0, This->set.pixelShaderConstantsF); HeapFree(GetProcessHeap(), 0, This->changed.pixelShaderConstantsF); + LIST_FOR_EACH_ENTRY_SAFE(constant, constant2, &This->set_vconstantsF, constant_entry, entry) { + HeapFree(GetProcessHeap(), 0, constant); + } + + LIST_FOR_EACH_ENTRY_SAFE(constant, constant2, &This->set_pconstantsF, constant_entry, entry) { + HeapFree(GetProcessHeap(), 0, constant); + } + HeapFree(GetProcessHeap(), 0, This); } return refCount; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index bfa75102a5d..5d7af026cd0 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1040,6 +1040,11 @@ typedef struct SAVEDSTATES { BOOL *vertexShaderConstantsF; } SAVEDSTATES; +typedef struct { + struct list entry; + int idx; +} constant_entry; + struct IWineD3DStateBlockImpl { /* IUnknown fields */ @@ -1054,6 +1059,8 @@ struct IWineD3DStateBlockImpl /* Array indicating whether things have been set or changed */ SAVEDSTATES changed; SAVEDSTATES set; + struct list set_vconstantsF; + struct list set_pconstantsF; /* Drawing - Vertex Shader or FVF related */ DWORD fvf;