wined3d: Support more than one texbem instruction per shader.

This commit is contained in:
Stefan Dösinger 2008-03-05 03:18:55 +01:00 committed by Alexandre Julliard
parent 739278baf1
commit 167a271434
6 changed files with 140 additions and 83 deletions

View File

@ -153,6 +153,7 @@ void shader_arb_load_constants(
IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) device; IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) device;
IWineD3DStateBlockImpl* stateBlock = deviceImpl->stateBlock; IWineD3DStateBlockImpl* stateBlock = deviceImpl->stateBlock;
WineD3D_GL_Info *gl_info = &deviceImpl->adapter->gl_info; WineD3D_GL_Info *gl_info = &deviceImpl->adapter->gl_info;
unsigned char i;
if (useVertexShader) { if (useVertexShader) {
IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader; IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader;
@ -180,25 +181,25 @@ void shader_arb_load_constants(
stateBlock->pixelShaderConstantF, stateBlock->pixelShaderConstantF,
deviceImpl->activeContext->pshader_const_dirty); deviceImpl->activeContext->pshader_const_dirty);
if(((IWineD3DPixelShaderImpl *) pshader)->bumpenvmatconst != -1) { for(i = 0; i < psi->numbumpenvmatconsts; i++) {
/* needsbumpmat stores the stage number from where to load the matrix. bumpenvmatconst stores the /* The state manager takes care that this function is always called if the bump env matrix changes
* number of the constant to load the matrix into.
* The state manager takes care that this function is always called if the bump env matrix changes
*/ */
float *data = (float *) &stateBlock->textureState[(int) psi->needsbumpmat][WINED3DTSS_BUMPENVMAT00]; float *data = (float *) &stateBlock->textureState[(int) psi->bumpenvmatconst[i].texunit][WINED3DTSS_BUMPENVMAT00];
GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->bumpenvmatconst, data)); GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->bumpenvmatconst[i].const_num, data));
deviceImpl->activeContext->pshader_const_dirty[psi->bumpenvmatconst[i].const_num] = 1;
if(((IWineD3DPixelShaderImpl *) pshader)->luminanceconst != -1) { if(psi->luminanceconst[i].const_num != -1) {
/* WINED3DTSS_BUMPENVLSCALE and WINED3DTSS_BUMPENVLOFFSET are next to each other. /* WINED3DTSS_BUMPENVLSCALE and WINED3DTSS_BUMPENVLOFFSET are next to each other.
* point gl to the scale, and load 4 floats. x = scale, y = offset, z and w are junk, we * point gl to the scale, and load 4 floats. x = scale, y = offset, z and w are junk, we
* don't care about them. The pointers are valid for sure because the stateblock is bigger. * don't care about them. The pointers are valid for sure because the stateblock is bigger.
* (they're WINED3DTSS_TEXTURETRANSFORMFLAGS and WINED3DTSS_ADDRESSW, so most likely 0 or NaN * (they're WINED3DTSS_TEXTURETRANSFORMFLAGS and WINED3DTSS_ADDRESSW, so most likely 0 or NaN
*/ */
float *scale = (float *) &stateBlock->textureState[(int) psi->needsbumpmat][WINED3DTSS_BUMPENVLSCALE]; float *scale = (float *) &stateBlock->textureState[(int) psi->luminanceconst[i].texunit][WINED3DTSS_BUMPENVLSCALE];
GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->luminanceconst, scale)); GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->luminanceconst[i].const_num, scale));
deviceImpl->activeContext->pshader_const_dirty[psi->luminanceconst] = 1; deviceImpl->activeContext->pshader_const_dirty[psi->luminanceconst[i].const_num] = 1;
} }
} }
if(((IWineD3DPixelShaderImpl *) pshader)->srgb_enabled && if(((IWineD3DPixelShaderImpl *) pshader)->srgb_enabled &&
!((IWineD3DPixelShaderImpl *) pshader)->srgb_mode_hardcoded) { !((IWineD3DPixelShaderImpl *) pshader)->srgb_mode_hardcoded) {
float comparison[4]; float comparison[4];
@ -236,7 +237,7 @@ void shader_generate_arb_declarations(
IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface; IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device;
DWORD i; DWORD i, cur;
char pshader = shader_is_pshader_version(This->baseShader.hex_version); char pshader = shader_is_pshader_version(This->baseShader.hex_version);
unsigned max_constantsF = min(This->baseShader.limits.constant_float, unsigned max_constantsF = min(This->baseShader.limits.constant_float,
(pshader ? GL_LIMITS(pshader_constantsF) : GL_LIMITS(vshader_constantsF))); (pshader ? GL_LIMITS(pshader_constantsF) : GL_LIMITS(vshader_constantsF)));
@ -267,29 +268,41 @@ void shader_generate_arb_declarations(
shader_addline(buffer, "MOV T%u, fragment.texcoord[%u];\n", i, i); shader_addline(buffer, "MOV T%u, fragment.texcoord[%u];\n", i, i);
} }
((IWineD3DPixelShaderImpl *)This)->bumpenvmatconst = -1; for(i = 0; i < (sizeof(reg_maps->bumpmat) / sizeof(reg_maps->bumpmat[0])); i++) {
((IWineD3DPixelShaderImpl *)This)->luminanceconst = -1; IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) This;
if(reg_maps->bumpmat != -1 /* Only a pshader can use texbem */) { if(!reg_maps->bumpmat[i]) continue;
cur = ps->numbumpenvmatconsts;
ps->bumpenvmatconst[cur].const_num = -1;
ps->bumpenvmatconst[cur].texunit = i;
ps->luminanceconst[cur].const_num = -1;
ps->luminanceconst[cur].texunit = i;
/* If the shader does not use all available constants, use the next free constant to load the bump mapping environment matrix from /* If the shader does not use all available constants, use the next free constant to load the bump mapping environment matrix from
* the stateblock into the shader. If no constant is available don't load, texbem will then just sample the texture without applying * the stateblock into the shader. If no constant is available don't load, texbem will then just sample the texture without applying
* bump mapping. * bump mapping.
*/ */
if(max_constantsF < GL_LIMITS(pshader_constantsF)) { if(max_constantsF + extra_constants_needed < GL_LIMITS(pshader_constantsF)) {
((IWineD3DPixelShaderImpl *)This)->bumpenvmatconst = max_constantsF; ps->bumpenvmatconst[cur].const_num = max_constantsF + extra_constants_needed;
shader_addline(buffer, "PARAM bumpenvmat%d = program.env[%d];\n", reg_maps->bumpmat, ((IWineD3DPixelShaderImpl *)This)->bumpenvmatconst); shader_addline(buffer, "PARAM bumpenvmat%d = program.env[%d];\n",
i, ps->bumpenvmatconst[cur].const_num);
extra_constants_needed++;
if(reg_maps->luminanceparams != -1 && max_constantsF +1 < GL_LIMITS(pshader_constantsF)) { if(reg_maps->luminanceparams && max_constantsF + extra_constants_needed < GL_LIMITS(pshader_constantsF)) {
extra_constants_needed += 1; ((IWineD3DPixelShaderImpl *)This)->luminanceconst[cur].const_num = max_constantsF + extra_constants_needed;
((IWineD3DPixelShaderImpl *)This)->luminanceconst = max_constantsF + 1; shader_addline(buffer, "PARAM luminance%d = program.env[%d];\n",
shader_addline(buffer, "PARAM luminance%d = program.env[%d];\n", reg_maps->luminanceparams, ((IWineD3DPixelShaderImpl *)This)->luminanceconst); i, ps->luminanceconst[cur].const_num);
} else if(reg_maps->luminanceparams != -1) { extra_constants_needed++;
} else if(reg_maps->luminanceparams) {
FIXME("No free constant to load the luminance parameters\n"); FIXME("No free constant to load the luminance parameters\n");
} }
} else { } else {
FIXME("No free constant found to load environemnt bump mapping matrix into the shader. texbem instruction will not apply bump mapping\n"); FIXME("No free constant found to load environemnt bump mapping matrix into the shader. texbem instruction will not apply bump mapping\n");
} }
extra_constants_needed += 1;
ps->numbumpenvmatconsts = cur + 1;
} }
if(device->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE] && pshader) { if(device->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE] && pshader) {
IWineD3DPixelShaderImpl *ps_impl = (IWineD3DPixelShaderImpl *) This; IWineD3DPixelShaderImpl *ps_impl = (IWineD3DPixelShaderImpl *) This;
/* If there are 2 constants left to use, use them to pass the sRGB correction values in. This way /* If there are 2 constants left to use, use them to pass the sRGB correction values in. This way
@ -891,7 +904,15 @@ void pshader_hw_bem(SHADER_OPCODE_ARG* arg) {
char src_name[2][50]; char src_name[2][50];
char dst_wmask[20]; char dst_wmask[20];
DWORD sampler_code = arg->dst & WINED3DSP_REGNUM_MASK; DWORD sampler_code = arg->dst & WINED3DSP_REGNUM_MASK;
BOOL has_bumpmat = (This->bumpenvmatconst != -1); BOOL has_bumpmat = FALSE;
int i;
for(i = 0; i < This->numbumpenvmatconsts; i++) {
if(This->bumpenvmatconst[i].const_num != -1 && This->bumpenvmatconst[i].texunit == sampler_code) {
has_bumpmat = TRUE;
break;
}
}
pshader_get_register_name(arg->shader, arg->dst, dst_name); pshader_get_register_name(arg->shader, arg->dst, dst_name);
shader_arb_get_write_mask(arg, arg->dst, dst_wmask); shader_arb_get_write_mask(arg, arg->dst, dst_wmask);
@ -1234,9 +1255,9 @@ void pshader_hw_texreg2rgb(SHADER_OPCODE_ARG* arg) {
void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) { void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
DWORD sampler_code = arg->dst & WINED3DSP_REGNUM_MASK; BOOL has_bumpmat = FALSE;
BOOL has_bumpmat = (This->bumpenvmatconst != -1); BOOL has_luminance = FALSE;
BOOL has_luminance = (This->luminanceconst != -1); int i;
DWORD dst = arg->dst; DWORD dst = arg->dst;
DWORD src = arg->src[0] & WINED3DSP_REGNUM_MASK; DWORD src = arg->src[0] & WINED3DSP_REGNUM_MASK;
@ -1250,12 +1271,25 @@ void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
/* Can directly use the name because texbem is only valid for <= 1.3 shaders */ /* Can directly use the name because texbem is only valid for <= 1.3 shaders */
pshader_get_register_name(arg->shader, dst, reg_coord); pshader_get_register_name(arg->shader, dst, reg_coord);
for(i = 0; i < This->numbumpenvmatconsts; i++) {
if(This->bumpenvmatconst[i].const_num != -1 && reg_dest_code == This->bumpenvmatconst[i].texunit) {
has_bumpmat = TRUE;
break;
}
}
for(i = 0; i < This->numbumpenvmatconsts; i++) {
if(This->luminanceconst[i].const_num != -1 && reg_dest_code == This->luminanceconst[i].texunit) {
has_luminance = TRUE;
break;
}
}
if(has_bumpmat) { if(has_bumpmat) {
/* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed */ /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed */
shader_addline(buffer, "SWZ TMP2, bumpenvmat%d, x, z, 0, 0;\n", sampler_code); shader_addline(buffer, "SWZ TMP2, bumpenvmat%d, x, z, 0, 0;\n", reg_dest_code);
shader_addline(buffer, "DP3 TMP.r, TMP2, T%u;\n", src); shader_addline(buffer, "DP3 TMP.r, TMP2, T%u;\n", src);
shader_addline(buffer, "SWZ TMP2, bumpenvmat%d, y, w, 0, 0;\n", sampler_code); shader_addline(buffer, "SWZ TMP2, bumpenvmat%d, y, w, 0, 0;\n", reg_dest_code);
shader_addline(buffer, "DP3 TMP.g, TMP2, T%u;\n", src); shader_addline(buffer, "DP3 TMP.g, TMP2, T%u;\n", src);
/* with projective textures, texbem only divides the static texture coord, not the displacement, /* with projective textures, texbem only divides the static texture coord, not the displacement,
@ -1274,7 +1308,7 @@ void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
if(arg->opcode->opcode == WINED3DSIO_TEXBEML && has_luminance) { if(arg->opcode->opcode == WINED3DSIO_TEXBEML && has_luminance) {
shader_addline(buffer, "MAD TMP, T%u.z, luminance%d.x, luminance%d.y;\n", shader_addline(buffer, "MAD TMP, T%u.z, luminance%d.x, luminance%d.y;\n",
src, sampler_code, sampler_code); src, reg_dest_code, reg_dest_code);
shader_addline(buffer, "MUL %s, %s, TMP;\n", reg_coord, reg_coord); shader_addline(buffer, "MUL %s, %s, TMP;\n", reg_coord, reg_coord);
} }

View File

@ -212,8 +212,8 @@ HRESULT shader_get_registers_used(
/* There are some minor differences between pixel and vertex shaders */ /* There are some minor differences between pixel and vertex shaders */
char pshader = shader_is_pshader_version(This->baseShader.hex_version); char pshader = shader_is_pshader_version(This->baseShader.hex_version);
reg_maps->bumpmat = -1; memset(reg_maps->bumpmat, 0, sizeof(reg_maps->bumpmat));
reg_maps->luminanceparams = -1; memset(reg_maps->luminanceparams, 0, sizeof(reg_maps->luminanceparams));
if (pToken == NULL) if (pToken == NULL)
return WINED3D_OK; return WINED3D_OK;
@ -349,6 +349,7 @@ HRESULT shader_get_registers_used(
/* Declare 1.X samplers implicitly, based on the destination reg. number */ /* Declare 1.X samplers implicitly, based on the destination reg. number */
if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1 && if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1 &&
pshader /* Filter different instructions with the same enum values in VS */ &&
(WINED3DSIO_TEX == curOpcode->opcode || (WINED3DSIO_TEX == curOpcode->opcode ||
WINED3DSIO_TEXBEM == curOpcode->opcode || WINED3DSIO_TEXBEM == curOpcode->opcode ||
WINED3DSIO_TEXBEML == curOpcode->opcode || WINED3DSIO_TEXBEML == curOpcode->opcode ||
@ -395,25 +396,17 @@ HRESULT shader_get_registers_used(
/* texbem is only valid with < 1.4 pixel shaders */ /* texbem is only valid with < 1.4 pixel shaders */
if(WINED3DSIO_TEXBEM == curOpcode->opcode || if(WINED3DSIO_TEXBEM == curOpcode->opcode ||
WINED3DSIO_TEXBEML == curOpcode->opcode) { WINED3DSIO_TEXBEML == curOpcode->opcode) {
if(reg_maps->bumpmat != -1 && reg_maps->bumpmat != sampler_code) { reg_maps->bumpmat[sampler_code] = TRUE;
FIXME("Pixel shader uses texbem instruction on more than 1 sampler\n");
} else {
reg_maps->bumpmat = sampler_code;
if(WINED3DSIO_TEXBEML == curOpcode->opcode) { if(WINED3DSIO_TEXBEML == curOpcode->opcode) {
reg_maps->luminanceparams = sampler_code; reg_maps->luminanceparams[sampler_code] = TRUE;
}
} }
} }
} }
if(WINED3DSIO_NRM == curOpcode->opcode) { if(WINED3DSIO_NRM == curOpcode->opcode) {
reg_maps->usesnrm = 1; reg_maps->usesnrm = 1;
} else if(WINED3DSIO_BEM == curOpcode->opcode) { } else if(WINED3DSIO_BEM == curOpcode->opcode && pshader) {
DWORD regnum = *pToken & WINED3DSP_REGNUM_MASK; DWORD regnum = *pToken & WINED3DSP_REGNUM_MASK;
if(reg_maps->bumpmat != -1 && reg_maps->bumpmat != regnum) { reg_maps->bumpmat[regnum] = TRUE;
FIXME("Pixel shader uses bem or texbem instruction on more than 1 sampler\n");
} else {
reg_maps->bumpmat = regnum;
}
} else if(WINED3DSIO_DSY == curOpcode->opcode) { } else if(WINED3DSIO_DSY == curOpcode->opcode) {
reg_maps->usesdsy = 1; reg_maps->usesdsy = 1;
} }

View File

@ -371,6 +371,7 @@ void shader_glsl_load_constants(
struct list *constant_list; struct list *constant_list;
GLhandleARB programId; GLhandleARB programId;
struct glsl_shader_prog_link *prog = stateBlock->glsl_program; struct glsl_shader_prog_link *prog = stateBlock->glsl_program;
unsigned int i;
if (!prog) { if (!prog) {
/* No GLSL program set - nothing to do. */ /* No GLSL program set - nothing to do. */
@ -429,25 +430,29 @@ void shader_glsl_load_constants(
/* Upload the environment bump map matrix if needed. The needsbumpmat member specifies the texture stage to load the matrix from. /* Upload the environment bump map matrix if needed. The needsbumpmat member specifies the texture stage to load the matrix from.
* It can't be 0 for a valid texbem instruction. * It can't be 0 for a valid texbem instruction.
*/ */
if(((IWineD3DPixelShaderImpl *) pshader)->needsbumpmat != -1) { for(i = 0; i < ((IWineD3DPixelShaderImpl *) pshader)->numbumpenvmatconsts; i++) {
float *data = (float *) &stateBlock->textureState[(int) ((IWineD3DPixelShaderImpl *) pshader)->needsbumpmat][WINED3DTSS_BUMPENVMAT00]; IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) pshader;
GL_EXTCALL(glUniformMatrix2fvARB(prog->bumpenvmat_location, 1, 0, data)); int stage = ps->luminanceconst[i].texunit;
float *data = (float *) &stateBlock->textureState[(int) ps->bumpenvmatconst[i].texunit][WINED3DTSS_BUMPENVMAT00];
GL_EXTCALL(glUniformMatrix2fvARB(prog->bumpenvmat_location[i], 1, 0, data));
checkGLcall("glUniformMatrix2fvARB"); checkGLcall("glUniformMatrix2fvARB");
/* texbeml needs the luminance scale and offset too. If texbeml is used, needsbumpmat /* texbeml needs the luminance scale and offset too. If texbeml is used, needsbumpmat
* is set too, so we can check that in the needsbumpmat check * is set too, so we can check that in the needsbumpmat check
*/ */
if(((IWineD3DPixelShaderImpl *) pshader)->baseShader.reg_maps.luminanceparams != -1) { if(ps->baseShader.reg_maps.luminanceparams[stage]) {
int stage = ((IWineD3DPixelShaderImpl *) pshader)->baseShader.reg_maps.luminanceparams;
GLfloat *scale = (GLfloat *) &stateBlock->textureState[stage][WINED3DTSS_BUMPENVLSCALE]; GLfloat *scale = (GLfloat *) &stateBlock->textureState[stage][WINED3DTSS_BUMPENVLSCALE];
GLfloat *offset = (GLfloat *) &stateBlock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET]; GLfloat *offset = (GLfloat *) &stateBlock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET];
GL_EXTCALL(glUniform1fvARB(prog->luminancescale_location, 1, scale)); GL_EXTCALL(glUniform1fvARB(prog->luminancescale_location[i], 1, scale));
checkGLcall("glUniform1fvARB"); checkGLcall("glUniform1fvARB");
GL_EXTCALL(glUniform1fvARB(prog->luminanceoffset_location, 1, offset)); GL_EXTCALL(glUniform1fvARB(prog->luminanceoffset_location[i], 1, offset));
checkGLcall("glUniform1fvARB"); checkGLcall("glUniform1fvARB");
} }
} else if(((IWineD3DPixelShaderImpl *) pshader)->srgb_enabled && }
if(((IWineD3DPixelShaderImpl *) pshader)->srgb_enabled &&
!((IWineD3DPixelShaderImpl *) pshader)->srgb_mode_hardcoded) { !((IWineD3DPixelShaderImpl *) pshader)->srgb_mode_hardcoded) {
float comparison[4]; float comparison[4];
float mul_low[4]; float mul_low[4];
@ -540,14 +545,26 @@ void shader_generate_glsl_declarations(
} else { } else {
IWineD3DPixelShaderImpl *ps_impl = (IWineD3DPixelShaderImpl *) This; IWineD3DPixelShaderImpl *ps_impl = (IWineD3DPixelShaderImpl *) This;
if(reg_maps->bumpmat != -1) { ps_impl->numbumpenvmatconsts = 0;
shader_addline(buffer, "uniform mat2 bumpenvmat;\n"); for(i = 0; i < (sizeof(reg_maps->bumpmat) / sizeof(reg_maps->bumpmat[0])); i++) {
if(reg_maps->luminanceparams) { if(!reg_maps->bumpmat[i]) {
shader_addline(buffer, "uniform float luminancescale;\n"); continue;
shader_addline(buffer, "uniform float luminanceoffset;\n");
extra_constants_needed++;
} }
ps_impl->bumpenvmatconst[(int) ps_impl->numbumpenvmatconsts].texunit = i;
shader_addline(buffer, "uniform mat2 bumpenvmat%d;\n", i);
if(reg_maps->luminanceparams) {
ps_impl->luminanceconst[(int) ps_impl->numbumpenvmatconsts].texunit = i;
shader_addline(buffer, "uniform float luminancescale%d;\n", i);
shader_addline(buffer, "uniform float luminanceoffset%d;\n", i);
extra_constants_needed++; extra_constants_needed++;
} else {
ps_impl->luminanceconst[(int) ps_impl->numbumpenvmatconsts].texunit = -1;
}
extra_constants_needed++;
ps_impl->numbumpenvmatconsts++;
} }
if(device->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE]) { if(device->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE]) {
@ -2555,24 +2572,25 @@ void pshader_glsl_texbem(SHADER_OPCODE_ARG* arg) {
if(arg->opcode->opcode == WINED3DSIO_TEXBEML) { if(arg->opcode->opcode == WINED3DSIO_TEXBEML) {
glsl_src_param_t luminance_param; glsl_src_param_t luminance_param;
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_2, &luminance_param); shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_2, &luminance_param);
shader_addline(arg->buffer, "(%s(Psampler%u, T%u%s + vec4(bumpenvmat * %s, 0.0, 0.0)%s )*(%s * luminancescale + luminanceoffset))%s);\n", shader_addline(arg->buffer, "(%s(Psampler%u, T%u%s + vec4(bumpenvmat%d * %s, 0.0, 0.0)%s )*(%s * luminancescale%d + luminanceoffset%d))%s);\n",
sample_function.name, sampler_idx, sampler_idx, coord_mask, coord_param.param_str, coord_mask, sample_function.name, sampler_idx, sampler_idx, coord_mask, sampler_idx, coord_param.param_str, coord_mask,
luminance_param.param_str, dst_swizzle); luminance_param.param_str, sampler_idx, sampler_idx, dst_swizzle);
} else { } else {
shader_addline(arg->buffer, "%s(Psampler%u, T%u%s + vec4(bumpenvmat * %s, 0.0, 0.0)%s )%s);\n", shader_addline(arg->buffer, "%s(Psampler%u, T%u%s + vec4(bumpenvmat%d * %s, 0.0, 0.0)%s )%s);\n",
sample_function.name, sampler_idx, sampler_idx, coord_mask, coord_param.param_str, coord_mask, dst_swizzle); sample_function.name, sampler_idx, sampler_idx, coord_mask, sampler_idx, coord_param.param_str, coord_mask, dst_swizzle);
} }
} }
void pshader_glsl_bem(SHADER_OPCODE_ARG* arg) { void pshader_glsl_bem(SHADER_OPCODE_ARG* arg) {
glsl_src_param_t src0_param, src1_param; glsl_src_param_t src0_param, src1_param;
DWORD sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0|WINED3DSP_WRITEMASK_1, &src0_param); shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0|WINED3DSP_WRITEMASK_1, &src0_param);
shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_0|WINED3DSP_WRITEMASK_1, &src1_param); shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_0|WINED3DSP_WRITEMASK_1, &src1_param);
shader_glsl_append_dst(arg->buffer, arg); shader_glsl_append_dst(arg->buffer, arg);
shader_addline(arg->buffer, "%s + bumpenvmat * %s);\n", shader_addline(arg->buffer, "%s + bumpenvmat%d * %s);\n",
src0_param.param_str, src1_param.param_str); src0_param.param_str, sampler_idx, src1_param.param_str);
} }
/** Process the WINED3DSIO_TEXREG2AR instruction in GLSL /** Process the WINED3DSIO_TEXREG2AR instruction in GLSL
@ -3148,10 +3166,20 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use
entry->puniformI_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name)); entry->puniformI_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
} }
if(pshader) {
for(i = 0; i < ((IWineD3DPixelShaderImpl*)pshader)->numbumpenvmatconsts; i++) {
char name[32];
sprintf(name, "bumpenvmat%d", ((IWineD3DPixelShaderImpl*)pshader)->bumpenvmatconst[i].texunit);
entry->bumpenvmat_location[i] = GL_EXTCALL(glGetUniformLocationARB(programId, name));
sprintf(name, "luminancescale%d", ((IWineD3DPixelShaderImpl*)pshader)->luminanceconst[i].texunit);
entry->luminancescale_location[i] = GL_EXTCALL(glGetUniformLocationARB(programId, name));
sprintf(name, "luminanceoffset%d", ((IWineD3DPixelShaderImpl*)pshader)->luminanceconst[i].texunit);
entry->luminanceoffset_location[i] = GL_EXTCALL(glGetUniformLocationARB(programId, name));
}
}
entry->posFixup_location = GL_EXTCALL(glGetUniformLocationARB(programId, "posFixup")); entry->posFixup_location = GL_EXTCALL(glGetUniformLocationARB(programId, "posFixup"));
entry->bumpenvmat_location = GL_EXTCALL(glGetUniformLocationARB(programId, "bumpenvmat"));
entry->luminancescale_location = GL_EXTCALL(glGetUniformLocationARB(programId, "luminancescale"));
entry->luminanceoffset_location = GL_EXTCALL(glGetUniformLocationARB(programId, "luminanceoffset"));
entry->srgb_comparison_location = GL_EXTCALL(glGetUniformLocationARB(programId, "srgb_comparison")); entry->srgb_comparison_location = GL_EXTCALL(glGetUniformLocationARB(programId, "srgb_comparison"));
entry->srgb_mul_low_location = GL_EXTCALL(glGetUniformLocationARB(programId, "srgb_mul_low")); entry->srgb_mul_low_location = GL_EXTCALL(glGetUniformLocationARB(programId, "srgb_mul_low"));
entry->ycorrection_location = GL_EXTCALL(glGetUniformLocationARB(programId, "ycorrection")); entry->ycorrection_location = GL_EXTCALL(glGetUniformLocationARB(programId, "ycorrection"));

View File

@ -467,8 +467,6 @@ static inline VOID IWineD3DPixelShaderImpl_GenerateShader(
} }
} }
This->needsbumpmat = reg_maps->bumpmat;
#if 1 /* if were using the data buffer of device then we don't need to free it */ #if 1 /* if were using the data buffer of device then we don't need to free it */
HeapFree(GetProcessHeap(), 0, buffer.buffer); HeapFree(GetProcessHeap(), 0, buffer.buffer);
#endif #endif

View File

@ -2403,7 +2403,7 @@ static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, W
} tmpvalue; } tmpvalue;
if(stateblock->pixelShader && stage != 0 && if(stateblock->pixelShader && stage != 0 &&
((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams == stage) { ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
/* The pixel shader has to know the luminance scale. Do a constants update if it /* The pixel shader has to know the luminance scale. Do a constants update if it
* isn't scheduled anyway * isn't scheduled anyway
*/ */
@ -2427,7 +2427,7 @@ static void tex_bumpenvloffset(DWORD state, IWineD3DStateBlockImpl *stateblock,
} tmpvalue; } tmpvalue;
if(stateblock->pixelShader && stage != 0 && if(stateblock->pixelShader && stage != 0 &&
((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams == stage) { ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
/* The pixel shader has to know the luminance offset. Do a constants update if it /* The pixel shader has to know the luminance offset. Do a constants update if it
* isn't scheduled anyway * isn't scheduled anyway
*/ */
@ -2621,9 +2621,8 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
float mat[2][2]; float mat[2][2];
if(stateblock->pixelShader && stage != 0 && if(stateblock->pixelShader && stage != 0 &&
((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->needsbumpmat == stage) { ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) {
/* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
* anyway * anyway
*/ */

View File

@ -1735,9 +1735,9 @@ struct glsl_shader_prog_link {
GLhandleARB vuniformI_locations[MAX_CONST_I]; GLhandleARB vuniformI_locations[MAX_CONST_I];
GLhandleARB puniformI_locations[MAX_CONST_I]; GLhandleARB puniformI_locations[MAX_CONST_I];
GLhandleARB posFixup_location; GLhandleARB posFixup_location;
GLhandleARB bumpenvmat_location; GLhandleARB bumpenvmat_location[MAX_TEXTURES];
GLhandleARB luminancescale_location; GLhandleARB luminancescale_location[MAX_TEXTURES];
GLhandleARB luminanceoffset_location; GLhandleARB luminanceoffset_location[MAX_TEXTURES];
GLhandleARB srgb_comparison_location; GLhandleARB srgb_comparison_location;
GLhandleARB srgb_mul_low_location; GLhandleARB srgb_mul_low_location;
GLhandleARB ycorrection_location; GLhandleARB ycorrection_location;
@ -1788,7 +1788,7 @@ typedef struct shader_reg_maps {
/* Sampler usage tokens /* Sampler usage tokens
* Use 0 as default (bit 31 is always 1 on a valid token) */ * Use 0 as default (bit 31 is always 1 on a valid token) */
DWORD samplers[max(MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS)]; DWORD samplers[max(MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS)];
char bumpmat, luminanceparams; BOOL bumpmat[MAX_TEXTURES], luminanceparams[MAX_TEXTURES];
char usesnrm, vpos, usesdsy; char usesnrm, vpos, usesdsy;
char usesrelconstF; char usesrelconstF;
@ -2243,6 +2243,11 @@ enum vertexprocessing_mode {
pretransformed pretransformed
}; };
struct stb_const_desc {
char texunit;
UINT const_num;
};
typedef struct IWineD3DPixelShaderImpl { typedef struct IWineD3DPixelShaderImpl {
/* IUnknown parts */ /* IUnknown parts */
const IWineD3DPixelShaderVtbl *lpVtbl; const IWineD3DPixelShaderVtbl *lpVtbl;
@ -2262,9 +2267,9 @@ typedef struct IWineD3DPixelShaderImpl {
PSHADERDATA *data; PSHADERDATA *data;
/* Some information about the shader behavior */ /* Some information about the shader behavior */
char needsbumpmat; struct stb_const_desc bumpenvmatconst[MAX_TEXTURES];
UINT bumpenvmatconst; char numbumpenvmatconsts;
UINT luminanceconst; struct stb_const_desc luminanceconst[MAX_TEXTURES];
char srgb_enabled; char srgb_enabled;
char srgb_mode_hardcoded; char srgb_mode_hardcoded;
UINT srgb_low_const; UINT srgb_low_const;