mirror of
https://github.com/reactos/wine.git
synced 2024-11-29 14:40:56 +00:00
wined3d: Improve Sampler support on 2.0 and 3.0 shaders.
- track sampler declarations and store the sampler usage in reg_maps structure - store a fake sampler usage for 1.X shaders (defined as 2D sampler) - re-sync glsl TEX implementation with the ARB one (no idea why they diverged..) - use sampler type in new TEX implementation to support 2D, 3D, and Cube sampling - change drawprim to bind pixel shader samplers Additional improvements: - rename texture limit to texcoord to prevent confusion - add sampler limit, and use that for samplers - *not* the same as texcoord above
This commit is contained in:
parent
e99926ee06
commit
0d08316523
@ -339,6 +339,8 @@ void shader_get_registers_used(
|
||||
DWORD regtype = shader_get_regtype(param);
|
||||
unsigned int regnum = param & D3DSP_REGNUM_MASK;
|
||||
|
||||
/* Vshader: mark attributes used
|
||||
Pshader: mark 3.0 input registers used, save token */
|
||||
if (D3DSPR_INPUT == regtype) {
|
||||
|
||||
if (!pshader)
|
||||
@ -348,21 +350,36 @@ void shader_get_registers_used(
|
||||
|
||||
shader_parse_decl_usage(reg_maps->semantics_in, usage, param);
|
||||
|
||||
/* Vshader: mark 3.0 output registers used, save token */
|
||||
} else if (D3DSPR_OUTPUT == regtype) {
|
||||
reg_maps->packed_output[regnum] = 1;
|
||||
shader_parse_decl_usage(reg_maps->semantics_out, usage, param);
|
||||
}
|
||||
|
||||
/* Handle samplers here */
|
||||
/* Save sampler usage token */
|
||||
} else if (D3DSPR_SAMPLER == regtype)
|
||||
reg_maps->samplers[regnum] = usage;
|
||||
|
||||
/* Skip definitions (for now) */
|
||||
} else if (D3DSIO_DEF == curOpcode->opcode) {
|
||||
pToken += curOpcode->num_params;
|
||||
|
||||
/* Set texture registers, and temporary registers */
|
||||
/* Set texture, address, temporary registers */
|
||||
} else {
|
||||
int i, limit;
|
||||
|
||||
/* Declare 1.X samplers implicitly, based on the destination reg. number */
|
||||
if (D3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1 &&
|
||||
(D3DSIO_TEX == curOpcode->opcode ||
|
||||
D3DSIO_TEXM3x2TEX == curOpcode->opcode ||
|
||||
D3DSIO_TEXM3x3TEX == curOpcode->opcode ||
|
||||
D3DSIO_TEXM3x3SPEC == curOpcode->opcode ||
|
||||
D3DSIO_TEXM3x3VSPEC == curOpcode->opcode)) {
|
||||
|
||||
/* Fake sampler usage, only set reserved bit and ttype */
|
||||
DWORD sampler_code = *pToken & D3DSP_REGNUM_MASK;
|
||||
reg_maps->samplers[sampler_code] = (0x1 << 31) | D3DSTT_2D;
|
||||
}
|
||||
|
||||
/* This will loop over all the registers and try to
|
||||
* make a bitmask of the ones we're interested in.
|
||||
*
|
||||
@ -511,7 +528,7 @@ void shader_dump_param(
|
||||
DWORD regtype = shader_get_regtype(param);
|
||||
|
||||
/* There are some minor differences between pixel and vertex shaders */
|
||||
BOOL pshader = shader_is_pshader_version(This->baseShader.hex_version);
|
||||
char pshader = shader_is_pshader_version(This->baseShader.hex_version);
|
||||
|
||||
/* For one, we'd prefer color components to be shown for pshaders.
|
||||
* FIXME: use the swizzle function for this */
|
||||
@ -678,13 +695,13 @@ void shader_generate_arb_declarations(
|
||||
shader_addline(buffer, "ADDRESS A%ld;\n", i);
|
||||
}
|
||||
|
||||
for(i = 0; i < This->baseShader.limits.texture; i++) {
|
||||
for(i = 0; i < This->baseShader.limits.texcoord; i++) {
|
||||
if (reg_maps->texcoord[i])
|
||||
shader_addline(buffer,"TEMP T%lu;\n", i);
|
||||
}
|
||||
|
||||
/* Texture coordinate registers must be pre-loaded */
|
||||
for (i = 0; i < This->baseShader.limits.texture; i++) {
|
||||
for (i = 0; i < This->baseShader.limits.texcoord; i++) {
|
||||
if (reg_maps->texcoord[i])
|
||||
shader_addline(buffer, "MOV T%lu, fragment.texcoord[%lu];\n", i, i);
|
||||
}
|
||||
@ -704,15 +721,36 @@ void shader_generate_glsl_declarations(
|
||||
IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
|
||||
int i;
|
||||
|
||||
FIXME("GLSL not fully implemented yet.\n");
|
||||
/* There are some minor differences between pixel and vertex shaders */
|
||||
char pshader = shader_is_pshader_version(This->baseShader.hex_version);
|
||||
|
||||
/* Declare the constants (aka uniforms) */
|
||||
shader_addline(buffer, "uniform vec4 C[%u];\n", This->baseShader.limits.constant_float);
|
||||
|
||||
/* Declare texture samplers
|
||||
* TODO: Make this work for textures other than 2D */
|
||||
for (i = 0; i < This->baseShader.limits.texture; i++) {
|
||||
shader_addline(buffer, "uniform sampler2D mytex%lu;\n", i);
|
||||
/* Declare texture samplers */
|
||||
for (i = 0; i < This->baseShader.limits.sampler; i++) {
|
||||
if (reg_maps->samplers[i]) {
|
||||
|
||||
const char* prefix = pshader? "psampler": "vsampler";
|
||||
|
||||
DWORD stype = reg_maps->samplers[i] & D3DSP_TEXTURETYPE_MASK;
|
||||
switch (stype) {
|
||||
|
||||
case D3DSTT_2D:
|
||||
shader_addline(buffer, "uniform sampler2D %s%lu;\n", prefix, i);
|
||||
break;
|
||||
case D3DSTT_CUBE:
|
||||
shader_addline(buffer, "uniform samplerCube %s%lu;\n", prefix, i);
|
||||
break;
|
||||
case D3DSTT_VOLUME:
|
||||
shader_addline(buffer, "uniform sampler3D %s%lu;\n", prefix, i);
|
||||
break;
|
||||
default:
|
||||
shader_addline(buffer, "uniform unsupported_sampler %s%lu;\n", prefix, i);
|
||||
FIXME("Unrecognized sampler type: %#lx\n", stype);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Declare address variables */
|
||||
@ -722,8 +760,9 @@ void shader_generate_glsl_declarations(
|
||||
}
|
||||
|
||||
/* Declare texture coordinate temporaries and initialize them */
|
||||
for (i = 0; i < This->baseShader.limits.texture; i++) {
|
||||
shader_addline(buffer, "vec4 T%lu = gl_TexCoord[%lu];\n", i, i);
|
||||
for (i = 0; i < This->baseShader.limits.texcoord; i++) {
|
||||
if (reg_maps->texcoord[i])
|
||||
shader_addline(buffer, "vec4 T%lu = gl_TexCoord[%lu];\n", i, i);
|
||||
}
|
||||
|
||||
/* Declare input register temporaries */
|
||||
|
@ -1686,6 +1686,36 @@ void drawStridedSoftwareVS(IWineD3DDevice *iface, WineDirect3DVertexStridedData
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Loads (pixel shader) samplers
|
||||
*/
|
||||
void drawPrimLoadPSamplersGLSL(
|
||||
IWineD3DDevice* iface) {
|
||||
|
||||
IWineD3DDeviceImpl* This = (IWineD3DDeviceImpl *)iface;
|
||||
GLhandleARB programId = This->stateBlock->shaderPrgId;
|
||||
GLhandleARB name_loc;
|
||||
int i;
|
||||
char sampler_name[20];
|
||||
|
||||
if (programId == 0) {
|
||||
/* No GLSL program set - nothing to do. */
|
||||
return;
|
||||
}
|
||||
|
||||
for (i=0; i< GL_LIMITS(textures); ++i) {
|
||||
if (This->stateBlock->textures[i] != NULL) {
|
||||
snprintf(sampler_name, sizeof(sampler_name), "psampler%d", i);
|
||||
name_loc = GL_EXTCALL(glGetUniformLocationARB(programId, sampler_name));
|
||||
if (name_loc != -1) {
|
||||
TRACE_(d3d_shader)("Loading %s for texture %d\n", sampler_name, i);
|
||||
GL_EXTCALL(glUniform1iARB(name_loc, i));
|
||||
checkGLcall("glUniform1iARB");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads floating point constants (aka uniforms) into the currently set GLSL program.
|
||||
* When @constants_set == NULL, it will load all the constants.
|
||||
@ -1780,6 +1810,9 @@ void drawPrimLoadConstants(IWineD3DDevice *iface,
|
||||
}
|
||||
if (usePixelShader) {
|
||||
|
||||
/* Load pixel shader samplers */
|
||||
drawPrimLoadPSamplersGLSL(iface);
|
||||
|
||||
/* Load DirectX 9 float constants/uniforms for pixel shader */
|
||||
drawPrimLoadConstantsGLSL_F(iface, WINED3D_PSHADER_MAX_CONSTANTS,
|
||||
This->stateBlock->pixelShaderConstantF,
|
||||
|
@ -242,7 +242,10 @@ static void shader_glsl_get_register_name(
|
||||
}
|
||||
break;
|
||||
case D3DSPR_SAMPLER:
|
||||
sprintf(tmpStr, "mytex%lu", reg);
|
||||
if (pshader)
|
||||
sprintf(tmpStr, "psampler%lu", reg);
|
||||
else
|
||||
sprintf(tmpStr, "vsampler%lu", reg);
|
||||
break;
|
||||
case D3DSPR_COLOROUT:
|
||||
if (reg == 0)
|
||||
@ -729,30 +732,48 @@ void pshader_glsl_tex(SHADER_OPCODE_ARG* arg) {
|
||||
DWORD hex_version = This->baseShader.hex_version;
|
||||
|
||||
char dst_str[100], dst_reg[50], dst_mask[6];
|
||||
char src0_str[100], src0_reg[50], src0_mask[6];
|
||||
char src1_str[100], src1_reg[50], src1_mask[6];
|
||||
char coord_str[100], coord_reg[50], coord_mask[6];
|
||||
char sampler_str[100], sampler_reg[50], sampler_mask[6];
|
||||
DWORD reg_dest_code = arg->dst & D3DSP_REGNUM_MASK;
|
||||
DWORD sampler_code, sampler_type;
|
||||
|
||||
/* All versions have a destination register */
|
||||
shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
|
||||
|
||||
|
||||
/* 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(coord_reg, dst_reg);
|
||||
else
|
||||
shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, coord_reg, coord_mask, coord_str);
|
||||
|
||||
/* 1.0-1.4: Use destination register as coordinate source.
|
||||
* 2.0+: Use provided coordinate source register. */
|
||||
if (hex_version == D3DPS_VERSION(1,4)) {
|
||||
shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
|
||||
sprintf(src1_str, "mytex%lu", reg_dest_code);
|
||||
} else if (hex_version > D3DPS_VERSION(1,4)) {
|
||||
shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
|
||||
shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
|
||||
}
|
||||
|
||||
/* 1.0-1.4: Use destination register number as texture code.
|
||||
* 2.0+: Use provided sampler number as texure code. */
|
||||
if (hex_version < D3DPS_VERSION(1,4)) {
|
||||
shader_addline(buffer, "%s = texture2D(mytex%lu, gl_TexCoord[%lu].st);\n",
|
||||
dst_str, reg_dest_code, reg_dest_code);
|
||||
} else {
|
||||
shader_addline(buffer, "%s = texture2D(%s, %s.st);\n", dst_str, src1_str, src0_reg);
|
||||
if (hex_version < D3DPS_VERSION(2,0)) {
|
||||
sprintf(sampler_str, "psampler%lu", reg_dest_code);
|
||||
sampler_code = reg_dest_code;
|
||||
}
|
||||
else {
|
||||
shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, sampler_reg, sampler_mask, sampler_str);
|
||||
sampler_code = arg->src[1] & D3DSP_REGNUM_MASK;
|
||||
}
|
||||
|
||||
sampler_type = arg->reg_maps->samplers[sampler_code] & D3DSP_TEXTURETYPE_MASK;
|
||||
switch(sampler_type) {
|
||||
|
||||
case D3DSTT_2D:
|
||||
shader_addline(buffer, "%s = texture2D(%s, %s.st);\n", dst_str, sampler_str, coord_reg);
|
||||
break;
|
||||
case D3DSTT_CUBE:
|
||||
shader_addline(buffer, "%s = textureCube(%s, %s.stp);\n", dst_str, sampler_str, coord_reg);
|
||||
break;
|
||||
case D3DSTT_VOLUME:
|
||||
shader_addline(buffer, "%s = texture3D(%s, %s.stp);\n", dst_str, sampler_str, coord_reg);
|
||||
break;
|
||||
default:
|
||||
shader_addline(buffer, "%s = unrecognized_stype(%s, %s.stp);\n", dst_str, sampler_str, coord_reg);
|
||||
FIXME("Unrecognized sampler type: %#lx;\n", sampler_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -806,7 +827,7 @@ void pshader_glsl_texm3x2tex(SHADER_OPCODE_ARG* arg) {
|
||||
|
||||
shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str);
|
||||
shader_addline(buffer, "tmp0.y = dot(vec3(T%lu), vec3(%s));\n", reg, src0_str);
|
||||
shader_addline(buffer, "T%lu = texture2D(mytex%lu, tmp0.st);\n", reg, reg);
|
||||
shader_addline(buffer, "T%lu = texture2D(psampler%lu, tmp0.st);\n", reg, reg);
|
||||
}
|
||||
|
||||
void pshader_glsl_input_pack(
|
||||
|
@ -947,7 +947,8 @@ static void pshader_set_limits(
|
||||
This->baseShader.limits.constant_float = 8;
|
||||
This->baseShader.limits.constant_int = 0;
|
||||
This->baseShader.limits.constant_bool = 0;
|
||||
This->baseShader.limits.texture = 4;
|
||||
This->baseShader.limits.texcoord = 4;
|
||||
This->baseShader.limits.sampler = 4;
|
||||
This->baseShader.limits.packed_input = 0;
|
||||
break;
|
||||
|
||||
@ -956,7 +957,8 @@ static void pshader_set_limits(
|
||||
This->baseShader.limits.constant_float = 8;
|
||||
This->baseShader.limits.constant_int = 0;
|
||||
This->baseShader.limits.constant_bool = 0;
|
||||
This->baseShader.limits.texture = 6;
|
||||
This->baseShader.limits.texcoord = 6;
|
||||
This->baseShader.limits.sampler = 6;
|
||||
This->baseShader.limits.packed_input = 0;
|
||||
break;
|
||||
|
||||
@ -967,7 +969,8 @@ static void pshader_set_limits(
|
||||
This->baseShader.limits.constant_float = 32;
|
||||
This->baseShader.limits.constant_int = 16;
|
||||
This->baseShader.limits.constant_bool = 16;
|
||||
This->baseShader.limits.texture = 8;
|
||||
This->baseShader.limits.texcoord = 8;
|
||||
This->baseShader.limits.sampler = 16;
|
||||
This->baseShader.limits.packed_input = 0;
|
||||
break;
|
||||
|
||||
@ -976,15 +979,17 @@ static void pshader_set_limits(
|
||||
This->baseShader.limits.constant_float = 224;
|
||||
This->baseShader.limits.constant_int = 16;
|
||||
This->baseShader.limits.constant_bool = 16;
|
||||
This->baseShader.limits.texture = 0;
|
||||
This->baseShader.limits.texcoord = 0;
|
||||
This->baseShader.limits.sampler = 16;
|
||||
This->baseShader.limits.packed_input = 12;
|
||||
break;
|
||||
|
||||
default: This->baseShader.limits.temporary = 32;
|
||||
This->baseShader.limits.constant_float = 8;
|
||||
This->baseShader.limits.constant_int = 0;
|
||||
This->baseShader.limits.constant_bool = 0;
|
||||
This->baseShader.limits.texture = 8;
|
||||
This->baseShader.limits.constant_float = 32;
|
||||
This->baseShader.limits.constant_int = 16;
|
||||
This->baseShader.limits.constant_bool = 16;
|
||||
This->baseShader.limits.texcoord = 8;
|
||||
This->baseShader.limits.sampler = 16;
|
||||
This->baseShader.limits.packed_input = 0;
|
||||
FIXME("Unrecognized pixel shader version %#lx\n",
|
||||
This->baseShader.hex_version);
|
||||
@ -1124,7 +1129,7 @@ static void pshader_hw_tex(SHADER_OPCODE_ARG* arg) {
|
||||
get_register_name(dst, reg_dest, arg->reg_maps->constantsF);
|
||||
|
||||
/* 1.0-1.3: Use destination register as coordinate source.
|
||||
2.0+: Use provided coordinate source register. */
|
||||
1.4+: Use provided coordinate source register. */
|
||||
if (hex_version < D3DPS_VERSION(1,4))
|
||||
strcpy(reg_coord, reg_dest);
|
||||
else
|
||||
|
@ -712,7 +712,7 @@ inline static void vshader_program_add_param(SHADER_OPCODE_ARG *arg, const DWORD
|
||||
static void vshader_set_limits(
|
||||
IWineD3DVertexShaderImpl *This) {
|
||||
|
||||
This->baseShader.limits.texture = 0;
|
||||
This->baseShader.limits.texcoord = 0;
|
||||
This->baseShader.limits.attributes = 16;
|
||||
This->baseShader.limits.packed_input = 0;
|
||||
|
||||
@ -727,6 +727,7 @@ static void vshader_set_limits(
|
||||
This->baseShader.limits.constant_int = 0;
|
||||
This->baseShader.limits.address = 1;
|
||||
This->baseShader.limits.packed_output = 0;
|
||||
This->baseShader.limits.sampler = 0;
|
||||
break;
|
||||
|
||||
case D3DVS_VERSION(2,0):
|
||||
@ -736,6 +737,7 @@ static void vshader_set_limits(
|
||||
This->baseShader.limits.constant_int = 16;
|
||||
This->baseShader.limits.address = 1;
|
||||
This->baseShader.limits.packed_output = 0;
|
||||
This->baseShader.limits.sampler = 0;
|
||||
break;
|
||||
|
||||
case D3DVS_VERSION(3,0):
|
||||
@ -744,13 +746,15 @@ static void vshader_set_limits(
|
||||
This->baseShader.limits.constant_int = 32;
|
||||
This->baseShader.limits.address = 1;
|
||||
This->baseShader.limits.packed_output = 12;
|
||||
This->baseShader.limits.sampler = 4;
|
||||
break;
|
||||
|
||||
default: This->baseShader.limits.temporary = 12;
|
||||
This->baseShader.limits.constant_bool = 0;
|
||||
This->baseShader.limits.constant_int = 0;
|
||||
This->baseShader.limits.constant_bool = 16;
|
||||
This->baseShader.limits.constant_int = 16;
|
||||
This->baseShader.limits.address = 1;
|
||||
This->baseShader.limits.packed_output = 0;
|
||||
This->baseShader.limits.sampler = 0;
|
||||
FIXME("Unrecognized vertex shader version %#lx\n",
|
||||
This->baseShader.hex_version);
|
||||
}
|
||||
|
@ -1268,9 +1268,15 @@ typedef struct shader_reg_maps {
|
||||
char constantsF[MAX_CONST_F]; /* pixel, vertex */
|
||||
/* TODO: Integer and bool constants */
|
||||
|
||||
/* Semantics maps (semantic -> reg_token)
|
||||
* Use 0 as default (bit 31 is always 1 on a valid token) */
|
||||
DWORD* semantics_in; /* vertex, pixel */
|
||||
DWORD* semantics_out; /* vertex */
|
||||
|
||||
/* Sampler usage tokens
|
||||
* Use 0 as default (bit 31 is always 1 on a valid token) */
|
||||
DWORD samplers[MAX_SAMPLERS];
|
||||
|
||||
} shader_reg_maps;
|
||||
|
||||
#define SHADER_PGMSIZE 65535
|
||||
@ -1306,7 +1312,8 @@ typedef struct SHADER_OPCODE_ARG {
|
||||
|
||||
typedef struct SHADER_LIMITS {
|
||||
unsigned int temporary;
|
||||
unsigned int texture;
|
||||
unsigned int texcoord;
|
||||
unsigned int sampler;
|
||||
unsigned int constant_int;
|
||||
unsigned int constant_float;
|
||||
unsigned int constant_bool;
|
||||
|
Loading…
Reference in New Issue
Block a user