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:
@@ -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);
|
||||
}
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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,
|
||||
|
@@ -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"
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
|
@@ -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,
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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];
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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,
|
||||
|
@@ -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"
|
||||
|
@@ -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];
|
||||
|
@@ -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"
|
||||
|
@@ -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"
|
||||
|
@@ -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) {
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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>
|
||||
|
@@ -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
Reference in New Issue
Block a user