struct brw_context *brw = brw_context(ctx);
struct brw_wm_prog_key key;
+ /* As a temporary measure we assume that all programs use dFdy() (and hence
+ * need to be compiled differently depending on whether we're rendering to
+ * an FBO). FIXME: set this bool correctly based on the contents of the
+ * program.
+ */
+ bool program_uses_dfdy = true;
+
if (!prog->_LinkedShaders[MESA_SHADER_FRAGMENT])
return true;
if (fp->Base.InputsRead & FRAG_BIT_WPOS) {
key.drawable_height = ctx->DrawBuffer->Height;
+ }
+
+ if ((fp->Base.InputsRead & FRAG_BIT_WPOS) || program_uses_dfdy) {
key.render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer);
}
struct brw_reg src);
void generate_discard(fs_inst *inst);
void generate_ddx(fs_inst *inst, struct brw_reg dst, struct brw_reg src);
- void generate_ddy(fs_inst *inst, struct brw_reg dst, struct brw_reg src);
+ void generate_ddy(fs_inst *inst, struct brw_reg dst, struct brw_reg src,
+ bool negate_value);
void generate_spill(fs_inst *inst, struct brw_reg src);
void generate_unspill(fs_inst *inst, struct brw_reg dst);
void generate_pull_constant_load(fs_inst *inst, struct brw_reg dst);
brw_ADD(p, dst, src0, negate(src1));
}
+/* The negate_value boolean is used to negate the derivative computation for
+ * FBOs, since they place the origin at the upper left instead of the lower
+ * left.
+ */
void
-fs_visitor::generate_ddy(fs_inst *inst, struct brw_reg dst, struct brw_reg src)
+fs_visitor::generate_ddy(fs_inst *inst, struct brw_reg dst, struct brw_reg src,
+ bool negate_value)
{
struct brw_reg src0 = brw_reg(src.file, src.nr, 0,
BRW_REGISTER_TYPE_F,
BRW_WIDTH_4,
BRW_HORIZONTAL_STRIDE_0,
BRW_SWIZZLE_XYZW, WRITEMASK_XYZW);
- brw_ADD(p, dst, src0, negate(src1));
+ if (negate_value)
+ brw_ADD(p, dst, src1, negate(src0));
+ else
+ brw_ADD(p, dst, src0, negate(src1));
}
void
generate_ddx(inst, dst, src[0]);
break;
case FS_OPCODE_DDY:
- generate_ddy(inst, dst, src[0]);
+ generate_ddy(inst, dst, src[0], c->key.render_to_fbo);
break;
case FS_OPCODE_SPILL:
GLuint line_aa;
GLuint i;
+ /* As a temporary measure we assume that all programs use dFdy() (and hence
+ * need to be compiled differently depending on whether we're rendering to
+ * an FBO). FIXME: set this bool correctly based on the contents of the
+ * program.
+ */
+ bool program_uses_dfdy = true;
+
memset(key, 0, sizeof(*key));
/* Build the index for table lookup
*/
if (fp->program.Base.InputsRead & FRAG_BIT_WPOS) {
key->drawable_height = ctx->DrawBuffer->Height;
+ }
+
+ if ((fp->program.Base.InputsRead & FRAG_BIT_WPOS) || program_uses_dfdy) {
key->render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer);
}
const struct brw_reg *dst,
GLuint mask,
bool is_ddx,
- const struct brw_reg *arg0);
+ const struct brw_reg *arg0,
+ bool negate_value);
void emit_delta_xy(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
* between each other. We could probably do it like ddx and swizzle the right
* order later, but bail for now and just produce
* ((ss0.tl - ss0.bl)x4 (ss1.tl - ss1.bl)x4)
+ *
+ * The negate_value boolean is used to negate the d/dy computation for FBOs,
+ * since they place the origin at the upper left instead of the lower left.
*/
void emit_ddxy(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
bool is_ddx,
- const struct brw_reg *arg0)
+ const struct brw_reg *arg0,
+ bool negate_value)
{
int i;
struct brw_reg src0, src1;
BRW_HORIZONTAL_STRIDE_0,
BRW_SWIZZLE_XYZW, WRITEMASK_XYZW);
}
- brw_ADD(p, dst[i], src0, negate(src1));
+ if (negate_value)
+ brw_ADD(p, dst[i], src1, negate(src0));
+ else
+ brw_ADD(p, dst[i], src0, negate(src1));
}
}
if (mask & SATURATE)
break;
case OPCODE_DDX:
- emit_ddxy(p, dst, dst_flags, true, args[0]);
+ emit_ddxy(p, dst, dst_flags, true, args[0], false);
break;
case OPCODE_DDY:
- emit_ddxy(p, dst, dst_flags, false, args[0]);
+ emit_ddxy(p, dst, dst_flags, false, args[0], c->key.render_to_fbo);
break;
case OPCODE_DP2: