wined3d: Add the vertex shader footer in the main function.
This commit is contained in:
parent
5befed21f6
commit
d4312ebb16
|
@ -201,6 +201,8 @@ struct shader_arb_ctx_priv
|
||||||
int aL;
|
int aL;
|
||||||
|
|
||||||
unsigned int vs_clipplanes;
|
unsigned int vs_clipplanes;
|
||||||
|
BOOL footer_written;
|
||||||
|
BOOL in_main_func;
|
||||||
|
|
||||||
/* For 3.0 vertex shaders */
|
/* For 3.0 vertex shaders */
|
||||||
const char *vs_output[MAX_REG_OUTPUT];
|
const char *vs_output[MAX_REG_OUTPUT];
|
||||||
|
@ -2804,6 +2806,7 @@ static void shader_hw_label(const struct wined3d_shader_instruction *ins)
|
||||||
SHADER_BUFFER *buffer = ins->ctx->buffer;
|
SHADER_BUFFER *buffer = ins->ctx->buffer;
|
||||||
struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
|
struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
|
||||||
|
|
||||||
|
priv->in_main_func = FALSE;
|
||||||
/* Call instructions activate the NV extensions, not labels and rets. If there is an uncalled
|
/* Call instructions activate the NV extensions, not labels and rets. If there is an uncalled
|
||||||
* subroutine, don't generate a label that will make GL complain
|
* subroutine, don't generate a label that will make GL complain
|
||||||
*/
|
*/
|
||||||
|
@ -2812,13 +2815,105 @@ static void shader_hw_label(const struct wined3d_shader_instruction *ins)
|
||||||
shader_addline(buffer, "l%u:\n", ins->src[0].reg.idx);
|
shader_addline(buffer, "l%u:\n", ins->src[0].reg.idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vshader_add_footer(IWineD3DVertexShaderImpl *This, SHADER_BUFFER *buffer, const struct arb_vs_compile_args *args,
|
||||||
|
struct shader_arb_ctx_priv *priv_ctx)
|
||||||
|
{
|
||||||
|
const shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
|
||||||
|
IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)This->baseShader.device;
|
||||||
|
const WineD3D_GL_Info *gl_info = &device->adapter->gl_info;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
/* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used
|
||||||
|
* or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE),
|
||||||
|
* the fog frag coord is thrown away. If the fog frag coord is used, but not written by
|
||||||
|
* the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0)
|
||||||
|
*/
|
||||||
|
if(args->super.fog_src == VS_FOG_Z) {
|
||||||
|
shader_addline(buffer, "MOV result.fogcoord, TMP_OUT.z;\n");
|
||||||
|
} else if (!reg_maps->fog) {
|
||||||
|
/* posFixup.x is always 1.0, so we can savely use it */
|
||||||
|
shader_addline(buffer, "ADD result.fogcoord, posFixup.x, -posFixup.x;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the final position.
|
||||||
|
*
|
||||||
|
* OpenGL coordinates specify the center of the pixel while d3d coords specify
|
||||||
|
* the corner. The offsets are stored in z and w in posFixup. posFixup.y contains
|
||||||
|
* 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x
|
||||||
|
* contains 1.0 to allow a mad, but arb vs swizzles are too restricted for that.
|
||||||
|
*/
|
||||||
|
shader_addline(buffer, "MUL TA, posFixup, TMP_OUT.w;\n");
|
||||||
|
shader_addline(buffer, "ADD TMP_OUT.x, TMP_OUT.x, TA.z;\n");
|
||||||
|
shader_addline(buffer, "MAD TMP_OUT.y, TMP_OUT.y, posFixup.y, TA.w;\n");
|
||||||
|
|
||||||
|
if(use_nv_clip(gl_info) && priv_ctx->target_version >= NV2)
|
||||||
|
{
|
||||||
|
for(i = 0; i < priv_ctx->vs_clipplanes; i++)
|
||||||
|
{
|
||||||
|
shader_addline(buffer, "DP4 result.clip[%u].x, TMP_OUT, state.clip[%u].plane;\n", i, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(args->boolclip.clip_control[0])
|
||||||
|
{
|
||||||
|
unsigned int cur_clip = 0;
|
||||||
|
char component[4] = {'x', 'y', 'z', 'w'};
|
||||||
|
|
||||||
|
for(i = 0; i < GL_LIMITS(clipplanes); i++)
|
||||||
|
{
|
||||||
|
if(args->boolclip.clip_control[1] & (1 << i))
|
||||||
|
{
|
||||||
|
shader_addline(buffer, "DP4 TA.%c, TMP_OUT, state.clip[%u].plane;\n",
|
||||||
|
component[cur_clip++], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch(cur_clip)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
shader_addline(buffer, "MOV TA, -helper_const.w;\n");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
shader_addline(buffer, "MOV TA.yzw, -helper_const.w;\n");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
shader_addline(buffer, "MOV TA.zw, -helper_const.w;\n");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
shader_addline(buffer, "MOV TA.w, -helper_const.w;\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
shader_addline(buffer, "MOV result.texcoord[%u], TA;\n",
|
||||||
|
args->boolclip.clip_control[0] - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c
|
||||||
|
* and the glsl equivalent
|
||||||
|
*/
|
||||||
|
if(need_helper_const(gl_info)) {
|
||||||
|
shader_addline(buffer, "MAD TMP_OUT.z, TMP_OUT.z, helper_const.x, -TMP_OUT.w;\n");
|
||||||
|
} else {
|
||||||
|
shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, TMP_OUT.z;\n");
|
||||||
|
shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, -TMP_OUT.w;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
shader_addline(buffer, "MOV result.position, TMP_OUT;\n");
|
||||||
|
|
||||||
|
priv_ctx->footer_written = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void shader_hw_ret(const struct wined3d_shader_instruction *ins)
|
static void shader_hw_ret(const struct wined3d_shader_instruction *ins)
|
||||||
{
|
{
|
||||||
SHADER_BUFFER *buffer = ins->ctx->buffer;
|
SHADER_BUFFER *buffer = ins->ctx->buffer;
|
||||||
struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
|
struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
|
||||||
|
IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *) ins->ctx->shader;
|
||||||
|
BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
|
||||||
|
|
||||||
if(priv->target_version == ARB) return;
|
if(priv->target_version == ARB) return;
|
||||||
|
|
||||||
|
if(vshader)
|
||||||
|
{
|
||||||
|
if(priv->in_main_func) vshader_add_footer((IWineD3DVertexShaderImpl *) shader, buffer, priv->cur_vs_args, priv);
|
||||||
|
}
|
||||||
|
|
||||||
shader_addline(buffer, "RET;\n");
|
shader_addline(buffer, "RET;\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3565,89 +3660,6 @@ static void init_output_registers(IWineD3DVertexShaderImpl *shader, DWORD sig_nu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vshader_add_footer(IWineD3DVertexShaderImpl *This, SHADER_BUFFER *buffer, const struct arb_vs_compile_args *args,
|
|
||||||
struct shader_arb_ctx_priv *priv_ctx)
|
|
||||||
{
|
|
||||||
const shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
|
|
||||||
IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)This->baseShader.device;
|
|
||||||
const WineD3D_GL_Info *gl_info = &device->adapter->gl_info;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
/* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used
|
|
||||||
* or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE),
|
|
||||||
* the fog frag coord is thrown away. If the fog frag coord is used, but not written by
|
|
||||||
* the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0)
|
|
||||||
*/
|
|
||||||
if(args->super.fog_src == VS_FOG_Z) {
|
|
||||||
shader_addline(buffer, "MOV result.fogcoord, TMP_OUT.z;\n");
|
|
||||||
} else if (!reg_maps->fog) {
|
|
||||||
/* posFixup.x is always 1.0, so we can savely use it */
|
|
||||||
shader_addline(buffer, "ADD result.fogcoord, posFixup.x, -posFixup.x;\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write the final position.
|
|
||||||
*
|
|
||||||
* OpenGL coordinates specify the center of the pixel while d3d coords specify
|
|
||||||
* the corner. The offsets are stored in z and w in posFixup. posFixup.y contains
|
|
||||||
* 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x
|
|
||||||
* contains 1.0 to allow a mad, but arb vs swizzles are too restricted for that.
|
|
||||||
*/
|
|
||||||
shader_addline(buffer, "MUL TA, posFixup, TMP_OUT.w;\n");
|
|
||||||
shader_addline(buffer, "ADD TMP_OUT.x, TMP_OUT.x, TA.z;\n");
|
|
||||||
shader_addline(buffer, "MAD TMP_OUT.y, TMP_OUT.y, posFixup.y, TA.w;\n");
|
|
||||||
|
|
||||||
if(use_nv_clip(gl_info) && priv_ctx->target_version >= NV2)
|
|
||||||
{
|
|
||||||
for(i = 0; i < priv_ctx->vs_clipplanes; i++)
|
|
||||||
{
|
|
||||||
shader_addline(buffer, "DP4 result.clip[%u].x, TMP_OUT, state.clip[%u].plane;\n", i, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(args->boolclip.clip_control[0])
|
|
||||||
{
|
|
||||||
unsigned int cur_clip = 0;
|
|
||||||
char component[4] = {'x', 'y', 'z', 'w'};
|
|
||||||
|
|
||||||
for(i = 0; i < GL_LIMITS(clipplanes); i++)
|
|
||||||
{
|
|
||||||
if(args->boolclip.clip_control[1] & (1 << i))
|
|
||||||
{
|
|
||||||
shader_addline(buffer, "DP4 TA.%c, TMP_OUT, state.clip[%u].plane;\n",
|
|
||||||
component[cur_clip++], i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch(cur_clip)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
shader_addline(buffer, "MOV TA, -helper_const.w;\n");
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
shader_addline(buffer, "MOV TA.yzw, -helper_const.w;\n");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
shader_addline(buffer, "MOV TA.zw, -helper_const.w;\n");
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
shader_addline(buffer, "MOV TA.w, -helper_const.w;\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
shader_addline(buffer, "MOV result.texcoord[%u], TA;\n",
|
|
||||||
args->boolclip.clip_control[0] - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c
|
|
||||||
* and the glsl equivalent
|
|
||||||
*/
|
|
||||||
if(need_helper_const(gl_info)) {
|
|
||||||
shader_addline(buffer, "MAD TMP_OUT.z, TMP_OUT.z, helper_const.x, -TMP_OUT.w;\n");
|
|
||||||
} else {
|
|
||||||
shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, TMP_OUT.z;\n");
|
|
||||||
shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, -TMP_OUT.w;\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
shader_addline(buffer, "MOV result.position, TMP_OUT;\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* GL locking is done by the caller */
|
/* GL locking is done by the caller */
|
||||||
static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This,
|
static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This,
|
||||||
SHADER_BUFFER *buffer, const struct arb_vs_compile_args *args, struct arb_vs_compiled_shader *compiled)
|
SHADER_BUFFER *buffer, const struct arb_vs_compile_args *args, struct arb_vs_compiled_shader *compiled)
|
||||||
|
@ -3750,10 +3762,12 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The shader starts with the main function */
|
||||||
|
priv_ctx.in_main_func = TRUE;
|
||||||
/* Base Shader Body */
|
/* Base Shader Body */
|
||||||
shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, &priv_ctx);
|
shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, &priv_ctx);
|
||||||
|
|
||||||
vshader_add_footer(This, buffer, args, &priv_ctx);
|
if(!priv_ctx.footer_written) vshader_add_footer(This, buffer, args, &priv_ctx);
|
||||||
|
|
||||||
shader_addline(buffer, "END\n");
|
shader_addline(buffer, "END\n");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue