* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
*
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
*
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*/
+
+/**
+ * @file iris_draw.c
+ *
+ * The main driver hooks for drawing and launching compute shaders.
+ */
+
#include <stdio.h>
#include <errno.h>
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "util/u_inlines.h"
#include "util/u_transfer.h"
+#include "util/u_upload_mgr.h"
#include "intel/compiler/brw_compiler.h"
#include "iris_context.h"
+#include "iris_defines.h"
-#define __gen_address_type unsigned
-#define __gen_user_data void
-
-static uint64_t
-__gen_combine_address(void *user_data, void *location,
- unsigned address, uint32_t delta)
+/**
+ * Record the current primitive mode and restart information, flagging
+ * related packets as dirty if necessary.
+ */
+static void
+iris_update_draw_info(struct iris_context *ice,
+ const struct pipe_draw_info *info)
{
- return delta;
+ if (ice->state.prim_mode != info->mode) {
+ ice->state.prim_mode = info->mode;
+ ice->state.dirty |= IRIS_DIRTY_VF_TOPOLOGY;
+ }
+
+ if (info->mode == PIPE_PRIM_PATCHES &&
+ ice->state.vertices_per_patch != info->vertices_per_patch) {
+ ice->state.vertices_per_patch = info->vertices_per_patch;
+ ice->state.dirty |= IRIS_DIRTY_VF_TOPOLOGY;
+
+ /* Flag constants dirty for gl_PatchVerticesIn if needed. */
+ const struct shader_info *tcs_info =
+ iris_get_shader_info(ice, MESA_SHADER_TESS_CTRL);
+ if (tcs_info &&
+ tcs_info->system_values_read & (1ull << SYSTEM_VALUE_VERTICES_IN)) {
+ ice->state.dirty |= IRIS_DIRTY_CONSTANTS_TCS;
+ ice->state.shaders[MESA_SHADER_TESS_CTRL].cbuf0_needs_upload = true;
+ }
+ }
+
+ if (ice->state.primitive_restart != info->primitive_restart ||
+ ice->state.cut_index != info->restart_index) {
+ ice->state.dirty |= IRIS_DIRTY_VF;
+ ice->state.primitive_restart = info->primitive_restart;
+ ice->state.cut_index = info->restart_index;
+ }
+
+ if (info->indirect) {
+ pipe_resource_reference(&ice->draw.draw_params_res,
+ info->indirect->buffer);
+ ice->draw.draw_params_offset = info->indirect->offset +
+ (info->index_size ? 12 : 8);
+ ice->draw.params.firstvertex = 0;
+ ice->draw.params.baseinstance = 0;
+ ice->state.dirty |= IRIS_DIRTY_VERTEX_BUFFERS |
+ IRIS_DIRTY_VERTEX_ELEMENTS |
+ IRIS_DIRTY_VF_SGVS;
+ } else if (ice->draw.is_indirect ||
+ ice->draw.params.firstvertex !=
+ (info->index_size ? info->index_bias : info->start) ||
+ (ice->draw.params.baseinstance != info->start_instance)) {
+ pipe_resource_reference(&ice->draw.draw_params_res, NULL);
+ ice->draw.draw_params_offset = 0;
+ ice->draw.params.firstvertex =
+ info->index_size ? info->index_bias : info->start;
+ ice->draw.params.baseinstance = info->start_instance;
+ ice->state.dirty |= IRIS_DIRTY_VERTEX_BUFFERS |
+ IRIS_DIRTY_VERTEX_ELEMENTS |
+ IRIS_DIRTY_VF_SGVS;
+ }
+ ice->draw.is_indirect = info->indirect;
+
+ if (ice->draw.derived_params.drawid != info->drawid ||
+ ice->draw.derived_params.is_indexed_draw != (info->index_size ? ~0 : 0)) {
+ ice->draw.derived_params.drawid = info->drawid;
+ ice->draw.derived_params.is_indexed_draw = info->index_size ? ~0 : 0;
+ ice->state.dirty |= IRIS_DIRTY_VERTEX_BUFFERS |
+ IRIS_DIRTY_VERTEX_ELEMENTS |
+ IRIS_DIRTY_VF_SGVS;
+ }
}
-#define __genxml_cmd_length(cmd) cmd ## _length
-#define __genxml_cmd_length_bias(cmd) cmd ## _length_bias
-#define __genxml_cmd_header(cmd) cmd ## _header
-#define __genxml_cmd_pack(cmd) cmd ## _pack
+/**
+ * The pipe->draw_vbo() driver hook. Performs a draw on the GPU.
+ */
+void
+iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
+{
+ struct iris_context *ice = (struct iris_context *) ctx;
+ struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
+
+ if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
+ return;
+
+ /* We can't safely re-emit 3DSTATE_SO_BUFFERS because it may zero the
+ * write offsets, changing the behavior.
+ */
+ if (unlikely(INTEL_DEBUG & DEBUG_REEMIT))
+ ice->state.dirty |= IRIS_ALL_DIRTY_FOR_RENDER & ~IRIS_DIRTY_SO_BUFFERS;
+
+ iris_batch_maybe_flush(batch, 1500);
+
+ iris_update_draw_info(ice, info);
+
+ iris_update_compiled_shaders(ice);
+
+ if (ice->state.dirty & IRIS_DIRTY_RENDER_RESOLVES_AND_FLUSHES) {
+ bool draw_aux_buffer_disabled[BRW_MAX_DRAW_BUFFERS] = { };
+ for (gl_shader_stage stage = 0; stage < MESA_SHADER_COMPUTE; stage++) {
+ if (ice->shaders.prog[stage])
+ iris_predraw_resolve_inputs(ice, batch, draw_aux_buffer_disabled,
+ stage, true);
+ }
+ iris_predraw_resolve_framebuffer(ice, batch, draw_aux_buffer_disabled);
+ }
-#define iris_pack_command(cmd, dst, name) \
- for (struct cmd name = { __genxml_cmd_header(cmd) }, \
- *_dst = (void *)(dst); __builtin_expect(_dst != NULL, 1); \
- __genxml_cmd_pack(cmd)(NULL, (void *)dst, &name), \
- _dst = NULL)
+ iris_binder_reserve_3d(ice);
-#define iris_pack_state(cmd, dst, name) \
- for (struct cmd name = {}, \
- *_dst = (void *)(dst); __builtin_expect(_dst != NULL, 1); \
- __genxml_cmd_pack(cmd)(NULL, (void *)_dst, &name), \
- _dst = NULL)
+ ice->vtbl.update_surface_base_address(batch, &ice->state.binder);
+ ice->vtbl.upload_render_state(ice, batch, info);
-#include "genxml/genX_pack.h"
-#include "genxml/gen_macros.h"
+ iris_postdraw_update_resolve_tracking(ice, batch);
+
+ ice->state.dirty &= ~IRIS_ALL_DIRTY_FOR_RENDER;
+}
static void
-iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
+iris_update_grid_size_resource(struct iris_context *ice,
+ const struct pipe_grid_info *grid)
+{
+ const struct iris_screen *screen = (void *) ice->ctx.screen;
+ const struct isl_device *isl_dev = &screen->isl_dev;
+ struct iris_state_ref *grid_ref = &ice->state.grid_size;
+ struct iris_state_ref *state_ref = &ice->state.grid_surf_state;
+
+ // XXX: if the shader doesn't actually care about the grid info,
+ // don't bother uploading the surface?
+
+ if (grid->indirect) {
+ pipe_resource_reference(&grid_ref->res, grid->indirect);
+ grid_ref->offset = grid->indirect_offset;
+
+ /* Zero out the grid size so that the next non-indirect grid launch will
+ * re-upload it properly.
+ */
+ memset(ice->state.last_grid, 0, sizeof(ice->state.last_grid));
+ } else {
+ /* If the size is the same, we don't need to upload anything. */
+ if (memcmp(ice->state.last_grid, grid->grid, sizeof(grid->grid)) == 0)
+ return;
+
+ memcpy(ice->state.last_grid, grid->grid, sizeof(grid->grid));
+
+ u_upload_data(ice->state.dynamic_uploader, 0, sizeof(grid->grid), 4,
+ grid->grid, &grid_ref->offset, &grid_ref->res);
+ }
+
+ void *surf_map = NULL;
+ u_upload_alloc(ice->state.surface_uploader, 0, isl_dev->ss.size,
+ isl_dev->ss.align, &state_ref->offset, &state_ref->res,
+ &surf_map);
+ state_ref->offset +=
+ iris_bo_offset_from_base_address(iris_resource_bo(state_ref->res));
+ isl_buffer_fill_state(&screen->isl_dev, surf_map,
+ .address = grid_ref->offset +
+ iris_resource_bo(grid_ref->res)->gtt_offset,
+ .size_B = sizeof(grid->grid),
+ .format = ISL_FORMAT_RAW,
+ .stride_B = 1,
+ .mocs = 4); // XXX: MOCS
+
+ ice->state.dirty |= IRIS_DIRTY_BINDINGS_CS;
+}
+
+void
+iris_launch_grid(struct pipe_context *ctx, const struct pipe_grid_info *grid)
{
struct iris_context *ice = (struct iris_context *) ctx;
+ struct iris_batch *batch = &ice->batches[IRIS_BATCH_COMPUTE];
+
+ if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
+ return;
+
+ if (unlikely(INTEL_DEBUG & DEBUG_REEMIT))
+ ice->state.dirty |= IRIS_ALL_DIRTY_FOR_COMPUTE;
+
+ /* We can't do resolves on the compute engine, so awkwardly, we have to
+ * do them on the render batch...
+ */
+ if (ice->state.dirty & IRIS_DIRTY_COMPUTE_RESOLVES_AND_FLUSHES) {
+ iris_predraw_resolve_inputs(ice, &ice->batches[IRIS_BATCH_RENDER], NULL,
+ MESA_SHADER_COMPUTE, false);
+ }
+
+ iris_batch_maybe_flush(batch, 1500);
+
+ //if (dirty & IRIS_DIRTY_UNCOMPILED_CS)
+ iris_update_compiled_compute_shader(ice);
+
+ iris_update_grid_size_resource(ice, grid);
+
+ iris_binder_reserve_compute(ice);
+ ice->vtbl.update_surface_base_address(batch, &ice->state.binder);
+
+ if (ice->state.compute_predicate) {
+ ice->vtbl.load_register_mem64(batch, MI_PREDICATE_RESULT,
+ ice->state.compute_predicate, 0);
+ ice->state.compute_predicate = NULL;
+ }
+
+ ice->vtbl.upload_compute_state(ice, batch, grid);
+
+ ice->state.dirty &= ~IRIS_ALL_DIRTY_FOR_COMPUTE;
- iris_upload_render_state(ice, draw);
-
-#if 0
- l3 configuration
-
- 3DSTATE_VIEWPORT_STATE_POINTERS_CC - CC_VIEWPORT
- -> from iris_depth_stencil_alpha_state
-
- 3DSTATE_VIEWPORT_STATE_POINTERS_SF_CL - SF_CLIP_VIEWPORT
- -> pipe_viewport_state for matrix elements, guardband is calculated
- from those. can calculate screen space from matrix apparently...
-
- 3DSTATE_SCISSOR_STATE_POINTERS - SCISSOR_RECT
- -> from ice->state.scissors
-
- 3DSTATE_PUSH_CONSTANT_ALLOC_*
- 3DSTATE_URB_*
- -> TODO
-
- 3DSTATE_PS_BLEND
- 3DSTATE_BLEND_STATE_POINTERS - BLEND_STATE
- -> from iris_blend_state (most) + iris_depth_stencil_alpha_state
- (alpha test function/enable) + has writeable RT from ???????
-
- 3DSTATE_CC_STATE_POINTERS - COLOR_CALC_STATE
- -> from ice->state.blend_color + iris_depth_stencil_alpha_state
- (ref_value)
-
- 3DSTATE_CONSTANT_* - push constants
- -> TODO
-
- Surfaces:
- - pull constants
- - ubos/ssbos/abos
- - images
- - textures
- - render targets - write and read
- 3DSTATE_BINDING_TABLE_POINTERS_*
- -> TODO
-
- 3DSTATE_SAMPLER_STATE_POINTERS_*
- -> TODO
-
- 3DSTATE_MULTISAMPLE
- 3DSTATE_SAMPLE_MASK
-
- 3DSTATE_VS
- 3DSTATE_HS
- 3DSTATE_TE
- 3DSTATE_DS
- 3DSTATE_GS
- 3DSTATE_PS_EXTRA
- 3DSTATE_PS
- 3DSTATE_STREAMOUT
- 3DSTATE_SO_BUFFER
- 3DSTATE_SO_DECL_LIST
-
- 3DSTATE_CLIP
- -> iris_raster_state + ??? (Non-perspective Bary, ForceZeroRTAIndex)
-
- 3DSTATE_RASTER
- 3DSTATE_SF
- -> iris_raster_state
-
- 3DSTATE_WM
- -> iris_raster_state + FS state (barycentric, EDSC)
- 3DSTATE_SBE
- -> iris_raster_state (point sprite texture coordinate origin)
- -> bunch of shader state...
- 3DSTATE_SBE_SWIZ
- -> FS state
-
- 3DSTATE_DEPTH_BUFFER
- 3DSTATE_HIER_DEPTH_BUFFER
- 3DSTATE_STENCIL_BUFFER
- 3DSTATE_CLEAR_PARAMS
- -> iris_framebuffer_state?
-
- 3DSTATE_VF_TOPOLOGY
- -> pipe_draw_info (prim_mode)
- 3DSTATE_VF
- -> pipe_draw_info (restart_index, primitive_restart)
-
- 3DSTATE_INDEX_BUFFER
- -> pipe_draw_info (index)
- 3DSTATE_VERTEX_BUFFERS
- -> pipe_vertex_buffer (set_vertex_buffer hook)
- 3DSTATE_VERTEX_ELEMENTS
- -> iris_vertex_element
- 3DSTATE_VF_INSTANCING
- -> iris_vertex_element
- 3DSTATE_VF_SGVS
- -> TODO ???
- 3DSTATE_VF_COMPONENT_PACKING
- -> TODO ???
-
- 3DPRIMITIVE
- -> pipe_draw_info
-
- rare:
- 3DSTATE_POLY_STIPPLE_OFFSET
- 3DSTATE_POLY_STIPPLE_PATTERN
- -> ice->state.poly_stipple
- 3DSTATE_LINE_STIPPLE
- -> iris_raster_state
-
- once:
- 3DSTATE_AA_LINE_PARAMETERS
- 3DSTATE_WM_CHROMAKEY
- 3DSTATE_SAMPLE_PATTERN
- 3DSTATE_DRAWING_RECTANGLE
- 3DSTATE_WM_HZ_OP
-#endif
+ /* Note: since compute shaders can't access the framebuffer, there's
+ * no need to call iris_postdraw_update_resolve_tracking.
+ */
}