i965/fs: Add support for translating ir_triop_fma into MAD.
[mesa.git] / src / mesa / drivers / dri / i965 / intel_batchbuffer.c
index 409df29c7d1b4c29493759068751f023921cf3ee..56048293ade71225b9856adea734fe283767febb 100644 (file)
@@ -25,7 +25,6 @@
  * 
  **************************************************************************/
 
-#include "intel_context.h"
 #include "intel_batchbuffer.h"
 #include "intel_buffer_objects.h"
 #include "intel_reg.h"
@@ -34,7 +33,7 @@
 #include "brw_context.h"
 
 static void
-intel_batchbuffer_reset(struct intel_context *intel);
+intel_batchbuffer_reset(struct brw_context *brw);
 
 struct cached_batch_item {
    struct cached_batch_item *next;
@@ -42,9 +41,10 @@ struct cached_batch_item {
    uint16_t size;
 };
 
-static void clear_cache( struct intel_context *intel )
+static void
+clear_cache(struct brw_context *brw)
 {
-   struct cached_batch_item *item = intel->batch.cached_items;
+   struct cached_batch_item *item = brw->batch.cached_items;
 
    while (item) {
       struct cached_batch_item *next = item->next;
@@ -52,93 +52,93 @@ static void clear_cache( struct intel_context *intel )
       item = next;
    }
 
-   intel->batch.cached_items = NULL;
+   brw->batch.cached_items = NULL;
 }
 
 void
-intel_batchbuffer_init(struct intel_context *intel)
+intel_batchbuffer_init(struct brw_context *brw)
 {
-   intel_batchbuffer_reset(intel);
+   intel_batchbuffer_reset(brw);
 
-   if (intel->gen >= 6) {
+   if (brw->gen >= 6) {
       /* We can't just use brw_state_batch to get a chunk of space for
        * the gen6 workaround because it involves actually writing to
        * the buffer, and the kernel doesn't let us write to the batch.
        */
-      intel->batch.workaround_bo = drm_intel_bo_alloc(intel->bufmgr,
+      brw->batch.workaround_bo = drm_intel_bo_alloc(brw->bufmgr,
                                                      "pipe_control workaround",
                                                      4096, 4096);
    }
 
-   if (!intel->has_llc) {
-      intel->batch.cpu_map = malloc(BATCH_SZ);
-      intel->batch.map = intel->batch.cpu_map;
+   if (!brw->has_llc) {
+      brw->batch.cpu_map = malloc(BATCH_SZ);
+      brw->batch.map = brw->batch.cpu_map;
    }
 }
 
 static void
-intel_batchbuffer_reset(struct intel_context *intel)
+intel_batchbuffer_reset(struct brw_context *brw)
 {
-   if (intel->batch.last_bo != NULL) {
-      drm_intel_bo_unreference(intel->batch.last_bo);
-      intel->batch.last_bo = NULL;
+   if (brw->batch.last_bo != NULL) {
+      drm_intel_bo_unreference(brw->batch.last_bo);
+      brw->batch.last_bo = NULL;
    }
-   intel->batch.last_bo = intel->batch.bo;
+   brw->batch.last_bo = brw->batch.bo;
 
-   clear_cache(intel);
+   clear_cache(brw);
 
-   intel->batch.bo = drm_intel_bo_alloc(intel->bufmgr, "batchbuffer",
+   brw->batch.bo = drm_intel_bo_alloc(brw->bufmgr, "batchbuffer",
                                        BATCH_SZ, 4096);
-   if (intel->has_llc) {
-      drm_intel_bo_map(intel->batch.bo, true);
-      intel->batch.map = intel->batch.bo->virtual;
+   if (brw->has_llc) {
+      drm_intel_bo_map(brw->batch.bo, true);
+      brw->batch.map = brw->batch.bo->virtual;
    }
 
-   intel->batch.reserved_space = BATCH_RESERVED;
-   intel->batch.state_batch_offset = intel->batch.bo->size;
-   intel->batch.used = 0;
-   intel->batch.needs_sol_reset = false;
+   brw->batch.reserved_space = BATCH_RESERVED;
+   brw->batch.state_batch_offset = brw->batch.bo->size;
+   brw->batch.used = 0;
+   brw->batch.needs_sol_reset = false;
 }
 
 void
-intel_batchbuffer_save_state(struct intel_context *intel)
+intel_batchbuffer_save_state(struct brw_context *brw)
 {
-   intel->batch.saved.used = intel->batch.used;
-   intel->batch.saved.reloc_count =
-      drm_intel_gem_bo_get_reloc_count(intel->batch.bo);
+   brw->batch.saved.used = brw->batch.used;
+   brw->batch.saved.reloc_count =
+      drm_intel_gem_bo_get_reloc_count(brw->batch.bo);
 }
 
 void
-intel_batchbuffer_reset_to_saved(struct intel_context *intel)
+intel_batchbuffer_reset_to_saved(struct brw_context *brw)
 {
-   drm_intel_gem_bo_clear_relocs(intel->batch.bo, intel->batch.saved.reloc_count);
+   drm_intel_gem_bo_clear_relocs(brw->batch.bo, brw->batch.saved.reloc_count);
 
-   intel->batch.used = intel->batch.saved.used;
+   brw->batch.used = brw->batch.saved.used;
 
    /* Cached batch state is dead, since we just cleared some unknown part of the
     * batchbuffer.  Assume that the caller resets any other state necessary.
     */
-   clear_cache(intel);
+   clear_cache(brw);
 }
 
 void
-intel_batchbuffer_free(struct intel_context *intel)
+intel_batchbuffer_free(struct brw_context *brw)
 {
-   free(intel->batch.cpu_map);
-   drm_intel_bo_unreference(intel->batch.last_bo);
-   drm_intel_bo_unreference(intel->batch.bo);
-   drm_intel_bo_unreference(intel->batch.workaround_bo);
-   clear_cache(intel);
+   free(brw->batch.cpu_map);
+   drm_intel_bo_unreference(brw->batch.last_bo);
+   drm_intel_bo_unreference(brw->batch.bo);
+   drm_intel_bo_unreference(brw->batch.workaround_bo);
+   clear_cache(brw);
 }
 
 static void
-do_batch_dump(struct intel_context *intel)
+do_batch_dump(struct brw_context *brw)
 {
    struct drm_intel_decode *decode;
-   struct intel_batchbuffer *batch = &intel->batch;
+   struct intel_batchbuffer *batch = &brw->batch;
    int ret;
 
-   decode = drm_intel_decode_context_alloc(intel->intelScreen->deviceID);
+   decode = drm_intel_decode_context_alloc(brw->intelScreen->deviceID);
    if (!decode)
       return;
 
@@ -166,19 +166,19 @@ do_batch_dump(struct intel_context *intel)
    if (ret == 0) {
       drm_intel_bo_unmap(batch->bo);
 
-      brw_debug_batch(intel);
+      brw_debug_batch(brw);
    }
 }
 
 /* TODO: Push this whole function into bufmgr.
  */
 static int
-do_flush_locked(struct intel_context *intel)
+do_flush_locked(struct brw_context *brw)
 {
-   struct intel_batchbuffer *batch = &intel->batch;
+   struct intel_batchbuffer *batch = &brw->batch;
    int ret = 0;
 
-   if (intel->has_llc) {
+   if (brw->has_llc) {
       drm_intel_bo_unmap(batch->bo);
    } else {
       ret = drm_intel_bo_subdata(batch->bo, 0, 4*batch->used, batch->map);
@@ -190,10 +190,10 @@ do_flush_locked(struct intel_context *intel)
       }
    }
 
-   if (!intel->intelScreen->no_hw) {
+   if (!brw->intelScreen->no_hw) {
       int flags;
 
-      if (intel->gen < 6 || !batch->is_blit) {
+      if (brw->gen < 6 || !batch->is_blit) {
         flags = I915_EXEC_RENDER;
       } else {
         flags = I915_EXEC_BLT;
@@ -204,74 +204,81 @@ do_flush_locked(struct intel_context *intel)
 
       if (ret == 0) {
          if (unlikely(INTEL_DEBUG & DEBUG_AUB))
-            brw_annotate_aub(intel);
-        if (intel->hw_ctx == NULL || batch->is_blit) {
+            brw_annotate_aub(brw);
+        if (brw->hw_ctx == NULL || batch->is_blit) {
            ret = drm_intel_bo_mrb_exec(batch->bo, 4 * batch->used, NULL, 0, 0,
                                        flags);
         } else {
-           ret = drm_intel_gem_bo_context_exec(batch->bo, intel->hw_ctx,
+           ret = drm_intel_gem_bo_context_exec(batch->bo, brw->hw_ctx,
                                                4 * batch->used, flags);
         }
       }
    }
 
    if (unlikely(INTEL_DEBUG & DEBUG_BATCH))
-      do_batch_dump(intel);
+      do_batch_dump(brw);
 
    if (ret != 0) {
       fprintf(stderr, "intel_do_flush_locked failed: %s\n", strerror(-ret));
       exit(1);
    }
-   intel->vtbl.new_batch(intel);
+   brw->vtbl.new_batch(brw);
 
    return ret;
 }
 
 int
-_intel_batchbuffer_flush(struct intel_context *intel,
+_intel_batchbuffer_flush(struct brw_context *brw,
                         const char *file, int line)
 {
    int ret;
 
-   if (intel->batch.used == 0)
+   if (brw->batch.used == 0)
       return 0;
 
-   if (intel->first_post_swapbuffers_batch == NULL) {
-      intel->first_post_swapbuffers_batch = intel->batch.bo;
-      drm_intel_bo_reference(intel->first_post_swapbuffers_batch);
+   if (brw->first_post_swapbuffers_batch == NULL) {
+      brw->first_post_swapbuffers_batch = brw->batch.bo;
+      drm_intel_bo_reference(brw->first_post_swapbuffers_batch);
    }
 
-   if (unlikely(INTEL_DEBUG & DEBUG_BATCH))
-      fprintf(stderr, "%s:%d: Batchbuffer flush with %db used\n", file, line,
-             4*intel->batch.used);
+   if (unlikely(INTEL_DEBUG & DEBUG_BATCH)) {
+      int bytes_for_commands = 4 * brw->batch.used;
+      int bytes_for_state = brw->batch.bo->size - brw->batch.state_batch_offset;
+      int total_bytes = bytes_for_commands + bytes_for_state;
+      fprintf(stderr, "%s:%d: Batchbuffer flush with %4db (pkt) + "
+              "%4db (state) = %4db (%0.1f%%)\n", file, line,
+              bytes_for_commands, bytes_for_state,
+              total_bytes,
+              100.0f * total_bytes / BATCH_SZ);
+   }
 
-   intel->batch.reserved_space = 0;
+   brw->batch.reserved_space = 0;
 
-   if (intel->vtbl.finish_batch)
-      intel->vtbl.finish_batch(intel);
+   if (brw->vtbl.finish_batch)
+      brw->vtbl.finish_batch(brw);
 
    /* Mark the end of the buffer. */
-   intel_batchbuffer_emit_dword(intel, MI_BATCH_BUFFER_END);
-   if (intel->batch.used & 1) {
+   intel_batchbuffer_emit_dword(brw, MI_BATCH_BUFFER_END);
+   if (brw->batch.used & 1) {
       /* Round batchbuffer usage to 2 DWORDs. */
-      intel_batchbuffer_emit_dword(intel, MI_NOOP);
+      intel_batchbuffer_emit_dword(brw, MI_NOOP);
    }
 
-   intel_upload_finish(intel);
+   intel_upload_finish(brw);
 
    /* Check that we didn't just wrap our batchbuffer at a bad time. */
-   assert(!intel->no_batch_wrap);
+   assert(!brw->no_batch_wrap);
 
-   ret = do_flush_locked(intel);
+   ret = do_flush_locked(brw);
 
    if (unlikely(INTEL_DEBUG & DEBUG_SYNC)) {
       fprintf(stderr, "waiting for idle\n");
-      drm_intel_bo_wait_rendering(intel->batch.bo);
+      drm_intel_bo_wait_rendering(brw->batch.bo);
    }
 
    /* Reset the buffer:
     */
-   intel_batchbuffer_reset(intel);
+   intel_batchbuffer_reset(brw);
 
    return ret;
 }
@@ -280,14 +287,14 @@ _intel_batchbuffer_flush(struct intel_context *intel,
 /*  This is the only way buffers get added to the validate list.
  */
 bool
-intel_batchbuffer_emit_reloc(struct intel_context *intel,
+intel_batchbuffer_emit_reloc(struct brw_context *brw,
                              drm_intel_bo *buffer,
                              uint32_t read_domains, uint32_t write_domain,
                             uint32_t delta)
 {
    int ret;
 
-   ret = drm_intel_bo_emit_reloc(intel->batch.bo, 4*intel->batch.used,
+   ret = drm_intel_bo_emit_reloc(brw->batch.bo, 4*brw->batch.used,
                                 buffer, delta,
                                 read_domains, write_domain);
    assert(ret == 0);
@@ -298,13 +305,13 @@ intel_batchbuffer_emit_reloc(struct intel_context *intel,
     * the buffer doesn't move and we can short-circuit the relocation processing
     * in the kernel
     */
-   intel_batchbuffer_emit_dword(intel, buffer->offset + delta);
+   intel_batchbuffer_emit_dword(brw, buffer->offset + delta);
 
    return true;
 }
 
 bool
-intel_batchbuffer_emit_reloc_fenced(struct intel_context *intel,
+intel_batchbuffer_emit_reloc_fenced(struct brw_context *brw,
                                    drm_intel_bo *buffer,
                                    uint32_t read_domains,
                                    uint32_t write_domain,
@@ -312,7 +319,7 @@ intel_batchbuffer_emit_reloc_fenced(struct intel_context *intel,
 {
    int ret;
 
-   ret = drm_intel_bo_emit_reloc_fence(intel->batch.bo, 4*intel->batch.used,
+   ret = drm_intel_bo_emit_reloc_fence(brw->batch.bo, 4*brw->batch.used,
                                       buffer, delta,
                                       read_domains, write_domain);
    assert(ret == 0);
@@ -323,42 +330,42 @@ intel_batchbuffer_emit_reloc_fenced(struct intel_context *intel,
     * be, in case the buffer doesn't move and we can short-circuit the
     * relocation processing in the kernel
     */
-   intel_batchbuffer_emit_dword(intel, buffer->offset + delta);
+   intel_batchbuffer_emit_dword(brw, buffer->offset + delta);
 
    return true;
 }
 
 void
-intel_batchbuffer_data(struct intel_context *intel,
+intel_batchbuffer_data(struct brw_context *brw,
                        const void *data, GLuint bytes, bool is_blit)
 {
    assert((bytes & 3) == 0);
-   intel_batchbuffer_require_space(intel, bytes, is_blit);
-   __memcpy(intel->batch.map + intel->batch.used, data, bytes);
-   intel->batch.used += bytes >> 2;
+   intel_batchbuffer_require_space(brw, bytes, is_blit);
+   __memcpy(brw->batch.map + brw->batch.used, data, bytes);
+   brw->batch.used += bytes >> 2;
 }
 
 void
-intel_batchbuffer_cached_advance(struct intel_context *intel)
+intel_batchbuffer_cached_advance(struct brw_context *brw)
 {
-   struct cached_batch_item **prev = &intel->batch.cached_items, *item;
-   uint32_t sz = (intel->batch.used - intel->batch.emit) * sizeof(uint32_t);
-   uint32_t *start = intel->batch.map + intel->batch.emit;
+   struct cached_batch_item **prev = &brw->batch.cached_items, *item;
+   uint32_t sz = (brw->batch.used - brw->batch.emit) * sizeof(uint32_t);
+   uint32_t *start = brw->batch.map + brw->batch.emit;
    uint16_t op = *start >> 16;
 
    while (*prev) {
       uint32_t *old;
 
       item = *prev;
-      old = intel->batch.map + item->header;
+      old = brw->batch.map + item->header;
       if (op == *old >> 16) {
         if (item->size == sz && memcmp(old, start, sz) == 0) {
-           if (prev != &intel->batch.cached_items) {
+           if (prev != &brw->batch.cached_items) {
               *prev = item->next;
-              item->next = intel->batch.cached_items;
-              intel->batch.cached_items = item;
+              item->next = brw->batch.cached_items;
+              brw->batch.cached_items = item;
            }
-           intel->batch.used = intel->batch.emit;
+           brw->batch.used = brw->batch.emit;
            return;
         }
 
@@ -371,12 +378,12 @@ intel_batchbuffer_cached_advance(struct intel_context *intel)
    if (item == NULL)
       return;
 
-   item->next = intel->batch.cached_items;
-   intel->batch.cached_items = item;
+   item->next = brw->batch.cached_items;
+   brw->batch.cached_items = item;
 
 emit:
    item->size = sz;
-   item->header = intel->batch.emit;
+   item->header = brw->batch.emit;
 }
 
 /**
@@ -392,9 +399,9 @@ emit:
  * already flushed (e.g., via a preceding MI_FLUSH).
  */
 void
-intel_emit_depth_stall_flushes(struct intel_context *intel)
+intel_emit_depth_stall_flushes(struct brw_context *brw)
 {
-   assert(intel->gen >= 6 && intel->gen <= 7);
+   assert(brw->gen >= 6 && brw->gen <= 7);
 
    BEGIN_BATCH(4);
    OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
@@ -419,22 +426,22 @@ intel_emit_depth_stall_flushes(struct intel_context *intel)
 }
 
 /**
- * From the BSpec, volume 2a.03: VS Stage Input / State:
- * "[DevIVB] A PIPE_CONTROL with Post-Sync Operation set to 1h and a depth
+ * From the Ivybridge PRM, Volume 2 Part 1, Section 3.2 (VS Stage Input):
+ * "A PIPE_CONTROL with Post-Sync Operation set to 1h and a depth
  *  stall needs to be sent just prior to any 3DSTATE_VS, 3DSTATE_URB_VS,
  *  3DSTATE_CONSTANT_VS, 3DSTATE_BINDING_TABLE_POINTER_VS,
  *  3DSTATE_SAMPLER_STATE_POINTER_VS command.  Only one PIPE_CONTROL needs
  *  to be sent before any combination of VS associated 3DSTATE."
  */
 void
-gen7_emit_vs_workaround_flush(struct intel_context *intel)
+gen7_emit_vs_workaround_flush(struct brw_context *brw)
 {
-   assert(intel->gen == 7);
+   assert(brw->gen == 7);
 
    BEGIN_BATCH(4);
    OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
    OUT_BATCH(PIPE_CONTROL_DEPTH_STALL | PIPE_CONTROL_WRITE_IMMEDIATE);
-   OUT_RELOC(intel->batch.workaround_bo,
+   OUT_RELOC(brw->batch.workaround_bo,
             I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, 0);
    OUT_BATCH(0); /* write data */
    ADVANCE_BATCH();
@@ -478,9 +485,9 @@ gen7_emit_vs_workaround_flush(struct intel_context *intel)
  * really our business.  That leaves only stall at scoreboard.
  */
 void
-intel_emit_post_sync_nonzero_flush(struct intel_context *intel)
+intel_emit_post_sync_nonzero_flush(struct brw_context *brw)
 {
-   if (!intel->batch.need_workaround_flush)
+   if (!brw->batch.need_workaround_flush)
       return;
 
    BEGIN_BATCH(4);
@@ -494,12 +501,12 @@ intel_emit_post_sync_nonzero_flush(struct intel_context *intel)
    BEGIN_BATCH(4);
    OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
    OUT_BATCH(PIPE_CONTROL_WRITE_IMMEDIATE);
-   OUT_RELOC(intel->batch.workaround_bo,
+   OUT_RELOC(brw->batch.workaround_bo,
             I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, 0);
    OUT_BATCH(0); /* write data */
    ADVANCE_BATCH();
 
-   intel->batch.need_workaround_flush = false;
+   brw->batch.need_workaround_flush = false;
 }
 
 /* Emit a pipelined flush to either flush render and texture cache for
@@ -509,10 +516,10 @@ intel_emit_post_sync_nonzero_flush(struct intel_context *intel)
  * This is also used for the always_flush_cache driconf debug option.
  */
 void
-intel_batchbuffer_emit_mi_flush(struct intel_context *intel)
+intel_batchbuffer_emit_mi_flush(struct brw_context *brw)
 {
-   if (intel->gen >= 6) {
-      if (intel->batch.is_blit) {
+   if (brw->gen >= 6) {
+      if (brw->batch.is_blit) {
         BEGIN_BATCH_BLT(4);
         OUT_BATCH(MI_FLUSH_DW);
         OUT_BATCH(0);
@@ -520,14 +527,14 @@ intel_batchbuffer_emit_mi_flush(struct intel_context *intel)
         OUT_BATCH(0);
         ADVANCE_BATCH();
       } else {
-        if (intel->gen == 6) {
+        if (brw->gen == 6) {
            /* Hardware workaround: SNB B-Spec says:
             *
             * [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache
             * Flush Enable =1, a PIPE_CONTROL with any non-zero
             * post-sync-op is required.
             */
-           intel_emit_post_sync_nonzero_flush(intel);
+           intel_emit_post_sync_nonzero_flush(brw);
         }
 
         BEGIN_BATCH(4);