#include "brw_context.h"
#include "brw_wm.h"
-static GLboolean can_do_pln(struct intel_context *intel,
- const struct brw_reg *deltas)
+static bool
+can_do_pln(struct intel_context *intel, const struct brw_reg *deltas)
{
struct brw_context *brw = brw_context(&intel->ctx);
if (!brw->has_pln)
- return GL_FALSE;
+ return false;
if (deltas[1].nr != deltas[0].nr + 1)
- return GL_FALSE;
+ return false;
if (intel->gen < 6 && ((deltas[0].nr & 1) != 0))
- return GL_FALSE;
+ return false;
- return GL_TRUE;
-}
-
-/* Not quite sure how correct this is - need to understand horiz
- * vs. vertical strides a little better.
- */
-static INLINE struct brw_reg sechalf( struct brw_reg reg )
-{
- if (reg.vstride)
- reg.nr++;
- return reg;
+ return true;
}
/* Return the SrcReg index of the channels that can be immediate float operands
* instead of usage of PROGRAM_CONSTANT values through push/pull.
*/
-GLboolean
+bool
brw_wm_arg_can_be_immediate(enum prog_opcode opcode, int arg)
{
int opcode_array[] = {
*/
if (opcode == OPCODE_MAD || opcode == OPCODE_LRP) {
if (arg == 1 || arg == 2)
- return GL_TRUE;
+ return true;
}
if (opcode > ARRAY_SIZE(opcode_array))
- return GL_FALSE;
+ return false;
return arg == opcode_array[opcode] - 1;
}
const struct brw_reg *arg0)
{
struct brw_compile *p = &c->func;
+ struct intel_context *intel = &p->brw->intel;
+ struct brw_reg delta_x = retype(arg0[0], BRW_REGISTER_TYPE_W);
+ struct brw_reg delta_y = retype(arg0[1], BRW_REGISTER_TYPE_W);
if (mask & WRITEMASK_X) {
+ if (intel->gen >= 6) {
+ struct brw_reg delta_x_f = retype(delta_x, BRW_REGISTER_TYPE_F);
+ brw_MOV(p, delta_x_f, delta_x);
+ delta_x = delta_x_f;
+ }
+
if (c->fp->program.PixelCenterInteger) {
/* X' = X */
- brw_MOV(p,
- dst[0],
- retype(arg0[0], BRW_REGISTER_TYPE_W));
+ brw_MOV(p, dst[0], delta_x);
} else {
/* X' = X + 0.5 */
- brw_ADD(p,
- dst[0],
- retype(arg0[0], BRW_REGISTER_TYPE_W),
- brw_imm_f(0.5));
+ brw_ADD(p, dst[0], delta_x, brw_imm_f(0.5));
}
}
if (mask & WRITEMASK_Y) {
+ if (intel->gen >= 6) {
+ struct brw_reg delta_y_f = retype(delta_y, BRW_REGISTER_TYPE_F);
+ brw_MOV(p, delta_y_f, delta_y);
+ delta_y = delta_y_f;
+ }
+
if (c->fp->program.OriginUpperLeft) {
if (c->fp->program.PixelCenterInteger) {
/* Y' = Y */
- brw_MOV(p,
- dst[1],
- retype(arg0[1], BRW_REGISTER_TYPE_W));
+ brw_MOV(p, dst[1], delta_y);
} else {
- /* Y' = Y + 0.5 */
- brw_ADD(p,
- dst[1],
- retype(arg0[1], BRW_REGISTER_TYPE_W),
- brw_imm_f(0.5));
+ brw_ADD(p, dst[1], delta_y, brw_imm_f(0.5));
}
} else {
float center_offset = c->fp->program.PixelCenterInteger ? 0.0 : 0.5;
/* Y' = (height - 1) - Y + center */
- brw_ADD(p,
- dst[1],
- negate(retype(arg0[1], BRW_REGISTER_TYPE_W)),
+ brw_ADD(p, dst[1], negate(delta_y),
brw_imm_f(c->key.drawable_height - 1 + center_offset));
}
}
if (c->dispatch_width == 16) {
brw_math_16(p, dst[3],
BRW_MATH_FUNCTION_INV,
- BRW_MATH_SATURATE_NONE,
2, src,
BRW_MATH_PRECISION_FULL);
} else {
brw_math(p, dst[3],
BRW_MATH_FUNCTION_INV,
- BRW_MATH_SATURATE_NONE,
2, src,
BRW_MATH_DATA_VECTOR,
BRW_MATH_PRECISION_FULL);
* 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,
- GLboolean is_ddx,
- const struct brw_reg *arg0)
+ bool is_ddx,
+ 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)
const struct brw_reg *arg0,
const struct brw_reg *arg1)
{
- int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
+ int dst_chan = ffs(mask & WRITEMASK_XYZW) - 1;
if (!(mask & WRITEMASK_XYZW))
return; /* Do not emit dead code */
const struct brw_reg *arg0,
const struct brw_reg *arg1)
{
- int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
+ int dst_chan = ffs(mask & WRITEMASK_XYZW) - 1;
if (!(mask & WRITEMASK_XYZW))
return; /* Do not emit dead code */
const struct brw_reg *arg0,
const struct brw_reg *arg1)
{
- int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
+ int dst_chan = ffs(mask & WRITEMASK_XYZW) - 1;
if (!(mask & WRITEMASK_XYZW))
return; /* Do not emit dead code */
const struct brw_reg *arg0,
const struct brw_reg *arg1)
{
- const int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
+ const int dst_chan = ffs(mask & WRITEMASK_XYZW) - 1;
if (!(mask & WRITEMASK_XYZW))
return; /* Do not emit dead code */
{
struct brw_compile *p = &c->func;
struct intel_context *intel = &p->brw->intel;
- int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
- GLuint saturate = ((mask & SATURATE) ?
- BRW_MATH_SATURATE_SATURATE :
- BRW_MATH_SATURATE_NONE);
+ int dst_chan = ffs(mask & WRITEMASK_XYZW) - 1;
struct brw_reg src;
+ if (!(mask & WRITEMASK_XYZW))
+ return; /* Do not emit dead code */
+
+ assert(is_power_of_two(mask & WRITEMASK_XYZW));
+
if (intel->gen >= 6 && ((arg0[0].hstride == BRW_HORIZONTAL_STRIDE_0 ||
arg0[0].file != BRW_GENERAL_REGISTER_FILE) ||
arg0[0].negate || arg0[0].abs)) {
src = arg0[0];
}
- if (!(mask & WRITEMASK_XYZW))
- return; /* Do not emit dead code */
-
- assert(is_power_of_two(mask & WRITEMASK_XYZW));
-
/* Send two messages to perform all 16 operations:
*/
brw_push_insn_state(p);
+ brw_set_saturate(p, (mask & SATURATE) ? 1 : 0);
brw_set_compression_control(p, BRW_COMPRESSION_NONE);
brw_math(p,
dst[dst_chan],
function,
- saturate,
2,
src,
BRW_MATH_DATA_VECTOR,
brw_math(p,
offset(dst[dst_chan],1),
function,
- saturate,
3,
sechalf(src),
BRW_MATH_DATA_VECTOR,
{
struct brw_compile *p = &c->func;
struct intel_context *intel = &p->brw->intel;
- int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
+ int dst_chan = ffs(mask & WRITEMASK_XYZW) - 1;
if (!(mask & WRITEMASK_XYZW))
return; /* Do not emit dead code */
struct brw_reg temp_dst = dst[dst_chan];
if (arg0[0].hstride == BRW_HORIZONTAL_STRIDE_0) {
- if (arg1[0].hstride == BRW_HORIZONTAL_STRIDE_0) {
- /* Both scalar arguments. Do scalar calc. */
- src0.hstride = BRW_HORIZONTAL_STRIDE_1;
- src1.hstride = BRW_HORIZONTAL_STRIDE_1;
- temp_dst.hstride = BRW_HORIZONTAL_STRIDE_1;
- temp_dst.width = BRW_WIDTH_1;
-
- if (arg0[0].subnr != 0) {
- brw_MOV(p, temp_dst, src0);
- src0 = temp_dst;
-
- /* Ouch. We've used the temp as a dst, and we still
- * need a temp to store arg1 in, because src and dst
- * offsets have to be equal. Leaving this up to
- * glsl2-965 to handle correctly.
- */
- assert(arg1[0].subnr == 0);
- } else if (arg1[0].subnr != 0) {
- brw_MOV(p, temp_dst, src1);
- src1 = temp_dst;
- }
- } else {
- brw_MOV(p, temp_dst, src0);
- src0 = temp_dst;
- }
- } else if (arg1[0].hstride == BRW_HORIZONTAL_STRIDE_0) {
- brw_MOV(p, temp_dst, src1);
- src1 = temp_dst;
+ brw_MOV(p, temp_dst, src0);
+ src0 = temp_dst;
+ }
+
+ if (arg1[0].hstride == BRW_HORIZONTAL_STRIDE_0) {
+ /* This is a heinous hack to get a temporary register for use
+ * in case both arg0 and arg1 are constants. Why you're
+ * doing exponentiation on constant values in the shader, we
+ * don't know.
+ *
+ * max_wm_grf is almost surely less than the maximum GRF, and
+ * gen6 doesn't care about the number of GRFs used in a
+ * shader like pre-gen6 did.
+ */
+ struct brw_reg temp = brw_vec8_grf(c->max_wm_grf, 0);
+ brw_MOV(p, temp, src1);
+ src1 = temp;
}
brw_set_saturate(p, (mask & SATURATE) ? 1 : 0);
sechalf(src0),
sechalf(src1));
}
-
- /* Splat a scalar result into all the channels. */
- if (arg0[0].hstride == BRW_HORIZONTAL_STRIDE_0 &&
- arg1[0].hstride == BRW_HORIZONTAL_STRIDE_0) {
- temp_dst.hstride = BRW_HORIZONTAL_STRIDE_0;
- temp_dst.vstride = BRW_VERTICAL_STRIDE_0;
- brw_MOV(p, dst[dst_chan], temp_dst);
- }
} else {
- GLuint saturate = ((mask & SATURATE) ?
- BRW_MATH_SATURATE_SATURATE :
- BRW_MATH_SATURATE_NONE);
-
brw_set_compression_control(p, BRW_COMPRESSION_NONE);
brw_MOV(p, brw_message_reg(3), arg1[0]);
if (c->dispatch_width == 16) {
brw_MOV(p, brw_message_reg(5), sechalf(arg1[0]));
}
+ brw_set_saturate(p, (mask & SATURATE) ? 1 : 0);
brw_set_compression_control(p, BRW_COMPRESSION_NONE);
brw_math(p,
dst[dst_chan],
function,
- saturate,
2,
arg0[0],
BRW_MATH_DATA_VECTOR,
brw_math(p,
offset(dst[dst_chan],1),
function,
- saturate,
4,
sechalf(arg0[0]),
BRW_MATH_DATA_VECTOR,
struct brw_reg depth_payload,
GLuint tex_idx,
GLuint sampler,
- GLboolean shadow)
+ bool shadow)
{
struct brw_compile *p = &c->func;
struct intel_context *intel = &p->brw->intel;
nr_texcoords = 1;
break;
case TEXTURE_2D_INDEX:
+ case TEXTURE_1D_ARRAY_INDEX:
case TEXTURE_RECT_INDEX:
+ case TEXTURE_EXTERNAL_INDEX:
emit = WRITEMASK_XY;
nr_texcoords = 2;
break;
case TEXTURE_3D_INDEX:
+ case TEXTURE_2D_ARRAY_INDEX:
case TEXTURE_CUBE_INDEX:
emit = WRITEMASK_XYZ;
nr_texcoords = 3;
if (intel->gen < 5 && c->dispatch_width == 8)
nr_texcoords = 3;
- /* For shadow comparisons, we have to supply u,v,r. */
- if (shadow)
- nr_texcoords = 3;
+ if (shadow) {
+ if (intel->gen < 7) {
+ /* For shadow comparisons, we have to supply u,v,r. */
+ nr_texcoords = 3;
+ } else {
+ /* On Ivybridge, the shadow comparitor comes first. Just load it. */
+ brw_MOV(p, brw_message_reg(cur_mrf), arg[2]);
+ cur_mrf += mrf_per_channel;
+ }
+ }
/* Emit the texcoords. */
for (i = 0; i < nr_texcoords; i++) {
+ if (c->key.tex.gl_clamp_mask[i] & (1 << sampler))
+ brw_set_saturate(p, true);
+
if (emit & (1<<i))
brw_MOV(p, brw_message_reg(cur_mrf), arg[i]);
else
brw_MOV(p, brw_message_reg(cur_mrf), brw_imm_f(0));
cur_mrf += mrf_per_channel;
+
+ brw_set_saturate(p, false);
}
/* Fill in the shadow comparison reference value. */
- if (shadow) {
+ if (shadow && intel->gen < 7) {
if (intel->gen >= 5) {
/* Fill in the cube map array index value. */
brw_MOV(p, brw_message_reg(cur_mrf), brw_imm_f(0));
if (intel->gen >= 5) {
if (shadow)
- msg_type = BRW_SAMPLER_MESSAGE_SAMPLE_COMPARE_GEN5;
+ msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_COMPARE;
else
- msg_type = BRW_SAMPLER_MESSAGE_SAMPLE_GEN5;
+ msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE;
} else {
/* Note that G45 and older determines shadow compare and dispatch width
* from message length for most messages.
msg_type,
response_length,
cur_mrf - 1,
- 0,
1,
- simd_mode);
+ simd_mode,
+ BRW_SAMPLER_RETURN_FORMAT_FLOAT32);
}
*/
if (c->dispatch_width == 16 || intel->gen < 5) {
if (intel->gen >= 5)
- msg_type = BRW_SAMPLER_MESSAGE_SAMPLE_BIAS_GEN5;
+ msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_BIAS;
else
msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS;
mrf_per_channel = 2;
dst_retyped = retype(vec16(dst[0]), BRW_REGISTER_TYPE_UW);
response_length = 8;
} else {
- msg_type = BRW_SAMPLER_MESSAGE_SAMPLE_BIAS_GEN5;
+ msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_BIAS;
mrf_per_channel = 1;
dst_retyped = retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW);
response_length = 4;
break;
case TEXTURE_2D_INDEX:
case TEXTURE_RECT_INDEX:
+ case TEXTURE_EXTERNAL_INDEX:
brw_MOV(p, brw_message_reg(2 + 0 * mrf_per_channel), arg[0]);
brw_MOV(p, brw_message_reg(2 + 1 * mrf_per_channel), arg[1]);
brw_MOV(p, brw_message_reg(2 + 2 * mrf_per_channel), brw_imm_f(0));
msg_type,
response_length,
msgLength,
- 0,
1,
- BRW_SAMPLER_SIMD_MODE_SIMD16);
+ BRW_SAMPLER_SIMD_MODE_SIMD16,
+ BRW_SAMPLER_RETURN_FORMAT_FLOAT32);
}
{
struct brw_compile *p = &c->func;
struct intel_context *intel = &p->brw->intel;
- struct brw_reg dst;
-
- if (c->dispatch_width == 16)
- dst = retype(vec16(brw_null_reg()), BRW_REGISTER_TYPE_UW);
- else
- dst = retype(vec8(brw_null_reg()), BRW_REGISTER_TYPE_UW);
+ uint32_t msg_control;
/* Pass through control information:
+ *
+ * Gen6 has done m1 mov in emit_fb_write() for current SIMD16 case.
*/
/* mov (8) m1.0<1>:ud r1.0<8;8,1>:ud { Align1 NoMask } */
- if (intel->gen < 6) /* gen6, use headerless for fb write */
+ if (intel->gen < 6)
{
brw_push_insn_state(p);
brw_set_mask_control(p, BRW_MASK_DISABLE); /* ? */
brw_pop_insn_state(p);
}
+ if (c->dispatch_width == 16)
+ msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE;
+ else
+ msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_SINGLE_SOURCE_SUBSPAN01;
+
/* Send framebuffer write message: */
/* send (16) null.0<1>:uw m0 r0.0<8;8,1>:uw 0x85a04000:ud { Align1 EOT } */
brw_fb_WRITE(p,
c->dispatch_width,
- dst,
base_reg,
retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW),
+ msg_control,
target,
nr,
0,
- eot);
+ eot,
+ true);
}
*/
brw_push_insn_state(p);
+ if (c->key.clamp_fragment_color)
+ brw_set_saturate(p, 1);
+
for (channel = 0; channel < 4; channel++) {
if (intel->gen >= 6) {
/* gen6 SIMD16 single source DP write looks like:
}
}
}
+
+ brw_set_saturate(p, 0);
+
/* skip over the regs populated above:
*/
if (c->dispatch_width == 16)
*/
brw_push_insn_state(p);
brw_set_mask_control(p, BRW_MASK_DISABLE);
- brw_MOV(p, brw_message_reg(0), brw_vec8_grf(0, 0));
+ brw_MOV(p, retype(brw_message_reg(0), BRW_REGISTER_TYPE_UD),
+ retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UD));
brw_pop_insn_state(p);
if (target != 0) {
else {
struct brw_reg v1_null_ud = vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD));
struct brw_reg ip = brw_ip_reg();
- struct brw_instruction *jmp;
+ int jmp;
brw_set_compression_control(p, BRW_COMPRESSION_NONE);
brw_set_conditionalmod(p, BRW_CONDITIONAL_Z);
get_element_ud(brw_vec8_grf(1,0), 6),
brw_imm_ud(1<<26));
- jmp = brw_JMPI(p, ip, ip, brw_imm_w(0));
+ jmp = brw_JMPI(p, ip, ip, brw_imm_w(0)) - p->store;
{
emit_aa(c, arg1, 2);
fire_fb_write(c, 0, nr, target, eot);
break;
case OPCODE_DDX:
- emit_ddxy(p, dst, dst_flags, GL_TRUE, args[0]);
+ emit_ddxy(p, dst, dst_flags, true, args[0], false);
break;
case OPCODE_DDY:
- emit_ddxy(p, dst, dst_flags, GL_FALSE, args[0]);
+ /* Make sure fp->program.UsesDFdy flag got set (otherwise there's no
+ * guarantee that c->key.render_to_fbo is set).
+ */
+ assert(c->fp->program.UsesDFdy);
+ emit_ddxy(p, dst, dst_flags, false, args[0], c->key.render_to_fbo);
break;
case OPCODE_DP2: