wined3d: Place immediate constants in the same array as global constants.

- move DEF, DEFI, DEFB handling into the register counting pass
- keep track of defined constants as a linked list (because there's a
  few of them)
- apply immediate constants after global constants in the constant
  loading function
- both types of constants now get loaded with array notation in the
  shader (into the same array)
oldstable
Ivan Gyurdiev 2006-07-09 22:51:03 -06:00 committed by Alexandre Julliard
parent 915174d8d9
commit e9de563e41
6 changed files with 259 additions and 206 deletions

View File

@ -46,6 +46,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
* or GL_FRAGMENT_PROGRAM_ARB (for pixel shaders)
*/
void shader_arb_load_constantsF(
IWineD3DBaseShaderImpl* This,
WineD3D_GL_Info *gl_info,
GLuint target_type,
unsigned max_constants,
@ -53,6 +54,7 @@ void shader_arb_load_constantsF(
BOOL* constants_set) {
int i;
struct list* ptr;
for (i=0; i<max_constants; ++i) {
if (NULL == constants_set || constants_set[i]) {
@ -64,6 +66,22 @@ void shader_arb_load_constantsF(
checkGLcall("glProgramEnvParameter4fvARB");
}
}
/* Load immediate constants */
ptr = list_head(&This->baseShader.constantsF);
while (ptr) {
local_constant* lconst = LIST_ENTRY(ptr, struct local_constant, entry);
unsigned int idx = lconst->idx;
GLfloat* values = (GLfloat*) lconst->value;
TRACE("Loading local constants %i: %f, %f, %f, %f\n", idx,
values[0], values[1], values[2], values[3]);
GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, idx, values));
checkGLcall("glProgramEnvParameter4fvARB");
ptr = list_next(&This->baseShader.constantsF, ptr);
}
}
/**
@ -81,19 +99,20 @@ void shader_arb_load_constants(
WineD3D_GL_Info *gl_info = &((IWineD3DImpl*)stateBlock->wineD3DDevice->wineD3D)->gl_info;
if (useVertexShader) {
IWineD3DVertexShaderImpl* vshader = (IWineD3DVertexShaderImpl*) stateBlock->vertexShader;
IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader;
IWineD3DVertexShaderImpl* vshader_impl = (IWineD3DVertexShaderImpl*) stateBlock->vertexShader;
IWineD3DVertexDeclarationImpl* vertexDeclaration =
(IWineD3DVertexDeclarationImpl*) vshader->vertexDeclaration;
(IWineD3DVertexDeclarationImpl*) vshader_impl->vertexDeclaration;
if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) {
/* Load DirectX 8 float constants for vertex shader */
shader_arb_load_constantsF(gl_info, GL_VERTEX_PROGRAM_ARB,
shader_arb_load_constantsF(vshader, gl_info, GL_VERTEX_PROGRAM_ARB,
WINED3D_VSHADER_MAX_CONSTANTS,
vertexDeclaration->constants, NULL);
}
/* Load DirectX 9 float constants for vertex shader */
shader_arb_load_constantsF(gl_info, GL_VERTEX_PROGRAM_ARB,
shader_arb_load_constantsF(vshader, gl_info, GL_VERTEX_PROGRAM_ARB,
WINED3D_VSHADER_MAX_CONSTANTS,
stateBlock->vertexShaderConstantF,
stateBlock->set.vertexShaderConstantsF);
@ -101,8 +120,10 @@ void shader_arb_load_constants(
if (usePixelShader) {
IWineD3DBaseShaderImpl* pshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader;
/* 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(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB, WINED3D_PSHADER_MAX_CONSTANTS,
stateBlock->pixelShaderConstantF,
stateBlock->set.pixelShaderConstantsF);
}
@ -264,7 +285,8 @@ static void vshader_program_add_input_param_swizzle(const DWORD param, int is_co
}
}
static void pshader_get_register_name(const DWORD param, char* regstr, CHAR *constants) {
static void pshader_get_register_name(
const DWORD param, char* regstr) {
DWORD reg = param & D3DSP_REGNUM_MASK;
DWORD regtype = shader_get_regtype(param);
@ -281,10 +303,7 @@ static void pshader_get_register_name(const DWORD param, char* regstr, CHAR *con
}
break;
case D3DSPR_CONST:
if (constants[reg])
sprintf(regstr, "C%lu", reg);
else
sprintf(regstr, "C[%lu]", reg);
sprintf(regstr, "C[%lu]", reg);
break;
case D3DSPR_TEXTURE: /* case D3DSPR_ADDR: */
sprintf(regstr,"T%lu", reg);
@ -347,15 +366,7 @@ static void vshader_program_add_param(SHADER_OPCODE_ARG *arg, const DWORD param,
strcat(hwLine, tmpReg);
break;
case D3DSPR_CONST:
/* FIXME: some constants are named so we need a constants map*/
if (arg->reg_maps->constantsF[reg]) {
if (param & D3DVS_ADDRMODE_RELATIVE) {
FIXME("Relative addressing not expected for a named constant %lu\n", reg);
}
sprintf(tmpReg, "C%lu", reg);
} else {
sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
}
sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
strcat(hwLine, tmpReg);
break;
case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
@ -394,8 +405,7 @@ static void pshader_gen_input_modifier_line (
SHADER_BUFFER* buffer,
const DWORD instr,
int tmpreg,
char *outregstr,
CHAR *constants) {
char *outregstr) {
/* Generate a line that does the input modifier computation and return the input register to use */
char regstr[256];
@ -406,7 +416,7 @@ static void pshader_gen_input_modifier_line (
insert_line = 1;
/* Get register name */
pshader_get_register_name(instr, regstr, constants);
pshader_get_register_name(instr, regstr);
pshader_get_input_register_swizzle(instr, swzstr);
switch (instr & D3DSP_SRCMOD_MASK) {
@ -469,22 +479,6 @@ inline static void pshader_gen_output_modifier_line(
regstr, write_mask, regstr, shift_tab[shift]);
}
/** Process the D3DSIO_DEF opcode into an ARB string - creates a local vec4
* float constant, and stores it's usage on the regmaps. */
void shader_hw_def(SHADER_OPCODE_ARG* arg) {
DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
shader_addline(arg->buffer,
"PARAM C%lu = { %f, %f, %f, %f };\n", reg,
*((const float *)(arg->src + 0)),
*((const float *)(arg->src + 1)),
*((const float *)(arg->src + 2)),
*((const float *)(arg->src + 3)) );
arg->reg_maps->constantsF[reg] = 1;
}
void pshader_hw_cnd(SHADER_OPCODE_ARG* arg) {
SHADER_BUFFER* buffer = arg->buffer;
@ -495,14 +489,14 @@ void pshader_hw_cnd(SHADER_OPCODE_ARG* arg) {
/* FIXME: support output modifiers */
/* Handle output register */
pshader_get_register_name(arg->dst, dst_name, arg->reg_maps->constantsF);
pshader_get_register_name(arg->dst, dst_name);
pshader_get_write_mask(arg->dst, dst_wmask);
strcat(dst_name, dst_wmask);
/* Generate input register names (with modifiers) */
pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_name[0], arg->reg_maps->constantsF);
pshader_gen_input_modifier_line(buffer, arg->src[1], 1, src_name[1], arg->reg_maps->constantsF);
pshader_gen_input_modifier_line(buffer, arg->src[2], 2, src_name[2], arg->reg_maps->constantsF);
pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_name[0]);
pshader_gen_input_modifier_line(buffer, arg->src[1], 1, src_name[1]);
pshader_gen_input_modifier_line(buffer, arg->src[2], 2, src_name[2]);
shader_addline(buffer, "ADD TMP, -%s, coefdiv.x;\n", src_name[0]);
shader_addline(buffer, "CMP %s, TMP, %s, %s;\n", dst_name, src_name[1], src_name[2]);
@ -518,14 +512,14 @@ void pshader_hw_cmp(SHADER_OPCODE_ARG* arg) {
/* FIXME: support output modifiers */
/* Handle output register */
pshader_get_register_name(arg->dst, dst_name, arg->reg_maps->constantsF);
pshader_get_register_name(arg->dst, dst_name);
pshader_get_write_mask(arg->dst, dst_wmask);
strcat(dst_name, dst_wmask);
/* Generate input register names (with modifiers) */
pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_name[0], arg->reg_maps->constantsF);
pshader_gen_input_modifier_line(buffer, arg->src[1], 1, src_name[1], arg->reg_maps->constantsF);
pshader_gen_input_modifier_line(buffer, arg->src[2], 2, src_name[2], arg->reg_maps->constantsF);
pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_name[0]);
pshader_gen_input_modifier_line(buffer, arg->src[1], 1, src_name[1]);
pshader_gen_input_modifier_line(buffer, arg->src[2], 2, src_name[2]);
shader_addline(buffer, "CMP %s, %s, %s, %s;\n", dst_name,
src_name[0], src_name[2], src_name[1]);
@ -574,10 +568,10 @@ void pshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
/* Generate input register names (with modifiers) */
for (i = 1; i < curOpcode->num_params; ++i)
pshader_gen_input_modifier_line(buffer, src[i-1], i-1, operands[i], arg->reg_maps->constantsF);
pshader_gen_input_modifier_line(buffer, src[i-1], i-1, operands[i]);
/* Handle output register */
pshader_get_register_name(dst, output_rname, arg->reg_maps->constantsF);
pshader_get_register_name(dst, output_rname);
strcpy(operands[0], output_rname);
pshader_get_write_mask(dst, output_wmask);
strcat(operands[0], output_wmask);
@ -614,14 +608,14 @@ void pshader_hw_tex(SHADER_OPCODE_ARG* arg) {
/* All versions have a destination register */
reg_dest_code = dst & D3DSP_REGNUM_MASK;
pshader_get_register_name(dst, reg_dest, arg->reg_maps->constantsF);
pshader_get_register_name(dst, reg_dest);
/* 1.0-1.3: Use destination register as coordinate source.
1.4+: Use provided coordinate source register. */
if (hex_version < D3DPS_VERSION(1,4))
strcpy(reg_coord, reg_dest);
else
pshader_gen_input_modifier_line(buffer, src[0], 0, reg_coord, arg->reg_maps->constantsF);
pshader_gen_input_modifier_line(buffer, src[0], 0, reg_coord);
/* 1.0-1.4: Use destination register number as texture code.
2.0+: Use provided sampler number as texure code. */
@ -693,7 +687,7 @@ void pshader_hw_texm3x2pad(SHADER_OPCODE_ARG* arg) {
SHADER_BUFFER* buffer = arg->buffer;
char src0_name[50];
pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, arg->reg_maps->constantsF);
pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name);
shader_addline(buffer, "DP3 TMP.x, T%lu, %s;\n", reg, src0_name);
}
@ -703,7 +697,7 @@ void pshader_hw_texm3x2tex(SHADER_OPCODE_ARG* arg) {
SHADER_BUFFER* buffer = arg->buffer;
char src0_name[50];
pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, arg->reg_maps->constantsF);
pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name);
shader_addline(buffer, "DP3 TMP.y, T%lu, %s;\n", reg, src0_name);
shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg, reg);
}
@ -716,7 +710,7 @@ void pshader_hw_texm3x3pad(SHADER_OPCODE_ARG* arg) {
SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state;
char src0_name[50];
pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, arg->reg_maps->constantsF);
pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name);
shader_addline(buffer, "DP3 TMP.%c, T%lu, %s;\n", 'x' + current_state->current_row, reg, src0_name);
current_state->texcoord_w[current_state->current_row++] = reg;
}
@ -729,7 +723,7 @@ void pshader_hw_texm3x3tex(SHADER_OPCODE_ARG* arg) {
SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state;
char src0_name[50];
pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, arg->reg_maps->constantsF);
pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name);
shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, src0_name);
/* Cubemap textures will be more used than 3D ones. */
@ -745,7 +739,7 @@ void pshader_hw_texm3x3vspec(SHADER_OPCODE_ARG* arg) {
SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state;
char src0_name[50];
pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, arg->reg_maps->constantsF);
pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name);
shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, src0_name);
/* Construct the eye-ray vector from w coordinates */
@ -772,7 +766,7 @@ void pshader_hw_texm3x3spec(SHADER_OPCODE_ARG* arg) {
SHADER_BUFFER* buffer = arg->buffer;
char src0_name[50];
pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, arg->reg_maps->constantsF);
pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name);
shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, src0_name);
/* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */

View File

@ -174,7 +174,7 @@ unsigned int shader_get_float_offset(const DWORD reg) {
/* Note that this does not count the loop register
* as an address register. */
void shader_get_registers_used(
HRESULT shader_get_registers_used(
IWineD3DBaseShader *iface,
shader_reg_maps* reg_maps,
semantic* semantics_in,
@ -187,7 +187,7 @@ void shader_get_registers_used(
char pshader = shader_is_pshader_version(This->baseShader.hex_version);
if (pToken == NULL)
return;
return WINED3D_OK;
while (D3DVS_END() != *pToken) {
CONST SHADER_OPCODE* curOpcode;
@ -245,8 +245,31 @@ void shader_get_registers_used(
} else if (D3DSPR_SAMPLER == regtype)
reg_maps->samplers[regnum] = usage;
/* Skip definitions (for now) */
} else if (D3DSIO_DEF == curOpcode->opcode) {
local_constant* lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant));
if (!lconst) return E_OUTOFMEMORY;
lconst->idx = *pToken & D3DSP_REGNUM_MASK;
memcpy(&lconst->value, pToken + 1, 4 * sizeof(DWORD));
list_add_head(&This->baseShader.constantsF, &lconst->entry);
pToken += curOpcode->num_params;
} else if (D3DSIO_DEFI == curOpcode->opcode) {
local_constant* lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant));
if (!lconst) return E_OUTOFMEMORY;
lconst->idx = *pToken & D3DSP_REGNUM_MASK;
memcpy(&lconst->value, pToken + 1, 4 * sizeof(DWORD));
list_add_head(&This->baseShader.constantsI, &lconst->entry);
pToken += curOpcode->num_params;
} else if (D3DSIO_DEFB == curOpcode->opcode) {
local_constant* lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant));
if (!lconst) return E_OUTOFMEMORY;
lconst->idx = *pToken & D3DSP_REGNUM_MASK;
memcpy(&lconst->value, pToken + 1, 1 * sizeof(DWORD));
list_add_head(&This->baseShader.constantsB, &lconst->entry);
pToken += curOpcode->num_params;
/* If there's a loop in the shader */
@ -315,6 +338,8 @@ void shader_get_registers_used(
}
}
}
return WINED3D_OK;
}
static void shader_dump_decl_usage(
@ -655,7 +680,10 @@ void shader_generate_main(
/* Nothing to do */
} else if (D3DSIO_DCL == curOpcode->opcode ||
D3DSIO_NOP == curOpcode->opcode) {
D3DSIO_NOP == curOpcode->opcode ||
D3DSIO_DEF == curOpcode->opcode ||
D3DSIO_DEFI == curOpcode->opcode ||
D3DSIO_DEFB == curOpcode->opcode) {
pToken += shader_skip_opcode(This, curOpcode, opcode_token);
@ -682,15 +710,7 @@ void shader_generate_main(
DWORD param, addr_token = 0;
/* DEF* instructions have constant src parameters, not registers */
if (curOpcode->opcode == D3DSIO_DEF ||
curOpcode->opcode == D3DSIO_DEFI ||
curOpcode->opcode == D3DSIO_DEFB) {
param = *pToken++;
} else
pToken += shader_get_param(iface, pToken, &param, &addr_token);
pToken += shader_get_param(iface, pToken, &param, &addr_token);
hw_arg.src[i-1] = param;
hw_arg.src_addr[i-1] = addr_token;
}
@ -882,4 +902,16 @@ void shader_trace_init(
}
}
/* TODO: Move other shared code here */
void shader_delete_constant_list(
struct list* clist) {
struct list *ptr;
struct local_constant* constant;
ptr = list_head(clist);
while (ptr) {
constant = LIST_ENTRY(ptr, struct local_constant, entry);
ptr = list_next(clist, ptr);
HeapFree(GetProcessHeap(), 0, constant);
}
}

View File

@ -78,17 +78,19 @@ void shader_glsl_load_psamplers(
* When @constants_set == NULL, it will load all the constants.
*/
void shader_glsl_load_constantsF(
IWineD3DBaseShaderImpl* This,
WineD3D_GL_Info *gl_info,
GLhandleARB programId,
unsigned max_constants,
float* constants,
BOOL* constants_set,
char is_pshader) {
BOOL* constants_set) {
GLhandleARB tmp_loc;
int i;
char tmp_name[7];
char is_pshader = shader_is_pshader_version(This->baseShader.hex_version);
const char* prefix = is_pshader? "PC":"VC";
struct list* ptr;
for (i=0; i<max_constants; ++i) {
if (NULL == constants_set || constants_set[i]) {
@ -108,6 +110,26 @@ void shader_glsl_load_constantsF(
}
}
}
/* Load immediate constants */
ptr = list_head(&This->baseShader.constantsF);
while (ptr) {
local_constant* lconst = LIST_ENTRY(ptr, struct local_constant, entry);
unsigned int idx = lconst->idx;
GLfloat* values = (GLfloat*) lconst->value;
TRACE("Loading local constants %i: %f, %f, %f, %f\n", idx,
values[0], values[1], values[2], values[3]);
snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, idx);
tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
if (tmp_loc != -1) {
/* We found this uniform name in the program - go ahead and send the data */
GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, values));
checkGLcall("glUniform4fvARB");
}
ptr = list_next(&This->baseShader.constantsF, ptr);
}
}
/**
@ -115,17 +137,19 @@ void shader_glsl_load_constantsF(
* When @constants_set == NULL, it will load all the constants.
*/
void shader_glsl_load_constantsI(
IWineD3DBaseShaderImpl* This,
WineD3D_GL_Info *gl_info,
GLhandleARB programId,
unsigned max_constants,
int* constants,
BOOL* constants_set,
char is_pshader) {
BOOL* constants_set) {
GLhandleARB tmp_loc;
int i;
char tmp_name[7];
char is_pshader = shader_is_pshader_version(This->baseShader.hex_version);
const char* prefix = is_pshader? "PI":"VI";
struct list* ptr;
for (i=0; i<max_constants; ++i) {
if (NULL == constants_set || constants_set[i]) {
@ -144,6 +168,26 @@ void shader_glsl_load_constantsI(
}
}
}
/* Load immediate constants */
ptr = list_head(&This->baseShader.constantsI);
while (ptr) {
local_constant* lconst = LIST_ENTRY(ptr, struct local_constant, entry);
unsigned int idx = lconst->idx;
GLint* values = (GLint*) lconst->value;
TRACE("Loading local constants %i: %i, %i, %i, %i\n", idx,
values[0], values[1], values[2], values[3]);
snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, idx);
tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
if (tmp_loc != -1) {
/* We found this uniform name in the program - go ahead and send the data */
GL_EXTCALL(glUniform4ivARB(tmp_loc, 1, values));
checkGLcall("glUniform4ivARB");
}
ptr = list_next(&This->baseShader.constantsI, ptr);
}
}
/**
@ -151,17 +195,19 @@ void shader_glsl_load_constantsI(
* When @constants_set == NULL, it will load all the constants.
*/
void shader_glsl_load_constantsB(
IWineD3DBaseShaderImpl* This,
WineD3D_GL_Info *gl_info,
GLhandleARB programId,
unsigned max_constants,
BOOL* constants,
BOOL* constants_set,
char is_pshader) {
BOOL* constants_set) {
GLhandleARB tmp_loc;
int i;
char tmp_name[7];
char is_pshader = shader_is_pshader_version(This->baseShader.hex_version);
const char* prefix = is_pshader? "PB":"VB";
struct list* ptr;
for (i=0; i<max_constants; ++i) {
if (NULL == constants_set || constants_set[i]) {
@ -179,6 +225,25 @@ void shader_glsl_load_constantsB(
}
}
}
/* Load immediate constants */
ptr = list_head(&This->baseShader.constantsB);
while (ptr) {
local_constant* lconst = LIST_ENTRY(ptr, struct local_constant, entry);
unsigned int idx = lconst->idx;
GLint* values = (GLint*) lconst->value;
TRACE("Loading local constants %i: %i\n", idx, values[0]);
snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, idx);
tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
if (tmp_loc != -1) {
/* We found this uniform name in the program - go ahead and send the data */
GL_EXTCALL(glUniform1ivARB(tmp_loc, 1, values));
checkGLcall("glUniform1ivARB");
}
ptr = list_next(&This->baseShader.constantsB, ptr);
}
}
@ -201,51 +266,55 @@ void shader_glsl_load_constants(
}
if (useVertexShader) {
IWineD3DVertexShaderImpl* vshader = (IWineD3DVertexShaderImpl*) stateBlock->vertexShader;
IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader;
IWineD3DVertexShaderImpl* vshader_impl = (IWineD3DVertexShaderImpl*) vshader;
IWineD3DVertexDeclarationImpl* vertexDeclaration =
(IWineD3DVertexDeclarationImpl*) vshader->vertexDeclaration;
(IWineD3DVertexDeclarationImpl*) vshader_impl->vertexDeclaration;
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,
vertexDeclaration->constants, NULL, 0);
shader_glsl_load_constantsF(vshader, gl_info, programId, WINED3D_VSHADER_MAX_CONSTANTS,
vertexDeclaration->constants, NULL);
}
/* Load DirectX 9 float constants/uniforms for vertex shader */
shader_glsl_load_constantsF(gl_info, programId, WINED3D_VSHADER_MAX_CONSTANTS,
shader_glsl_load_constantsF(vshader, gl_info, programId, WINED3D_VSHADER_MAX_CONSTANTS,
stateBlock->vertexShaderConstantF,
stateBlock->set.vertexShaderConstantsF, 0);
stateBlock->set.vertexShaderConstantsF);
/* Load DirectX 9 integer constants/uniforms for vertex shader */
shader_glsl_load_constantsI(gl_info, programId, MAX_CONST_I,
shader_glsl_load_constantsI(vshader, gl_info, programId, MAX_CONST_I,
stateBlock->vertexShaderConstantI,
stateBlock->set.vertexShaderConstantsI, 0);
stateBlock->set.vertexShaderConstantsI);
/* Load DirectX 9 boolean constants/uniforms for vertex shader */
shader_glsl_load_constantsB(gl_info, programId, MAX_CONST_B,
shader_glsl_load_constantsB(vshader, gl_info, programId, MAX_CONST_B,
stateBlock->vertexShaderConstantB,
stateBlock->set.vertexShaderConstantsB, 0);
stateBlock->set.vertexShaderConstantsB);
}
if (usePixelShader) {
IWineD3DBaseShaderImpl* pshader = (IWineD3DBaseShaderImpl*) stateBlock->pixelShader;
/* Load pixel shader samplers */
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(pshader, gl_info, programId, WINED3D_PSHADER_MAX_CONSTANTS,
stateBlock->pixelShaderConstantF,
stateBlock->set.pixelShaderConstantsF, 1);
stateBlock->set.pixelShaderConstantsF);
/* Load DirectX 9 integer constants/uniforms for pixel shader */
shader_glsl_load_constantsI(gl_info, programId, MAX_CONST_I,
shader_glsl_load_constantsI(pshader, gl_info, programId, MAX_CONST_I,
stateBlock->pixelShaderConstantI,
stateBlock->set.pixelShaderConstantsI, 1);
stateBlock->set.pixelShaderConstantsI);
/* Load DirectX 9 boolean constants/uniforms for pixel shader */
shader_glsl_load_constantsB(gl_info, programId, MAX_CONST_B,
shader_glsl_load_constantsB(pshader, gl_info, programId, MAX_CONST_B,
stateBlock->pixelShaderConstantB,
stateBlock->set.pixelShaderConstantsB, 1);
stateBlock->set.pixelShaderConstantsB);
}
}
@ -510,61 +579,34 @@ static void shader_glsl_get_register_name(
{
const char* prefix = pshader? "PC":"VC";
if (arg->reg_maps->constantsF[reg]) {
/* Use a local constant declared by "def" */
if (param & D3DVS_ADDRMODE_RELATIVE) {
/* FIXME: Copy all constants (local & global) into a single array
* to handle this case where we want a relative address from a
* local constant. */
FIXME("Relative addressing not yet supported on named constants\n");
} else {
sprintf(tmpStr, "%s%lu", prefix, reg);
}
} else {
/* Use a global constant declared in Set____ShaderConstantF() */
if (param & D3DVS_ADDRMODE_RELATIVE) {
/* Relative addressing on shaders 2.0+ have a relative address token,
* prior to that, it was hard-coded as "A0.x" because there's only 1 register */
if (D3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 2) {
char relStr[100], relReg[50], relMask[6];
shader_glsl_add_param(arg, addr_token, 0, TRUE, relReg, relMask, relStr);
sprintf(tmpStr, "%s[%s + %lu]", prefix, relStr, reg);
} else {
sprintf(tmpStr, "%s[A0.x + %lu]", prefix, reg);
}
} else {
/* Just a normal global constant - no relative addressing */
sprintf(tmpStr, "%s[%lu]", prefix, reg);
}
}
/* Relative addressing */
if (param & D3DVS_ADDRMODE_RELATIVE) {
/* Relative addressing on shaders 2.0+ have a relative address token,
* prior to that, it was hard-coded as "A0.x" because there's only 1 register */
if (D3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 2) {
char relStr[100], relReg[50], relMask[6];
shader_glsl_add_param(arg, addr_token, 0, TRUE, relReg, relMask, relStr);
sprintf(tmpStr, "%s[%s + %lu]", prefix, relStr, reg);
} else
sprintf(tmpStr, "%s[A0.x + %lu]", prefix, reg);
} else
sprintf(tmpStr, "%s[%lu]", prefix, reg);
break;
}
case D3DSPR_CONSTINT:
if (arg->reg_maps->constantsI[reg]) {
/* Integer vector was defined locally using "defi" */
sprintf(tmpStr, "I%lu", reg);
} else {
/* Uniform integer value - pixel or vertex specific */
if (pshader) {
sprintf(tmpStr, "PI[%lu]", reg);
} else {
sprintf(tmpStr, "VI[%lu]", reg);
}
}
if (pshader)
sprintf(tmpStr, "PI[%lu]", reg);
else
sprintf(tmpStr, "VI[%lu]", reg);
break;
case D3DSPR_CONSTBOOL:
if (arg->reg_maps->constantsB[reg]) {
/* Boolean was defined locally using "defb" */
sprintf(tmpStr, "B%lu", reg);
} else {
/* Uniform boolean value - pixel or vertex specific */
if (pshader) {
sprintf(tmpStr, "PB[%lu]", reg);
} else {
sprintf(tmpStr, "VB[%lu]", reg);
}
}
if (pshader)
sprintf(tmpStr, "PB[%lu]", reg);
else
sprintf(tmpStr, "VB[%lu]", reg);
break;
case D3DSPR_TEXTURE: /* case D3DSPR_ADDR: */
if (pshader) {
@ -1041,51 +1083,6 @@ void shader_glsl_lrp(SHADER_OPCODE_ARG* arg) {
tmpLine, src2_str, src0_str, src1_str, src2_str, dst_mask);
}
/** Process the D3DSIO_DEF opcode into a GLSL string - creates a local vec4
* float constant, and stores it's usage on the regmaps. */
void shader_glsl_def(SHADER_OPCODE_ARG* arg) {
DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) arg->shader;
char pshader = shader_is_pshader_version(This->baseShader.hex_version);
const char* prefix = pshader? "PC":"VC";
shader_addline(arg->buffer,
"const vec4 %s%lu = vec4(%f, %f, %f, %f);\n", prefix, reg,
*((const float *)(arg->src + 0)),
*((const float *)(arg->src + 1)),
*((const float *)(arg->src + 2)),
*((const float *)(arg->src + 3)) );
arg->reg_maps->constantsF[reg] = 1;
}
/** Process the D3DSIO_DEFI opcode into a GLSL string - creates a local ivec4
* integer constant, and stores it's usage on the regmaps. */
void shader_glsl_defi(SHADER_OPCODE_ARG* arg) {
DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
shader_addline(arg->buffer,
"const ivec4 I%lu = ivec4(%ld, %ld, %ld, %ld);\n", reg,
(long)arg->src[0], (long)arg->src[1],
(long)arg->src[2], (long)arg->src[3]);
arg->reg_maps->constantsI[reg] = 1;
}
/** Process the D3DSIO_DEFB opcode into a GLSL string - creates a local boolean
* constant, and stores it's usage on the regmaps. */
void shader_glsl_defb(SHADER_OPCODE_ARG* arg) {
DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
shader_addline(arg->buffer, "const bool B%lu = %s;\n", reg, (arg->src[0]) ? "true" : "false");
arg->reg_maps->constantsB[reg] = 1;
}
/** Process the D3DSIO_LIT instruction in GLSL:
* dst.x = dst.w = 1.0
* dst.y = (src0.x > 0) ? src0.x

View File

@ -72,13 +72,16 @@ static ULONG WINAPI IWineD3DPixelShaderImpl_Release(IWineD3DPixelShader *iface)
TRACE("(%p) : Releasing from %ld\n", This, This->ref);
ref = InterlockedDecrement(&This->ref);
if (ref == 0) {
HeapFree(GetProcessHeap(), 0, This);
if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) {
/* If this shader is still attached to a program, GL will perform a lazy delete */
TRACE("Deleting shader object %u\n", This->baseShader.prgId);
GL_EXTCALL(glDeleteObjectARB(This->baseShader.prgId));
checkGLcall("glDeleteObjectARB");
}
shader_delete_constant_list(&This->baseShader.constantsF);
shader_delete_constant_list(&This->baseShader.constantsB);
shader_delete_constant_list(&This->baseShader.constantsI);
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
}
@ -690,9 +693,9 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = {
{D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 0, 1, pshader_label, NULL, NULL, 0, 0},
/* Constant definitions */
{D3DSIO_DEF, "def", "undefined", 1, 5, pshader_def, shader_hw_def, shader_glsl_def, 0, 0},
{D3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 1, 2, pshader_defb, NULL, shader_glsl_defb, 0, 0},
{D3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 1, 5, pshader_defi, NULL, shader_glsl_defi, 0, 0},
{D3DSIO_DEF, "def", "undefined", 1, 5, pshader_def, NULL, NULL, 0, 0},
{D3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 1, 2, pshader_defb, NULL, NULL, 0, 0},
{D3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 1, 5, pshader_defi, NULL, NULL, 0, 0},
/* Texture */
{D3DSIO_TEXCOORD, "texcoord", "undefined", 1, 1, pshader_texcoord, pshader_hw_texcoord, pshader_glsl_texcoord, 0, D3DPS_VERSION(1,3)},
@ -898,16 +901,23 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateShader(
static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *iface, CONST DWORD *pFunction) {
IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface;
HRESULT hr;
shader_reg_maps reg_maps;
/* First pass: trace shader */
shader_trace_init((IWineD3DBaseShader*) This, pFunction);
pshader_set_limits(This);
/* Initialize immediate constant lists */
list_init(&This->baseShader.constantsF);
list_init(&This->baseShader.constantsB);
list_init(&This->baseShader.constantsI);
/* Second pass: figure out which registers are used, what the semantics are, etc.. */
memset(&reg_maps, 0, sizeof(shader_reg_maps));
shader_get_registers_used((IWineD3DBaseShader*) This, &reg_maps,
memset(&reg_maps, 0, sizeof(shader_reg_maps));
hr = shader_get_registers_used((IWineD3DBaseShader*) This, &reg_maps,
This->semantics_in, NULL, pFunction);
if (hr != WINED3D_OK) return hr;
/* FIXME: validate reg_maps against OpenGL */
/* Generate HW shader in needed */
@ -920,13 +930,12 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *i
TRACE("(%p) : Copying the function\n", This);
if (NULL != pFunction) {
This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
if (!This->baseShader.function) return E_OUTOFMEMORY;
memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
} else {
This->baseShader.function = NULL;
}
/* TODO: Some proper return values for failures */
TRACE("(%p) : Returning WINED3D_OK\n", This);
return WINED3D_OK;
}

View File

@ -531,9 +531,9 @@ CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
{D3DSIO_DCL, "dcl", NULL, 0, 2, vshader_dcl, NULL, NULL, 0, 0},
/* Constant definitions */
{D3DSIO_DEF, "def", NULL, 1, 5, vshader_def, shader_hw_def, shader_glsl_def, 0, 0},
{D3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 1, 2, vshader_defb, NULL, shader_glsl_defb, 0, 0},
{D3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 1, 5, vshader_defi, NULL, shader_glsl_defi, 0, 0},
{D3DSIO_DEF, "def", NULL, 1, 5, vshader_def, NULL, NULL, 0, 0},
{D3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 1, 2, vshader_defb, NULL, NULL, 0, 0},
{D3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 1, 5, vshader_defi, NULL, NULL, 0, 0},
/* Flow control - requires GLSL or software shaders */
{D3DSIO_REP , "rep", GLNAME_REQUIRE_GLSL, 0, 1, vshader_rep, NULL, NULL, 0, 0},
@ -1045,7 +1045,11 @@ static ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface
GL_EXTCALL(glDeleteObjectARB(This->baseShader.prgId));
checkGLcall("glDeleteObjectARB");
}
HeapFree(GetProcessHeap(), 0, This);
shader_delete_constant_list(&This->baseShader.constantsF);
shader_delete_constant_list(&This->baseShader.constantsB);
shader_delete_constant_list(&This->baseShader.constantsI);
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
}
@ -1099,12 +1103,18 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader*
static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
HRESULT hr;
shader_reg_maps reg_maps;
/* First pass: trace shader */
shader_trace_init((IWineD3DBaseShader*) This, pFunction);
vshader_set_limits(This);
/* Initialize immediate constant lists */
list_init(&This->baseShader.constantsF);
list_init(&This->baseShader.constantsB);
list_init(&This->baseShader.constantsI);
/* Preload semantics for d3d8 shaders */
if (This->vertexDeclaration) {
IWineD3DVertexDeclarationImpl* vdecl = (IWineD3DVertexDeclarationImpl*) This->vertexDeclaration;
@ -1117,8 +1127,9 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader
/* Second pass: figure out registers used, semantics, etc.. */
memset(&reg_maps, 0, sizeof(shader_reg_maps));
shader_get_registers_used((IWineD3DBaseShader*) This, &reg_maps,
hr = shader_get_registers_used((IWineD3DBaseShader*) This, &reg_maps,
This->semantics_in, This->semantics_out, pFunction);
if (hr != WINED3D_OK) return hr;
/* Generate HW shader in needed */
This->baseShader.shader_mode = wined3d_settings.vs_selected_mode;
@ -1128,6 +1139,7 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader
/* copy the function ... because it will certainly be released by application */
if (NULL != pFunction) {
This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
if (!This->baseShader.function) return E_OUTOFMEMORY;
memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
} else {
This->baseShader.function = NULL;

View File

@ -1279,7 +1279,6 @@ struct glsl_shader_prog_link {
#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
@ -1288,6 +1287,12 @@ typedef struct semantic {
DWORD reg;
} semantic;
typedef struct local_constant {
struct list entry;
unsigned int idx;
DWORD value[4];
} local_constant;
typedef struct shader_reg_maps {
char texcoord[MAX_REG_TEXCRD]; /* pixel < 3.0 */
@ -1297,10 +1302,6 @@ 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 constantsI[MAX_CONST_I]; /* pixel & vertex >= 2.0 */
char constantsB[MAX_CONST_B]; /* pixel & vertex >= 2.0 */
/* Sampler usage tokens
* Use 0 as default (bit 31 is always 1 on a valid token) */
DWORD samplers[MAX_SAMPLERS];
@ -1372,6 +1373,9 @@ extern const SHADER_OPCODE* shader_get_opcode(
IWineD3DBaseShader *iface,
const DWORD code);
extern void shader_delete_constant_list(
struct list* clist);
/* Vertex shader utility functions */
extern BOOL vshader_get_input(
IWineD3DVertexShader* iface,
@ -1475,6 +1479,11 @@ typedef struct IWineD3DBaseShaderClass
/* Type of shader backend */
int shader_mode;
/* Immediate constants (override global ones) */
struct list constantsB;
struct list constantsF;
struct list constantsI;
} IWineD3DBaseShaderClass;
typedef struct IWineD3DBaseShaderImpl {
@ -1486,7 +1495,7 @@ typedef struct IWineD3DBaseShaderImpl {
IWineD3DBaseShaderClass baseShader;
} IWineD3DBaseShaderImpl;
extern void shader_get_registers_used(
extern HRESULT shader_get_registers_used(
IWineD3DBaseShader *iface,
shader_reg_maps* reg_maps,
semantic* semantics_in,