iris: comment everything

1. Write the code
2. Add comments
3. PROFIT (or just avoid cost of explaining or relearning things...)
This commit is contained in:
Kenneth Graunke
2018-07-30 23:49:34 -07:00
parent 387a414f2c
commit dfe1ee4f6f
20 changed files with 911 additions and 118 deletions

View File

@@ -22,6 +22,23 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file iris_batch.c
*
* Batchbuffer and command submission module.
*
* Every API draw call results in a number of GPU commands, which we
* collect into a "batch buffer". Typically, many draw calls are grouped
* into a single batch to amortize command submission overhead.
*
* We submit batches to the kernel using the I915_GEM_EXECBUFFER2 ioctl.
* One critical piece of data is the "validation list", which contains a
* list of the buffer objects (BOs) which the commands in the GPU need.
* The kernel will make sure these are resident and pinned at the correct
* virtual memory address before executing our batch. If a BO is not in
* the validation list, it effectively does not exist, so take care.
*/
#include "iris_batch.h"
#include "iris_binder.h"
#include "iris_bufmgr.h"
@@ -46,12 +63,13 @@
*/
#define BATCH_RESERVED 16
static void decode_batch(struct iris_batch *batch);
static void
iris_batch_reset(struct iris_batch *batch);
UNUSED static void
/**
* Debugging code to dump the validation list, used by INTEL_DEBUG=submit.
*/
static void
dump_validation_list(struct iris_batch *batch)
{
fprintf(stderr, "Validation list (length %d):\n", batch->exec_count);
@@ -72,6 +90,9 @@ dump_validation_list(struct iris_batch *batch)
}
}
/**
* Return BO information to the batch decoder (for debugging).
*/
static struct gen_batch_decode_bo
decode_get_bo(void *v_batch, uint64_t address)
{
@@ -95,6 +116,17 @@ decode_get_bo(void *v_batch, uint64_t address)
return (struct gen_batch_decode_bo) { };
}
/**
* Decode the current batch.
*/
static void
decode_batch(struct iris_batch *batch)
{
void *map = iris_bo_map(batch->dbg, batch->exec_bos[0], MAP_READ);
gen_print_batch(&batch->decoder, map, batch->primary_batch_size,
batch->exec_bos[0]->gtt_offset);
}
static bool
uint_key_compare(const void *a, const void *b)
{
@@ -280,6 +312,13 @@ iris_batch_maybe_flush(struct iris_batch *batch, unsigned estimate)
}
}
/**
* Ensure the current command buffer has \param size bytes of space
* remaining. If not, this creates a secondary batch buffer and emits
* a jump from the primary batch to the start of the secondary.
*
* Most callers want iris_get_command_space() instead.
*/
void
iris_require_command_space(struct iris_batch *batch, unsigned size)
{
@@ -306,6 +345,12 @@ iris_require_command_space(struct iris_batch *batch, unsigned size)
}
}
/**
* Allocate space in the current command buffer, and return a pointer
* to the mapped area so the caller can write commands there.
*
* This should be called whenever emitting commands.
*/
void *
iris_get_command_space(struct iris_batch *batch, unsigned bytes)
{
@@ -315,6 +360,9 @@ iris_get_command_space(struct iris_batch *batch, unsigned bytes)
return map;
}
/**
* Helper to emit GPU commands - allocates space, copies them there.
*/
void
iris_batch_emit(struct iris_batch *batch, const void *data, unsigned size)
{
@@ -346,6 +394,9 @@ iris_finish_batch(struct iris_batch *batch)
batch->primary_batch_size = batch_bytes_used(batch);
}
/**
* Submit the batch to the GPU via execbuffer2.
*/
static int
submit_batch(struct iris_batch *batch, int in_fence_fd, int *out_fence_fd)
{
@@ -410,11 +461,14 @@ submit_batch(struct iris_batch *batch, int in_fence_fd, int *out_fence_fd)
}
/**
* The in_fence_fd is ignored if -1. Otherwise this function takes ownership
* of the fd.
* Flush the batch buffer, submitting it to the GPU and resetting it so
* we're ready to emit the next batch.
*
* The out_fence_fd is ignored if NULL. Otherwise, the caller takes ownership
* of the returned fd.
* \param in_fence_fd is ignored if -1. Otherwise, this function takes
* ownership of the fd.
*
* \param out_fence_fd is ignored if NULL. Otherwise, the caller must
* take ownership of the returned fd.
*/
int
_iris_batch_flush_fence(struct iris_batch *batch,
@@ -484,6 +538,11 @@ _iris_batch_flush_fence(struct iris_batch *batch,
return 0;
}
/**
* Does the current batch refer to the given BO?
*
* (In other words, is the BO in the current batch's validation list?)
*/
bool
iris_batch_references(struct iris_batch *batch, struct iris_bo *bo)
{
@@ -498,7 +557,11 @@ iris_batch_references(struct iris_batch *batch, struct iris_bo *bo)
return false;
}
/* This is the only way buffers get added to the validate list.
/**
* Add a buffer to the current batch's validation list.
*
* You must call this on any BO you wish to use in this batch, to ensure
* that it's resident when the GPU commands execute.
*/
void
iris_use_pinned_bo(struct iris_batch *batch,
@@ -510,18 +573,3 @@ iris_use_pinned_bo(struct iris_batch *batch,
if (writable)
batch->validation_list[index].flags |= EXEC_OBJECT_WRITE;
}
static void
decode_batch(struct iris_batch *batch)
{
//if (batch->bo != batch->exec_bos[0]) {
void *map = iris_bo_map(batch->dbg, batch->exec_bos[0], MAP_READ);
gen_print_batch(&batch->decoder, map, batch->primary_batch_size,
batch->exec_bos[0]->gtt_offset);
//fprintf(stderr, "Secondary batch...\n");
//}
//gen_print_batch(&batch->decoder, batch->map, batch_bytes_used(batch),
//batch->bo->gtt_offset);
}

View File

@@ -21,6 +21,37 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file iris_binder.c
*
* Shader programs refer to most resources via integer handles. These are
* indexes (BTIs) into a "Binding Table", which is simply a list of pointers
* to SURFACE_STATE entries. Each shader stage has its own binding table,
* set by the 3DSTATE_BINDING_TABLE_POINTERS_* commands. Both the binding
* table itself and the SURFACE_STATEs are relative to Surface State Base
* Address, so they all live in IRIS_MEMZONE_SURFACE.
*
* Unfortunately, the hardware designers made 3DSTATE_BINDING_TABLE_POINTERS
* only accept a 16-bit pointer. This means that all binding tables have to
* live within the 64kB range starting at Surface State Base Address. (The
* actual SURFACE_STATE entries can live anywhere in the 4GB zone, as the
* binding table entries are full 32-bit pointers.)
*
* We stream out binding tables dynamically, storing them in a single 64kB
* "binder" buffer, located at IRIS_BINDER_ADDRESS. Before emitting a draw
* call, we reserve space for any new binding tables needed by bound shaders.
* If there is no space, we flush the batch and swap out the binder for a
* new empty BO.
*
* XXX: This should be fancier. We currently replace the binder with a
* fresh BO on every batch, which causes the kernel to stall, trying to
* pin the new buffer at the same memory address as the old one. We ought
* to avoid this by using a ringbuffer, tracking the busy section of the BO,
* and cycling back around where possible to avoid replacing it at all costs.
*
* XXX: if we do have to flush, we should emit a performance warning.
*/
#include <stdlib.h>
#include "util/u_math.h"
#include "iris_binder.h"
@@ -28,7 +59,7 @@
#include "iris_context.h"
/**
* Reserve a block of space in the binder.
* Reserve a block of space in the binder, given the raw size in bytes.
*/
uint32_t
iris_binder_reserve(struct iris_batch *batch, unsigned size)
@@ -58,6 +89,9 @@ iris_binder_reserve(struct iris_batch *batch, unsigned size)
/**
* Reserve and record binder space for 3D pipeline shader stages.
*
* Note that you must actually populate the new binding tables after
* calling this command - the new area is uninitialized.
*/
void
iris_binder_reserve_3d(struct iris_batch *batch,
@@ -109,6 +143,9 @@ iris_init_binder(struct iris_binder *binder, struct iris_bufmgr *bufmgr)
binder->insert_point = INIT_INSERT_POINT;
}
/**
* Is the binder empty? (If so, old binding table pointers are stale.)
*/
bool
iris_binder_is_empty(struct iris_binder *binder)
{

View File

@@ -68,6 +68,12 @@ iris_get_blorp_format(enum pipe_format pf)
}
}
/**
* The pipe->blit() driver hook.
*
* This performs a blit between two surfaces, which copies data but may
* also perform format conversion, scaling, flipping, and so on.
*/
static void
iris_blit(struct pipe_context *ctx, const struct pipe_blit_info *info)
{
@@ -161,6 +167,12 @@ iris_blit(struct pipe_context *ctx, const struct pipe_blit_info *info)
blorp_batch_finish(&blorp_batch);
}
/**
* The pipe->resource_copy_region() driver hook.
*
* This implements ARB_copy_image semantics - a raw memory copy between
* compatible view classes.
*/
static void
iris_resource_copy_region(struct pipe_context *ctx,
struct pipe_resource *dst,

View File

@@ -20,6 +20,21 @@
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file iris_blorp.c
*
* ============================= GENXML CODE =============================
* [This file is compiled once per generation.]
* =======================================================================
*
* GenX specific code for working with BLORP (blitting, resolves, clears
* on the 3D engine). This provides the driver-specific hooks needed to
* implement the BLORP API.
*
* See iris_blit.c, iris_clear.c, and so on.
*/
#include <assert.h>
#include "iris_batch.h"

View File

@@ -21,6 +21,28 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file iris_border_color.c
*
* Each SAMPLER_STATE points to a SAMPLER_BORDER_COLOR_STATE entry,
* describing the color to return when sampling outside the texture
* when using CLAMP_TO_BORDER wrap modes.
*
* These must be stored relative to Dynamic State Base Address.
* Unfortunately, the hardware designers only gave us a 24-bit pointer
* rather than an actual graphics address, so it must be stored in the
* bottom 16MB of that memory zone. This means we can't simply use
* u_upload_mgr like we do for most state.
*
* To work around this, we maintain a single "border color pool" BO
* which we pin at the base of IRIS_MEMZONE_DYNAMIC. Since most border
* colors are the same (typically black or white), we maintain a hash
* table of known colors, and reuse the same entries. This avoids
* wasting a lot of space in the pool.
*
* If it ever does fill up, we simply flush.
*/
#include <stdlib.h>
#include "util/u_math.h"
#include "iris_binder.h"
@@ -84,6 +106,7 @@ iris_border_color_pool_reserve(struct iris_context *ice, unsigned count)
(IRIS_BORDER_COLOR_POOL_SIZE - pool->insert_point) / BC_ALIGNMENT;
if (remaining_entries < count) {
/* It's safe to flush because we're called outside of state upload. */
if (iris_batch_references(&ice->render_batch, pool->bo))
iris_batch_flush(&ice->render_batch);
@@ -94,7 +117,8 @@ iris_border_color_pool_reserve(struct iris_context *ice, unsigned count)
/**
* Upload a border color (or use a cached version).
*
* Returns the offset into the border color pool BO.
* Returns the offset into the border color pool BO. Note that you must
* reserve space ahead of time by calling iris_border_color_pool_reserve().
*/
uint32_t
iris_upload_border_color(struct iris_context *ice,

View File

@@ -21,6 +21,17 @@
* IN THE SOFTWARE.
*/
/**
* @file iris_bufmgr.c
*
* The Iris buffer manager.
*
* XXX: write better comments
* - BOs
* - Explain BO cache
* - main interface to GEM in the kernel
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -380,7 +391,7 @@ __vma_alloc(struct iris_bufmgr *bufmgr,
addr = util_vma_heap_alloc(&bufmgr->vma_allocator[memzone], size,
alignment);
}
assert((addr >> 48ull) == 0);
assert((addr % alignment) == 0);
return addr;

View File

@@ -35,6 +35,11 @@
#include "iris_screen.h"
#include "intel/compiler/brw_compiler.h"
/**
* The pipe->clear() driver hook.
*
* This clears buffers attached to the current draw framebuffer.
*/
static void
iris_clear(struct pipe_context *ctx,
unsigned buffers,

View File

@@ -42,6 +42,7 @@ iris_flush(struct pipe_context *ctx,
iris_batch_flush(&ice->render_batch);
// XXX: bogus!!!
if (fence)
*fence = NULL;
}
@@ -59,6 +60,9 @@ get_time(void)
return tp.tv_sec + tp.tv_nsec / 1000000000.0;
}
/**
* The pipe->set_debug_callback() driver hook.
*/
static void
iris_set_debug_callback(struct pipe_context *ctx,
const struct pipe_debug_callback *cb)
@@ -71,6 +75,9 @@ iris_set_debug_callback(struct pipe_context *ctx,
memset(&ice->dbg, 0, sizeof(ice->dbg));
}
/**
* Destroy a context, freeing any associated memory.
*/
static void
iris_destroy_context(struct pipe_context *ctx)
{
@@ -103,6 +110,11 @@ iris_destroy_context(struct pipe_context *ctx)
unreachable("Unknown hardware generation"); \
}
/**
* Create a context.
*
* This is where each context begins.
*/
struct pipe_context *
iris_create_context(struct pipe_screen *pscreen, void *priv, unsigned flags)
{

View File

@@ -38,16 +38,22 @@ struct iris_context;
struct blorp_batch;
struct blorp_params;
#define IRIS_RESOURCE_FLAG_SHADER_MEMZONE (PIPE_RESOURCE_FLAG_DRV_PRIV << 0)
#define IRIS_RESOURCE_FLAG_SURFACE_MEMZONE (PIPE_RESOURCE_FLAG_DRV_PRIV << 1)
#define IRIS_RESOURCE_FLAG_DYNAMIC_MEMZONE (PIPE_RESOURCE_FLAG_DRV_PRIV << 2)
#define IRIS_MAX_TEXTURE_SAMPLERS 32
/* IRIS_MAX_ABOS and IRIS_MAX_SSBOS must be the same. */
#define IRIS_MAX_ABOS 16
#define IRIS_MAX_SSBOS 16
#define IRIS_MAX_VIEWPORTS 16
/**
* Dirty flags. When state changes, we flag some combination of these
* to indicate that particular GPU commands need to be re-emitted.
*
* Each bit typically corresponds to a single 3DSTATE_* command packet, but
* in rare cases they map to a group of related packets that need to be
* emitted together.
*
* See iris_upload_render_state().
*/
#define IRIS_DIRTY_COLOR_CALC_STATE (1ull << 0)
#define IRIS_DIRTY_POLYGON_STIPPLE (1ull << 1)
#define IRIS_DIRTY_SCISSOR_RECT (1ull << 2)
@@ -106,7 +112,9 @@ struct blorp_params;
*
* Shader programs may depend on non-orthogonal state. These flags are
* used to indicate that a shader's key depends on the state provided by
* a certain Gallium CSO.
* a certain Gallium CSO. Changing any CSOs marked as a dependency will
* cause the driver to re-compute the shader key, possibly triggering a
* shader recompile.
*/
enum iris_nos_dep {
IRIS_NOS_FRAMEBUFFER,
@@ -119,6 +127,9 @@ enum iris_nos_dep {
struct iris_depth_stencil_alpha_state;
/**
* Cache IDs for the in-memory program cache (ice->shaders.cache).
*/
enum iris_program_cache_id {
IRIS_CACHE_VS = MESA_SHADER_VERTEX,
IRIS_CACHE_TCS = MESA_SHADER_TESS_CTRL,
@@ -131,11 +142,11 @@ enum iris_program_cache_id {
/** @{
*
* PIPE_CONTROL operation, a combination MI_FLUSH and register write with
* additional flushing control.
* Defines for PIPE_CONTROL operations, which trigger cache flushes,
* synchronization, pipelined memory writes, and so on.
*
* The bits here are not the actual hardware values. The actual values
* shift around a bit per-generation, so we just have flags for each
* The bits here are not the actual hardware values. The actual fields
* move between various generations, so we just have flags for each
* potential operation, and use genxml to encode the actual packet.
*/
enum pipe_control_flags
@@ -180,6 +191,13 @@ enum pipe_control_flags
/** @} */
/**
* A compiled shader variant, containing a pointer to the GPU assembly,
* as well as program data and other packets needed by state upload.
*
* There can be several iris_compiled_shader variants per API-level shader
* (iris_uncompiled_shader), due to state-based recompiles (brw_*_prog_key).
*/
struct iris_compiled_shader {
/** Reference to the uploaded assembly. */
struct iris_state_ref assembly;
@@ -203,6 +221,9 @@ struct iris_compiled_shader {
uint8_t derived_data[0];
};
/**
* Constant buffer (UBO) information. See iris_set_const_buffer().
*/
struct iris_const_buffer {
/** The resource and offset for the actual constant data */
struct iris_state_ref data;
@@ -211,12 +232,18 @@ struct iris_const_buffer {
struct iris_state_ref surface_state;
};
/**
* API context state that is replicated per shader stage.
*/
struct iris_shader_state {
struct iris_const_buffer constbuf[PIPE_MAX_CONSTANT_BUFFERS];
struct pipe_resource *ssbo[PIPE_MAX_SHADER_BUFFERS];
struct iris_state_ref ssbo_surface_state[PIPE_MAX_SHADER_BUFFERS];
};
/**
* Virtual table for generation-specific (genxml) function calls.
*/
struct iris_vtable {
void (*destroy_state)(struct iris_context *ice);
void (*init_render_context)(struct iris_screen *screen,
@@ -248,6 +275,11 @@ struct iris_vtable {
struct brw_wm_prog_key *key);
};
/**
* A pool containing SAMPLER_BORDER_COLOR_STATE entries.
*
* See iris_border_color.c for more information.
*/
struct iris_border_color_pool {
struct iris_bo *bo;
void *map;
@@ -257,15 +289,27 @@ struct iris_border_color_pool {
struct hash_table *ht;
};
/**
* The API context (derived from pipe_context).
*
* Most driver state is tracked here.
*/
struct iris_context {
struct pipe_context ctx;
/** A debug callback for KHR_debug output. */
struct pipe_debug_callback dbg;
/** Slab allocator for iris_transfer_map objects. */
struct slab_child_pool transfer_pool;
struct iris_vtable vtbl;
struct blorp_context blorp;
/** The main batch for rendering. */
struct iris_batch render_batch;
struct {
struct iris_uncompiled_shader *uncompiled[MESA_SHADER_STAGES];
struct iris_compiled_shader *prog[MESA_SHADER_STAGES];
@@ -279,14 +323,10 @@ struct iris_context {
unsigned urb_size;
} shaders;
struct blorp_context blorp;
/** The main batch for rendering */
struct iris_batch render_batch;
struct {
uint64_t dirty;
uint64_t dirty_for_nos[IRIS_NOS_COUNT];
unsigned num_viewports;
unsigned sample_mask;
struct iris_blend_state *cso_blend;
@@ -300,6 +340,7 @@ struct iris_context {
struct pipe_stencil_ref stencil_ref;
struct pipe_framebuffer_state framebuffer;
/** GenX-specific current state */
struct iris_genx_state *genx;
struct iris_state_ref sampler_table[MESA_SHADER_STAGES];

View File

@@ -20,6 +20,13 @@
* 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"
@@ -31,6 +38,9 @@
#include "intel/compiler/brw_compiler.h"
#include "iris_context.h"
/**
* 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)
{

View File

@@ -21,6 +21,13 @@
* IN THE SOFTWARE.
*/
/**
* @file iris_formats.c
*
* Converts Gallium formats (PIPE_FORMAT_*) to hardware ones (ISL_FORMAT_*).
* Provides information about which formats support what features.
*/
#include "util/bitscan.h"
#include "util/macros.h"
#include "util/u_format.h"
@@ -391,6 +398,12 @@ iris_isl_format_for_pipe_format(enum pipe_format pf)
return table[pf];
}
/**
* The pscreen->is_format_supported() driver hook.
*
* Returns true if the given format is supported for the given usage
* (PIPE_BIND_*) and sample count.
*/
boolean
iris_is_format_supported(struct pipe_screen *pscreen,
enum pipe_format pformat,

View File

@@ -21,6 +21,35 @@
* IN THE SOFTWARE.
*/
/**
* @file iris_pipe_control.c
*
* PIPE_CONTROL is the main flushing and synchronization primitive on Intel
* GPUs. It can invalidate caches, stall until rendering reaches various
* stages of completion, write to memory, and other things. In a way, it's
* a swiss army knife command - it has all kinds of capabilities, but some
* significant limitations as well.
*
* Unfortunately, it's notoriously complicated and difficult to use. Many
* sub-commands can't be used together. Some are meant to be used at the
* top of the pipeline (invalidating caches before drawing), while some are
* meant to be used at the end (stalling or flushing after drawing).
*
* Also, there's a list of restrictions a mile long, which vary by generation.
* Do this before doing that, or suffer the consequences (usually a GPU hang).
*
* This file contains helpers for emitting them safely. You can simply call
* iris_emit_pipe_control_flush() with the desired operations (as logical
* PIPE_CONTROL_* bits), and it will take care of splitting it into multiple
* PIPE_CONTROL commands as necessary. The per-generation workarounds are
* applied in iris_emit_raw_pipe_control() in iris_state.c.
*
* This file also contains our cache tracking helpers. We have sets for
* the render cache, depth cache, and so on. If a BO is in the set, then
* it may have data in that cache. These take care of emitting flushes for
* render-to-texture, format reinterpretation issues, and other situations.
*/
#include "iris_context.h"
#include "util/hash_table.h"
#include "util/set.h"

View File

@@ -20,6 +20,16 @@
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file iris_program.c
*
* This file contains the driver interface for compiling shaders.
*
* See iris_program_cache.c for the in-memory program cache where the
* compiled shaders are stored.
*/
#include <stdio.h>
#include <errno.h>
#include "pipe/p_defines.h"
@@ -39,6 +49,15 @@ get_new_program_id(struct iris_screen *screen)
return p_atomic_inc_return(&screen->program_id);
}
/**
* An uncompiled, API-facing shader. This is the Gallium CSO for shaders.
* It primarily contains the NIR for the shader.
*
* Each API-facing shader can be compiled into multiple shader variants,
* based on non-orthogonal state dependencies, recorded in the shader key.
*
* See iris_compiled_shader, which represents a compiled shader variant.
*/
struct iris_uncompiled_shader {
nir_shader *nir;
@@ -52,6 +71,14 @@ struct iris_uncompiled_shader {
// XXX: need unify_interfaces() at link time...
/**
* The pipe->create_[stage]_state() driver hooks.
*
* Performs basic NIR preprocessing, records any state dependencies, and
* returns an iris_uncompiled_shader as the Gallium CSO.
*
* Actual shader compilation to assembly happens later, at first use.
*/
static void *
iris_create_shader_state(struct pipe_context *ctx,
const struct pipe_shader_state *state)
@@ -101,9 +128,16 @@ iris_create_shader_state(struct pipe_context *ctx,
break;
}
// XXX: precompile!
return ish;
}
/**
* The pipe->delete_[stage]_state() driver hooks.
*
* Frees the iris_uncompiled_shader.
*/
static void
iris_delete_shader_state(struct pipe_context *ctx, void *state)
{
@@ -113,6 +147,12 @@ iris_delete_shader_state(struct pipe_context *ctx, void *state)
free(ish);
}
/**
* The pipe->bind_[stage]_state() driver hook.
*
* Binds an uncompiled shader as the current one for a particular stage.
* Updates dirty tracking to account for the shader's NOS.
*/
static void
bind_state(struct iris_context *ice,
struct iris_uncompiled_shader *ish,
@@ -124,6 +164,9 @@ bind_state(struct iris_context *ice,
ice->shaders.uncompiled[stage] = ish;
ice->state.dirty |= dirty_bit;
/* Record that CSOs need to mark IRIS_DIRTY_UNCOMPILED_XS when they change
* (or that they no longer need to do so).
*/
for (int i = 0; i < IRIS_NOS_COUNT; i++) {
if (nos & (1 << i))
ice->state.dirty_for_nos[i] |= dirty_bit;
@@ -149,6 +192,7 @@ iris_bind_tes_state(struct pipe_context *ctx, void *state)
{
struct iris_context *ice = (struct iris_context *)ctx;
/* Enabling/disabling optional stages requires a URB reconfiguration. */
if (!!state != !!ice->shaders.uncompiled[MESA_SHADER_TESS_EVAL])
ice->state.dirty |= IRIS_DIRTY_URB;
@@ -160,6 +204,7 @@ iris_bind_gs_state(struct pipe_context *ctx, void *state)
{
struct iris_context *ice = (struct iris_context *)ctx;
/* Enabling/disabling optional stages requires a URB reconfiguration. */
if (!!state != !!ice->shaders.uncompiled[MESA_SHADER_GEOMETRY])
ice->state.dirty |= IRIS_DIRTY_URB;
@@ -244,6 +289,11 @@ assign_common_binding_table_offsets(const struct gen_device_info *devinfo,
return next_binding_table_offset;
}
/**
* Associate NIR uniform variables with the prog_data->param[] mechanism
* used by the backend. Also, decide which UBOs we'd like to push in an
* ideal situation (though the backend can reduce this).
*/
static void
iris_setup_uniforms(const struct brw_compiler *compiler,
void *mem_ctx,
@@ -266,6 +316,11 @@ iris_setup_uniforms(const struct brw_compiler *compiler,
brw_nir_analyze_ubo_ranges(compiler, nir, NULL, prog_data->ubo_ranges);
}
/**
* If we still have regular uniforms as push constants after the backend
* compilation, set up a UBO range for them. This will be used to fill
* out the 3DSTATE_CONSTANT_* packets which cause the data to be pushed.
*/
static void
iris_setup_push_uniform_range(const struct brw_compiler *compiler,
struct brw_stage_prog_data *prog_data)
@@ -282,6 +337,9 @@ iris_setup_push_uniform_range(const struct brw_compiler *compiler,
}
}
/**
* Compile a vertex shader, and upload the assembly.
*/
static bool
iris_compile_vs(struct iris_context *ice,
struct iris_uncompiled_shader *ish,
@@ -330,6 +388,11 @@ iris_compile_vs(struct iris_context *ice,
return true;
}
/**
* Update the current vertex shader variant.
*
* Fill out the key, look in the cache, compile and bind if needed.
*/
static void
iris_update_compiled_vs(struct iris_context *ice)
{
@@ -345,6 +408,9 @@ iris_update_compiled_vs(struct iris_context *ice)
UNUSED bool success = iris_compile_vs(ice, ish, &key);
}
/**
* Get the shader_info for a given stage, or NULL if the stage is disabled.
*/
const struct shader_info *
iris_get_shader_info(const struct iris_context *ice, gl_shader_stage stage)
{
@@ -388,6 +454,9 @@ get_unified_tess_slots(const struct iris_context *ice,
}
}
/**
* Compile a tessellation control shader, and upload the assembly.
*/
static bool
iris_compile_tcs(struct iris_context *ice,
struct iris_uncompiled_shader *ish,
@@ -427,6 +496,11 @@ iris_compile_tcs(struct iris_context *ice,
return true;
}
/**
* Update the current tessellation control shader variant.
*
* Fill out the key, look in the cache, compile and bind if needed.
*/
static void
iris_update_compiled_tcs(struct iris_context *ice)
{
@@ -458,6 +532,9 @@ iris_update_compiled_tcs(struct iris_context *ice)
UNUSED bool success = iris_compile_tcs(ice, tcs, &key);
}
/**
* Compile a tessellation evaluation shader, and upload the assembly.
*/
static bool
iris_compile_tes(struct iris_context *ice,
struct iris_uncompiled_shader *ish,
@@ -505,6 +582,11 @@ iris_compile_tes(struct iris_context *ice,
return true;
}
/**
* Update the current tessellation evaluation shader variant.
*
* Fill out the key, look in the cache, compile and bind if needed.
*/
static void
iris_update_compiled_tes(struct iris_context *ice)
{
@@ -526,6 +608,9 @@ iris_update_compiled_tes(struct iris_context *ice)
UNUSED bool success = iris_compile_tes(ice, ish, &key);
}
/**
* Compile a geometry shader, and upload the assembly.
*/
static bool
iris_compile_gs(struct iris_context *ice,
struct iris_uncompiled_shader *ish,
@@ -573,7 +658,11 @@ iris_compile_gs(struct iris_context *ice,
return true;
}
/**
* Update the current geometry shader variant.
*
* Fill out the key, look in the cache, compile and bind if needed.
*/
static void
iris_update_compiled_gs(struct iris_context *ice)
{
@@ -594,6 +683,9 @@ iris_update_compiled_gs(struct iris_context *ice)
UNUSED bool success = iris_compile_gs(ice, ish, &key);
}
/**
* Compile a fragment (pixel) shader, and upload the assembly.
*/
static bool
iris_compile_fs(struct iris_context *ice,
struct iris_uncompiled_shader *ish,
@@ -637,6 +729,11 @@ iris_compile_fs(struct iris_context *ice,
return true;
}
/**
* Update the current fragment shader variant.
*
* Fill out the key, look in the cache, compile and bind if needed.
*/
static void
iris_update_compiled_fs(struct iris_context *ice)
{
@@ -652,6 +749,11 @@ iris_update_compiled_fs(struct iris_context *ice)
iris_compile_fs(ice, ish, &key, ice->shaders.last_vue_map);
}
/**
* Get the compiled shader for the last enabled geometry stage.
*
* This stage is the one which will feed stream output and the rasterizer.
*/
static struct iris_compiled_shader *
last_vue_shader(struct iris_context *ice)
{
@@ -664,6 +766,12 @@ last_vue_shader(struct iris_context *ice)
return ice->shaders.prog[MESA_SHADER_VERTEX];
}
/**
* Update the last enabled stage's VUE map.
*
* When the shader feeding the rasterizer's output interface changes, we
* need to re-emit various packets.
*/
static void
update_last_vue_map(struct iris_context *ice,
struct brw_stage_prog_data *prog_data)
@@ -692,6 +800,9 @@ update_last_vue_map(struct iris_context *ice,
ice->shaders.last_vue_map = &vue_prog_data->vue_map;
}
/**
* Get the prog_data for a given stage, or NULL if the stage is disabled.
*/
static struct brw_vue_prog_data *
get_vue_prog_data(struct iris_context *ice, gl_shader_stage stage)
{
@@ -701,6 +812,13 @@ get_vue_prog_data(struct iris_context *ice, gl_shader_stage stage)
return (void *) ice->shaders.prog[stage]->prog_data;
}
/**
* Update the current shader variants for the given state.
*
* This should be called on every draw call to ensure that the correct
* shaders are bound. It will also flag any dirty state triggered by
* swapping out those shaders.
*/
void
iris_update_compiled_shaders(struct iris_context *ice)
{
@@ -732,6 +850,7 @@ iris_update_compiled_shaders(struct iris_context *ice)
iris_update_compiled_fs(ice);
// ...
/* Changing shader interfaces may require a URB configuration. */
if (!(dirty & IRIS_DIRTY_URB)) {
for (int i = MESA_SHADER_VERTEX; i <= MESA_SHADER_GEOMETRY; i++) {
struct brw_vue_prog_data *old = old_prog_datas[i];

View File

@@ -20,6 +20,15 @@
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file iris_program_cache.c
*
* The in-memory program cache. This is basically a hash table mapping
* API-specified shaders and a state key to a compiled variant. It also
* takes care of uploading shader assembly into a BO for use on the GPU.
*/
#include <stdio.h>
#include <errno.h>
#include "pipe/p_defines.h"

View File

@@ -20,6 +20,13 @@
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file iris_query.c
*
* XXX: this file is EMPTY. it will eventually implement query objects!
*/
#include <stdio.h>
#include <errno.h>
#include "pipe/p_defines.h"

View File

@@ -20,6 +20,15 @@
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file iris_resource.c
*
* Resources are images, buffers, and other objects used by the GPU.
*
* XXX: explain resources
*/
#include <stdio.h>
#include <errno.h>
#include "pipe/p_defines.h"
@@ -336,7 +345,7 @@ iris_resource_from_handle(struct pipe_screen *pscreen,
unreachable("invalid winsys handle type");
}
if (!res->bo)
return NULL;
return NULL;
uint64_t modifier = whandle->modifier;
if (modifier == DRM_FORMAT_MOD_INVALID) {

View File

@@ -27,6 +27,10 @@
#include "util/u_inlines.h"
#include "intel/isl/isl.h"
#define IRIS_RESOURCE_FLAG_SHADER_MEMZONE (PIPE_RESOURCE_FLAG_DRV_PRIV << 0)
#define IRIS_RESOURCE_FLAG_SURFACE_MEMZONE (PIPE_RESOURCE_FLAG_DRV_PRIV << 1)
#define IRIS_RESOURCE_FLAG_DYNAMIC_MEMZONE (PIPE_RESOURCE_FLAG_DRV_PRIV << 2)
/**
* Resources represent a GPU buffer object or image (mipmap tree).
*
@@ -71,6 +75,9 @@ struct iris_transfer {
void (*unmap)(struct iris_transfer *);
};
/**
* Unwrap a pipe_resource to get the underlying iris_bo (for convenience).
*/
static inline struct iris_bo *
iris_resource_bo(struct pipe_resource *p_res)
{

View File

@@ -20,6 +20,17 @@
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file iris_screen.c
*
* Screen related driver hooks and capability lists.
*
* A program may use multiple rendering contexts (iris_context), but
* they all share a common screen (iris_screen). Global driver state
* can be stored in the screen; it may be accessed by multiple threads.
*/
#include <stdio.h>
#include <errno.h>
#include <sys/ioctl.h>

View File

@@ -39,18 +39,28 @@ struct iris_bo;
struct iris_screen {
struct pipe_screen base;
/** Global slab allocator for iris_transfer_map objects */
struct slab_parent_pool transfer_pool;
/** drm device file descriptor */
int fd;
/** PCI ID for our GPU device */
int pci_id;
/** Global program_string_id counter (see get_program_string_id()) */
unsigned program_id;
struct gen_device_info devinfo;
struct isl_device isl_dev;
struct iris_bufmgr *bufmgr;
struct iris_bo *workaround_bo;
struct brw_compiler *compiler;
/**
* A buffer containing nothing useful, for hardware workarounds that
* require scratch writes or reads from some unimportant memory.
*/
struct iris_bo *workaround_bo;
};
struct pipe_screen *iris_screen_create(int fd);

File diff suppressed because it is too large Load Diff