#include "dev/gen_device_info.h"
#include "common/gen_sample_positions.h"
#include "genxml/gen_macros.h"
+#include "common/gen_guardband.h"
#include "main/bufferobj.h"
#include "main/context.h"
#include "main/macros.h"
#include "main/state.h"
+#include "genX_boilerplate.h"
+
#include "brw_context.h"
+#include "brw_cs.h"
#include "brw_draw.h"
#include "brw_multisample_state.h"
#include "brw_state.h"
#include "main/viewport.h"
#include "util/half_float.h"
-UNUSED static void *
-emit_dwords(struct brw_context *brw, unsigned n)
-{
- intel_batchbuffer_begin(brw, n);
- uint32_t *map = brw->batch.map_next;
- brw->batch.map_next += n;
- intel_batchbuffer_advance(brw);
- return map;
-}
-
-struct brw_address {
- struct brw_bo *bo;
- unsigned reloc_flags;
- uint32_t offset;
-};
-
-#define __gen_address_type struct brw_address
-#define __gen_user_data struct brw_context
-
-static uint64_t
-__gen_combine_address(struct brw_context *brw, void *location,
- struct brw_address address, uint32_t delta)
-{
- struct intel_batchbuffer *batch = &brw->batch;
- uint32_t offset;
-
- if (address.bo == NULL) {
- return address.offset + delta;
- } else {
- if (GEN_GEN < 6 && brw_ptr_in_state_buffer(batch, location)) {
- offset = (char *) location - (char *) brw->batch.state.map;
- return brw_state_reloc(batch, offset, address.bo,
- address.offset + delta,
- address.reloc_flags);
- }
-
- assert(!brw_ptr_in_state_buffer(batch, location));
-
- offset = (char *) location - (char *) brw->batch.batch.map;
- return brw_batch_reloc(batch, offset, address.bo,
- address.offset + delta,
- address.reloc_flags);
- }
-}
-
-UNUSED static struct brw_address
-rw_bo(struct brw_bo *bo, uint32_t offset)
-{
- return (struct brw_address) {
- .bo = bo,
- .offset = offset,
- .reloc_flags = RELOC_WRITE,
- };
-}
-
-static struct brw_address
-ro_bo(struct brw_bo *bo, uint32_t offset)
-{
- return (struct brw_address) {
- .bo = bo,
- .offset = offset,
- };
-}
-
-static struct brw_address
-rw_32_bo(struct brw_bo *bo, uint32_t offset)
-{
- return (struct brw_address) {
- .bo = bo,
- .offset = offset,
- .reloc_flags = RELOC_WRITE | RELOC_32BIT,
- };
-}
-
-static struct brw_address
-ro_32_bo(struct brw_bo *bo, uint32_t offset)
-{
- return (struct brw_address) {
- .bo = bo,
- .offset = offset,
- .reloc_flags = RELOC_32BIT,
- };
-}
-
-UNUSED static struct brw_address
-ggtt_bo(struct brw_bo *bo, uint32_t offset)
-{
- return (struct brw_address) {
- .bo = bo,
- .offset = offset,
- .reloc_flags = RELOC_WRITE | RELOC_NEEDS_GGTT,
- };
-}
-
#if GEN_GEN == 4
static struct brw_address
KSP(struct brw_context *brw, uint32_t offset)
}
#endif
-#include "genxml/genX_pack.h"
-
-#define _brw_cmd_length(cmd) cmd ## _length
-#define _brw_cmd_length_bias(cmd) cmd ## _length_bias
-#define _brw_cmd_header(cmd) cmd ## _header
-#define _brw_cmd_pack(cmd) cmd ## _pack
-
-#define brw_batch_emit(brw, cmd, name) \
- for (struct cmd name = { _brw_cmd_header(cmd) }, \
- *_dst = emit_dwords(brw, _brw_cmd_length(cmd)); \
- __builtin_expect(_dst != NULL, 1); \
- _brw_cmd_pack(cmd)(brw, (void *)_dst, &name), \
- _dst = NULL)
-
-#define brw_batch_emitn(brw, cmd, n, ...) ({ \
- uint32_t *_dw = emit_dwords(brw, n); \
- struct cmd template = { \
- _brw_cmd_header(cmd), \
- .DWordLength = n - _brw_cmd_length_bias(cmd), \
- __VA_ARGS__ \
- }; \
- _brw_cmd_pack(cmd)(brw, _dw, &template); \
- _dw + 1; /* Array starts at dw[1] */ \
- })
-
-#define brw_state_emit(brw, cmd, align, offset, name) \
- for (struct cmd name = {}, \
- *_dst = brw_state_batch(brw, _brw_cmd_length(cmd) * 4, \
- align, offset); \
- __builtin_expect(_dst != NULL, 1); \
- _brw_cmd_pack(cmd)(brw, (void *)_dst, &name), \
- _dst = NULL)
+#if GEN_GEN >= 7
+static void
+emit_lrm(struct brw_context *brw, uint32_t reg, struct brw_address addr)
+{
+ brw_batch_emit(brw, GENX(MI_LOAD_REGISTER_MEM), lrm) {
+ lrm.RegisterAddress = reg;
+ lrm.MemoryAddress = addr;
+ }
+}
+#endif
+
+#if GEN_GEN == 7
+static void
+emit_lri(struct brw_context *brw, uint32_t reg, uint32_t imm)
+{
+ brw_batch_emit(brw, GENX(MI_LOAD_REGISTER_IMM), lri) {
+ lri.RegisterOffset = reg;
+ lri.DataDWord = imm;
+ }
+}
+#endif
/**
* Polygon stipple packet
unsigned buffer_nr,
struct brw_bo *bo,
unsigned start_offset,
- MAYBE_UNUSED unsigned end_offset,
+ UNUSED unsigned end_offset,
unsigned stride,
- MAYBE_UNUSED unsigned step_rate)
+ UNUSED unsigned step_rate)
{
struct GENX(VERTEX_BUFFER_STATE) buf_state = {
.VertexBufferIndex = buffer_nr,
#endif
#if GEN_GEN == 11
- .VertexBufferMOCS = ICL_MOCS_WB,
+ .MOCS = ICL_MOCS_WB,
#elif GEN_GEN == 10
- .VertexBufferMOCS = CNL_MOCS_WB,
+ .MOCS = CNL_MOCS_WB,
#elif GEN_GEN == 9
- .VertexBufferMOCS = SKL_MOCS_WB,
+ .MOCS = SKL_MOCS_WB,
#elif GEN_GEN == 8
- .VertexBufferMOCS = BDW_MOCS_WB,
+ .MOCS = BDW_MOCS_WB,
#elif GEN_GEN == 7
- .VertexBufferMOCS = GEN7_MOCS_L3,
+ .MOCS = GEN7_MOCS_L3,
#endif
};
* In the relocation world, we have no idea what the addresses will be, so
* we can't apply this workaround. Instead, we tell the kernel to move it
* to the low 4GB regardless.
+ *
+ * This HW issue is gone on Gen11+.
*/
static void
vf_invalidate_for_vb_48bit_transitions(struct brw_context *brw)
{
-#if GEN_GEN >= 8
+#if GEN_GEN >= 8 && GEN_GEN < 11
bool need_invalidate = false;
- unsigned i;
- for (i = 0; i < brw->vb.nr_buffers; i++) {
+ for (unsigned i = 0; i < brw->vb.nr_buffers; i++) {
uint16_t high_bits = pinned_bo_high_bits(brw->vb.buffers[i].bo);
if (high_bits != brw->vb.last_bo_high_bits[i]) {
}
}
- /* Don't bother with draw parameter buffers - those are generated by
- * the driver so we can select a consistent memory zone.
- */
+ if (brw->draw.draw_params_bo) {
+ uint16_t high_bits = pinned_bo_high_bits(brw->draw.draw_params_bo);
+
+ if (brw->vb.last_bo_high_bits[brw->vb.nr_buffers] != high_bits) {
+ need_invalidate = true;
+ brw->vb.last_bo_high_bits[brw->vb.nr_buffers] = high_bits;
+ }
+ }
+
+ if (brw->draw.derived_draw_params_bo) {
+ uint16_t high_bits = pinned_bo_high_bits(brw->draw.derived_draw_params_bo);
+
+ if (brw->vb.last_bo_high_bits[brw->vb.nr_buffers + 1] != high_bits) {
+ need_invalidate = true;
+ brw->vb.last_bo_high_bits[brw->vb.nr_buffers + 1] = high_bits;
+ }
+ }
if (need_invalidate) {
- brw_emit_pipe_control_flush(brw, PIPE_CONTROL_VF_CACHE_INVALIDATE);
+ brw_emit_pipe_control_flush(brw, PIPE_CONTROL_VF_CACHE_INVALIDATE | PIPE_CONTROL_CS_STALL);
}
#endif
}
*/
for (unsigned i = 0; i < brw->vb.nr_enabled; i++) {
struct brw_vertex_element *input = brw->vb.enabled[i];
- const struct gl_array_attributes *glattrib = input->glattrib;
- uint32_t format = brw_get_vertex_surface_type(brw, glattrib);
+ uint32_t format = brw_get_vertex_surface_type(brw, input->glformat);
if (uploads_needed(format, input->is_dual_slot) > 1)
nr_elements++;
unsigned i;
for (i = 0; i < brw->vb.nr_enabled; i++) {
const struct brw_vertex_element *input = brw->vb.enabled[i];
- const struct gl_array_attributes *glattrib = input->glattrib;
- uint32_t format = brw_get_vertex_surface_type(brw, glattrib);
+ const struct gl_vertex_format *glformat = input->glformat;
+ uint32_t format = brw_get_vertex_surface_type(brw, glformat);
uint32_t comp0 = VFCOMP_STORE_SRC;
uint32_t comp1 = VFCOMP_STORE_SRC;
uint32_t comp2 = VFCOMP_STORE_SRC;
* entry. */
const unsigned offset = input->offset + c * 16;
- const struct gl_array_attributes *glattrib = input->glattrib;
const int size = (GEN_GEN < 8 && is_passthru_format(format)) ?
- upload_format_size(upload_format) : glattrib->Size;
+ upload_format_size(upload_format) : glformat->Size;
switch (size) {
- case 0: comp0 = VFCOMP_STORE_0;
- case 1: comp1 = VFCOMP_STORE_0;
- case 2: comp2 = VFCOMP_STORE_0;
+ case 0: comp0 = VFCOMP_STORE_0; /* fallthrough */
+ case 1: comp1 = VFCOMP_STORE_0; /* fallthrough */
+ case 2: comp2 = VFCOMP_STORE_0; /* fallthrough */
case 3:
- if (GEN_GEN >= 8 && glattrib->Doubles) {
+ if (GEN_GEN >= 8 && glformat->Doubles) {
comp3 = VFCOMP_STORE_0;
- } else if (glattrib->Integer) {
+ } else if (glformat->Integer) {
comp3 = VFCOMP_STORE_1_INT;
} else {
comp3 = VFCOMP_STORE_1_FP;
* to be specified as VFCOMP_STORE_0 in order to output a 256-bit
* vertex element."
*/
- if (glattrib->Doubles && !input->is_dual_slot) {
+ if (glformat->Doubles && !input->is_dual_slot) {
/* Store vertex elements which correspond to double and dvec2 vertex
* shader inputs as 128-bit vertex elements, instead of 256-bits.
*/
#if GEN_GEN >= 6
if (gen6_edgeflag_input) {
- const struct gl_array_attributes *glattrib = gen6_edgeflag_input->glattrib;
- const uint32_t format = brw_get_vertex_surface_type(brw, glattrib);
+ const struct gl_vertex_format *glformat = gen6_edgeflag_input->glformat;
+ const uint32_t format = brw_get_vertex_surface_type(brw, glformat);
struct GENX(VERTEX_ELEMENT_STATE) elem_state = {
.Valid = true,
.mesa = _NEW_POLYGON,
.brw = BRW_NEW_BATCH |
BRW_NEW_BLORP |
+ BRW_NEW_VERTEX_PROGRAM |
BRW_NEW_VERTICES |
BRW_NEW_VS_PROG_DATA,
},
brw_batch_emit(brw, GENX(3DSTATE_INDEX_BUFFER), ib) {
#if GEN_GEN < 8 && !GEN_IS_HASWELL
- ib.CutIndexEnable = brw->prim_restart.enable_cut_index;
+ assert(brw->ib.enable_cut_index == brw->prim_restart.enable_cut_index);
+ ib.CutIndexEnable = brw->ib.enable_cut_index;
#endif
- ib.IndexFormat = brw_get_index_type(index_buffer->index_size);
+ ib.IndexFormat = brw_get_index_type(1 << index_buffer->index_size_shift);
/* The VF cache designers apparently cut corners, and made the cache
* only consider the bottom 32 bits of memory addresses. If you happen
*/
ib.BufferStartingAddress = ro_32_bo(brw->ib.bo, 0);
#if GEN_GEN >= 8
- ib.IndexBufferMOCS = GEN_GEN >= 9 ? SKL_MOCS_WB : BDW_MOCS_WB;
+ ib.MOCS = GEN_GEN >= 9 ? SKL_MOCS_WB : BDW_MOCS_WB;
ib.BufferSize = brw->ib.size;
#else
ib.BufferEndingAddress = ro_bo(brw->ib.bo, brw->ib.size - 1);
brw_batch_emit(brw, GENX(3DSTATE_VF), vf) {
if (ctx->Array._PrimitiveRestart && brw->ib.ib) {
vf.IndexedDrawCutIndexEnable = true;
- vf.CutIndex = _mesa_primitive_restart_index(ctx, brw->ib.index_size);
+ vf.CutIndex = ctx->Array._RestartIndex[brw->ib.index_size - 1];
}
}
}
};
#endif
+static void
+genX(upload_vf_statistics)(struct brw_context *brw)
+{
+ brw_batch_emit(brw, GENX(3DSTATE_VF_STATISTICS), vf) {
+ vf.StatisticsEnable = true;
+ }
+}
+
+const struct brw_tracked_state genX(vf_statistics) = {
+ .dirty = {
+ .mesa = 0,
+ .brw = BRW_NEW_BLORP | BRW_NEW_CONTEXT,
+ },
+ .emit = genX(upload_vf_statistics),
+};
+
#if GEN_GEN >= 6
/**
* Determine the appropriate attribute override value to store into the
*/
bool drawing_points = brw_is_drawing_points(brw);
- for (int attr = 0; attr < VARYING_SLOT_MAX; attr++) {
+ for (uint8_t idx = 0; idx < wm_prog_data->urb_setup_attribs_count; idx++) {
+ uint8_t attr = wm_prog_data->urb_setup_attribs[idx];
int input_index = wm_prog_data->urb_setup[attr];
- if (input_index < 0)
- continue;
+ assert(0 <= input_index);
/* _NEW_POINT */
bool point_sprite = false;
if (ctx->Line.SmoothFlag) {
sf.LineEndCapAntialiasingRegionWidth = _10pixels;
#if GEN_GEN <= 7
- sf.AntiAliasingEnable = true;
+ sf.AntialiasingEnable = true;
#endif
}
#define INIT_THREAD_DISPATCH_FIELDS(pkt, prefix) \
pkt.KernelStartPointer = KSP(brw, stage_state->prog_offset); \
+ /* WA_1606682166 */ \
pkt.SamplerCount = \
- DIV_ROUND_UP(CLAMP(stage_state->sampler_count, 0, 16), 4); \
- /* Gen 11 workarounds table #2056 WABTPPrefetchDisable suggests to \
- * disable prefetching of binding tables in A0 and B0 steppings. \
- * TODO: Revisit this WA on C0 stepping. \
- */ \
- pkt.BindingTableEntryCount = \
GEN_GEN == 11 ? \
0 : \
+ DIV_ROUND_UP(CLAMP(stage_state->sampler_count, 0, 16), 4); \
+ pkt.BindingTableEntryCount = \
stage_prog_data->binding_table.size_bytes / 4; \
pkt.FloatingPointMode = stage_prog_data->use_alt_mode; \
\
bbox[0] = MAX2(ctx->ViewportArray[i].X, 0);
bbox[1] = MIN2(bbox[0] + ctx->ViewportArray[i].Width, fb_width);
- bbox[2] = MAX2(ctx->ViewportArray[i].Y, 0);
+ bbox[2] = CLAMP(ctx->ViewportArray[i].Y, 0, fb_height);
bbox[3] = MIN2(bbox[2] + ctx->ViewportArray[i].Height, fb_height);
_mesa_intersect_scissor_bounding_box(ctx, i, bbox);
/* ---------------------------------------------------------------------- */
-static void
-brw_calculate_guardband_size(uint32_t fb_width, uint32_t fb_height,
- float m00, float m11, float m30, float m31,
- float *xmin, float *xmax,
- float *ymin, float *ymax)
-{
- /* According to the "Vertex X,Y Clamping and Quantization" section of the
- * Strips and Fans documentation:
- *
- * "The vertex X and Y screen-space coordinates are also /clamped/ to the
- * fixed-point "guardband" range supported by the rasterization hardware"
- *
- * and
- *
- * "In almost all circumstances, if an object’s vertices are actually
- * modified by this clamping (i.e., had X or Y coordinates outside of
- * the guardband extent the rendered object will not match the intended
- * result. Therefore software should take steps to ensure that this does
- * not happen - e.g., by clipping objects such that they do not exceed
- * these limits after the Drawing Rectangle is applied."
- *
- * I believe the fundamental restriction is that the rasterizer (in
- * the SF/WM stages) have a limit on the number of pixels that can be
- * rasterized. We need to ensure any coordinates beyond the rasterizer
- * limit are handled by the clipper. So effectively that limit becomes
- * the clipper's guardband size.
- *
- * It goes on to say:
- *
- * "In addition, in order to be correctly rendered, objects must have a
- * screenspace bounding box not exceeding 8K in the X or Y direction.
- * This additional restriction must also be comprehended by software,
- * i.e., enforced by use of clipping."
- *
- * This makes no sense. Gen7+ hardware supports 16K render targets,
- * and you definitely need to be able to draw polygons that fill the
- * surface. Our assumption is that the rasterizer was limited to 8K
- * on Sandybridge, which only supports 8K surfaces, and it was actually
- * increased to 16K on Ivybridge and later.
- *
- * So, limit the guardband to 16K on Gen7+ and 8K on Sandybridge.
- */
- const float gb_size = GEN_GEN >= 7 ? 16384.0f : 8192.0f;
-
- /* Workaround: prevent gpu hangs on SandyBridge
- * by disabling guardband clipping for odd dimensions.
- */
- if (GEN_GEN == 6 && (fb_width & 1 || fb_height & 1)) {
- *xmin = -1.0f;
- *xmax = 1.0f;
- *ymin = -1.0f;
- *ymax = 1.0f;
- return;
- }
-
- if (m00 != 0 && m11 != 0) {
- /* First, we compute the screen-space render area */
- const float ss_ra_xmin = MIN3( 0, m30 + m00, m30 - m00);
- const float ss_ra_xmax = MAX3( fb_width, m30 + m00, m30 - m00);
- const float ss_ra_ymin = MIN3( 0, m31 + m11, m31 - m11);
- const float ss_ra_ymax = MAX3(fb_height, m31 + m11, m31 - m11);
-
- /* We want the guardband to be centered on that */
- const float ss_gb_xmin = (ss_ra_xmin + ss_ra_xmax) / 2 - gb_size;
- const float ss_gb_xmax = (ss_ra_xmin + ss_ra_xmax) / 2 + gb_size;
- const float ss_gb_ymin = (ss_ra_ymin + ss_ra_ymax) / 2 - gb_size;
- const float ss_gb_ymax = (ss_ra_ymin + ss_ra_ymax) / 2 + gb_size;
-
- /* Now we need it in native device coordinates */
- const float ndc_gb_xmin = (ss_gb_xmin - m30) / m00;
- const float ndc_gb_xmax = (ss_gb_xmax - m30) / m00;
- const float ndc_gb_ymin = (ss_gb_ymin - m31) / m11;
- const float ndc_gb_ymax = (ss_gb_ymax - m31) / m11;
-
- /* Thanks to Y-flipping and ORIGIN_UPPER_LEFT, the Y coordinates may be
- * flipped upside-down. X should be fine though.
- */
- assert(ndc_gb_xmin <= ndc_gb_xmax);
- *xmin = ndc_gb_xmin;
- *xmax = ndc_gb_xmax;
- *ymin = MIN2(ndc_gb_ymin, ndc_gb_ymax);
- *ymax = MAX2(ndc_gb_ymin, ndc_gb_ymax);
- } else {
- /* The viewport scales to 0, so nothing will be rendered. */
- *xmin = 0.0f;
- *xmax = 0.0f;
- *ymin = 0.0f;
- *ymax = 0.0f;
- }
-}
-
static void
genX(upload_sf_clip_viewport)(struct brw_context *brw)
{
sfv.ViewportMatrixElementm30 = translate[0],
sfv.ViewportMatrixElementm31 = translate[1] * y_scale + y_bias,
sfv.ViewportMatrixElementm32 = translate[2],
- brw_calculate_guardband_size(fb_width, fb_height,
+ gen_calculate_guardband_size(fb_width, fb_height,
sfv.ViewportMatrixElementm00,
sfv.ViewportMatrixElementm11,
sfv.ViewportMatrixElementm30,
dstA = fix_dual_blend_alpha_to_one(dstA);
}
- entry->ColorBufferBlendEnable = true;
+ /* BRW_NEW_FS_PROG_DATA */
+ const struct brw_wm_prog_data *wm_prog_data =
+ brw_wm_prog_data(brw->wm.base.prog_data);
+
+ /* The Dual Source Blending documentation says:
+ *
+ * "If SRC1 is included in a src/dst blend factor and
+ * a DualSource RT Write message is not used, results
+ * are UNDEFINED. (This reflects the same restriction in DX APIs,
+ * where undefined results are produced if “o1” is not written
+ * by a PS – there are no default values defined).
+ * If SRC1 is not included in a src/dst blend factor,
+ * dual source blending must be disabled."
+ *
+ * There is no way to gracefully fix this undefined situation
+ * so we just disable the blending to prevent possible issues.
+ */
+ entry->ColorBufferBlendEnable =
+ !ctx->Color.Blend[0]._UsesDualSrc || wm_prog_data->dual_src_blend;
+
entry->DestinationBlendFactor = blend_factor(dstRGB);
entry->SourceBlendFactor = blend_factor(srcRGB);
entry->DestinationAlphaBlendFactor = blend_factor(dstA);
#endif
}
-static const struct brw_tracked_state genX(blend_state) = {
+UNUSED static const struct brw_tracked_state genX(blend_state) = {
.dirty = {
.mesa = _NEW_BUFFERS |
_NEW_COLOR |
_NEW_MULTISAMPLE,
.brw = BRW_NEW_BATCH |
BRW_NEW_BLORP |
+ BRW_NEW_FS_PROG_DATA |
BRW_NEW_STATE_BASE_ADDRESS,
},
.emit = genX(upload_blend_state),
const struct gl_buffer_binding *binding =
&ctx->UniformBufferBindings[block->Binding];
- if (binding->BufferObject == ctx->Shared->NullBufferObj) {
+ if (!binding->BufferObject) {
static unsigned msg_id = 0;
- _mesa_gl_debug(ctx, &msg_id, MESA_DEBUG_SOURCE_API,
- MESA_DEBUG_TYPE_UNDEFINED,
- MESA_DEBUG_SEVERITY_HIGH,
- "UBO %d unbound, %s shader uniform data "
- "will be undefined.",
- range->block,
- _mesa_shader_stage_to_string(stage));
+ _mesa_gl_debugf(ctx, &msg_id, MESA_DEBUG_SOURCE_API,
+ MESA_DEBUG_TYPE_UNDEFINED,
+ MESA_DEBUG_SEVERITY_HIGH,
+ "UBO %d unbound, %s shader uniform data "
+ "will be undefined.",
+ range->block,
+ _mesa_shader_stage_to_string(stage));
continue;
}
#endif
}
-static const struct brw_tracked_state genX(color_calc_state) = {
+UNUSED static const struct brw_tracked_state genX(color_calc_state) = {
.dirty = {
.mesa = _NEW_COLOR |
_NEW_STENCIL |
};
+/* ---------------------------------------------------------------------- */
+
+#if GEN_IS_HASWELL
+static void
+genX(upload_color_calc_and_blend_state)(struct brw_context *brw)
+{
+ genX(upload_blend_state)(brw);
+ genX(upload_color_calc_state)(brw);
+}
+
+/* On Haswell when BLEND_STATE is emitted CC_STATE should also be re-emitted,
+ * this workarounds the flickering shadows in several games.
+ */
+static const struct brw_tracked_state genX(cc_and_blend_state) = {
+ .dirty = {
+ .mesa = _NEW_BUFFERS |
+ _NEW_COLOR |
+ _NEW_STENCIL |
+ _NEW_MULTISAMPLE,
+ .brw = BRW_NEW_BATCH |
+ BRW_NEW_BLORP |
+ BRW_NEW_CC_STATE |
+ BRW_NEW_FS_PROG_DATA |
+ BRW_NEW_STATE_BASE_ADDRESS,
+ },
+ .emit = genX(upload_color_calc_and_blend_state),
+};
+#endif
+
/* ---------------------------------------------------------------------- */
#if GEN_GEN >= 7
sob.SOBufferEnable = true;
sob.StreamOffsetWriteEnable = true;
sob.StreamOutputBufferOffsetAddressEnable = true;
- sob.SOBufferMOCS = mocs_wb;
+ sob.MOCS = mocs_wb;
sob.SurfaceSize = MAX2(xfb_obj->Size[i] / 4, 1) - 1;
sob.StreamOutputBufferOffsetAddress =
*/
ps.VectorMaskEnable = GEN_GEN >= 8;
- ps.SamplerCount =
- DIV_ROUND_UP(CLAMP(stage_state->sampler_count, 0, 16), 4);
+ /* WA_1606682166:
+ * "Incorrect TDL's SSP address shift in SARB for 16:6 & 18:8 modes.
+ * Disable the Sampler state prefetch functionality in the SARB by
+ * programming 0xB000[30] to '1'."
+ */
+ ps.SamplerCount = GEN_GEN == 11 ?
+ 0 : DIV_ROUND_UP(CLAMP(stage_state->sampler_count, 0, 16), 4);
/* BRW_NEW_FS_PROG_DATA */
- /* Gen 11 workarounds table #2056 WABTPPrefetchDisable suggests to disable
- * prefetching of binding tables in A0 and B0 steppings.
- * TODO: Revisit this workaround on C0 stepping.
- */
- ps.BindingTableEntryCount = GEN_GEN == 11 ?
- 0 :
- prog_data->base.binding_table.size_bytes / 4;
+ ps.BindingTableEntryCount = prog_data->base.binding_table.size_bytes / 4;
if (prog_data->base.use_alt_mode)
ps.FloatingPointMode = Alternate;
hs.IncludeVertexHandles = true;
hs.MaximumNumberofThreads = devinfo->max_tcs_threads - 1;
+
+#if GEN_GEN >= 9
+ hs.DispatchMode = vue_prog_data->dispatch_mode;
+ hs.IncludePrimitiveID = tcs_prog_data->include_primitive_id;
+#endif
}
}
}
struct brw_cs_prog_data *cs_prog_data = brw_cs_prog_data(prog_data);
const struct gen_device_info *devinfo = &brw->screen->devinfo;
+ const struct brw_cs_parameters cs_params = brw_cs_get_parameters(brw);
+
if (INTEL_DEBUG & DEBUG_SHADER_TIME) {
brw_emit_buffer_surface_state(
brw, &stage_state->surf_offset[
vfe.URBEntryAllocationSize = GEN_GEN >= 8 ? 2 : 0;
const uint32_t vfe_curbe_allocation =
- ALIGN(cs_prog_data->push.per_thread.regs * cs_prog_data->threads +
+ ALIGN(cs_prog_data->push.per_thread.regs * cs_params.threads +
cs_prog_data->push.cross_thread.regs, 2);
vfe.CURBEAllocationSize = vfe_curbe_allocation;
}
- if (cs_prog_data->push.total.size > 0) {
+ const unsigned push_const_size =
+ brw_cs_push_const_total_size(cs_prog_data, cs_params.threads);
+ if (push_const_size > 0) {
brw_batch_emit(brw, GENX(MEDIA_CURBE_LOAD), curbe) {
- curbe.CURBETotalDataLength =
- ALIGN(cs_prog_data->push.total.size, 64);
+ curbe.CURBETotalDataLength = ALIGN(push_const_size, 64);
curbe.CURBEDataStartAddress = stage_state->push_const_offset;
}
}
/* BRW_NEW_SURFACES and BRW_NEW_*_CONSTBUF */
memcpy(bind, stage_state->surf_offset,
prog_data->binding_table.size_bytes);
+ const uint64_t ksp = brw->cs.base.prog_offset +
+ brw_cs_prog_data_prog_offset(cs_prog_data,
+ cs_params.simd_size);
const struct GENX(INTERFACE_DESCRIPTOR_DATA) idd = {
- .KernelStartPointer = brw->cs.base.prog_offset,
+ .KernelStartPointer = ksp,
.SamplerStatePointer = stage_state->sampler_offset,
- .SamplerCount = DIV_ROUND_UP(CLAMP(stage_state->sampler_count, 0, 16), 4),
+ /* WA_1606682166 */
+ .SamplerCount = GEN_GEN == 11 ? 0 :
+ DIV_ROUND_UP(CLAMP(stage_state->sampler_count, 0, 16), 4),
.BindingTablePointer = stage_state->bind_bo_offset,
.ConstantURBEntryReadLength = cs_prog_data->push.per_thread.regs,
- .NumberofThreadsinGPGPUThreadGroup = cs_prog_data->threads,
+ .NumberofThreadsinGPGPUThreadGroup = cs_params.threads,
.SharedLocalMemorySize = encode_slm_size(GEN_GEN,
prog_data->total_shared),
.BarrierEnable = cs_prog_data->uses_barrier,
.emit = genX(upload_cs_state)
};
+#define GPGPU_DISPATCHDIMX 0x2500
+#define GPGPU_DISPATCHDIMY 0x2504
+#define GPGPU_DISPATCHDIMZ 0x2508
+
+#define MI_PREDICATE_SRC0 0x2400
+#define MI_PREDICATE_SRC1 0x2408
+
+static void
+prepare_indirect_gpgpu_walker(struct brw_context *brw)
+{
+ GLintptr indirect_offset = brw->compute.num_work_groups_offset;
+ struct brw_bo *bo = brw->compute.num_work_groups_bo;
+
+ emit_lrm(brw, GPGPU_DISPATCHDIMX, ro_bo(bo, indirect_offset + 0));
+ emit_lrm(brw, GPGPU_DISPATCHDIMY, ro_bo(bo, indirect_offset + 4));
+ emit_lrm(brw, GPGPU_DISPATCHDIMZ, ro_bo(bo, indirect_offset + 8));
+
+#if GEN_GEN <= 7
+ /* Clear upper 32-bits of SRC0 and all 64-bits of SRC1 */
+ emit_lri(brw, MI_PREDICATE_SRC0 + 4, 0);
+ emit_lri(brw, MI_PREDICATE_SRC1 , 0);
+ emit_lri(brw, MI_PREDICATE_SRC1 + 4, 0);
+
+ /* Load compute_dispatch_indirect_x_size into SRC0 */
+ emit_lrm(brw, MI_PREDICATE_SRC0, ro_bo(bo, indirect_offset + 0));
+
+ /* predicate = (compute_dispatch_indirect_x_size == 0); */
+ brw_batch_emit(brw, GENX(MI_PREDICATE), mip) {
+ mip.LoadOperation = LOAD_LOAD;
+ mip.CombineOperation = COMBINE_SET;
+ mip.CompareOperation = COMPARE_SRCS_EQUAL;
+ }
+
+ /* Load compute_dispatch_indirect_y_size into SRC0 */
+ emit_lrm(brw, MI_PREDICATE_SRC0, ro_bo(bo, indirect_offset + 4));
+
+ /* predicate |= (compute_dispatch_indirect_y_size == 0); */
+ brw_batch_emit(brw, GENX(MI_PREDICATE), mip) {
+ mip.LoadOperation = LOAD_LOAD;
+ mip.CombineOperation = COMBINE_OR;
+ mip.CompareOperation = COMPARE_SRCS_EQUAL;
+ }
+
+ /* Load compute_dispatch_indirect_z_size into SRC0 */
+ emit_lrm(brw, MI_PREDICATE_SRC0, ro_bo(bo, indirect_offset + 8));
+
+ /* predicate |= (compute_dispatch_indirect_z_size == 0); */
+ brw_batch_emit(brw, GENX(MI_PREDICATE), mip) {
+ mip.LoadOperation = LOAD_LOAD;
+ mip.CombineOperation = COMBINE_OR;
+ mip.CompareOperation = COMPARE_SRCS_EQUAL;
+ }
+
+ /* predicate = !predicate; */
+#define COMPARE_FALSE 1
+ brw_batch_emit(brw, GENX(MI_PREDICATE), mip) {
+ mip.LoadOperation = LOAD_LOADINV;
+ mip.CombineOperation = COMBINE_OR;
+ mip.CompareOperation = COMPARE_FALSE;
+ }
+#endif
+}
+
+static void
+genX(emit_gpgpu_walker)(struct brw_context *brw)
+{
+ const GLuint *num_groups = brw->compute.num_work_groups;
+
+ bool indirect = brw->compute.num_work_groups_bo != NULL;
+ if (indirect)
+ prepare_indirect_gpgpu_walker(brw);
+
+ const struct brw_cs_parameters cs_params = brw_cs_get_parameters(brw);
+
+ const uint32_t right_mask =
+ brw_cs_right_mask(cs_params.group_size, cs_params.simd_size);
+
+ brw_batch_emit(brw, GENX(GPGPU_WALKER), ggw) {
+ ggw.IndirectParameterEnable = indirect;
+ ggw.PredicateEnable = GEN_GEN <= 7 && indirect;
+ ggw.SIMDSize = cs_params.simd_size / 16;
+ ggw.ThreadDepthCounterMaximum = 0;
+ ggw.ThreadHeightCounterMaximum = 0;
+ ggw.ThreadWidthCounterMaximum = cs_params.threads - 1;
+ ggw.ThreadGroupIDXDimension = num_groups[0];
+ ggw.ThreadGroupIDYDimension = num_groups[1];
+ ggw.ThreadGroupIDZDimension = num_groups[2];
+ ggw.RightExecutionMask = right_mask;
+ ggw.BottomExecutionMask = 0xffffffff;
+ }
+
+ brw_batch_emit(brw, GENX(MEDIA_STATE_FLUSH), msf);
+}
+
#endif
/* ---------------------------------------------------------------------- */
dstA = fix_dual_blend_alpha_to_one(dstA);
}
- pb.ColorBufferBlendEnable = true;
+ /* BRW_NEW_FS_PROG_DATA */
+ const struct brw_wm_prog_data *wm_prog_data =
+ brw_wm_prog_data(brw->wm.base.prog_data);
+
+ /* The Dual Source Blending documentation says:
+ *
+ * "If SRC1 is included in a src/dst blend factor and
+ * a DualSource RT Write message is not used, results
+ * are UNDEFINED. (This reflects the same restriction in DX APIs,
+ * where undefined results are produced if “o1” is not written
+ * by a PS – there are no default values defined).
+ * If SRC1 is not included in a src/dst blend factor,
+ * dual source blending must be disabled."
+ *
+ * There is no way to gracefully fix this undefined situation
+ * so we just disable the blending to prevent possible issues.
+ */
+ pb.ColorBufferBlendEnable =
+ !color->Blend[0]._UsesDualSrc || wm_prog_data->dual_src_blend;
pb.SourceAlphaBlendFactor = brw_translate_blend_factor(srcA);
pb.DestinationAlphaBlendFactor = brw_translate_blend_factor(dstA);
pb.SourceBlendFactor = brw_translate_blend_factor(srcRGB);
_NEW_MULTISAMPLE,
.brw = BRW_NEW_BLORP |
BRW_NEW_CONTEXT |
- BRW_NEW_FRAGMENT_PROGRAM,
+ BRW_NEW_FRAGMENT_PROGRAM |
+ BRW_NEW_FS_PROG_DATA,
},
.emit = genX(upload_ps_blend)
};
* Emit a 3DSTATE_SAMPLER_STATE_POINTERS_{VS,HS,GS,DS,PS} packet.
*/
static void
-genX(emit_sampler_state_pointers_xs)(MAYBE_UNUSED struct brw_context *brw,
- MAYBE_UNUSED struct brw_stage_state *stage_state)
+genX(emit_sampler_state_pointers_xs)(UNUSED struct brw_context *brw,
+ UNUSED struct brw_stage_state *stage_state)
{
#if GEN_GEN >= 7
static const uint16_t packet_headers[] = {
static void
genX(upload_default_color)(struct brw_context *brw,
const struct gl_sampler_object *sampler,
- MAYBE_UNUSED mesa_format format, GLenum base_format,
+ mesa_format format, GLenum base_format,
bool is_integer_format, bool is_stencil_sampling,
uint32_t *sdc_offset)
{
}
static uint32_t
-translate_wrap_mode(GLenum wrap, MAYBE_UNUSED bool using_nearest)
+translate_wrap_mode(GLenum wrap, UNUSED bool using_nearest)
{
switch (wrap) {
case GL_REPEAT:
#if GEN_GEN < 6
static const struct brw_tracked_state *render_atoms[] =
{
+ &genX(vf_statistics),
+
/* Once all the programs are done, we know how large urb entry
* sizes need to be and can decide if we need to change the urb
* layout.
#elif GEN_GEN == 6
static const struct brw_tracked_state *render_atoms[] =
{
+ &genX(vf_statistics),
+
&genX(sf_clip_viewport),
/* Command packets: */
#elif GEN_GEN == 7
static const struct brw_tracked_state *render_atoms[] =
{
+ &genX(vf_statistics),
+
/* Command packets: */
&genX(cc_vp),
&gen7_l3_state,
&gen7_push_constant_space,
&gen7_urb,
+#if GEN_IS_HASWELL
+ &genX(cc_and_blend_state),
+#else
&genX(blend_state), /* must do before cc unit */
&genX(color_calc_state), /* must do before cc unit */
+#endif
&genX(depth_stencil_state), /* must do before cc unit */
&brw_vs_image_surfaces, /* Before vs push/pull constants and binding table */
#elif GEN_GEN >= 8
static const struct brw_tracked_state *render_atoms[] =
{
+ &genX(vf_statistics),
+
&genX(cc_vp),
&genX(sf_clip_viewport),
compute_atoms, ARRAY_SIZE(compute_atoms));
brw->vtbl.emit_mi_report_perf_count = genX(emit_mi_report_perf_count);
+ brw->vtbl.emit_compute_walker = genX(emit_gpgpu_walker);
#endif
}