wined3d: Make the number of floating point shader constants
dynamic
Jason Green
jave27 at gmail.com
Fri Jun 30 09:47:44 CDT 2006
Here is an updated patch. The only effective difference since the
first patch is how many constants we declare in the
arb/glsl_declarations. The first patch didn't declare enough pixel
shader constants for shader models 1 & 2 that used locally defined
constants.
On 6/30/06, Jason Green <jave27 at gmail.com> wrote:
> The size of the floating point constant array is different for every
> card. This patch uses the GL limits for both ARB and GLSL shaders to
> dynamically allocate the number of float constants available.
>
> - Makes the register_maps struct allocate the memory dynamically
> - Makes the stateblock allocate the space for the constants and the
> set/changed flags dynamically
> - Removes the hack for MESA drivers
> - Declare the number supported in the shader programs as (gl_max -
> number of locally defined constants by DEF, DEFI, and DEFB [ - number
> of other uniforms which may be present in GLSL shaders])
>
>
>
-------------- next part --------------
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index ec6cb14..bffff58 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -88,13 +88,13 @@ void shader_arb_load_constants(
if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) {
/* Load DirectX 8 float constants for vertex shader */
shader_arb_load_constantsF(gl_info, GL_VERTEX_PROGRAM_ARB,
- WINED3D_VSHADER_MAX_CONSTANTS,
+ GL_LIMITS(vshader_constantsF),
vertexDeclaration->constants, NULL);
}
/* Load DirectX 9 float constants for vertex shader */
shader_arb_load_constantsF(gl_info, GL_VERTEX_PROGRAM_ARB,
- WINED3D_VSHADER_MAX_CONSTANTS,
+ GL_LIMITS(vshader_constantsF),
stateBlock->vertexShaderConstantF,
stateBlock->set.vertexShaderConstantsF);
}
@@ -102,7 +102,7 @@ void shader_arb_load_constants(
if (usePixelShader) {
/* Load DirectX 9 float constants for pixel shader */
- shader_arb_load_constantsF(gl_info, GL_FRAGMENT_PROGRAM_ARB, WINED3D_PSHADER_MAX_CONSTANTS,
+ shader_arb_load_constantsF(gl_info, GL_FRAGMENT_PROGRAM_ARB, GL_LIMITS(pshader_constantsF),
stateBlock->pixelShaderConstantF,
stateBlock->set.pixelShaderConstantsF);
}
@@ -112,10 +112,14 @@ void shader_arb_load_constants(
void shader_generate_arb_declarations(
IWineD3DBaseShader *iface,
shader_reg_maps* reg_maps,
- SHADER_BUFFER* buffer) {
+ SHADER_BUFFER* buffer,
+ WineD3D_GL_Info* gl_info) {
IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
DWORD i;
+ char pshader = shader_is_pshader_version(This->baseShader.hex_version);
+ unsigned max_constantsF = min(This->baseShader.limits.constant_float,
+ (pshader ? GL_LIMITS(pshader_constantsF) : GL_LIMITS(vshader_constantsF)) - reg_maps->num_local_constants);
for(i = 0; i < This->baseShader.limits.temporary; i++) {
if (reg_maps->temporary[i])
@@ -140,8 +144,7 @@ void shader_generate_arb_declarations(
/* Need to PARAM the environment parameters (constants) so we can use relative addressing */
shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
- This->baseShader.limits.constant_float,
- This->baseShader.limits.constant_float - 1);
+ max_constantsF, max_constantsF - 1);
}
/** Process the D3DSIO_DEF opcode into an ARB string - creates a local vec4
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index e9e3097..5342a31 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -360,8 +360,11 @@ void shader_get_registers_used(
reg_maps->samplers[regnum] = usage;
/* Skip definitions (for now) */
- } else if (D3DSIO_DEF == curOpcode->opcode) {
+ } else if (D3DSIO_DEF == curOpcode->opcode
+ || D3DSIO_DEFI == curOpcode->opcode
+ || D3DSIO_DEFB == curOpcode->opcode) {
pToken += curOpcode->num_params;
+ reg_maps->num_local_constants++;
/* If there's a loop in the shader */
} else if (D3DSIO_LOOP == curOpcode->opcode) {
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 087ba92..eedce59 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -416,6 +416,33 @@ static void delete_glsl_shader_list(IWin
}
}
+/** Allocates the correct amount of space for pixel and vertex shader constants,
+ * along with their set/changed flags on the given stateblock object
+ */
+static HRESULT allocate_shader_constants(IWineD3DDevice* iface, IWineD3DStateBlockImpl* object) {
+
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+
+#define WINED3D_MEMCHECK(_object) if (NULL == _object) { FIXME("Out of memory!\n"); return E_OUTOFMEMORY; }
+
+ /* Allocate space for floating point constants */
+ object->pixelShaderConstantF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(float) * GL_LIMITS(pshader_constantsF) * 4);
+ WINED3D_MEMCHECK(object->pixelShaderConstantF);
+ object->set.pixelShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BOOL) * GL_LIMITS(pshader_constantsF) );
+ WINED3D_MEMCHECK(object->set.pixelShaderConstantsF);
+ object->changed.pixelShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BOOL) * GL_LIMITS(pshader_constantsF));
+ WINED3D_MEMCHECK(object->changed.pixelShaderConstantsF);
+ object->vertexShaderConstantF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(float) * GL_LIMITS(vshader_constantsF) * 4);
+ WINED3D_MEMCHECK(object->vertexShaderConstantF);
+ object->set.vertexShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BOOL) * GL_LIMITS(vshader_constantsF));
+ WINED3D_MEMCHECK(object->set.vertexShaderConstantsF);
+ object->changed.vertexShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BOOL) * GL_LIMITS(vshader_constantsF));
+ WINED3D_MEMCHECK(object->changed.vertexShaderConstantsF);
+
+#undef WINED3D_MEMCHECK
+
+ return WINED3D_OK;
+}
/* Apply the current values to the specified texture stage */
static void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD texture_idx, DWORD Flags) {
@@ -782,10 +809,15 @@ static HRESULT WINAPI IWineD3DDeviceImpl
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DStateBlockImpl *object;
int i, j;
+ HRESULT temp_result;
D3DCREATEOBJECTINSTANCE(object, StateBlock)
object->blockType = Type;
+ temp_result = allocate_shader_constants(iface, object);
+ if (WINED3D_OK != temp_result)
+ return temp_result;
+
/* Special case - Used during initialization to produce a placeholder stateblock
so other functions called can update a state block */
if (Type == WINED3DSBT_INIT) {
@@ -820,11 +852,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl
object->changed.pixelShader = TRUE;
/* Pixel Shader Constants */
- for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
+ for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
object->changed.pixelShaderConstantsF[i] = TRUE;
+ for (i = 0; i < MAX_CONST_B; ++i)
object->changed.pixelShaderConstantsB[i] = TRUE;
+ for (i = 0; i < MAX_CONST_I; ++i)
object->changed.pixelShaderConstantsI[i] = TRUE;
- }
+
for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
}
@@ -848,11 +882,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl
object->changed.vertexShader = TRUE;
/* Vertex Shader Constants */
- for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
+ for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i)
object->changed.vertexShaderConstantsF[i] = TRUE;
+ for (i = 0; i < MAX_CONST_B; ++i)
object->changed.vertexShaderConstantsB[i] = TRUE;
+ for (i = 0; i < MAX_CONST_I; ++i)
object->changed.vertexShaderConstantsI[i] = TRUE;
- }
+
for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
}
@@ -4672,7 +4708,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
UINT count) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- int i, cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
+ int i, cnt = min(count, MAX_CONST_B - (start + 1));
TRACE("(iface %p, srcData %p, start %d, count %d)\n",
iface, srcData, start, count);
@@ -4697,7 +4733,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
UINT count) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
+ int cnt = min(count, MAX_CONST_B - (start + 1));
TRACE("(iface %p, dstData %p, start %d, count %d)\n",
iface, dstData, start, count);
@@ -4716,7 +4752,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
UINT count) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- int i, cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
+ int i, cnt = min(count, MAX_CONST_I - (start + 1));
TRACE("(iface %p, srcData %p, start %d, count %d)\n",
iface, srcData, start, count);
@@ -4741,7 +4777,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
UINT count) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
+ int cnt = min(count, MAX_CONST_I - (start + 1));
TRACE("(iface %p, dstData %p, start %d, count %d)\n",
iface, dstData, start, count);
@@ -4760,7 +4796,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
UINT count) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- int i, cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
+ int i, cnt = min(count, GL_LIMITS(vshader_constantsF) - (start + 1));
TRACE("(iface %p, srcData %p, start %d, count %d)\n",
iface, srcData, start, count);
@@ -4785,7 +4821,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
UINT count) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
+ int cnt = min(count, GL_LIMITS(vshader_constantsF) - (start + 1));
TRACE("(iface %p, dstData %p, start %d, count %d)\n",
iface, dstData, start, count);
@@ -4846,7 +4882,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
UINT count) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- int i, cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
+ int i, cnt = min(count, MAX_CONST_B - (start + 1));
TRACE("(iface %p, srcData %p, start %d, count %d)\n",
iface, srcData, start, count);
@@ -4871,7 +4907,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
UINT count) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
+ int cnt = min(count, MAX_CONST_B - (start + 1));
TRACE("(iface %p, dstData %p, start %d, count %d)\n",
iface, dstData, start, count);
@@ -4890,7 +4926,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
UINT count) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- int i, cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
+ int i, cnt = min(count, MAX_CONST_I - (start + 1));
TRACE("(iface %p, srcData %p, start %d, count %d)\n",
iface, srcData, start, count);
@@ -4915,7 +4951,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
UINT count) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
+ int cnt = min(count, MAX_CONST_I - (start + 1));
TRACE("(iface %p, dstData %p, start %d, count %d)\n",
iface, dstData, start, count);
@@ -4934,7 +4970,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
UINT count) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- int i, cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
+ int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - (start + 1));
TRACE("(iface %p, srcData %p, start %d, count %d)\n",
iface, srcData, start, count);
@@ -4959,7 +4995,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
UINT count) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
+ int cnt = min(count, GL_LIMITS(pshader_constantsF) - (start + 1));
TRACE("(iface %p, dstData %p, start %d, count %d)\n",
iface, dstData, start, count);
@@ -5796,6 +5832,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl
static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DStateBlockImpl *object;
+ HRESULT temp_result;
+
TRACE("(%p)", This);
if (This->isRecordingState) {
@@ -5807,7 +5845,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl
FIXME("(%p)Error allocating memory for stateblock\n", This);
return E_OUTOFMEMORY;
}
- TRACE("(%p) creted object %p\n", This, object);
+
+ temp_result = allocate_shader_constants(iface, object);
+ if (WINED3D_OK != temp_result)
+ return temp_result;
+
+ TRACE("(%p) created object %p\n", This, object);
object->wineD3DDevice= This;
/** FIXME: object->parent = parent; **/
object->parent = NULL;
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index e7d225b..91383e1 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -762,6 +762,9 @@ #undef USE_GL_FUNC
else
wined3d_settings.shader_mode = SHADER_SW;
+ /* Maximum float constants allowed in the shaders */
+ gl_info->max_vshader_constantsF = vshader_get_max_constantsF();
+ gl_info->max_pshader_constantsF = pshader_get_max_constantsF();
/* If we created a dummy context, throw it away */
if (NULL != fake_ctx) WineD3D_ReleaseFakeGLContext(fake_ctx);
@@ -1736,11 +1739,7 @@ #endif
TRACE_(d3d_caps)("Vertex shader functionality not available\n");
}
- if (This->gl_info.gl_vendor == VENDOR_MESA || This->gl_info.gl_vendor == VENDOR_WINE) {
- *pCaps->MaxVertexShaderConst = 95;
- } else {
- *pCaps->MaxVertexShaderConst = WINED3D_VSHADER_MAX_CONSTANTS;
- }
+ *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
if (wined3d_settings.ps_mode == PS_HW && wined3d_settings.shader_mode == SHADER_GLSL
&& DeviceType != WINED3DDEVTYPE_REF) {
@@ -1849,6 +1848,11 @@ static HRESULT WINAPI IWineD3DImpl_Crea
object->adapterNo = Adapter;
object->devType = DeviceType;
+ /* Setup some defaults for creating the implicit swapchain */
+ ENTER_GL();
+ IWineD3DImpl_FillGLCaps(&This->gl_info, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
+ LEAVE_GL();
+
TRACE("(%p) : Creating stateblock\n", This);
/* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
if (WINED3D_OK != IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
@@ -1861,13 +1865,6 @@ static HRESULT WINAPI IWineD3DImpl_Crea
TRACE("(%p) : Created stateblock (%p)\n", This, object->stateBlock);
object->updateStateBlock = object->stateBlock;
IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
- /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
-
- /* Setup some defaults for creating the implicit swapchain */
- ENTER_GL();
- IWineD3DImpl_FillGLCaps(&This->gl_info, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
- LEAVE_GL();
-
/* set the state of the device to valid */
object->state = WINED3D_OK;
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 94871c0..91674d9 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -207,12 +207,12 @@ void shader_glsl_load_constants(
if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) {
/* Load DirectX 8 float constants/uniforms for vertex shader */
- shader_glsl_load_constantsF(gl_info, programId, WINED3D_VSHADER_MAX_CONSTANTS,
+ shader_glsl_load_constantsF(gl_info, programId, GL_LIMITS(vshader_constantsF),
vertexDeclaration->constants, NULL, 0);
}
/* Load DirectX 9 float constants/uniforms for vertex shader */
- shader_glsl_load_constantsF(gl_info, programId, WINED3D_VSHADER_MAX_CONSTANTS,
+ shader_glsl_load_constantsF(gl_info, programId, GL_LIMITS(vshader_constantsF),
stateBlock->vertexShaderConstantF,
stateBlock->set.vertexShaderConstantsF, 0);
@@ -233,7 +233,7 @@ void shader_glsl_load_constants(
shader_glsl_load_psamplers(gl_info, iface);
/* Load DirectX 9 float constants/uniforms for pixel shader */
- shader_glsl_load_constantsF(gl_info, programId, WINED3D_PSHADER_MAX_CONSTANTS,
+ shader_glsl_load_constantsF(gl_info, programId, GL_LIMITS(pshader_constantsF),
stateBlock->pixelShaderConstantF,
stateBlock->set.pixelShaderConstantsF, 1);
@@ -253,7 +253,8 @@ void shader_glsl_load_constants(
void shader_generate_glsl_declarations(
IWineD3DBaseShader *iface,
shader_reg_maps* reg_maps,
- SHADER_BUFFER* buffer) {
+ SHADER_BUFFER* buffer,
+ WineD3D_GL_Info* gl_info) {
IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
int i;
@@ -263,8 +264,11 @@ void shader_generate_glsl_declarations(
char prefix = pshader ? 'P' : 'V';
/* Declare the constants (aka uniforms) */
- if (This->baseShader.limits.constant_float > 0)
- shader_addline(buffer, "uniform vec4 %cC[%u];\n", prefix, This->baseShader.limits.constant_float);
+ if (This->baseShader.limits.constant_float > 0) {
+ unsigned max_constantsF = min(This->baseShader.limits.constant_float,
+ (pshader ? GL_LIMITS(pshader_constantsF) : GL_LIMITS(vshader_constantsF)) - reg_maps->num_local_constants);
+ shader_addline(buffer, "uniform vec4 %cC[%u];\n", prefix, max_constantsF);
+ }
if (This->baseShader.limits.constant_int > 0)
shader_addline(buffer, "uniform ivec4 %cI[%u];\n", prefix, This->baseShader.limits.constant_int);
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index 532be0b..12a9f25 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -32,6 +32,26 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
#define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
+/** Returns the maximum allowable pixel shader constants/uniforms based on GL Maximums */
+int pshader_get_max_constantsF() {
+
+ int gl_max;
+
+ if (wined3d_settings.shader_mode == SHADER_GLSL) {
+ glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
+ checkGLcall("glGetIntegerv");
+
+ } else if (wined3d_settings.shader_mode == SHADER_ARB) {
+ glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max);
+ checkGLcall("glGetProgramivARB");
+
+ } else {
+ /* TODO: Fixup software shaders */
+ gl_max = 96;
+ }
+ return gl_max;
+}
+
#if 0 /* Must not be 1 in cvs version */
# define PSTRACE(A) TRACE A
# define TRACE_VSVECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w)
@@ -1313,6 +1333,7 @@ inline static VOID IWineD3DPixelShaderIm
memset(®_maps, 0, sizeof(shader_reg_maps));
memset(semantics_in, 0, WINED3DSHADERDECLUSAGE_MAX_USAGE * sizeof(DWORD));
+ reg_maps.constantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, GL_LIMITS(pshader_constantsF));
reg_maps.semantics_in = semantics_in;
reg_maps.semantics_out = NULL;
shader_get_registers_used((IWineD3DBaseShader*) This, ®_maps, pFunction);
@@ -1339,7 +1360,7 @@ #endif
GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
/* Base Declarations */
- shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, ®_maps, &buffer);
+ shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, ®_maps, &buffer, &GLINFO_LOCATION);
/* Pack 3.0 inputs */
if (This->baseShader.hex_version >= D3DPS_VERSION(3,0))
@@ -1375,7 +1396,7 @@ #endif
shader_addline(&buffer, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
/* Base Declarations */
- shader_generate_arb_declarations( (IWineD3DBaseShader*) This, ®_maps, &buffer);
+ shader_generate_arb_declarations( (IWineD3DBaseShader*) This, ®_maps, &buffer, &GLINFO_LOCATION);
/* Base Shader Body */
shader_generate_main( (IWineD3DBaseShader*) This, &buffer, ®_maps, pFunction);
@@ -1404,6 +1425,8 @@ #endif
}
}
+ HeapFree(GetProcessHeap(), 0, reg_maps.constantsF);
+
#if 1 /* if were using the data buffer of device then we don't need to free it */
HeapFree(GetProcessHeap(), 0, buffer.buffer);
#endif
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c
index 5d26682..4f614af 100644
--- a/dlls/wined3d/stateblock.c
+++ b/dlls/wined3d/stateblock.c
@@ -88,7 +88,14 @@ static ULONG WINAPI IWineD3DStateBlockI
if (NULL != This->vertexDecl) {
IWineD3DVertexDeclaration_Release(This->vertexDecl);
}
-
+
+ HeapFree(GetProcessHeap(), 0, This->vertexShaderConstantF);
+ HeapFree(GetProcessHeap(), 0, This->set.vertexShaderConstantsF);
+ HeapFree(GetProcessHeap(), 0, This->changed.vertexShaderConstantsF);
+ HeapFree(GetProcessHeap(), 0, This->pixelShaderConstantF);
+ HeapFree(GetProcessHeap(), 0, This->set.pixelShaderConstantsF);
+ HeapFree(GetProcessHeap(), 0, This->changed.pixelShaderConstantsF);
+
/* NOTE: according to MSDN: The application is responsible for making sure the texture references are cleared down */
for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
if (This->textures[counter]) {
@@ -166,9 +173,8 @@ static HRESULT WINAPI IWineD3DStateBloc
This->vertexShader = targetStateBlock->vertexShader;
}
- /* Vertex Shader Constants */
- for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
-
+ /* Vertex Shader Float Constants */
+ for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) {
if (This->set.vertexShaderConstantsF[i]) {
TRACE("Setting %p from %p %d to { %f, %f, %f, %f }\n", This, targetStateBlock, i,
targetStateBlock->vertexShaderConstantF[i * 4],
@@ -181,7 +187,10 @@ static HRESULT WINAPI IWineD3DStateBloc
This->vertexShaderConstantF[i * 4 + 2] = targetStateBlock->vertexShaderConstantF[i * 4 + 2];
This->vertexShaderConstantF[i * 4 + 3] = targetStateBlock->vertexShaderConstantF[i * 4 + 3];
}
-
+ }
+
+ /* Vertex Shader Integer Constants */
+ for (i = 0; i < MAX_CONST_I; ++i) {
if (This->set.vertexShaderConstantsI[i]) {
TRACE("Setting %p from %p %d to { %d, %d, %d, %d }\n", This, targetStateBlock, i,
targetStateBlock->vertexShaderConstantI[i * 4],
@@ -194,7 +203,10 @@ static HRESULT WINAPI IWineD3DStateBloc
This->vertexShaderConstantI[i * 4 + 2] = targetStateBlock->vertexShaderConstantI[i * 4 + 2];
This->vertexShaderConstantI[i * 4 + 3] = targetStateBlock->vertexShaderConstantI[i * 4 + 3];
}
-
+ }
+
+ /* Vertex Shader Boolean Constants */
+ for (i = 0; i < MAX_CONST_B; ++i) {
if (This->set.vertexShaderConstantsB[i]) {
TRACE("Setting %p from %p %d to %s\n", This, targetStateBlock, i,
targetStateBlock->vertexShaderConstantB[i]? "TRUE":"FALSE");
@@ -202,7 +214,7 @@ static HRESULT WINAPI IWineD3DStateBloc
This->vertexShaderConstantB[i] = targetStateBlock->vertexShaderConstantB[i];
}
}
-
+
/* Lights... For a recorded state block, we just had a chain of actions to perform,
so we need to walk that chain and update any actions which differ */
src = This->lights;
@@ -249,8 +261,8 @@ static HRESULT WINAPI IWineD3DStateBloc
This->pixelShader = targetStateBlock->pixelShader;
}
- for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
-
+ /* Pixel Shader Float Constants */
+ for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) {
if (This->set.pixelShaderConstantsF[i]) {
TRACE("Setting %p from %p %d to { %f, %f, %f, %f }\n", This, targetStateBlock, i,
targetStateBlock->pixelShaderConstantF[i * 4],
@@ -263,7 +275,10 @@ static HRESULT WINAPI IWineD3DStateBloc
This->pixelShaderConstantF[i * 4 + 2] = targetStateBlock->pixelShaderConstantF[i * 4 + 2];
This->pixelShaderConstantF[i * 4 + 3] = targetStateBlock->pixelShaderConstantF[i * 4 + 3];
}
-
+ }
+
+ /* Pixel Shader Integer Constants */
+ for (i = 0; i < MAX_CONST_I; ++i) {
if (This->set.pixelShaderConstantsI[i]) {
TRACE("Setting %p from %p %d to { %d, %d, %d, %d }\n", This, targetStateBlock, i,
targetStateBlock->pixelShaderConstantI[i * 4],
@@ -276,7 +291,10 @@ static HRESULT WINAPI IWineD3DStateBloc
This->pixelShaderConstantI[i * 4 + 2] = targetStateBlock->pixelShaderConstantI[i * 4 + 2];
This->pixelShaderConstantI[i * 4 + 3] = targetStateBlock->pixelShaderConstantI[i * 4 + 3];
}
-
+ }
+
+ /* Pixel Shader Boolean Constants */
+ for (i = 0; i < MAX_CONST_B; ++i) {
if (This->set.pixelShaderConstantsB[i]) {
TRACE("Setting %p from %p %d to %s\n", This, targetStateBlock, i,
targetStateBlock->pixelShaderConstantB[i]? "TRUE":"FALSE");
@@ -442,16 +460,17 @@ should really perform a delta so that on
}
/* Vertex Shader Constants */
- for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
+ for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i)
if (This->set.vertexShaderConstantsF[i] && This->changed.vertexShaderConstantsF[i])
IWineD3DDevice_SetVertexShaderConstantF(pDevice, i, This->vertexShaderConstantF + i * 4, 1);
+ for (i = 0; i < MAX_CONST_I; i++)
if (This->set.vertexShaderConstantsI[i] && This->changed.vertexShaderConstantsI[i])
IWineD3DDevice_SetVertexShaderConstantI(pDevice, i, This->vertexShaderConstantI + i * 4, 1);
+ for (i = 0; i < MAX_CONST_B; i++)
if (This->set.vertexShaderConstantsB[i] && This->changed.vertexShaderConstantsB[i])
IWineD3DDevice_SetVertexShaderConstantB(pDevice, i, This->vertexShaderConstantB + i, 1);
- }
}
if (/*TODO: 'magic' statetype, replace with BOOL This->blockType == D3DSBT_RECORDED || */ This->blockType == D3DSBT_ALL || This->blockType == D3DSBT_PIXELSTATE) {
@@ -462,13 +481,17 @@ should really perform a delta so that on
}
/* Pixel Shader Constants */
- for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
+ for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) {
if (This->set.pixelShaderConstantsF[i] && This->changed.pixelShaderConstantsF[i])
IWineD3DDevice_SetPixelShaderConstantF(pDevice, i, This->pixelShaderConstantF + i * 4, 1);
+ }
+ for (i = 0; i < MAX_CONST_I; i++) {
if (This->set.pixelShaderConstantsI[i] && This->changed.pixelShaderConstantsI[i])
IWineD3DDevice_SetPixelShaderConstantI(pDevice, i, This->pixelShaderConstantI + i * 4, 1);
-
+ }
+
+ for (i = 0; i < MAX_CONST_B; i++) {
if (This->set.pixelShaderConstantsB[i] && This->changed.pixelShaderConstantsB[i])
IWineD3DDevice_SetPixelShaderConstantB(pDevice, i, This->pixelShaderConstantB + i, 1);
}
diff --git a/dlls/wined3d/vertexdeclaration.c b/dlls/wined3d/vertexdeclaration.c
index 5cd014f..c6c6a49 100644
--- a/dlls/wined3d/vertexdeclaration.c
+++ b/dlls/wined3d/vertexdeclaration.c
@@ -307,7 +307,8 @@ #define MAKE_LOOKUP(_reg,_usage,_usagein
DWORD count = ((token & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT);
DWORD constaddress = ((token & D3DVSD_CONSTADDRESSMASK) >> D3DVSD_CONSTADDRESSSHIFT);
if (This->constants == NULL ) {
- This->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_VSHADER_CONSTANTS * 4 * sizeof(float));
+ This->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ vshader_get_max_constantsF() * 4 * sizeof(float));
}
TRACE(" 0x%08lx CONST(%lu, %lu)\n", token, constaddress, count);
for (i = 0; i < count; ++i) {
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index 86eff1f..eaf1c82 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -32,6 +32,33 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
#define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
+/** Returns the maximum float constants/uniforms that a vertex shader can have */
+int vshader_get_max_constantsF() {
+
+ int gl_max;
+
+ if (wined3d_settings.shader_mode == SHADER_GLSL) {
+ glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
+ checkGLcall("glGetIntegerv");
+ /* FIXME:
+ * GL has a maximum number of Uniforms allowed in a single linked program.
+ * To abide by this, we need to subtract the sum of all the other uniforms
+ * that we may be using. If apps need to use the full 256 constants for shaders 3.0,
+ * and the hardware won't support that many uniforms, this will pose a problem.
+ */
+ gl_max = gl_max - MAX_CONST_B - MAX_CONST_I - MAX_SAMPLERS;
+
+ } else if (wined3d_settings.shader_mode == SHADER_ARB) {
+ glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max);
+ checkGLcall("glGetProgramivARB");
+
+ } else {
+ /* TODO: Fixup software shaders */
+ gl_max = 96;
+ }
+ return gl_max;
+}
+
/* Shader debugging - Change the following line to enable debugging of software
vertex shaders */
#if 0 /* Musxt not be 1 in cvs version */
@@ -715,7 +742,7 @@ static void vshader_set_limits(
This->baseShader.limits.packed_input = 0;
/* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
- This->baseShader.limits.constant_float = WINED3D_VSHADER_MAX_CONSTANTS;
+ This->baseShader.limits.constant_float = GL_LIMITS(vshader_constantsF);
switch (This->baseShader.hex_version) {
case D3DVS_VERSION(1,0):
@@ -846,6 +873,7 @@ inline static VOID IWineD3DVertexShaderI
memset(®_maps, 0, sizeof(shader_reg_maps));
memset(semantics_out, 0, WINED3DSHADERDECLUSAGE_MAX_USAGE * sizeof(DWORD));
+ reg_maps.constantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, GL_LIMITS(vshader_constantsF));
reg_maps.semantics_in = This->arrayUsageMap;
reg_maps.semantics_out = semantics_out;
shader_get_registers_used((IWineD3DBaseShader*) This, ®_maps, pFunction);
@@ -872,7 +900,7 @@ #endif
GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
/* Base Declarations */
- shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, ®_maps, &buffer);
+ shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, ®_maps, &buffer, &GLINFO_LOCATION);
/* Base Shader Body */
shader_generate_main( (IWineD3DBaseShader*) This, &buffer, ®_maps, pFunction);
@@ -896,13 +924,8 @@ #endif
/* Create the hw ARB shader */
shader_addline(&buffer, "!!ARBvp1.0\n");
- /* Mesa supports only 95 constants */
- if (GL_VEND(MESA) || GL_VEND(WINE))
- This->baseShader.limits.constant_float =
- min(95, This->baseShader.limits.constant_float);
-
/* Base Declarations */
- shader_generate_arb_declarations( (IWineD3DBaseShader*) This, ®_maps, &buffer);
+ shader_generate_arb_declarations( (IWineD3DBaseShader*) This, ®_maps, &buffer, &GLINFO_LOCATION);
/* Base Shader Body */
shader_generate_main( (IWineD3DBaseShader*) This, &buffer, ®_maps, pFunction);
@@ -929,6 +952,8 @@ #endif
}
}
+ HeapFree(GetProcessHeap(), 0, reg_maps.constantsF);
+
#if 1 /* if were using the data buffer of device then we don't need to free it */
HeapFree(GetProcessHeap(), 0, buffer.buffer);
#endif
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 53dee67..301d03b 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -53,8 +53,8 @@ #define MAX_ACTIVE_LIGHTS 8
#define MAX_CLIPPLANES D3DMAXUSERCLIPPLANES
#define MAX_LEVELS 256
-#define MAX_VSHADER_CONSTANTS 96
-#define MAX_PSHADER_CONSTANTS 32
+#define MAX_CONST_I 16
+#define MAX_CONST_B 16
/* Used for CreateStateBlock */
#define NUM_SAVEDPIXELSTATES_R 35
@@ -1012,13 +1012,13 @@ typedef struct SAVEDSTATES {
BOOL clipplane[MAX_CLIPPLANES];
BOOL vertexDecl;
BOOL pixelShader;
- BOOL pixelShaderConstantsB[MAX_PSHADER_CONSTANTS];
- BOOL pixelShaderConstantsI[MAX_PSHADER_CONSTANTS];
- BOOL pixelShaderConstantsF[MAX_PSHADER_CONSTANTS];
+ BOOL pixelShaderConstantsB[MAX_CONST_B];
+ BOOL pixelShaderConstantsI[MAX_CONST_I];
+ BOOL *pixelShaderConstantsF;
BOOL vertexShader;
- BOOL vertexShaderConstantsB[MAX_VSHADER_CONSTANTS];
- BOOL vertexShaderConstantsI[MAX_VSHADER_CONSTANTS];
- BOOL vertexShaderConstantsF[MAX_VSHADER_CONSTANTS];
+ BOOL vertexShaderConstantsB[MAX_CONST_B];
+ BOOL vertexShaderConstantsI[MAX_CONST_I];
+ BOOL *vertexShaderConstantsF;
} SAVEDSTATES;
struct IWineD3DStateBlockImpl
@@ -1044,9 +1044,9 @@ struct IWineD3DStateBlockImpl
IWineD3DVertexShader *vertexShader;
/* Vertex Shader Constants */
- BOOL vertexShaderConstantB[MAX_VSHADER_CONSTANTS];
- INT vertexShaderConstantI[MAX_VSHADER_CONSTANTS * 4];
- float vertexShaderConstantF[MAX_VSHADER_CONSTANTS * 4];
+ BOOL vertexShaderConstantB[MAX_CONST_B];
+ INT vertexShaderConstantI[MAX_CONST_I * 4];
+ float *vertexShaderConstantF;
/* Stream Source */
BOOL streamIsUP;
@@ -1080,9 +1080,9 @@ struct IWineD3DStateBlockImpl
IWineD3DPixelShader *pixelShader;
/* Pixel Shader Constants */
- BOOL pixelShaderConstantB[MAX_PSHADER_CONSTANTS];
- INT pixelShaderConstantI[MAX_PSHADER_CONSTANTS * 4];
- float pixelShaderConstantF[MAX_PSHADER_CONSTANTS * 4];
+ BOOL pixelShaderConstantB[MAX_CONST_B];
+ INT pixelShaderConstantI[MAX_CONST_I * 4];
+ float *pixelShaderConstantF;
/* Indexed Vertex Blending */
D3DVERTEXBLENDFLAGS vertex_blend;
@@ -1277,9 +1277,6 @@ #define MAX_REG_TEXCRD 8
#define MAX_REG_INPUT 12
#define MAX_REG_OUTPUT 12
#define MAX_ATTRIBS 16
-#define MAX_CONST_F 256
-#define MAX_CONST_I 16
-#define MAX_CONST_B 16
typedef struct shader_reg_maps {
@@ -1290,10 +1287,12 @@ typedef struct shader_reg_maps {
char packed_output[MAX_REG_OUTPUT]; /* vertex >= 3.0 */
char attributes[MAX_ATTRIBS]; /* vertex */
- char constantsF[MAX_CONST_F]; /* pixel, vertex */
+ char *constantsF; /* pixel, vertex */
char constantsI[MAX_CONST_I]; /* pixel & vertex >= 2.0 */
char constantsB[MAX_CONST_B]; /* pixel & vertex >= 2.0 */
-
+
+ int num_local_constants; /* pixel, vertex */
+
/* Semantics maps (semantic -> reg_token)
* Use 0 as default (bit 31 is always 1 on a valid token) */
DWORD* semantics_in; /* vertex, pixel */
@@ -1370,6 +1369,9 @@ extern const SHADER_OPCODE* shader_get_o
IWineD3DBaseShader *iface,
const DWORD code);
+extern int vshader_get_max_constantsF();
+extern int pshader_get_max_constantsF();
+
/* ARB_[vertex/fragment]_program helper functions */
extern void shader_arb_load_constants(
IWineD3DStateBlock* iface,
@@ -1458,12 +1460,14 @@ extern void shader_get_registers_used(
extern void shader_generate_glsl_declarations(
IWineD3DBaseShader *iface,
shader_reg_maps* reg_maps,
- SHADER_BUFFER* buffer);
+ SHADER_BUFFER* buffer,
+ WineD3D_GL_Info* gl_info);
extern void shader_generate_arb_declarations(
IWineD3DBaseShader *iface,
shader_reg_maps* reg_maps,
- SHADER_BUFFER* buffer);
+ SHADER_BUFFER* buffer,
+ WineD3D_GL_Info* gl_info);
extern void shader_generate_main(
IWineD3DBaseShader *iface,
diff --git a/include/wine/wined3d_gl.h b/include/wine/wined3d_gl.h
index 038cbaf..0636d06 100644
--- a/include/wine/wined3d_gl.h
+++ b/include/wine/wined3d_gl.h
@@ -1679,6 +1679,9 @@ typedef struct _WineD3D_GL_Info {
UINT max_blends;
UINT max_anisotropy;
+ unsigned max_vshader_constantsF;
+ unsigned max_pshader_constantsF;
+
GL_PSVersion ps_arb_version;
GL_PSVersion ps_nv_version;
More information about the wine-patches
mailing list