wined3d: Create a separate function to record register usage.
This commit is contained in:
parent
b6682f96f7
commit
e001876163
|
@ -468,6 +468,78 @@ static void shader_delete_constant_list(struct list* clist) {
|
|||
list_init(clist);
|
||||
}
|
||||
|
||||
static void shader_record_register_usage(IWineD3DBaseShaderImpl *This, struct shader_reg_maps *reg_maps,
|
||||
DWORD register_type, UINT register_idx, BOOL has_rel_addr, BOOL pshader)
|
||||
{
|
||||
switch (register_type)
|
||||
{
|
||||
case WINED3DSPR_TEXTURE: /* WINED3DSPR_ADDR */
|
||||
if (pshader) reg_maps->texcoord[register_idx] = 1;
|
||||
else reg_maps->address[register_idx] = 1;
|
||||
break;
|
||||
|
||||
case WINED3DSPR_TEMP:
|
||||
reg_maps->temporary[register_idx] = 1;
|
||||
break;
|
||||
|
||||
case WINED3DSPR_INPUT:
|
||||
if (!pshader) reg_maps->attributes[register_idx] = 1;
|
||||
else
|
||||
{
|
||||
if (has_rel_addr)
|
||||
{
|
||||
/* If relative addressing is used, we must assume that all registers
|
||||
* are used. Even if it is a construct like v3[aL], we can't assume
|
||||
* that v0, v1 and v2 aren't read because aL can be negative */
|
||||
unsigned int i;
|
||||
for (i = 0; i < MAX_REG_INPUT; ++i)
|
||||
{
|
||||
((IWineD3DPixelShaderImpl *)This)->input_reg_used[i] = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
((IWineD3DPixelShaderImpl *)This)->input_reg_used[register_idx] = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WINED3DSPR_RASTOUT:
|
||||
if (register_idx == 1) reg_maps->fog = 1;
|
||||
break;
|
||||
|
||||
case WINED3DSPR_MISCTYPE:
|
||||
if (pshader && register_idx == 0) reg_maps->vpos = 1;
|
||||
break;
|
||||
|
||||
case WINED3DSPR_CONST:
|
||||
if (has_rel_addr)
|
||||
{
|
||||
if (!pshader)
|
||||
{
|
||||
if (register_idx <= ((IWineD3DVertexShaderImpl *)This)->min_rel_offset)
|
||||
((IWineD3DVertexShaderImpl *)This)->min_rel_offset = register_idx;
|
||||
else if (register_idx >= ((IWineD3DVertexShaderImpl *)This)->max_rel_offset)
|
||||
((IWineD3DVertexShaderImpl *)This)->max_rel_offset = register_idx;
|
||||
}
|
||||
reg_maps->usesrelconstF = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case WINED3DSPR_CONSTINT:
|
||||
reg_maps->integer_constants |= (1 << register_idx);
|
||||
break;
|
||||
|
||||
case WINED3DSPR_CONSTBOOL:
|
||||
reg_maps->boolean_constants |= (1 << register_idx);
|
||||
break;
|
||||
|
||||
default:
|
||||
TRACE("Not recording register of type %#x and idx %u\n", register_type, register_idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note that this does not count the loop register
|
||||
* as an address register. */
|
||||
|
||||
|
@ -481,7 +553,6 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_m
|
|||
unsigned int cur_loop_depth = 0, max_loop_depth = 0;
|
||||
const DWORD* pToken = byte_code;
|
||||
char pshader;
|
||||
unsigned int intconst = 0, boolconst = 0;
|
||||
|
||||
/* There are some minor differences between pixel and vertex shaders */
|
||||
|
||||
|
@ -625,7 +696,7 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_m
|
|||
pToken += param_size;
|
||||
|
||||
/* Rep and Loop always use an integer constant for the control parameters */
|
||||
intconst |= (1 << (reg & WINED3DSP_REGNUM_MASK));
|
||||
reg_maps->integer_constants |= (1 << (reg & WINED3DSP_REGNUM_MASK));
|
||||
}
|
||||
else if (ins.handler_idx == WINED3DSIH_ENDLOOP
|
||||
|| ins.handler_idx == WINED3DSIH_ENDREP)
|
||||
|
@ -708,70 +779,19 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_m
|
|||
regtype = shader_get_regtype(param);
|
||||
reg = param & WINED3DSP_REGNUM_MASK;
|
||||
|
||||
if (WINED3DSPR_TEXTURE == regtype) { /* vs: WINED3DSPR_ADDR */
|
||||
|
||||
if (pshader)
|
||||
reg_maps->texcoord[reg] = 1;
|
||||
else
|
||||
reg_maps->address[reg] = 1;
|
||||
}
|
||||
|
||||
else if (WINED3DSPR_TEMP == regtype)
|
||||
reg_maps->temporary[reg] = 1;
|
||||
|
||||
else if (WINED3DSPR_INPUT == regtype) {
|
||||
if( !pshader)
|
||||
reg_maps->attributes[reg] = 1;
|
||||
else {
|
||||
if(param & WINED3DSHADER_ADDRMODE_RELATIVE) {
|
||||
/* If relative addressing is used, we must assume that all registers
|
||||
* are used. Even if it is a construct like v3[aL], we can't assume
|
||||
* that v0, v1 and v2 aren't read because aL can be negative
|
||||
*/
|
||||
unsigned int i;
|
||||
for(i = 0; i < MAX_REG_INPUT; i++) {
|
||||
((IWineD3DPixelShaderImpl *) This)->input_reg_used[i] = TRUE;
|
||||
}
|
||||
} else {
|
||||
((IWineD3DPixelShaderImpl *) This)->input_reg_used[reg] = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (WINED3DSPR_RASTOUT == regtype && reg == 1)
|
||||
reg_maps->fog = 1;
|
||||
|
||||
else if (WINED3DSPR_MISCTYPE == regtype && reg == 0 && pshader)
|
||||
reg_maps->vpos = 1;
|
||||
|
||||
else if(WINED3DSPR_CONST == regtype) {
|
||||
if(param & WINED3DSHADER_ADDRMODE_RELATIVE) {
|
||||
if(!pshader) {
|
||||
if(reg <= ((IWineD3DVertexShaderImpl *) This)->min_rel_offset) {
|
||||
((IWineD3DVertexShaderImpl *) This)->min_rel_offset = reg;
|
||||
} else if(reg >= ((IWineD3DVertexShaderImpl *) This)->max_rel_offset) {
|
||||
((IWineD3DVertexShaderImpl *) This)->max_rel_offset = reg;
|
||||
}
|
||||
}
|
||||
reg_maps->usesrelconstF = TRUE;
|
||||
}
|
||||
}
|
||||
else if(WINED3DSPR_CONSTINT == regtype) {
|
||||
intconst |= (1 << reg);
|
||||
}
|
||||
else if(WINED3DSPR_CONSTBOOL == regtype) {
|
||||
boolconst |= (1 << reg);
|
||||
}
|
||||
|
||||
/* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and is used
|
||||
* in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel shaders because TECRDOUT
|
||||
* isn't used in them, but future register types might cause issues
|
||||
*/
|
||||
else if (WINED3DSPR_TEXCRDOUT == regtype && i == 0 /* Only look at writes */
|
||||
/* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and
|
||||
* is used in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel
|
||||
* shaders because TECRDOUT isn't used in them, but future register types might cause issues */
|
||||
if (regtype == WINED3DSPR_TEXCRDOUT && i == 0 /* Only look at writes */
|
||||
&& !pshader && WINED3DSHADER_VERSION_MAJOR(shader_version) < 3)
|
||||
{
|
||||
reg_maps->texcoord_mask[reg] |= shader_get_writemask(param);
|
||||
}
|
||||
else
|
||||
{
|
||||
shader_record_register_usage(This, reg_maps, regtype, reg,
|
||||
param & WINED3DSHADER_ADDRMODE_RELATIVE, pshader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -779,8 +799,6 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_m
|
|||
reg_maps->loop_depth = max_loop_depth;
|
||||
|
||||
This->baseShader.functionLength = ((char *)pToken - (char *)byte_code);
|
||||
This->baseShader.num_bool_consts = count_bits(boolconst);
|
||||
This->baseShader.num_int_consts = count_bits(intconst);
|
||||
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
|
|
@ -558,13 +558,15 @@ static void shader_glsl_load_constants(
|
|||
prog->vuniformF_locations, &priv->vconst_heap, priv->stack, constant_version);
|
||||
|
||||
/* Load DirectX 9 integer constants/uniforms for vertex shader */
|
||||
if(vshader->baseShader.num_int_consts) {
|
||||
if (vshader->baseShader.reg_maps.integer_constants)
|
||||
{
|
||||
shader_glsl_load_constantsI(vshader, gl_info, prog->vuniformI_locations,
|
||||
stateBlock->vertexShaderConstantI, stateBlock->changed.vertexShaderConstantsI);
|
||||
}
|
||||
|
||||
/* Load DirectX 9 boolean constants/uniforms for vertex shader */
|
||||
if(vshader->baseShader.num_bool_consts) {
|
||||
if (vshader->baseShader.reg_maps.boolean_constants)
|
||||
{
|
||||
shader_glsl_load_constantsB(vshader, gl_info, programId,
|
||||
stateBlock->vertexShaderConstantB, stateBlock->changed.vertexShaderConstantsB);
|
||||
}
|
||||
|
@ -583,13 +585,15 @@ static void shader_glsl_load_constants(
|
|||
prog->puniformF_locations, &priv->pconst_heap, priv->stack, constant_version);
|
||||
|
||||
/* Load DirectX 9 integer constants/uniforms for pixel shader */
|
||||
if(pshader->baseShader.num_int_consts) {
|
||||
if (pshader->baseShader.reg_maps.integer_constants)
|
||||
{
|
||||
shader_glsl_load_constantsI(pshader, gl_info, prog->puniformI_locations,
|
||||
stateBlock->pixelShaderConstantI, stateBlock->changed.pixelShaderConstantsI);
|
||||
}
|
||||
|
||||
/* Load DirectX 9 boolean constants/uniforms for pixel shader */
|
||||
if(pshader->baseShader.num_bool_consts) {
|
||||
if (pshader->baseShader.reg_maps.boolean_constants)
|
||||
{
|
||||
shader_glsl_load_constantsB(pshader, gl_info, programId,
|
||||
stateBlock->pixelShaderConstantB, stateBlock->changed.pixelShaderConstantsB);
|
||||
}
|
||||
|
@ -748,12 +752,12 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
|
|||
* (Unfortunately the Nvidia driver doesn't store 128 and -128 in one float
|
||||
*/
|
||||
max_constantsF = GL_LIMITS(vshader_constantsF) - 3;
|
||||
max_constantsF -= This->baseShader.num_int_consts;
|
||||
max_constantsF -= count_bits(This->baseShader.reg_maps.integer_constants);
|
||||
/* Strictly speaking a bool only uses one scalar, but the nvidia(Linux) compiler doesn't pack them properly,
|
||||
* so each scalar requires a full vec4. We could work around this by packing the booleans ourselves, but
|
||||
* for now take this into account when calculating the number of available constants
|
||||
*/
|
||||
max_constantsF -= This->baseShader.num_bool_consts;
|
||||
max_constantsF -= count_bits(This->baseShader.reg_maps.boolean_constants);
|
||||
/* Set by driver quirks in directx.c */
|
||||
max_constantsF -= GLINFO_LOCATION.reserved_glsl_constants;
|
||||
} else {
|
||||
|
@ -767,10 +771,10 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
|
|||
/* Always declare the full set of constants, the compiler can remove the unused ones because d3d doesn't(yet)
|
||||
* support indirect int and bool constant addressing. This avoids problems if the app uses e.g. i0 and i9.
|
||||
*/
|
||||
if (This->baseShader.limits.constant_int > 0 && This->baseShader.num_int_consts)
|
||||
if (This->baseShader.limits.constant_int > 0 && This->baseShader.reg_maps.integer_constants)
|
||||
shader_addline(buffer, "uniform ivec4 %cI[%u];\n", prefix, This->baseShader.limits.constant_int);
|
||||
|
||||
if (This->baseShader.limits.constant_bool > 0 && This->baseShader.num_bool_consts)
|
||||
if (This->baseShader.limits.constant_bool > 0 && This->baseShader.reg_maps.boolean_constants)
|
||||
shader_addline(buffer, "uniform bool %cB[%u];\n", prefix, This->baseShader.limits.constant_bool);
|
||||
|
||||
if(!pshader) {
|
||||
|
|
|
@ -416,6 +416,8 @@ typedef struct shader_reg_maps
|
|||
char attributes[MAX_ATTRIBS]; /* vertex */
|
||||
char labels[MAX_LABELS]; /* pixel, vertex */
|
||||
DWORD texcoord_mask[MAX_REG_TEXCRD]; /* vertex < 3.0 */
|
||||
WORD integer_constants; /* MAX_CONST_I, 16 */
|
||||
WORD boolean_constants; /* MAX_CONST_B, 16 */
|
||||
|
||||
/* Sampler usage tokens
|
||||
* Use 0 as default (bit 31 is always 1 on a valid token) */
|
||||
|
@ -2318,7 +2320,6 @@ typedef struct IWineD3DBaseShaderClass
|
|||
UINT functionLength;
|
||||
UINT cur_loop_depth, cur_loop_regno;
|
||||
BOOL load_local_constsF;
|
||||
BOOL num_bool_consts, num_int_consts;
|
||||
|
||||
/* Type of shader backend */
|
||||
int shader_mode;
|
||||
|
|
Loading…
Reference in New Issue