wined3d: Implement a different constant dirtification algorithm.
Add a new property of the shader backend which indicates whether the shader backend is able to dirtify single constants rather than dirtifying vshader and pshader constants as a whole. Depending on this a different Set*ConstantF implementation is used which marks constants dirty. The ARB shader backend uses this and marks constants clean after uploading.
This commit is contained in:
parent
1dca65607b
commit
107e80a79c
|
@ -48,60 +48,51 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d_constants);
|
||||||
* @target_type should be either GL_VERTEX_PROGRAM_ARB (for vertex shaders)
|
* @target_type should be either GL_VERTEX_PROGRAM_ARB (for vertex shaders)
|
||||||
* or GL_FRAGMENT_PROGRAM_ARB (for pixel shaders)
|
* or GL_FRAGMENT_PROGRAM_ARB (for pixel shaders)
|
||||||
*/
|
*/
|
||||||
static void shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_Info *gl_info, GLuint target_type,
|
static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_Info *gl_info, GLuint target_type,
|
||||||
unsigned int max_constants, float* constants, struct list *constant_list) {
|
unsigned int max_constants, float* constants, char *dirty_consts) {
|
||||||
constants_entry *constant;
|
|
||||||
local_constant* lconst;
|
local_constant* lconst;
|
||||||
DWORD i, j, k;
|
DWORD i, j;
|
||||||
DWORD *idx;
|
unsigned int ret;
|
||||||
|
|
||||||
if (TRACE_ON(d3d_shader)) {
|
if (TRACE_ON(d3d_shader)) {
|
||||||
LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) {
|
for(i = 0; i < max_constants; i++) {
|
||||||
idx = constant->idx;
|
if(!dirty_consts[i]) continue;
|
||||||
j = constant->count;
|
TRACE_(d3d_constants)("Loading constants %i: %f, %f, %f, %f\n", i,
|
||||||
while (j--) {
|
|
||||||
i = *idx++;
|
|
||||||
TRACE_(d3d_constants)("Loading constants %i: %f, %f, %f, %f\n", i,
|
|
||||||
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]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* In 1.X pixel shaders constants are implicitly clamped in the range [-1;1] */
|
/* In 1.X pixel shaders constants are implicitly clamped in the range [-1;1] */
|
||||||
if(target_type == GL_FRAGMENT_PROGRAM_ARB &&
|
if(target_type == GL_FRAGMENT_PROGRAM_ARB &&
|
||||||
WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1) {
|
WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1) {
|
||||||
float lcl_const[4];
|
float lcl_const[4];
|
||||||
LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) {
|
for(i = 0; i < max_constants; i++) {
|
||||||
idx = constant->idx;
|
if(!dirty_consts[i]) continue;
|
||||||
j = constant->count;
|
dirty_consts[i] = 0;
|
||||||
while (j--) {
|
|
||||||
i = *idx++;
|
|
||||||
k = i * 4;
|
|
||||||
if(constants[k + 0] > 1.0) lcl_const[0] = 1.0;
|
|
||||||
else if(constants[k + 0] < -1.0) lcl_const[0] = -1.0;
|
|
||||||
else lcl_const[0] = constants[k + 0];
|
|
||||||
|
|
||||||
if(constants[k + 1] > 1.0) lcl_const[1] = 1.0;
|
j = 4 * i;
|
||||||
else if(constants[k + 1] < -1.0) lcl_const[1] = -1.0;
|
if(constants[j + 0] > 1.0) lcl_const[0] = 1.0;
|
||||||
else lcl_const[1] = constants[k + 1];
|
else if(constants[j + 0] < -1.0) lcl_const[0] = -1.0;
|
||||||
|
else lcl_const[0] = constants[j + 0];
|
||||||
|
|
||||||
if(constants[k + 2] > 1.0) lcl_const[2] = 1.0;
|
if(constants[j + 1] > 1.0) lcl_const[1] = 1.0;
|
||||||
else if(constants[k + 2] < -1.0) lcl_const[2] = -1.0;
|
else if(constants[j + 1] < -1.0) lcl_const[1] = -1.0;
|
||||||
else lcl_const[2] = constants[k + 2];
|
else lcl_const[1] = constants[j + 1];
|
||||||
|
|
||||||
if(constants[k + 3] > 1.0) lcl_const[3] = 1.0;
|
if(constants[j + 2] > 1.0) lcl_const[2] = 1.0;
|
||||||
else if(constants[k + 3] < -1.0) lcl_const[3] = -1.0;
|
else if(constants[j + 2] < -1.0) lcl_const[2] = -1.0;
|
||||||
else lcl_const[3] = constants[k + 3];
|
else lcl_const[2] = constants[j + 2];
|
||||||
|
|
||||||
GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, lcl_const));
|
if(constants[j + 3] > 1.0) lcl_const[3] = 1.0;
|
||||||
}
|
else if(constants[j + 3] < -1.0) lcl_const[3] = -1.0;
|
||||||
|
else lcl_const[3] = constants[j + 3];
|
||||||
|
|
||||||
|
GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, lcl_const));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) {
|
for(i = 0; i < max_constants; i++) {
|
||||||
idx = constant->idx;
|
if(dirty_consts[i]) {
|
||||||
j = constant->count;
|
dirty_consts[i] = 0;
|
||||||
while (j--) {
|
|
||||||
i = *idx++;
|
|
||||||
GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, constants + (i * 4)));
|
GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, constants + (i * 4)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,10 +108,14 @@ static void shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Immediate constants are clamped for 1.X shaders at loading times */
|
/* Immediate constants are clamped for 1.X shaders at loading times */
|
||||||
|
ret = 0;
|
||||||
LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
|
LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
|
||||||
|
dirty_consts[lconst->idx] = 1; /* Dirtify so the non-immediate constant overwrites it next time */
|
||||||
|
ret = max(ret, lconst->idx);
|
||||||
GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, lconst->idx, (GLfloat*)lconst->value));
|
GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, lconst->idx, (GLfloat*)lconst->value));
|
||||||
}
|
}
|
||||||
checkGLcall("glProgramEnvParameter4fvARB()");
|
checkGLcall("glProgramEnvParameter4fvARB()");
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -142,10 +137,11 @@ void shader_arb_load_constants(
|
||||||
IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader;
|
IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader;
|
||||||
|
|
||||||
/* Load DirectX 9 float constants for vertex shader */
|
/* Load DirectX 9 float constants for vertex shader */
|
||||||
shader_arb_load_constantsF(vshader, gl_info, GL_VERTEX_PROGRAM_ARB,
|
deviceImpl->highest_dirty_vs_const = shader_arb_load_constantsF(
|
||||||
GL_LIMITS(vshader_constantsF),
|
vshader, gl_info, GL_VERTEX_PROGRAM_ARB,
|
||||||
stateBlock->vertexShaderConstantF,
|
deviceImpl->highest_dirty_vs_const,
|
||||||
&stateBlock->set_vconstantsF);
|
stateBlock->vertexShaderConstantF,
|
||||||
|
deviceImpl->activeContext->vshader_const_dirty);
|
||||||
|
|
||||||
/* Upload the position fixup */
|
/* Upload the position fixup */
|
||||||
GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, ARB_SHADER_PRIVCONST_POS, deviceImpl->posFixup));
|
GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, ARB_SHADER_PRIVCONST_POS, deviceImpl->posFixup));
|
||||||
|
@ -157,10 +153,12 @@ void shader_arb_load_constants(
|
||||||
IWineD3DPixelShaderImpl *psi = (IWineD3DPixelShaderImpl *) pshader;
|
IWineD3DPixelShaderImpl *psi = (IWineD3DPixelShaderImpl *) pshader;
|
||||||
|
|
||||||
/* Load DirectX 9 float constants for pixel shader */
|
/* Load DirectX 9 float constants for pixel shader */
|
||||||
shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB,
|
deviceImpl->highest_dirty_ps_const = shader_arb_load_constantsF(
|
||||||
GL_LIMITS(pshader_constantsF),
|
pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB,
|
||||||
stateBlock->pixelShaderConstantF,
|
deviceImpl->highest_dirty_ps_const,
|
||||||
&stateBlock->set_pconstantsF);
|
stateBlock->pixelShaderConstantF,
|
||||||
|
deviceImpl->activeContext->pshader_const_dirty);
|
||||||
|
|
||||||
if(((IWineD3DPixelShaderImpl *) pshader)->bumpenvmatconst != -1) {
|
if(((IWineD3DPixelShaderImpl *) pshader)->bumpenvmatconst != -1) {
|
||||||
/* needsbumpmat stores the stage number from where to load the matrix. bumpenvmatconst stores the
|
/* needsbumpmat stores the stage number from where to load the matrix. bumpenvmatconst stores the
|
||||||
* number of the constant to load the matrix into.
|
* number of the constant to load the matrix into.
|
||||||
|
@ -177,6 +175,7 @@ void shader_arb_load_constants(
|
||||||
*/
|
*/
|
||||||
float *scale = (float *) &stateBlock->textureState[(int) psi->needsbumpmat][WINED3DTSS_BUMPENVLSCALE];
|
float *scale = (float *) &stateBlock->textureState[(int) psi->needsbumpmat][WINED3DTSS_BUMPENVLSCALE];
|
||||||
GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->luminanceconst, scale));
|
GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->luminanceconst, scale));
|
||||||
|
deviceImpl->activeContext->pshader_const_dirty[psi->luminanceconst] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(((IWineD3DPixelShaderImpl *) pshader)->srgb_enabled &&
|
if(((IWineD3DPixelShaderImpl *) pshader)->srgb_enabled &&
|
||||||
|
@ -200,6 +199,9 @@ void shader_arb_load_constants(
|
||||||
GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->srgb_cmp_const, comparison));
|
GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->srgb_cmp_const, comparison));
|
||||||
GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->srgb_low_const, mul_low));
|
GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->srgb_low_const, mul_low));
|
||||||
checkGLcall("Load sRGB correction constants\n");
|
checkGLcall("Load sRGB correction constants\n");
|
||||||
|
deviceImpl->activeContext->pshader_const_dirty[psi->srgb_low_const] = 1;
|
||||||
|
deviceImpl->activeContext->pshader_const_dirty[psi->srgb_cmp_const] = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1769,6 +1771,10 @@ static void shader_arb_free(IWineD3DDevice *iface) {
|
||||||
HeapFree(GetProcessHeap(), 0, This->shader_priv);
|
HeapFree(GetProcessHeap(), 0, This->shader_priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL shader_arb_dirty_const(IWineD3DDevice *iface) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
const shader_backend_t arb_program_shader_backend = {
|
const shader_backend_t arb_program_shader_backend = {
|
||||||
&shader_arb_select,
|
&shader_arb_select,
|
||||||
&shader_arb_select_depth_blt,
|
&shader_arb_select_depth_blt,
|
||||||
|
@ -1778,6 +1784,7 @@ const shader_backend_t arb_program_shader_backend = {
|
||||||
&shader_arb_color_correction,
|
&shader_arb_color_correction,
|
||||||
&shader_arb_destroy,
|
&shader_arb_destroy,
|
||||||
&shader_arb_alloc,
|
&shader_arb_alloc,
|
||||||
&shader_arb_free
|
&shader_arb_free,
|
||||||
|
&shader_arb_dirty_const
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1104,6 +1104,7 @@ static void shader_none_color_correction(SHADER_OPCODE_ARG* arg) {}
|
||||||
static void shader_none_destroy(IWineD3DBaseShader *iface) {}
|
static void shader_none_destroy(IWineD3DBaseShader *iface) {}
|
||||||
static HRESULT shader_none_alloc(IWineD3DDevice *iface) {return WINED3D_OK;}
|
static HRESULT shader_none_alloc(IWineD3DDevice *iface) {return WINED3D_OK;}
|
||||||
static void shader_none_free(IWineD3DDevice *iface) {}
|
static void shader_none_free(IWineD3DDevice *iface) {}
|
||||||
|
static BOOL shader_none_dirty_const(IWineD3DDevice *iface) {return FALSE;}
|
||||||
|
|
||||||
const shader_backend_t none_shader_backend = {
|
const shader_backend_t none_shader_backend = {
|
||||||
&shader_none_select,
|
&shader_none_select,
|
||||||
|
@ -1114,7 +1115,8 @@ const shader_backend_t none_shader_backend = {
|
||||||
&shader_none_color_correction,
|
&shader_none_color_correction,
|
||||||
&shader_none_destroy,
|
&shader_none_destroy,
|
||||||
&shader_none_alloc,
|
&shader_none_alloc,
|
||||||
&shader_none_free
|
&shader_none_free,
|
||||||
|
&shader_none_dirty_const
|
||||||
};
|
};
|
||||||
|
|
||||||
/* *******************************************
|
/* *******************************************
|
||||||
|
|
|
@ -326,6 +326,17 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
|
||||||
ret->surface = (IWineD3DSurface *) target;
|
ret->surface = (IWineD3DSurface *) target;
|
||||||
ret->isPBuffer = create_pbuffer;
|
ret->isPBuffer = create_pbuffer;
|
||||||
ret->tid = GetCurrentThreadId();
|
ret->tid = GetCurrentThreadId();
|
||||||
|
if(This->shader_backend->shader_dirtifyable_constants((IWineD3DDevice *) This)) {
|
||||||
|
/* Create the dirty constants array and initialize them to dirty */
|
||||||
|
ret->vshader_const_dirty = HeapAlloc(GetProcessHeap(), 0,
|
||||||
|
sizeof(*ret->vshader_const_dirty) * GL_LIMITS(vshader_constantsF));
|
||||||
|
ret->pshader_const_dirty = HeapAlloc(GetProcessHeap(), 0,
|
||||||
|
sizeof(*ret->pshader_const_dirty) * GL_LIMITS(pshader_constantsF));
|
||||||
|
memset(ret->vshader_const_dirty, 1,
|
||||||
|
sizeof(*ret->vshader_const_dirty) * GL_LIMITS(vshader_constantsF));
|
||||||
|
memset(ret->pshader_const_dirty, 1,
|
||||||
|
sizeof(*ret->pshader_const_dirty) * GL_LIMITS(pshader_constantsF));
|
||||||
|
}
|
||||||
|
|
||||||
TRACE("Successfully created new context %p\n", ret);
|
TRACE("Successfully created new context %p\n", ret);
|
||||||
|
|
||||||
|
@ -478,6 +489,8 @@ void DestroyContext(IWineD3DDeviceImpl *This, WineD3DContext *context) {
|
||||||
} else ReleaseDC(context->win_handle, context->hdc);
|
} else ReleaseDC(context->win_handle, context->hdc);
|
||||||
pwglDeleteContext(context->glCtx);
|
pwglDeleteContext(context->glCtx);
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, context->vshader_const_dirty);
|
||||||
|
HeapFree(GetProcessHeap(), 0, context->pshader_const_dirty);
|
||||||
RemoveContextFromArray(This, context);
|
RemoveContextFromArray(This, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -900,6 +913,14 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
|
||||||
ERR("Failed to activate the new context\n");
|
ERR("Failed to activate the new context\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(This->activeContext->vshader_const_dirty) {
|
||||||
|
memset(This->activeContext->vshader_const_dirty, 1,
|
||||||
|
sizeof(This->activeContext->vshader_const_dirty) * GL_LIMITS(vshader_constantsF));
|
||||||
|
}
|
||||||
|
if(This->activeContext->pshader_const_dirty) {
|
||||||
|
memset(This->activeContext->pshader_const_dirty, 1,
|
||||||
|
sizeof(This->activeContext->pshader_const_dirty) * GL_LIMITS(pshader_constantsF));
|
||||||
|
}
|
||||||
This->activeContext = context;
|
This->activeContext = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2116,6 +2116,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR
|
||||||
if(wined3d_settings.logo) {
|
if(wined3d_settings.logo) {
|
||||||
IWineD3DDeviceImpl_LoadLogo(This, wined3d_settings.logo);
|
IWineD3DDeviceImpl_LoadLogo(This, wined3d_settings.logo);
|
||||||
}
|
}
|
||||||
|
This->highest_dirty_ps_const = 0;
|
||||||
|
This->highest_dirty_vs_const = 0;
|
||||||
return WINED3D_OK;
|
return WINED3D_OK;
|
||||||
|
|
||||||
err_out:
|
err_out:
|
||||||
|
@ -3450,6 +3452,41 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
|
||||||
return WINED3D_OK;
|
return WINED3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF_DirtyConst(
|
||||||
|
IWineD3DDevice *iface,
|
||||||
|
UINT start,
|
||||||
|
CONST float *srcData,
|
||||||
|
UINT count) {
|
||||||
|
|
||||||
|
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
TRACE("(iface %p, srcData %p, start %d, count %d)\n",
|
||||||
|
iface, srcData, start, count);
|
||||||
|
|
||||||
|
/* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
|
||||||
|
if (srcData == NULL || start + count > GL_LIMITS(vshader_constantsF) || start > GL_LIMITS(vshader_constantsF))
|
||||||
|
return WINED3DERR_INVALIDCALL;
|
||||||
|
|
||||||
|
memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
|
||||||
|
if(TRACE_ON(d3d)) {
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
|
||||||
|
srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
|
||||||
|
* context. On a context switch the old context will be fully dirtified
|
||||||
|
*/
|
||||||
|
memset(This->activeContext->vshader_const_dirty + start, 1,
|
||||||
|
sizeof(*This->activeContext->vshader_const_dirty) * count);
|
||||||
|
This->highest_dirty_vs_const = max(This->highest_dirty_vs_const, start+count);
|
||||||
|
|
||||||
|
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
|
||||||
|
|
||||||
|
return WINED3D_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
|
static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
|
||||||
IWineD3DDevice *iface,
|
IWineD3DDevice *iface,
|
||||||
UINT start,
|
UINT start,
|
||||||
|
@ -3843,6 +3880,41 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
|
||||||
return WINED3D_OK;
|
return WINED3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF_DirtyConst(
|
||||||
|
IWineD3DDevice *iface,
|
||||||
|
UINT start,
|
||||||
|
CONST float *srcData,
|
||||||
|
UINT count) {
|
||||||
|
|
||||||
|
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
TRACE("(iface %p, srcData %p, start %d, count %d)\n",
|
||||||
|
iface, srcData, start, count);
|
||||||
|
|
||||||
|
/* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
|
||||||
|
if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF))
|
||||||
|
return WINED3DERR_INVALIDCALL;
|
||||||
|
|
||||||
|
memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
|
||||||
|
if(TRACE_ON(d3d)) {
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
|
||||||
|
srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
|
||||||
|
* context. On a context switch the old context will be fully dirtified
|
||||||
|
*/
|
||||||
|
memset(This->activeContext->pshader_const_dirty + start, 1,
|
||||||
|
sizeof(*This->activeContext->pshader_const_dirty) * count);
|
||||||
|
This->highest_dirty_ps_const = max(This->highest_dirty_ps_const, start+count);
|
||||||
|
|
||||||
|
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
|
||||||
|
|
||||||
|
return WINED3D_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
|
static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
|
||||||
IWineD3DDevice *iface,
|
IWineD3DDevice *iface,
|
||||||
UINT start,
|
UINT start,
|
||||||
|
@ -7423,6 +7495,151 @@ const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
|
||||||
IWineD3DDeviceImpl_EnumResources
|
IWineD3DDeviceImpl_EnumResources
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const IWineD3DDeviceVtbl IWineD3DDevice_DirtyConst_Vtbl =
|
||||||
|
{
|
||||||
|
/*** IUnknown methods ***/
|
||||||
|
IWineD3DDeviceImpl_QueryInterface,
|
||||||
|
IWineD3DDeviceImpl_AddRef,
|
||||||
|
IWineD3DDeviceImpl_Release,
|
||||||
|
/*** IWineD3DDevice methods ***/
|
||||||
|
IWineD3DDeviceImpl_GetParent,
|
||||||
|
/*** Creation methods**/
|
||||||
|
IWineD3DDeviceImpl_CreateVertexBuffer,
|
||||||
|
IWineD3DDeviceImpl_CreateIndexBuffer,
|
||||||
|
IWineD3DDeviceImpl_CreateStateBlock,
|
||||||
|
IWineD3DDeviceImpl_CreateSurface,
|
||||||
|
IWineD3DDeviceImpl_CreateTexture,
|
||||||
|
IWineD3DDeviceImpl_CreateVolumeTexture,
|
||||||
|
IWineD3DDeviceImpl_CreateVolume,
|
||||||
|
IWineD3DDeviceImpl_CreateCubeTexture,
|
||||||
|
IWineD3DDeviceImpl_CreateQuery,
|
||||||
|
IWineD3DDeviceImpl_CreateAdditionalSwapChain,
|
||||||
|
IWineD3DDeviceImpl_CreateVertexDeclaration,
|
||||||
|
IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF,
|
||||||
|
IWineD3DDeviceImpl_CreateVertexShader,
|
||||||
|
IWineD3DDeviceImpl_CreatePixelShader,
|
||||||
|
IWineD3DDeviceImpl_CreatePalette,
|
||||||
|
/*** Odd functions **/
|
||||||
|
IWineD3DDeviceImpl_Init3D,
|
||||||
|
IWineD3DDeviceImpl_Uninit3D,
|
||||||
|
IWineD3DDeviceImpl_SetFullscreen,
|
||||||
|
IWineD3DDeviceImpl_SetMultithreaded,
|
||||||
|
IWineD3DDeviceImpl_EvictManagedResources,
|
||||||
|
IWineD3DDeviceImpl_GetAvailableTextureMem,
|
||||||
|
IWineD3DDeviceImpl_GetBackBuffer,
|
||||||
|
IWineD3DDeviceImpl_GetCreationParameters,
|
||||||
|
IWineD3DDeviceImpl_GetDeviceCaps,
|
||||||
|
IWineD3DDeviceImpl_GetDirect3D,
|
||||||
|
IWineD3DDeviceImpl_GetDisplayMode,
|
||||||
|
IWineD3DDeviceImpl_SetDisplayMode,
|
||||||
|
IWineD3DDeviceImpl_GetHWND,
|
||||||
|
IWineD3DDeviceImpl_SetHWND,
|
||||||
|
IWineD3DDeviceImpl_GetNumberOfSwapChains,
|
||||||
|
IWineD3DDeviceImpl_GetRasterStatus,
|
||||||
|
IWineD3DDeviceImpl_GetSwapChain,
|
||||||
|
IWineD3DDeviceImpl_Reset,
|
||||||
|
IWineD3DDeviceImpl_SetDialogBoxMode,
|
||||||
|
IWineD3DDeviceImpl_SetCursorProperties,
|
||||||
|
IWineD3DDeviceImpl_SetCursorPosition,
|
||||||
|
IWineD3DDeviceImpl_ShowCursor,
|
||||||
|
IWineD3DDeviceImpl_TestCooperativeLevel,
|
||||||
|
/*** Getters and setters **/
|
||||||
|
IWineD3DDeviceImpl_SetClipPlane,
|
||||||
|
IWineD3DDeviceImpl_GetClipPlane,
|
||||||
|
IWineD3DDeviceImpl_SetClipStatus,
|
||||||
|
IWineD3DDeviceImpl_GetClipStatus,
|
||||||
|
IWineD3DDeviceImpl_SetCurrentTexturePalette,
|
||||||
|
IWineD3DDeviceImpl_GetCurrentTexturePalette,
|
||||||
|
IWineD3DDeviceImpl_SetDepthStencilSurface,
|
||||||
|
IWineD3DDeviceImpl_GetDepthStencilSurface,
|
||||||
|
IWineD3DDeviceImpl_SetFVF,
|
||||||
|
IWineD3DDeviceImpl_GetFVF,
|
||||||
|
IWineD3DDeviceImpl_SetGammaRamp,
|
||||||
|
IWineD3DDeviceImpl_GetGammaRamp,
|
||||||
|
IWineD3DDeviceImpl_SetIndices,
|
||||||
|
IWineD3DDeviceImpl_GetIndices,
|
||||||
|
IWineD3DDeviceImpl_SetBaseVertexIndex,
|
||||||
|
IWineD3DDeviceImpl_GetBaseVertexIndex,
|
||||||
|
IWineD3DDeviceImpl_SetLight,
|
||||||
|
IWineD3DDeviceImpl_GetLight,
|
||||||
|
IWineD3DDeviceImpl_SetLightEnable,
|
||||||
|
IWineD3DDeviceImpl_GetLightEnable,
|
||||||
|
IWineD3DDeviceImpl_SetMaterial,
|
||||||
|
IWineD3DDeviceImpl_GetMaterial,
|
||||||
|
IWineD3DDeviceImpl_SetNPatchMode,
|
||||||
|
IWineD3DDeviceImpl_GetNPatchMode,
|
||||||
|
IWineD3DDeviceImpl_SetPaletteEntries,
|
||||||
|
IWineD3DDeviceImpl_GetPaletteEntries,
|
||||||
|
IWineD3DDeviceImpl_SetPixelShader,
|
||||||
|
IWineD3DDeviceImpl_GetPixelShader,
|
||||||
|
IWineD3DDeviceImpl_SetPixelShaderConstantB,
|
||||||
|
IWineD3DDeviceImpl_GetPixelShaderConstantB,
|
||||||
|
IWineD3DDeviceImpl_SetPixelShaderConstantI,
|
||||||
|
IWineD3DDeviceImpl_GetPixelShaderConstantI,
|
||||||
|
IWineD3DDeviceImpl_SetPixelShaderConstantF_DirtyConst,
|
||||||
|
IWineD3DDeviceImpl_GetPixelShaderConstantF,
|
||||||
|
IWineD3DDeviceImpl_SetRenderState,
|
||||||
|
IWineD3DDeviceImpl_GetRenderState,
|
||||||
|
IWineD3DDeviceImpl_SetRenderTarget,
|
||||||
|
IWineD3DDeviceImpl_GetRenderTarget,
|
||||||
|
IWineD3DDeviceImpl_SetFrontBackBuffers,
|
||||||
|
IWineD3DDeviceImpl_SetSamplerState,
|
||||||
|
IWineD3DDeviceImpl_GetSamplerState,
|
||||||
|
IWineD3DDeviceImpl_SetScissorRect,
|
||||||
|
IWineD3DDeviceImpl_GetScissorRect,
|
||||||
|
IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
|
||||||
|
IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
|
||||||
|
IWineD3DDeviceImpl_SetStreamSource,
|
||||||
|
IWineD3DDeviceImpl_GetStreamSource,
|
||||||
|
IWineD3DDeviceImpl_SetStreamSourceFreq,
|
||||||
|
IWineD3DDeviceImpl_GetStreamSourceFreq,
|
||||||
|
IWineD3DDeviceImpl_SetTexture,
|
||||||
|
IWineD3DDeviceImpl_GetTexture,
|
||||||
|
IWineD3DDeviceImpl_SetTextureStageState,
|
||||||
|
IWineD3DDeviceImpl_GetTextureStageState,
|
||||||
|
IWineD3DDeviceImpl_SetTransform,
|
||||||
|
IWineD3DDeviceImpl_GetTransform,
|
||||||
|
IWineD3DDeviceImpl_SetVertexDeclaration,
|
||||||
|
IWineD3DDeviceImpl_GetVertexDeclaration,
|
||||||
|
IWineD3DDeviceImpl_SetVertexShader,
|
||||||
|
IWineD3DDeviceImpl_GetVertexShader,
|
||||||
|
IWineD3DDeviceImpl_SetVertexShaderConstantB,
|
||||||
|
IWineD3DDeviceImpl_GetVertexShaderConstantB,
|
||||||
|
IWineD3DDeviceImpl_SetVertexShaderConstantI,
|
||||||
|
IWineD3DDeviceImpl_GetVertexShaderConstantI,
|
||||||
|
IWineD3DDeviceImpl_SetVertexShaderConstantF_DirtyConst,
|
||||||
|
IWineD3DDeviceImpl_GetVertexShaderConstantF,
|
||||||
|
IWineD3DDeviceImpl_SetViewport,
|
||||||
|
IWineD3DDeviceImpl_GetViewport,
|
||||||
|
IWineD3DDeviceImpl_MultiplyTransform,
|
||||||
|
IWineD3DDeviceImpl_ValidateDevice,
|
||||||
|
IWineD3DDeviceImpl_ProcessVertices,
|
||||||
|
/*** State block ***/
|
||||||
|
IWineD3DDeviceImpl_BeginStateBlock,
|
||||||
|
IWineD3DDeviceImpl_EndStateBlock,
|
||||||
|
/*** Scene management ***/
|
||||||
|
IWineD3DDeviceImpl_BeginScene,
|
||||||
|
IWineD3DDeviceImpl_EndScene,
|
||||||
|
IWineD3DDeviceImpl_Present,
|
||||||
|
IWineD3DDeviceImpl_Clear,
|
||||||
|
/*** Drawing ***/
|
||||||
|
IWineD3DDeviceImpl_DrawPrimitive,
|
||||||
|
IWineD3DDeviceImpl_DrawIndexedPrimitive,
|
||||||
|
IWineD3DDeviceImpl_DrawPrimitiveUP,
|
||||||
|
IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
|
||||||
|
IWineD3DDeviceImpl_DrawPrimitiveStrided,
|
||||||
|
IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided,
|
||||||
|
IWineD3DDeviceImpl_DrawRectPatch,
|
||||||
|
IWineD3DDeviceImpl_DrawTriPatch,
|
||||||
|
IWineD3DDeviceImpl_DeletePatch,
|
||||||
|
IWineD3DDeviceImpl_ColorFill,
|
||||||
|
IWineD3DDeviceImpl_UpdateTexture,
|
||||||
|
IWineD3DDeviceImpl_UpdateSurface,
|
||||||
|
IWineD3DDeviceImpl_GetFrontBufferData,
|
||||||
|
/*** object tracking ***/
|
||||||
|
IWineD3DDeviceImpl_ResourceReleased,
|
||||||
|
IWineD3DDeviceImpl_EnumResources
|
||||||
|
};
|
||||||
|
|
||||||
const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
|
const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
|
||||||
WINED3DRS_ALPHABLENDENABLE ,
|
WINED3DRS_ALPHABLENDENABLE ,
|
||||||
|
|
|
@ -2876,6 +2876,14 @@ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prefer the vtable with functions optimized for single dirtifyable objects if the shader
|
||||||
|
* model can deal with that. It is essentially the same, just with adjusted
|
||||||
|
* Set*ShaderConstantF implementations
|
||||||
|
*/
|
||||||
|
if(object->shader_backend->shader_dirtifyable_constants((IWineD3DDevice *) object)) {
|
||||||
|
object->lpVtbl = &IWineD3DDevice_DirtyConst_Vtbl;
|
||||||
|
}
|
||||||
|
|
||||||
/* set the state of the device to valid */
|
/* set the state of the device to valid */
|
||||||
object->state = WINED3D_OK;
|
object->state = WINED3D_OK;
|
||||||
|
|
||||||
|
|
|
@ -3326,6 +3326,11 @@ static void shader_glsl_free(IWineD3DDevice *iface) {
|
||||||
HeapFree(GetProcessHeap(), 0, This->shader_priv);
|
HeapFree(GetProcessHeap(), 0, This->shader_priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL shader_glsl_dirty_const(IWineD3DDevice *iface) {
|
||||||
|
/* TODO: GL_EXT_bindable_uniform can be used to share constants accross shaders */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
const shader_backend_t glsl_shader_backend = {
|
const shader_backend_t glsl_shader_backend = {
|
||||||
&shader_glsl_select,
|
&shader_glsl_select,
|
||||||
&shader_glsl_select_depth_blt,
|
&shader_glsl_select_depth_blt,
|
||||||
|
@ -3335,5 +3340,6 @@ const shader_backend_t glsl_shader_backend = {
|
||||||
&shader_glsl_color_correction,
|
&shader_glsl_color_correction,
|
||||||
&shader_glsl_destroy,
|
&shader_glsl_destroy,
|
||||||
&shader_glsl_alloc,
|
&shader_glsl_alloc,
|
||||||
&shader_glsl_free
|
&shader_glsl_free,
|
||||||
|
&shader_glsl_dirty_const
|
||||||
};
|
};
|
||||||
|
|
|
@ -259,6 +259,7 @@ typedef struct {
|
||||||
void (*shader_destroy)(IWineD3DBaseShader *iface);
|
void (*shader_destroy)(IWineD3DBaseShader *iface);
|
||||||
HRESULT (*shader_alloc_private)(IWineD3DDevice *iface);
|
HRESULT (*shader_alloc_private)(IWineD3DDevice *iface);
|
||||||
void (*shader_free_private)(IWineD3DDevice *iface);
|
void (*shader_free_private)(IWineD3DDevice *iface);
|
||||||
|
BOOL (*shader_dirtifyable_constants)(IWineD3DDevice *iface);
|
||||||
} shader_backend_t;
|
} shader_backend_t;
|
||||||
|
|
||||||
extern const shader_backend_t glsl_shader_backend;
|
extern const shader_backend_t glsl_shader_backend;
|
||||||
|
@ -575,6 +576,8 @@ struct WineD3DContext {
|
||||||
char texShaderBumpMap;
|
char texShaderBumpMap;
|
||||||
BOOL fog_coord;
|
BOOL fog_coord;
|
||||||
|
|
||||||
|
char *vshader_const_dirty, *pshader_const_dirty;
|
||||||
|
|
||||||
/* The actual opengl context */
|
/* The actual opengl context */
|
||||||
HGLRC glCtx;
|
HGLRC glCtx;
|
||||||
HWND win_handle;
|
HWND win_handle;
|
||||||
|
@ -749,6 +752,7 @@ struct IWineD3DDeviceImpl
|
||||||
|
|
||||||
struct list resources; /* a linked list to track resources created by the device */
|
struct list resources; /* a linked list to track resources created by the device */
|
||||||
struct list shaders; /* a linked list to track shaders (pixel and vertex) */
|
struct list shaders; /* a linked list to track shaders (pixel and vertex) */
|
||||||
|
unsigned int highest_dirty_ps_const, highest_dirty_vs_const;
|
||||||
|
|
||||||
/* Render Target Support */
|
/* Render Target Support */
|
||||||
IWineD3DSurface **render_targets;
|
IWineD3DSurface **render_targets;
|
||||||
|
@ -842,7 +846,7 @@ struct IWineD3DDeviceImpl
|
||||||
struct WineD3DRectPatch *currentPatch;
|
struct WineD3DRectPatch *currentPatch;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl;
|
extern const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl, IWineD3DDevice_DirtyConst_Vtbl;
|
||||||
|
|
||||||
HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, DWORD Count,
|
HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, DWORD Count,
|
||||||
CONST WINED3DRECT* pRects, DWORD Flags, WINED3DCOLOR Color,
|
CONST WINED3DRECT* pRects, DWORD Flags, WINED3DCOLOR Color,
|
||||||
|
|
Loading…
Reference in New Issue