Commit 0d083165 authored by Ivan Gyurdiev's avatar Ivan Gyurdiev Committed by Alexandre Julliard

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
parent e99926ee
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment