#include <stdio.h>
#include <errno.h>
-#ifdef HAVE_VALGRIND
+#if HAVE_VALGRIND
#include <valgrind.h>
#include <memcheck.h>
#define VG(x) x
+#ifndef NDEBUG
#define __gen_validate_value(x) VALGRIND_CHECK_MEM_IS_DEFINED(&(x), sizeof(x))
+#endif
#else
#define VG(x)
#endif
#include "pipe/p_context.h"
#include "pipe/p_screen.h"
#include "util/u_inlines.h"
+#include "util/u_format.h"
+#include "util/u_framebuffer.h"
#include "util/u_transfer.h"
#include "util/u_upload_mgr.h"
#include "i915_drm.h"
return (struct iris_address) { .bo = bo, .offset = offset };
}
+static void *
+upload_state(struct u_upload_mgr *uploader,
+ struct iris_state_ref *ref,
+ unsigned size,
+ unsigned alignment)
+{
+ void *p = NULL;
+ u_upload_alloc(uploader, 0, size, alignment, &ref->offset, &ref->res, &p);
+ return p;
+}
+
static uint32_t *
stream_state(struct iris_batch *batch,
struct u_upload_mgr *uploader,
+ struct pipe_resource **out_res,
unsigned size,
unsigned alignment,
uint32_t *out_offset)
{
- struct pipe_resource *res = NULL;
void *ptr = NULL;
- u_upload_alloc(uploader, 0, size, alignment, out_offset, &res, &ptr);
+ u_upload_alloc(uploader, 0, size, alignment, out_offset, out_res, &ptr);
- struct iris_bo *bo = iris_resource_bo(res);
+ struct iris_bo *bo = iris_resource_bo(*out_res);
iris_use_pinned_bo(batch, bo, false);
*out_offset += iris_bo_offset_from_base_address(bo);
- pipe_resource_reference(&res, NULL);
-
return ptr;
}
static uint32_t
emit_state(struct iris_batch *batch,
struct u_upload_mgr *uploader,
+ struct pipe_resource **out_res,
const void *data,
unsigned size,
unsigned alignment)
{
unsigned offset = 0;
- uint32_t *map = stream_state(batch, uploader, size, alignment, &offset);
+ uint32_t *map =
+ stream_state(batch, uploader, out_res, size, alignment, &offset);
if (map)
memcpy(map, data, size);
return offset;
}
+#define cso_changed(x) (!old_cso || (old_cso->x != new_cso->x))
+#define cso_changed_memcmp(x) \
+ (!old_cso || memcmp(old_cso->x, new_cso->x, sizeof(old_cso->x)) != 0)
+
static void
iris_init_render_context(struct iris_screen *screen,
struct iris_batch *batch,
}
}
+struct iris_viewport_state {
+ uint32_t sf_cl_vp[GENX(SF_CLIP_VIEWPORT_length) * IRIS_MAX_VIEWPORTS];
+};
+
+struct iris_vertex_buffer_state {
+ uint32_t vertex_buffers[1 + 33 * GENX(VERTEX_BUFFER_STATE_length)];
+ struct pipe_resource *resources[33];
+ unsigned num_buffers;
+};
+
+struct iris_depth_buffer_state {
+ uint32_t packets[GENX(3DSTATE_DEPTH_BUFFER_length) +
+ GENX(3DSTATE_STENCIL_BUFFER_length) +
+ GENX(3DSTATE_HIER_DEPTH_BUFFER_length) +
+ GENX(3DSTATE_CLEAR_PARAMS_length)];
+};
+
+/**
+ * State that can't be stored directly in iris_context because the data
+ * layout varies per generation.
+ */
+struct iris_genx_state {
+ struct iris_viewport_state viewport;
+ struct iris_vertex_buffer_state vertex_buffers;
+ struct iris_depth_buffer_state depth_buffer;
+};
+
static void
iris_launch_grid(struct pipe_context *ctx, const struct pipe_grid_info *info)
{
}
struct iris_blend_state {
+ /** Partial 3DSTATE_PS_BLEND */
uint32_t ps_blend[GENX(3DSTATE_PS_BLEND_length)];
+
+ /** Partial BLEND_STATE */
uint32_t blend_state[GENX(BLEND_STATE_length) +
BRW_MAX_DRAW_BUFFERS * GENX(BLEND_STATE_ENTRY_length)];
{
struct iris_context *ice = (struct iris_context *) ctx;
ice->state.cso_blend = state;
- ice->state.dirty |= IRIS_DIRTY_CC_VIEWPORT;
- ice->state.dirty |= IRIS_DIRTY_WM_DEPTH_STENCIL;
+ ice->state.dirty |= IRIS_DIRTY_PS_BLEND;
+ ice->state.dirty |= IRIS_DIRTY_BLEND_STATE;
}
struct iris_depth_stencil_alpha_state {
+ /** Partial 3DSTATE_WM_DEPTH_STENCIL */
uint32_t wmds[GENX(3DSTATE_WM_DEPTH_STENCIL_length)];
+
+ /** Complete CC_VIEWPORT */
uint32_t cc_vp[GENX(CC_VIEWPORT_length)];
- struct pipe_alpha_state alpha; /* to BLEND_STATE, 3DSTATE_PS_BLEND */
+ /** Outbound to BLEND_STATE, 3DSTATE_PS_BLEND, COLOR_CALC_STATE */
+ struct pipe_alpha_state alpha;
};
static void *
struct iris_depth_stencil_alpha_state *new_cso = state;
if (new_cso) {
- if (!old_cso || old_cso->alpha.ref_value != new_cso->alpha.ref_value) {
+ if (cso_changed(alpha.ref_value))
ice->state.dirty |= IRIS_DIRTY_COLOR_CALC_STATE;
- }
+
+ if (cso_changed(alpha.enabled))
+ ice->state.dirty |= IRIS_DIRTY_PS_BLEND | IRIS_DIRTY_BLEND_STATE;
}
ice->state.cso_zsa = new_cso;
bool light_twoside; /* for shader state */
bool rasterizer_discard; /* for 3DSTATE_STREAMOUT */
bool half_pixel_center; /* for 3DSTATE_MULTISAMPLE */
+ bool line_stipple_enable;
+ bool poly_stipple_enable;
enum pipe_sprite_coord_mode sprite_coord_mode; /* PIPE_SPRITE_* */
uint16_t sprite_coord_enable;
};
cso->half_pixel_center = state->half_pixel_center;
cso->sprite_coord_mode = state->sprite_coord_mode;
cso->sprite_coord_enable = state->sprite_coord_enable;
+ cso->line_stipple_enable = state->line_stipple_enable;
+ cso->poly_stipple_enable = state->poly_stipple_enable;
iris_pack_command(GENX(3DSTATE_SF), cso->sf, sf) {
sf.StatisticsEnable = true;
sf.PointWidth = state->point_size;
if (state->flatshade_first) {
+ sf.TriangleFanProvokingVertexSelect = 1;
+ } else {
sf.TriangleStripListProvokingVertexSelect = 2;
sf.TriangleFanProvokingVertexSelect = 2;
sf.LineStripListProvokingVertexSelect = 1;
- } else {
- sf.TriangleFanProvokingVertexSelect = 1;
}
}
- /* COMPLETE! */
iris_pack_command(GENX(3DSTATE_RASTER), cso->raster, rr) {
rr.FrontWinding = state->front_ccw ? CounterClockwise : Clockwise;
rr.CullMode = translate_cull_mode(state->cull_face);
rr.GlobalDepthOffsetEnableSolid = state->offset_tri;
rr.GlobalDepthOffsetEnableWireframe = state->offset_line;
rr.GlobalDepthOffsetEnablePoint = state->offset_point;
- rr.GlobalDepthOffsetConstant = state->offset_units;
+ rr.GlobalDepthOffsetConstant = state->offset_units * 2;
rr.GlobalDepthOffsetScale = state->offset_scale;
rr.GlobalDepthOffsetClamp = state->offset_clamp;
rr.SmoothPointEnable = state->point_smooth;
cl.MaximumPointWidth = 255.875;
if (state->flatshade_first) {
+ cl.TriangleFanProvokingVertexSelect = 1;
+ } else {
cl.TriangleStripListProvokingVertexSelect = 2;
cl.TriangleFanProvokingVertexSelect = 2;
cl.LineStripListProvokingVertexSelect = 1;
- } else {
- cl.TriangleFanProvokingVertexSelect = 1;
}
}
if (new_cso) {
/* Try to avoid re-emitting 3DSTATE_LINE_STIPPLE, it's non-pipelined */
- if (!old_cso || memcmp(old_cso->line_stipple, new_cso->line_stipple,
- sizeof(old_cso->line_stipple)) != 0) {
+ if (cso_changed_memcmp(line_stipple))
ice->state.dirty |= IRIS_DIRTY_LINE_STIPPLE;
- }
- if (!old_cso ||
- old_cso->half_pixel_center != new_cso->half_pixel_center) {
+ if (cso_changed(half_pixel_center))
ice->state.dirty |= IRIS_DIRTY_MULTISAMPLE;
- }
+
+ if (cso_changed(line_stipple_enable) || cso_changed(poly_stipple_enable))
+ ice->state.dirty |= IRIS_DIRTY_WM;
}
ice->state.cso_rast = new_cso;
ice->state.dirty |= IRIS_DIRTY_RASTER;
+ ice->state.dirty |= IRIS_DIRTY_CLIP;
}
static uint32_t
[PIPE_TEX_WRAP_CLAMP_TO_BORDER] = TCM_CLAMP_BORDER,
[PIPE_TEX_WRAP_MIRROR_REPEAT] = TCM_MIRROR,
[PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE] = TCM_MIRROR_ONCE,
- [PIPE_TEX_WRAP_MIRROR_CLAMP] = -1, // XXX: ???
- [PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER] = -1, // XXX: ???
+
+ /* These are unsupported. */
+ [PIPE_TEX_WRAP_MIRROR_CLAMP] = -1,
+ [PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER] = -1,
};
return map[pipe_wrap];
}
};
static void *
-iris_create_sampler_state(struct pipe_context *pctx,
+iris_create_sampler_state(struct pipe_context *ctx,
const struct pipe_sampler_state *state)
{
struct iris_sampler_state *cso = CALLOC_STRUCT(iris_sampler_state);
if (!cso)
return NULL;
+ memcpy(&cso->base, state, sizeof(*state));
+
STATIC_ASSERT(PIPE_TEX_FILTER_NEAREST == MAPFILTER_NEAREST);
STATIC_ASSERT(PIPE_TEX_FILTER_LINEAR == MAPFILTER_LINEAR);
samp.MaxLOD = CLAMP(state->max_lod, 0, hw_max_lod);
samp.TextureLODBias = CLAMP(state->lod_bias, -16, 15);
- //samp.BorderColorPointer = <<comes from elsewhere>>
+ /* .BorderColorPointer is filled in by iris_bind_sampler_states. */
}
return cso;
gl_shader_stage stage = stage_from_pipe(p_stage);
assert(start + count <= IRIS_MAX_TEXTURE_SAMPLERS);
+ ice->state.num_samplers[stage] =
+ MAX2(ice->state.num_samplers[stage], start + count);
+
+ for (int i = 0; i < count; i++) {
+ ice->state.samplers[stage][start + i] = states[i];
+ }
- /* Assemble the SAMPLER_STATEs into a contiguous chunk of memory
- * relative to Dynamic State Base Address.
+ /* Assemble the SAMPLER_STATEs into a contiguous table that lives
+ * in the dynamic state memory zone, so we can point to it via the
+ * 3DSTATE_SAMPLER_STATE_POINTERS_* commands.
*/
- void *map = NULL;
- u_upload_alloc(ice->state.dynamic_uploader, 0,
- count * 4 * GENX(SAMPLER_STATE_length), 32,
- &ice->state.sampler_table_offset[stage],
- &ice->state.sampler_table_resource[stage],
- &map);
+ void *map = upload_state(ice->state.dynamic_uploader,
+ &ice->state.sampler_table[stage],
+ count * 4 * GENX(SAMPLER_STATE_length), 32);
if (unlikely(!map))
return;
- struct pipe_resource *res = ice->state.sampler_table_resource[stage];
- ice->state.sampler_table_offset[stage] +=
+ struct pipe_resource *res = ice->state.sampler_table[stage].res;
+ ice->state.sampler_table[stage].offset +=
iris_bo_offset_from_base_address(iris_resource_bo(res));
+ /* Make sure all land in the same BO */
+ iris_border_color_pool_reserve(ice, IRIS_MAX_TEXTURE_SAMPLERS);
+
for (int i = 0; i < count; i++) {
- struct iris_sampler_state *state = states[i];
+ struct iris_sampler_state *state = ice->state.samplers[stage][i];
/* Save a pointer to the iris_sampler_state, a few fields need
* to inform draw-time decisions.
*/
ice->state.samplers[stage][start + i] = state;
- if (state)
+ if (!state) {
+ memset(map, 0, 4 * GENX(SAMPLER_STATE_length));
+ } else if (!state->needs_border_color) {
memcpy(map, state->sampler_state, 4 * GENX(SAMPLER_STATE_length));
+ } else {
+ ice->state.need_border_colors = true;
+
+ /* Stream out the border color and merge the pointer. */
+ uint32_t offset =
+ iris_upload_border_color(ice, &state->base.border_color);
+
+ uint32_t dynamic[GENX(SAMPLER_STATE_length)];
+ iris_pack_state(GENX(SAMPLER_STATE), dynamic, dyns) {
+ dyns.BorderColorPointer = offset;
+ }
+
+ for (uint32_t j = 0; j < GENX(SAMPLER_STATE_length); j++)
+ ((uint32_t *) map)[j] = state->sampler_state[j] | dynamic[j];
+ }
map += GENX(SAMPLER_STATE_length);
}
- ice->state.num_samplers[stage] = count;
-
ice->state.dirty |= IRIS_DIRTY_SAMPLER_STATES_VS << stage;
}
struct isl_view view;
/** The resource (BO) holding our SURFACE_STATE. */
- struct pipe_resource *surface_state_resource;
- unsigned surface_state_offset;
-
- //uint32_t surface_state[GENX(RENDER_SURFACE_STATE_length)];
+ struct iris_state_ref surface_state;
};
/**
.b = pipe_swizzle_to_isl_channel(tmpl->swizzle_b),
.a = pipe_swizzle_to_isl_channel(tmpl->swizzle_a),
},
- .usage = ISL_SURF_USAGE_TEXTURE_BIT,
+ .usage = ISL_SURF_USAGE_TEXTURE_BIT |
+ (itex->surf.usage & ISL_SURF_USAGE_CUBE_BIT),
};
- void *map = NULL;
- u_upload_alloc(ice->state.surface_uploader, 0,
- 4 * GENX(RENDER_SURFACE_STATE_length), 64,
- &isv->surface_state_offset,
- &isv->surface_state_resource,
- &map);
+ void *map = upload_state(ice->state.surface_uploader, &isv->surface_state,
+ 4 * GENX(RENDER_SURFACE_STATE_length), 64);
if (!unlikely(map))
return NULL;
- struct iris_bo *state_bo = iris_resource_bo(isv->surface_state_resource);
- isv->surface_state_offset += iris_bo_offset_from_base_address(state_bo);
+ struct iris_bo *state_bo = iris_resource_bo(isv->surface_state.res);
+ isv->surface_state.offset += iris_bo_offset_from_base_address(state_bo);
isl_surf_fill_state(&screen->isl_dev, map,
.surf = &itex->surf, .view = &isv->view,
return &isv->pipe;
}
-struct iris_surface {
- struct pipe_surface pipe;
- struct isl_view view;
-
- /** The resource (BO) holding our SURFACE_STATE. */
- struct pipe_resource *surface_state_resource;
- unsigned surface_state_offset;
-
- // uint32_t surface_state[GENX(RENDER_SURFACE_STATE_length)];
-};
-
static struct pipe_surface *
iris_create_surface(struct pipe_context *ctx,
struct pipe_resource *tex,
struct iris_screen *screen = (struct iris_screen *)ctx->screen;
struct iris_surface *surf = calloc(1, sizeof(struct iris_surface));
struct pipe_surface *psurf = &surf->pipe;
- struct iris_resource *itex = (struct iris_resource *) tex;
+ struct iris_resource *res = (struct iris_resource *) tex;
if (!surf)
return NULL;
psurf->u.tex.last_layer = tmpl->u.tex.last_layer;
psurf->u.tex.level = tmpl->u.tex.level;
+ unsigned usage = 0;
+ if (tmpl->writable)
+ usage = ISL_SURF_USAGE_STORAGE_BIT;
+ else if (util_format_is_depth_or_stencil(tmpl->format))
+ usage = ISL_SURF_USAGE_DEPTH_BIT;
+ else
+ usage = ISL_SURF_USAGE_RENDER_TARGET_BIT;
+
surf->view = (struct isl_view) {
.format = iris_isl_format_for_pipe_format(tmpl->format),
.base_level = tmpl->u.tex.level,
.base_array_layer = tmpl->u.tex.first_layer,
.array_len = tmpl->u.tex.last_layer - tmpl->u.tex.first_layer + 1,
.swizzle = ISL_SWIZZLE_IDENTITY,
- // XXX: DEPTH_BIt, STENCIL_BIT...CUBE_BIT? Other bits?!
- .usage = ISL_SURF_USAGE_RENDER_TARGET_BIT,
+ .usage = usage,
};
- void *map = NULL;
- u_upload_alloc(ice->state.surface_uploader, 0,
- 4 * GENX(RENDER_SURFACE_STATE_length), 64,
- &surf->surface_state_offset,
- &surf->surface_state_resource,
- &map);
+ /* Bail early for depth/stencil */
+ if (res->surf.usage & (ISL_SURF_USAGE_DEPTH_BIT |
+ ISL_SURF_USAGE_STENCIL_BIT))
+ return psurf;
+
+
+ void *map = upload_state(ice->state.surface_uploader, &surf->surface_state,
+ 4 * GENX(RENDER_SURFACE_STATE_length), 64);
if (!unlikely(map))
return NULL;
- struct iris_bo *state_bo = iris_resource_bo(surf->surface_state_resource);
- surf->surface_state_offset += iris_bo_offset_from_base_address(state_bo);
+ struct iris_bo *state_bo = iris_resource_bo(surf->surface_state.res);
+ surf->surface_state.offset += iris_bo_offset_from_base_address(state_bo);
isl_surf_fill_state(&screen->isl_dev, map,
- .surf = &itex->surf, .view = &surf->view,
+ .surf = &res->surf, .view = &surf->view,
.mocs = MOCS_WB,
- .address = itex->bo->gtt_offset);
+ .address = res->bo->gtt_offset);
// .aux_surf =
// .clear_color = clear_color,
ice->state.num_textures[stage] = count;
- // XXX: ice->state.dirty |= (IRIS_DIRTY_BINDING_TABLE_VS << stage);
+ ice->state.dirty |= (IRIS_DIRTY_BINDINGS_VS << stage);
}
static void
{
struct iris_context *ice = (struct iris_context *) ctx;
- ice->state.num_scissors = num_scissors;
-
for (unsigned i = 0; i < num_scissors; i++) {
ice->state.scissors[start_slot + i] = states[i];
}
ice->state.dirty |= IRIS_DIRTY_WM_DEPTH_STENCIL;
}
-
-struct iris_viewport_state {
- uint32_t sf_cl_vp[GENX(SF_CLIP_VIEWPORT_length) * IRIS_MAX_VIEWPORTS];
-};
-
static float
viewport_extent(const struct pipe_viewport_state *state, int axis, float sign)
{
static void
iris_set_viewport_states(struct pipe_context *ctx,
unsigned start_slot,
- unsigned num_viewports,
- const struct pipe_viewport_state *state)
+ unsigned count,
+ const struct pipe_viewport_state *states)
{
struct iris_context *ice = (struct iris_context *) ctx;
- struct iris_viewport_state *cso =
- malloc(sizeof(struct iris_viewport_state));
+ struct iris_viewport_state *cso = &ice->state.genx->viewport;
uint32_t *vp_map = &cso->sf_cl_vp[start_slot];
// XXX: sf_cl_vp is only big enough for one slot, we don't iterate right
- for (unsigned i = 0; i < num_viewports; i++) {
+ for (unsigned i = 0; i < count; i++) {
+ const struct pipe_viewport_state *state = &states[start_slot + i];
iris_pack_state(GENX(SF_CLIP_VIEWPORT), vp_map, vp) {
- vp.ViewportMatrixElementm00 = state[i].scale[0];
- vp.ViewportMatrixElementm11 = state[i].scale[1];
- vp.ViewportMatrixElementm22 = state[i].scale[2];
- vp.ViewportMatrixElementm30 = state[i].translate[0];
- vp.ViewportMatrixElementm31 = state[i].translate[1];
- vp.ViewportMatrixElementm32 = state[i].translate[2];
+ vp.ViewportMatrixElementm00 = state->scale[0];
+ vp.ViewportMatrixElementm11 = state->scale[1];
+ vp.ViewportMatrixElementm22 = state->scale[2];
+ vp.ViewportMatrixElementm30 = state->translate[0];
+ vp.ViewportMatrixElementm31 = state->translate[1];
+ vp.ViewportMatrixElementm32 = state->translate[2];
/* XXX: in i965 this is computed based on the drawbuffer size,
* but we don't have that here...
*/
vp.XMaxClipGuardband = 1.0;
vp.YMinClipGuardband = -1.0;
vp.YMaxClipGuardband = 1.0;
- vp.XMinViewPort = viewport_extent(&state[i], 0, -1.0f);
- vp.XMaxViewPort = viewport_extent(&state[i], 0, 1.0f) - 1;
- vp.YMinViewPort = viewport_extent(&state[i], 1, -1.0f);
- vp.YMaxViewPort = viewport_extent(&state[i], 1, 1.0f) - 1;
+ vp.XMinViewPort = viewport_extent(state, 0, -1.0f);
+ vp.XMaxViewPort = viewport_extent(state, 0, 1.0f) - 1;
+ vp.YMinViewPort = viewport_extent(state, 1, -1.0f);
+ vp.YMaxViewPort = viewport_extent(state, 1, 1.0f) - 1;
}
vp_map += GENX(SF_CLIP_VIEWPORT_length);
}
- ice->state.cso_vp = cso;
- ice->state.num_viewports = num_viewports;
ice->state.dirty |= IRIS_DIRTY_SF_CL_VIEWPORT;
}
-struct iris_depth_state
-{
- uint32_t depth_buffer[GENX(3DSTATE_DEPTH_BUFFER_length)];
- uint32_t hier_depth_buffer[GENX(3DSTATE_HIER_DEPTH_BUFFER_length)];
- uint32_t stencil_buffer[GENX(3DSTATE_STENCIL_BUFFER_length)];
-};
-
static void
iris_set_framebuffer_state(struct pipe_context *ctx,
const struct pipe_framebuffer_state *state)
{
struct iris_context *ice = (struct iris_context *) ctx;
+ struct iris_screen *screen = (struct iris_screen *)ctx->screen;
+ struct isl_device *isl_dev = &screen->isl_dev;
struct pipe_framebuffer_state *cso = &ice->state.framebuffer;
if (cso->samples != state->samples) {
ice->state.dirty |= IRIS_DIRTY_BLEND_STATE;
}
- cso->width = state->width;
- cso->height = state->height;
- cso->layers = state->layers;
- cso->samples = state->samples;
+ if ((cso->layers == 0) == (state->layers == 0)) {
+ ice->state.dirty |= IRIS_DIRTY_CLIP;
+ }
- unsigned i;
- for (i = 0; i < state->nr_cbufs; i++)
- pipe_surface_reference(&cso->cbufs[i], state->cbufs[i]);
- for (; i < cso->nr_cbufs; i++)
- pipe_surface_reference(&cso->cbufs[i], NULL);
+ util_copy_framebuffer_state(cso, state);
+
+ struct iris_depth_buffer_state *cso_z = &ice->state.genx->depth_buffer;
+
+ struct isl_view view = {
+ .base_level = 0,
+ .levels = 1,
+ .base_array_layer = 0,
+ .array_len = 1,
+ .swizzle = ISL_SWIZZLE_IDENTITY,
+ };
+
+ struct isl_depth_stencil_hiz_emit_info info = {
+ .view = &view,
+ .mocs = MOCS_WB,
+ };
+
+ struct iris_resource *zres =
+ (void *) (cso->zsbuf ? cso->zsbuf->texture : NULL);
- cso->nr_cbufs = state->nr_cbufs;
+ if (zres) {
+ view.usage |= ISL_SURF_USAGE_DEPTH_BIT;
- pipe_surface_reference(&cso->zsbuf, state->zsbuf);
+ info.depth_surf = &zres->surf;
+ info.depth_address = zres->bo->gtt_offset;
- //struct isl_depth_stencil_hiz_emit_info info = {
- //.mocs = MOCS_WB,
- //};
+ view.format = zres->surf.format;
- // XXX: depth buffers
+ view.base_level = cso->zsbuf->u.tex.level;
+ view.base_array_layer = cso->zsbuf->u.tex.first_layer;
+ view.array_len =
+ cso->zsbuf->u.tex.last_layer - cso->zsbuf->u.tex.first_layer + 1;
+
+ info.hiz_usage = ISL_AUX_USAGE_NONE;
+ }
+
+#if 0
+ if (stencil_mt) {
+ view.usage |= ISL_SURF_USAGE_STENCIL_BIT;
+ info.stencil_surf = &stencil_mt->surf;
+
+ if (!depth_mt) {
+ view.base_level = stencil_irb->mt_level - stencil_irb->mt->first_level;
+ view.base_array_layer = stencil_irb->mt_layer;
+ view.array_len = MAX2(stencil_irb->layer_count, 1);
+ view.format = stencil_mt->surf.format;
+ }
+
+ uint32_t stencil_offset = 0;
+ info.stencil_address = stencil_mt->bo->gtt_offset + stencil_mt->offset;
+ }
+#endif
+
+ isl_emit_depth_stencil_hiz_s(isl_dev, cso_z->packets, &info);
+
+ ice->state.dirty |= IRIS_DIRTY_DEPTH_BUFFER;
+
+ /* Render target change */
+ ice->state.dirty |= IRIS_DIRTY_BINDINGS_FS;
}
static void
iris_set_constant_buffer(struct pipe_context *ctx,
enum pipe_shader_type p_stage, unsigned index,
- const struct pipe_constant_buffer *cb)
+ const struct pipe_constant_buffer *input)
{
struct iris_context *ice = (struct iris_context *) ctx;
+ struct iris_screen *screen = (struct iris_screen *)ctx->screen;
gl_shader_stage stage = stage_from_pipe(p_stage);
+ struct iris_shader_state *shs = &ice->shaders.state[stage];
+ struct iris_const_buffer *cbuf = &shs->constbuf[index];
+
+ if (input && (input->buffer || input->user_buffer)) {
+ if (input->user_buffer) {
+ u_upload_data(ctx->const_uploader, 0, input->buffer_size, 32,
+ input->user_buffer, &cbuf->data.offset,
+ &cbuf->data.res);
+ } else {
+ pipe_resource_reference(&cbuf->data.res, input->buffer);
+ }
+
+ // XXX: these are not retained forever, use a separate uploader?
+ void *map =
+ upload_state(ice->state.surface_uploader, &cbuf->surface_state,
+ 4 * GENX(RENDER_SURFACE_STATE_length), 64);
+ if (!unlikely(map)) {
+ pipe_resource_reference(&cbuf->data.res, NULL);
+ return;
+ }
+
+ struct iris_resource *res = (void *) cbuf->data.res;
+ struct iris_bo *surf_bo = iris_resource_bo(cbuf->surface_state.res);
+ cbuf->surface_state.offset += iris_bo_offset_from_base_address(surf_bo);
- util_copy_constant_buffer(&ice->shaders.state[stage].constbuf[index], cb);
+ isl_buffer_fill_state(&screen->isl_dev, map,
+ .address = res->bo->gtt_offset + cbuf->data.offset,
+ .size_B = input->buffer_size,
+ .format = ISL_FORMAT_R32G32B32A32_FLOAT,
+ .stride_B = 1,
+ .mocs = MOCS_WB)
+ } else {
+ pipe_resource_reference(&cbuf->data.res, NULL);
+ pipe_resource_reference(&cbuf->surface_state.res, NULL);
+ }
+
+ ice->state.dirty |= IRIS_DIRTY_CONSTANTS_VS << stage;
+ // XXX: maybe not necessary all the time...?
+ ice->state.dirty |= IRIS_DIRTY_BINDINGS_VS << stage;
}
static void
{
struct iris_sampler_view *isv = (void *) state;
pipe_resource_reference(&state->texture, NULL);
- pipe_resource_reference(&isv->surface_state_resource, NULL);
+ pipe_resource_reference(&isv->surface_state.res, NULL);
free(isv);
}
{
struct iris_surface *surf = (void *) p_surf;
pipe_resource_reference(&p_surf->texture, NULL);
- pipe_resource_reference(&surf->surface_state_resource, NULL);
+ pipe_resource_reference(&surf->surface_state.res, NULL);
free(surf);
}
free(state);
}
-struct iris_vertex_buffer_state {
- uint32_t vertex_buffers[1 + 33 * GENX(VERTEX_BUFFER_STATE_length)];
- struct iris_bo *bos[33];
- unsigned num_buffers;
-};
-
static void
iris_free_vertex_buffers(struct iris_vertex_buffer_state *cso)
{
- if (cso) {
- for (unsigned i = 0; i < cso->num_buffers; i++)
- iris_bo_unreference(cso->bos[i]);
- free(cso);
- }
+ for (unsigned i = 0; i < cso->num_buffers; i++)
+ pipe_resource_reference(&cso->resources[i], NULL);
}
static void
const struct pipe_vertex_buffer *buffers)
{
struct iris_context *ice = (struct iris_context *) ctx;
- struct iris_vertex_buffer_state *cso =
- malloc(sizeof(struct iris_vertex_buffer_state));
+ struct iris_vertex_buffer_state *cso = &ice->state.genx->vertex_buffers;
- /* If there are no buffers, do nothing. We can leave the stale
- * 3DSTATE_VERTEX_BUFFERS in place - as long as there are no vertex
- * elements that point to them, it should be fine.
- */
- if (!buffers)
- return;
+ iris_free_vertex_buffers(&ice->state.genx->vertex_buffers);
- iris_free_vertex_buffers(ice->state.cso_vertex_buffers);
+ if (!buffers)
+ count = 0;
cso->num_buffers = count;
iris_pack_command(GENX(3DSTATE_VERTEX_BUFFERS), cso->vertex_buffers, vb) {
- vb.DWordLength = 4 * cso->num_buffers - 1;
+ vb.DWordLength = 4 * MAX2(cso->num_buffers, 1) - 1;
}
uint32_t *vb_pack_dest = &cso->vertex_buffers[1];
+ if (count == 0) {
+ iris_pack_state(GENX(VERTEX_BUFFER_STATE), vb_pack_dest, vb) {
+ vb.VertexBufferIndex = start_slot;
+ vb.NullVertexBuffer = true;
+ vb.AddressModifyEnable = true;
+ }
+ }
+
for (unsigned i = 0; i < count; i++) {
assert(!buffers[i].is_user_buffer);
- struct iris_resource *res = (void *) buffers[i].buffer.resource;
- iris_bo_reference(res->bo);
- cso->bos[i] = res->bo;
+ pipe_resource_reference(&cso->resources[i], buffers[i].buffer.resource);
+ struct iris_resource *res = (void *) cso->resources[i];
iris_pack_state(GENX(VERTEX_BUFFER_STATE), vb_pack_dest, vb) {
vb.VertexBufferIndex = start_slot + i;
vb_pack_dest += GENX(VERTEX_BUFFER_STATE_length);
}
- ice->state.cso_vertex_buffers = cso;
ice->state.dirty |= IRIS_DIRTY_VERTEX_BUFFERS;
}
struct iris_vertex_element_state {
uint32_t vertex_elements[1 + 33 * GENX(VERTEX_ELEMENT_STATE_length)];
- uint32_t vf_instancing[GENX(3DSTATE_VF_INSTANCING_length)][33];
+ uint32_t vf_instancing[33 * GENX(3DSTATE_VF_INSTANCING_length)];
unsigned count;
};
struct iris_vertex_element_state *cso =
malloc(sizeof(struct iris_vertex_element_state));
- cso->count = count;
+ cso->count = MAX2(count, 1);
/* TODO:
* - create edge flag one
* - create SGV ones
* - if those are necessary, use count + 1/2/3... OR in the length
*/
- iris_pack_command(GENX(3DSTATE_VERTEX_ELEMENTS), cso->vertex_elements, ve);
+ iris_pack_command(GENX(3DSTATE_VERTEX_ELEMENTS), cso->vertex_elements, ve) {
+ ve.DWordLength = 1 + GENX(VERTEX_ELEMENT_STATE_length) * cso->count - 2;
+ }
uint32_t *ve_pack_dest = &cso->vertex_elements[1];
+ uint32_t *vfi_pack_dest = cso->vf_instancing;
+
+ if (count == 0) {
+ iris_pack_state(GENX(VERTEX_ELEMENT_STATE), ve_pack_dest, ve) {
+ ve.Valid = true;
+ ve.SourceElementFormat = ISL_FORMAT_R32G32B32A32_FLOAT;
+ ve.Component0Control = VFCOMP_STORE_0;
+ ve.Component1Control = VFCOMP_STORE_0;
+ ve.Component2Control = VFCOMP_STORE_0;
+ ve.Component3Control = VFCOMP_STORE_1_FP;
+ }
+
+ iris_pack_command(GENX(3DSTATE_VF_INSTANCING), vfi_pack_dest, vi) {
+ }
+ }
for (int i = 0; i < count; i++) {
enum isl_format isl_format =
- iris_isl_format_for_pipe_format(state[i].src_format);
+ iris_isl_format_for_pipe_format(state[i].src_format);
unsigned comp[4] = { VFCOMP_STORE_SRC, VFCOMP_STORE_SRC,
VFCOMP_STORE_SRC, VFCOMP_STORE_SRC };
ve.Component3Control = comp[3];
}
- iris_pack_command(GENX(3DSTATE_VF_INSTANCING), cso->vf_instancing[i], vi) {
+ iris_pack_command(GENX(3DSTATE_VF_INSTANCING), vfi_pack_dest, vi) {
vi.VertexElementIndex = i;
vi.InstancingEnable = state[i].instance_divisor > 0;
vi.InstanceDataStepRate = state[i].instance_divisor;
}
ve_pack_dest += GENX(VERTEX_ELEMENT_STATE_length);
+ vfi_pack_dest += GENX(3DSTATE_VF_INSTANCING_length);
}
return cso;
*out_length = DIV_ROUND_UP(last_read_slot - first_slot + 1, 2);
}
+static void
+iris_emit_sbe_swiz(struct iris_batch *batch,
+ const struct iris_context *ice,
+ unsigned urb_read_offset)
+{
+ struct GENX(SF_OUTPUT_ATTRIBUTE_DETAIL) attr_overrides[16] = {};
+ const struct brw_wm_prog_data *wm_prog_data = (void *)
+ ice->shaders.prog[MESA_SHADER_FRAGMENT]->prog_data;
+ const struct brw_vue_map *vue_map = ice->shaders.last_vue_map;
+ const struct iris_rasterizer_state *cso_rast = ice->state.cso_rast;
+
+ /* XXX: this should be generated when putting programs in place */
+
+ // XXX: raster->sprite_coord_enable
+
+ for (int fs_attr = 0; fs_attr < VARYING_SLOT_MAX; fs_attr++) {
+ const int input_index = wm_prog_data->urb_setup[fs_attr];
+ if (input_index < 0 || input_index >= 16)
+ continue;
+
+ struct GENX(SF_OUTPUT_ATTRIBUTE_DETAIL) *attr =
+ &attr_overrides[input_index];
+
+ /* Viewport and Layer are stored in the VUE header. We need to override
+ * them to zero if earlier stages didn't write them, as GL requires that
+ * they read back as zero when not explicitly set.
+ */
+ switch (fs_attr) {
+ case VARYING_SLOT_VIEWPORT:
+ case VARYING_SLOT_LAYER:
+ attr->ComponentOverrideX = true;
+ attr->ComponentOverrideW = true;
+ attr->ConstantSource = CONST_0000;
+
+ if (!(vue_map->slots_valid & VARYING_BIT_LAYER))
+ attr->ComponentOverrideY = true;
+ if (!(vue_map->slots_valid & VARYING_BIT_VIEWPORT))
+ attr->ComponentOverrideZ = true;
+ continue;
+
+ case VARYING_SLOT_PRIMITIVE_ID:
+ attr->ComponentOverrideX = true;
+ attr->ComponentOverrideY = true;
+ attr->ComponentOverrideZ = true;
+ attr->ComponentOverrideW = true;
+ attr->ConstantSource = PRIM_ID;
+ continue;
+
+ default:
+ break;
+ }
+
+ int slot = vue_map->varying_to_slot[fs_attr];
+
+ /* If there was only a back color written but not front, use back
+ * as the color instead of undefined.
+ */
+ if (slot == -1 && fs_attr == VARYING_SLOT_COL0)
+ slot = vue_map->varying_to_slot[VARYING_SLOT_BFC0];
+ if (slot == -1 && fs_attr == VARYING_SLOT_COL1)
+ slot = vue_map->varying_to_slot[VARYING_SLOT_BFC1];
+
+ /* Not written by the previous stage - undefined. */
+ if (slot == -1) {
+ attr->ComponentOverrideX = true;
+ attr->ComponentOverrideY = true;
+ attr->ComponentOverrideZ = true;
+ attr->ComponentOverrideW = true;
+ attr->ConstantSource = CONST_0001_FLOAT;
+ continue;
+ }
+
+ /* Compute the location of the attribute relative to the read offset,
+ * which is counted in 256-bit increments (two 128-bit VUE slots).
+ */
+ const int source_attr = slot - 2 * urb_read_offset;
+ assert(source_attr >= 0 && source_attr <= 32);
+ attr->SourceAttribute = source_attr;
+
+ /* If we are doing two-sided color, and the VUE slot following this one
+ * represents a back-facing color, then we need to instruct the SF unit
+ * to do back-facing swizzling.
+ */
+ if (cso_rast->light_twoside &&
+ ((vue_map->slot_to_varying[slot] == VARYING_SLOT_COL0 &&
+ vue_map->slot_to_varying[slot+1] == VARYING_SLOT_BFC0) ||
+ (vue_map->slot_to_varying[slot] == VARYING_SLOT_COL1 &&
+ vue_map->slot_to_varying[slot+1] == VARYING_SLOT_BFC1)))
+ attr->SwizzleSelect = INPUTATTR_FACING;
+ }
+
+ iris_emit_cmd(batch, GENX(3DSTATE_SBE_SWIZ), sbes) {
+ for (int i = 0; i < 16; i++)
+ sbes.Attribute[i] = attr_overrides[i];
+ }
+}
+
static void
iris_emit_sbe(struct iris_batch *batch, const struct iris_context *ice)
{
sbe.AttributeActiveComponentFormat[i] = ACTIVE_COMPONENT_XYZW;
}
}
+
+ iris_emit_sbe_swiz(batch, ice, urb_read_offset);
}
static void
key->replicate_alpha = fb->nr_cbufs > 1 &&
(zsa->alpha.enabled || blend->alpha_to_coverage);
+ /* XXX: only bother if COL0/1 are read */
+ key->flat_shade = rast->flatshade;
+
// key->force_dual_color_blend for unigine
#if 0
if (cso_rast->multisample) {
key->coherent_fb_fetch = true;
}
- //pkt.SamplerCount = \
- //DIV_ROUND_UP(CLAMP(stage_state->sampler_count, 0, 16), 4); \
- //pkt.PerThreadScratchSpace = prog_data->total_scratch == 0 ? 0 : \
- //ffs(stage_state->per_thread_scratch) - 11; \
+#if 0
+ // XXX: these need to go in INIT_THREAD_DISPATCH_FIELDS
+ pkt.SamplerCount = \
+ DIV_ROUND_UP(CLAMP(stage_state->sampler_count, 0, 16), 4); \
+ pkt.PerThreadScratchSpace = prog_data->total_scratch == 0 ? 0 : \
+ ffs(stage_state->per_thread_scratch) - 11; \
+
+#endif
static uint64_t
KSP(const struct iris_compiled_shader *shader)
{
- struct iris_resource *res = (void *) shader->buffer;
- return res->bo->gtt_offset + shader->offset;
+ struct iris_resource *res = (void *) shader->assembly.res;
+ return iris_bo_offset_from_base_address(res->bo) + shader->assembly.offset;
}
#define INIT_THREAD_DISPATCH_FIELDS(pkt, prefix) \
pkt.Enable = true;
static void
-iris_set_vs_state(const struct gen_device_info *devinfo,
- struct iris_compiled_shader *shader)
+iris_store_vs_state(const struct gen_device_info *devinfo,
+ struct iris_compiled_shader *shader)
{
struct brw_stage_prog_data *prog_data = shader->prog_data;
struct brw_vue_prog_data *vue_prog_data = (void *) prog_data;
}
static void
-iris_set_tcs_state(const struct gen_device_info *devinfo,
- struct iris_compiled_shader *shader)
+iris_store_tcs_state(const struct gen_device_info *devinfo,
+ struct iris_compiled_shader *shader)
{
struct brw_stage_prog_data *prog_data = shader->prog_data;
struct brw_vue_prog_data *vue_prog_data = (void *) prog_data;
}
static void
-iris_set_tes_state(const struct gen_device_info *devinfo,
- struct iris_compiled_shader *shader)
+iris_store_tes_state(const struct gen_device_info *devinfo,
+ struct iris_compiled_shader *shader)
{
struct brw_stage_prog_data *prog_data = shader->prog_data;
struct brw_vue_prog_data *vue_prog_data = (void *) prog_data;
}
static void
-iris_set_gs_state(const struct gen_device_info *devinfo,
- struct iris_compiled_shader *shader)
+iris_store_gs_state(const struct gen_device_info *devinfo,
+ struct iris_compiled_shader *shader)
{
struct brw_stage_prog_data *prog_data = shader->prog_data;
struct brw_vue_prog_data *vue_prog_data = (void *) prog_data;
gs.ControlDataHeaderSize =
gs_prog_data->control_data_header_size_hwords;
gs.InstanceControl = gs_prog_data->invocations - 1;
- gs.DispatchMode = SIMD8;
+ gs.DispatchMode = DISPATCH_MODE_SIMD8;
gs.IncludePrimitiveID = gs_prog_data->include_primitive_id;
gs.ControlDataFormat = gs_prog_data->control_data_format;
gs.ReorderMode = TRAILING;
}
static void
-iris_set_fs_state(const struct gen_device_info *devinfo,
- struct iris_compiled_shader *shader)
+iris_store_fs_state(const struct gen_device_info *devinfo,
+ struct iris_compiled_shader *shader)
{
struct brw_stage_prog_data *prog_data = shader->prog_data;
struct brw_wm_prog_data *wm_prog_data = (void *) shader->prog_data;
}
static void
-iris_set_derived_program_state(const struct gen_device_info *devinfo,
- enum iris_program_cache_id cache_id,
- struct iris_compiled_shader *shader)
+iris_store_derived_program_state(const struct gen_device_info *devinfo,
+ enum iris_program_cache_id cache_id,
+ struct iris_compiled_shader *shader)
{
switch (cache_id) {
case IRIS_CACHE_VS:
- iris_set_vs_state(devinfo, shader);
+ iris_store_vs_state(devinfo, shader);
break;
case IRIS_CACHE_TCS:
- iris_set_tcs_state(devinfo, shader);
+ iris_store_tcs_state(devinfo, shader);
break;
case IRIS_CACHE_TES:
- iris_set_tes_state(devinfo, shader);
+ iris_store_tes_state(devinfo, shader);
break;
case IRIS_CACHE_GS:
- iris_set_gs_state(devinfo, shader);
+ iris_store_gs_state(devinfo, shader);
break;
case IRIS_CACHE_FS:
- iris_set_fs_state(devinfo, shader);
+ iris_store_fs_state(devinfo, shader);
break;
case IRIS_CACHE_CS:
case IRIS_CACHE_BLORP:
bool writeable)
{
struct iris_surface *surf = (void *) p_surf;
- struct iris_resource *res = (void *) p_surf->texture;
- struct iris_resource *state_res = (void *) surf->surface_state_resource;
- iris_use_pinned_bo(batch, res->bo, writeable);
- iris_use_pinned_bo(batch, state_res->bo, false);
- return surf->surface_state_offset;
+ iris_use_pinned_bo(batch, iris_resource_bo(p_surf->texture), writeable);
+ iris_use_pinned_bo(batch, iris_resource_bo(surf->surface_state.res), false);
+
+ return surf->surface_state.offset;
}
static uint32_t
use_sampler_view(struct iris_batch *batch, struct iris_sampler_view *isv)
{
- struct iris_resource *res = (void *) isv->pipe.texture;
- struct iris_resource *state_res = (void *) isv->surface_state_resource;
- iris_use_pinned_bo(batch, res->bo, false);
- iris_use_pinned_bo(batch, state_res->bo, false);
+ iris_use_pinned_bo(batch, iris_resource_bo(isv->pipe.texture), false);
+ iris_use_pinned_bo(batch, iris_resource_bo(isv->surface_state.res), false);
+
+ return isv->surface_state.offset;
+}
+
+static uint32_t
+use_const_buffer(struct iris_batch *batch, struct iris_const_buffer *cbuf)
+{
+ iris_use_pinned_bo(batch, iris_resource_bo(cbuf->data.res), false);
+ iris_use_pinned_bo(batch, iris_resource_bo(cbuf->surface_state.res), false);
+
+ return cbuf->surface_state.offset;
+}
+
+static uint32_t
+use_null_surface(struct iris_batch *batch, struct iris_context *ice)
+{
+ struct iris_bo *state_bo = iris_resource_bo(ice->state.unbound_tex.res);
+
+ iris_use_pinned_bo(batch, state_bo, false);
+
+ return ice->state.unbound_tex.offset;
+}
+
+static void
+iris_populate_binding_table(struct iris_context *ice,
+ struct iris_batch *batch,
+ gl_shader_stage stage)
+{
+ const struct iris_binder *binder = &batch->binder;
+ struct iris_compiled_shader *shader = ice->shaders.prog[stage];
+ if (!shader)
+ return;
+
+ // Surfaces:
+ // - pull constants
+ // - ubos/ssbos/abos
+ // - images
+ // - textures
+ // - render targets - write and read
+
+ //struct brw_stage_prog_data *prog_data = (void *) shader->prog_data;
+ uint32_t *bt_map = binder->map + binder->bt_offset[stage];
+ int s = 0;
+
+ if (stage == MESA_SHADER_FRAGMENT) {
+ struct pipe_framebuffer_state *cso_fb = &ice->state.framebuffer;
+ for (unsigned i = 0; i < cso_fb->nr_cbufs; i++) {
+ bt_map[s++] = use_surface(batch, cso_fb->cbufs[i], true);
+ }
+ }
+
+ //assert(prog_data->binding_table.texture_start ==
+ //(ice->state.num_textures[stage] ? s : 0xd0d0d0d0));
+
+ for (int i = 0; i < ice->state.num_textures[stage]; i++) {
+ struct iris_sampler_view *view = ice->state.textures[stage][i];
+ bt_map[s++] = view ? use_sampler_view(batch, view)
+ : use_null_surface(batch, ice);
+ }
+
+ // XXX: want the number of BTE's to shorten this loop
+ struct iris_shader_state *shs = &ice->shaders.state[stage];
+ for (int i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
+ struct iris_const_buffer *cbuf = &shs->constbuf[i];
+ if (!cbuf->surface_state.res)
+ break;
+
+ bt_map[s++] = use_const_buffer(batch, cbuf);
+ }
+#if 0
+ // XXX: not implemented yet
+ assert(prog_data->binding_table.pull_constants_start == 0xd0d0d0d0);
+ assert(prog_data->binding_table.ubo_start == 0xd0d0d0d0);
+ assert(prog_data->binding_table.ssbo_start == 0xd0d0d0d0);
+ assert(prog_data->binding_table.image_start == 0xd0d0d0d0);
+ assert(prog_data->binding_table.shader_time_start == 0xd0d0d0d0);
+ //assert(prog_data->binding_table.plane_start[1] == 0xd0d0d0d0);
+ //assert(prog_data->binding_table.plane_start[2] == 0xd0d0d0d0);
+#endif
+}
- return isv->surface_state_offset;
+static void
+iris_use_optional_res(struct iris_batch *batch,
+ struct pipe_resource *res,
+ bool writeable)
+{
+ if (res) {
+ struct iris_bo *bo = iris_resource_bo(res);
+ iris_use_pinned_bo(batch, bo, writeable);
+ }
+}
+
+
+/**
+ * Pin any BOs which were installed by a previous batch, and restored
+ * via the hardware logical context mechanism.
+ *
+ * We don't need to re-emit all state every batch - the hardware context
+ * mechanism will save and restore it for us. This includes pointers to
+ * various BOs...which won't exist unless we ask the kernel to pin them
+ * by adding them to the validation list.
+ *
+ * We can skip buffers if we've re-emitted those packets, as we're
+ * overwriting those stale pointers with new ones, and don't actually
+ * refer to the old BOs.
+ */
+static void
+iris_restore_context_saved_bos(struct iris_context *ice,
+ struct iris_batch *batch,
+ const struct pipe_draw_info *draw)
+{
+ // XXX: whack IRIS_SHADER_DIRTY_BINDING_TABLE on new batch
+
+ const uint64_t clean = ~ice->state.dirty;
+
+ if (clean & IRIS_DIRTY_CC_VIEWPORT) {
+ iris_use_optional_res(batch, ice->state.last_res.cc_vp, false);
+ }
+
+ if (clean & IRIS_DIRTY_SF_CL_VIEWPORT) {
+ iris_use_optional_res(batch, ice->state.last_res.sf_cl_vp, false);
+ }
+
+ if (clean & IRIS_DIRTY_BLEND_STATE) {
+ iris_use_optional_res(batch, ice->state.last_res.blend, false);
+ }
+
+ if (clean & IRIS_DIRTY_COLOR_CALC_STATE) {
+ iris_use_optional_res(batch, ice->state.last_res.color_calc, false);
+ }
+
+ if (clean & IRIS_DIRTY_SCISSOR_RECT) {
+ iris_use_optional_res(batch, ice->state.last_res.scissor, false);
+ }
+
+ for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) {
+ if (clean & (IRIS_DIRTY_CONSTANTS_VS << stage))
+ continue;
+
+ struct iris_shader_state *shs = &ice->shaders.state[stage];
+ struct iris_compiled_shader *shader = ice->shaders.prog[stage];
+
+ if (!shader)
+ continue;
+
+ struct brw_stage_prog_data *prog_data = (void *) shader->prog_data;
+
+ for (int i = 0; i < 4; i++) {
+ const struct brw_ubo_range *range = &prog_data->ubo_ranges[i];
+
+ if (range->length == 0)
+ continue;
+
+ struct iris_const_buffer *cbuf = &shs->constbuf[range->block];
+ struct iris_resource *res = (void *) cbuf->data.res;
+
+ if (res)
+ iris_use_pinned_bo(batch, res->bo, false);
+ else
+ iris_use_pinned_bo(batch, batch->screen->workaround_bo, false);
+ }
+ }
+
+ for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) {
+ struct pipe_resource *res = ice->state.sampler_table[stage].res;
+ if (res)
+ iris_use_pinned_bo(batch, iris_resource_bo(res), false);
+ }
+
+ for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) {
+ if (clean & (IRIS_DIRTY_VS << stage)) {
+ struct iris_compiled_shader *shader = ice->shaders.prog[stage];
+ if (shader) {
+ struct iris_bo *bo = iris_resource_bo(shader->assembly.res);
+ iris_use_pinned_bo(batch, bo, false);
+ }
+
+ // XXX: scratch buffer
+ }
+ }
+
+ // XXX: 3DSTATE_SO_BUFFER
+
+ if (clean & IRIS_DIRTY_DEPTH_BUFFER) {
+ struct pipe_framebuffer_state *cso_fb = &ice->state.framebuffer;
+
+ if (cso_fb->zsbuf) {
+ struct iris_resource *zres = (void *) cso_fb->zsbuf->texture;
+ // XXX: depth might not be writable...
+ iris_use_pinned_bo(batch, zres->bo, true);
+ }
+ }
+
+ if (draw->index_size > 0) {
+ // XXX: index buffer
+ }
+
+ if (clean & IRIS_DIRTY_VERTEX_BUFFERS) {
+ struct iris_vertex_buffer_state *cso = &ice->state.genx->vertex_buffers;
+ for (unsigned i = 0; i < cso->num_buffers; i++) {
+ struct iris_resource *res = (void *) cso->resources[i];
+ iris_use_pinned_bo(batch, res->bo, false);
+ }
+ }
}
static void
struct iris_batch *batch,
const struct pipe_draw_info *draw)
{
- const uint64_t dirty =
- unlikely(INTEL_DEBUG & DEBUG_REEMIT) ? ~0ull : ice->state.dirty;
+ const uint64_t dirty = ice->state.dirty;
struct brw_wm_prog_data *wm_prog_data = (void *)
ice->shaders.prog[MESA_SHADER_FRAGMENT]->prog_data;
iris_emit_cmd(batch, GENX(3DSTATE_VIEWPORT_STATE_POINTERS_CC), ptr) {
ptr.CCViewportPointer =
emit_state(batch, ice->state.dynamic_uploader,
+ &ice->state.last_res.cc_vp,
cso->cc_vp, sizeof(cso->cc_vp), 32);
}
}
if (dirty & IRIS_DIRTY_SF_CL_VIEWPORT) {
- struct iris_viewport_state *cso = ice->state.cso_vp;
+ struct iris_viewport_state *cso = &ice->state.genx->viewport;
iris_emit_cmd(batch, GENX(3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP), ptr) {
ptr.SFClipViewportPointer =
- emit_state(batch, ice->state.dynamic_uploader, cso->sf_cl_vp,
- 4 * GENX(SF_CLIP_VIEWPORT_length) *
+ emit_state(batch, ice->state.dynamic_uploader,
+ &ice->state.last_res.sf_cl_vp,
+ cso->sf_cl_vp, 4 * GENX(SF_CLIP_VIEWPORT_length) *
ice->state.num_viewports, 64);
}
}
/* XXX: L3 State */
+ // XXX: this is only flagged at setup, we assume a static configuration
if (dirty & IRIS_DIRTY_URB) {
iris_upload_urb_config(ice, batch);
}
cso_fb->nr_cbufs * GENX(BLEND_STATE_ENTRY_length));
uint32_t blend_offset;
uint32_t *blend_map =
- stream_state(batch, ice->state.dynamic_uploader, 4 * num_dwords, 64,
- &blend_offset);
+ stream_state(batch, ice->state.dynamic_uploader,
+ &ice->state.last_res.blend,
+ 4 * num_dwords, 64, &blend_offset);
uint32_t blend_state_header;
iris_pack_state(GENX(BLEND_STATE), &blend_state_header, bs) {
uint32_t cc_offset;
void *cc_map =
stream_state(batch, ice->state.dynamic_uploader,
+ &ice->state.last_res.color_calc,
sizeof(uint32_t) * GENX(COLOR_CALC_STATE_length),
64, &cc_offset);
iris_pack_state(GENX(COLOR_CALC_STATE), cc_map, cc) {
if (!(dirty & (IRIS_DIRTY_CONSTANTS_VS << stage)))
continue;
- struct pipe_constant_buffer *cbuf0 =
- &ice->shaders.state[stage].constbuf[0];
-
- if (!ice->shaders.prog[stage] || cbuf0->buffer || !cbuf0->buffer_size)
- continue;
-
struct iris_shader_state *shs = &ice->shaders.state[stage];
- shs->const_size = cbuf0->buffer_size;
- u_upload_data(ice->ctx.const_uploader, 0, shs->const_size, 32,
- cbuf0->user_buffer, &shs->const_offset,
- &shs->push_resource);
- }
+ struct iris_compiled_shader *shader = ice->shaders.prog[stage];
- for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) {
- // XXX: wrong dirty tracking...
- if (!(dirty & (IRIS_DIRTY_CONSTANTS_VS << stage)))
+ if (!shader)
continue;
- struct iris_shader_state *shs = &ice->shaders.state[stage];
- struct iris_resource *res = (void *) shs->push_resource;
+ struct brw_stage_prog_data *prog_data = (void *) shader->prog_data;
iris_emit_cmd(batch, GENX(3DSTATE_CONSTANT_VS), pkt) {
pkt._3DCommandSubOpcode = push_constant_opcodes[stage];
- if (res) {
- pkt.ConstantBody.ReadLength[3] = shs->const_size;
- pkt.ConstantBody.Buffer[3] = ro_bo(res->bo, shs->const_offset);
+ if (prog_data) {
+ /* The Skylake PRM contains the following restriction:
+ *
+ * "The driver must ensure The following case does not occur
+ * without a flush to the 3D engine: 3DSTATE_CONSTANT_* with
+ * buffer 3 read length equal to zero committed followed by a
+ * 3DSTATE_CONSTANT_* with buffer 0 read length not equal to
+ * zero committed."
+ *
+ * To avoid this, we program the buffers in the highest slots.
+ * This way, slot 0 is only used if slot 3 is also used.
+ */
+ int n = 3;
+
+ for (int i = 3; i >= 0; i--) {
+ const struct brw_ubo_range *range = &prog_data->ubo_ranges[i];
+
+ if (range->length == 0)
+ continue;
+
+ // XXX: is range->block a constbuf index? it would be nice
+ struct iris_const_buffer *cbuf = &shs->constbuf[range->block];
+ struct iris_resource *res = (void *) cbuf->data.res;
+
+ assert(cbuf->data.offset % 32 == 0);
+
+ pkt.ConstantBody.ReadLength[n] = range->length;
+ pkt.ConstantBody.Buffer[n] =
+ res ? ro_bo(res->bo, range->start * 32 + cbuf->data.offset)
+ : ro_bo(batch->screen->workaround_bo, 0);
+ n--;
+ }
}
}
}
- // Surfaces:
- // - pull constants
- // - ubos/ssbos/abos
- // - images
- // - textures
- // - render targets - write and read
- // XXX: 3DSTATE_BINDING_TABLE_POINTERS_XS
+ struct iris_binder *binder = &batch->binder;
for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) {
- struct iris_compiled_shader *shader = ice->shaders.prog[stage];
- if (!shader) // XXX: dirty bits...also, emit a disable maybe?
- continue;
-
- struct brw_stage_prog_data *prog_data = (void *) shader->prog_data;
- uint32_t bt_offset = 0;
- uint32_t *bt_map = NULL;
- int s = 0;
-
- if (prog_data->binding_table.size_bytes != 0) {
- iris_use_pinned_bo(batch, ice->state.binder.bo, false);
- bt_map = iris_binder_reserve(&ice->state.binder,
- prog_data->binding_table.size_bytes,
- &bt_offset);
- }
-
- iris_emit_cmd(batch, GENX(3DSTATE_BINDING_TABLE_POINTERS_VS), ptr) {
- ptr._3DCommandSubOpcode = 38 + stage;
- ptr.PointertoVSBindingTable = bt_offset;
- }
-
- if (stage == MESA_SHADER_FRAGMENT) {
- struct pipe_framebuffer_state *cso_fb = &ice->state.framebuffer;
- for (unsigned i = 0; i < cso_fb->nr_cbufs; i++) {
- bt_map[s++] = use_surface(batch, cso_fb->cbufs[i], true);
+ if (dirty & (IRIS_DIRTY_BINDINGS_VS << stage)) {
+ iris_emit_cmd(batch, GENX(3DSTATE_BINDING_TABLE_POINTERS_VS), ptr) {
+ ptr._3DCommandSubOpcode = 38 + stage;
+ ptr.PointertoVSBindingTable = binder->bt_offset[stage];
}
}
+ }
- assert(prog_data->binding_table.texture_start ==
- (ice->state.num_textures[stage] ? s : 0xd0d0d0d0));
-
- for (int i = 0; i < ice->state.num_textures[stage]; i++) {
- struct iris_sampler_view *view = ice->state.textures[stage][i];
- bt_map[s++] = use_sampler_view(batch, view);
+ for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) {
+ if (dirty & (IRIS_DIRTY_BINDINGS_VS << stage)) {
+ iris_populate_binding_table(ice, batch, stage);
}
-
-#if 0
- // XXX: not implemented yet
- assert(prog_data->binding_table.pull_constants_start == 0xd0d0d0d0);
- assert(prog_data->binding_table.ubo_start == 0xd0d0d0d0);
- assert(prog_data->binding_table.ssbo_start == 0xd0d0d0d0);
- assert(prog_data->binding_table.image_start == 0xd0d0d0d0);
- assert(prog_data->binding_table.shader_time_start == 0xd0d0d0d0);
- //assert(prog_data->binding_table.plane_start[1] == 0xd0d0d0d0);
- //assert(prog_data->binding_table.plane_start[2] == 0xd0d0d0d0);
-#endif
}
+ if (ice->state.need_border_colors)
+ iris_use_pinned_bo(batch, ice->state.border_color_pool.bo, false);
+
for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) {
if (!(dirty & (IRIS_DIRTY_SAMPLER_STATES_VS << stage)) ||
!ice->shaders.prog[stage])
continue;
+ struct pipe_resource *res = ice->state.sampler_table[stage].res;
+ if (res)
+ iris_use_pinned_bo(batch, iris_resource_bo(res), false);
+
iris_emit_cmd(batch, GENX(3DSTATE_SAMPLER_STATE_POINTERS_VS), ptr) {
ptr._3DCommandSubOpcode = 43 + stage;
- ptr.PointertoVSSamplerState = ice->state.sampler_table_offset[stage];
+ ptr.PointertoVSSamplerState = ice->state.sampler_table[stage].offset;
}
}
struct iris_compiled_shader *shader = ice->shaders.prog[stage];
if (shader) {
- struct iris_resource *cache = (void *) shader->buffer;
+ struct iris_resource *cache = (void *) shader->assembly.res;
iris_use_pinned_bo(batch, cache->bo, false);
iris_batch_emit(batch, shader->derived_data,
iris_derived_program_state_size(stage));
cl.NonPerspectiveBarycentricEnable = true;
cl.ForceZeroRTAIndexEnable = cso_fb->layers == 0;
+ cl.MaximumVPIndex = ice->state.num_viewports - 1;
}
iris_emit_merge(batch, cso_rast->clip, dynamic_clip,
ARRAY_SIZE(cso_rast->clip));
}
- if (dirty & (IRIS_DIRTY_RASTER | IRIS_DIRTY_FS)) {
+ /* XXX: FS program updates needs to flag IRIS_DIRTY_WM */
+ if (dirty & IRIS_DIRTY_WM) {
struct iris_rasterizer_state *cso = ice->state.cso_rast;
uint32_t dynamic_wm[GENX(3DSTATE_WM_length)];
// -> iris_raster_state (point sprite texture coordinate origin)
// -> bunch of shader state...
iris_emit_sbe(batch, ice);
- iris_emit_cmd(batch, GENX(3DSTATE_SBE_SWIZ), sbe) {
- }
}
if (dirty & IRIS_DIRTY_PS_BLEND) {
iris_emit_merge(batch, cso->wmds, stencil_refs, ARRAY_SIZE(cso->wmds));
}
- if (dirty & IRIS_DIRTY_SCISSOR) {
- // XXX: allocate at set_scissor time?
- uint32_t scissor_offset = ice->state.num_scissors == 0 ? 0 :
- emit_state(batch, ice->state.dynamic_uploader, ice->state.scissors,
+ if (dirty & IRIS_DIRTY_SCISSOR_RECT) {
+ uint32_t scissor_offset =
+ emit_state(batch, ice->state.dynamic_uploader,
+ &ice->state.last_res.scissor,
+ ice->state.scissors,
sizeof(struct pipe_scissor_state) *
- ice->state.num_scissors, 32);
+ ice->state.num_viewports, 32);
iris_emit_cmd(batch, GENX(3DSTATE_SCISSOR_STATE_POINTERS), ptr) {
ptr.ScissorRectPointer = scissor_offset;
}
}
- // XXX: 3DSTATE_DEPTH_BUFFER
- // XXX: 3DSTATE_HIER_DEPTH_BUFFER
- // XXX: 3DSTATE_STENCIL_BUFFER
- // XXX: 3DSTATE_CLEAR_PARAMS
+ if (dirty & IRIS_DIRTY_DEPTH_BUFFER) {
+ struct pipe_framebuffer_state *cso_fb = &ice->state.framebuffer;
+ struct iris_depth_buffer_state *cso_z = &ice->state.genx->depth_buffer;
+
+ iris_batch_emit(batch, cso_z->packets, sizeof(cso_z->packets));
+
+ if (cso_fb->zsbuf) {
+ struct iris_resource *zres = (void *) cso_fb->zsbuf->texture;
+ // XXX: depth might not be writable...
+ iris_use_pinned_bo(batch, zres->bo, true);
+ }
+ }
if (dirty & IRIS_DIRTY_POLYGON_STIPPLE) {
iris_emit_cmd(batch, GENX(3DSTATE_POLY_STIPPLE_PATTERN), poly) {
}
if (draw->index_size > 0) {
- struct iris_resource *res = (struct iris_resource *)draw->index.resource;
+ struct iris_resource *res = NULL;
+ unsigned offset;
- assert(!draw->has_user_indices);
+ if (draw->has_user_indices) {
+ u_upload_data(ice->ctx.stream_uploader, 0,
+ draw->count * draw->index_size, 4, draw->index.user,
+ &offset, (struct pipe_resource **) &res);
+ } else {
+ res = (struct iris_resource *) draw->index.resource;
+ offset = 0;
+ }
iris_emit_cmd(batch, GENX(3DSTATE_INDEX_BUFFER), ib) {
- ib.IndexFormat = draw->index_size;
+ ib.IndexFormat = draw->index_size >> 1;
ib.MOCS = MOCS_WB;
ib.BufferSize = res->bo->size;
- ib.BufferStartingAddress = ro_bo(res->bo, 0);
+ ib.BufferStartingAddress = ro_bo(res->bo, offset);
}
}
if (dirty & IRIS_DIRTY_VERTEX_BUFFERS) {
- struct iris_vertex_buffer_state *cso = ice->state.cso_vertex_buffers;
-
- STATIC_ASSERT(GENX(VERTEX_BUFFER_STATE_length) == 4);
- STATIC_ASSERT((GENX(VERTEX_BUFFER_STATE_BufferStartingAddress_bits) % 32) == 0);
+ struct iris_vertex_buffer_state *cso = &ice->state.genx->vertex_buffers;
+ const unsigned vb_dwords = GENX(VERTEX_BUFFER_STATE_length);
- iris_batch_emit(batch, cso->vertex_buffers,
- sizeof(uint32_t) * (1 + 4 * cso->num_buffers));
+ if (cso->num_buffers > 0) {
+ iris_batch_emit(batch, cso->vertex_buffers, sizeof(uint32_t) *
+ (1 + vb_dwords * cso->num_buffers));
- for (unsigned i = 0; i < cso->num_buffers; i++) {
- iris_use_pinned_bo(batch, cso->bos[i], false);
+ for (unsigned i = 0; i < cso->num_buffers; i++) {
+ struct iris_resource *res = (void *) cso->resources[i];
+ iris_use_pinned_bo(batch, res->bo, false);
+ }
}
}
struct iris_vertex_element_state *cso = ice->state.cso_vertex_elements;
iris_batch_emit(batch, cso->vertex_elements, sizeof(uint32_t) *
(1 + cso->count * GENX(VERTEX_ELEMENT_STATE_length)));
- for (int i = 0; i < cso->count; i++) {
- iris_batch_emit(batch, cso->vf_instancing[i], sizeof(uint32_t) *
- (cso->count * GENX(3DSTATE_VF_INSTANCING_length)));
- }
+ iris_batch_emit(batch, cso->vf_instancing, sizeof(uint32_t) *
+ cso->count * GENX(3DSTATE_VF_INSTANCING_length));
for (int i = 0; i < cso->count; i++) {
/* TODO: vertexid, instanceid support */
iris_emit_cmd(batch, GENX(3DSTATE_VF_SGVS), sgvs);
//prim.BaseVertexLocation = ...;
}
+
+ if (!batch->contains_draw) {
+ iris_restore_context_saved_bos(ice, batch, draw);
+ batch->contains_draw = true;
+ }
}
+/**
+ * State module teardown.
+ */
static void
iris_destroy_state(struct iris_context *ice)
{
+ iris_free_vertex_buffers(&ice->state.genx->vertex_buffers);
+
// XXX: unreference resources/surfaces.
for (unsigned i = 0; i < ice->state.framebuffer.nr_cbufs; i++) {
pipe_surface_reference(&ice->state.framebuffer.cbufs[i], NULL);
}
pipe_surface_reference(&ice->state.framebuffer.zsbuf, NULL);
+
+ for (int stage = 0; stage < MESA_SHADER_STAGES; stage++) {
+ pipe_resource_reference(&ice->state.sampler_table[stage].res, NULL);
+ }
+ free(ice->state.genx);
+
+ pipe_resource_reference(&ice->state.last_res.cc_vp, NULL);
+ pipe_resource_reference(&ice->state.last_res.sf_cl_vp, NULL);
+ pipe_resource_reference(&ice->state.last_res.color_calc, NULL);
+ pipe_resource_reference(&ice->state.last_res.scissor, NULL);
+ pipe_resource_reference(&ice->state.last_res.blend, NULL);
}
static unsigned
genX(init_state)(struct iris_context *ice)
{
struct pipe_context *ctx = &ice->ctx;
+ struct iris_screen *screen = (struct iris_screen *)ctx->screen;
ctx->create_blend_state = iris_create_blend_state;
ctx->create_depth_stencil_alpha_state = iris_create_zsa_state;
ice->vtbl.upload_render_state = iris_upload_render_state;
ice->vtbl.emit_raw_pipe_control = iris_emit_raw_pipe_control;
ice->vtbl.derived_program_state_size = iris_derived_program_state_size;
- ice->vtbl.set_derived_program_state = iris_set_derived_program_state;
+ ice->vtbl.store_derived_program_state = iris_store_derived_program_state;
ice->vtbl.populate_vs_key = iris_populate_vs_key;
ice->vtbl.populate_tcs_key = iris_populate_tcs_key;
ice->vtbl.populate_tes_key = iris_populate_tes_key;
ice->vtbl.populate_fs_key = iris_populate_fs_key;
ice->state.dirty = ~0ull;
+
+ ice->state.num_viewports = 1;
+ ice->state.genx = calloc(1, sizeof(struct iris_genx_state));
+
+ /* Make a 1x1x1 null surface for unbound textures */
+ void *null_surf_map =
+ upload_state(ice->state.surface_uploader, &ice->state.unbound_tex,
+ 4 * GENX(RENDER_SURFACE_STATE_length), 64);
+ isl_null_fill_state(&screen->isl_dev, null_surf_map, isl_extent3d(1, 1, 1));
}