Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************                                                                                  
  2.  *                                                                                                                                                          
  3.  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.                                                                                                
  4.  * All Rights Reserved.                                                                                                                                      
  5.  *                                                                                                                                                          
  6.  * Permission is hereby granted, free of charge, to any person obtaining a                                                                                  
  7.  * copy of this software and associated documentation files (the                                                                                            
  8.  * "Software"), to deal in the Software without restriction, including                                                                                      
  9.  * without limitation the rights to use, copy, modify, merge, publish,                                                                                      
  10.  * distribute, sub license, and/or sell copies of the Software, and to                                                                                      
  11.  * permit persons to whom the Software is furnished to do so, subject to                                                                                    
  12.  * the following conditions:                                                                                                                                
  13.  *                                                                                                                                                          
  14.  * The above copyright notice and this permission notice (including the                                                                                      
  15.  * next paragraph) shall be included in all copies or substantial portions                                                                                  
  16.  * of the Software.                                                                                                                                          
  17.  *                                                                                                                                                          
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS                                                                                  
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF                                                                                                
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.                                                                                  
  21.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR                                                                                    
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,                                                                                  
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE                                                                                        
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                                                                                                    
  25.  *                                                                                                                                                          
  26.  **************************************************************************/      
  27.  
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <assert.h>
  31.  
  32. #include "intel_batchbuffer.h"
  33.  
  34. #define MAX_BATCH_SIZE          0x400000
  35.  
  36. static void
  37. intel_batchbuffer_reset(struct intel_batchbuffer *batch, int buffer_size)
  38. {
  39.     struct intel_driver_data *intel = batch->intel;
  40.     int batch_size = buffer_size;
  41.  
  42.     assert(batch->flag == I915_EXEC_RENDER ||
  43.            batch->flag == I915_EXEC_BLT ||
  44.            batch->flag == I915_EXEC_BSD ||
  45.            batch->flag == I915_EXEC_VEBOX);
  46.  
  47.     dri_bo_unreference(batch->buffer);
  48.     batch->buffer = dri_bo_alloc(intel->bufmgr,
  49.                                  "batch buffer",
  50.                                  batch_size,
  51.                                  0x1000);
  52.     assert(batch->buffer);
  53.     dri_bo_map(batch->buffer, 1);
  54.     assert(batch->buffer->virtual);
  55.     batch->map = batch->buffer->virtual;
  56.     batch->size = batch_size;
  57.     batch->ptr = batch->map;
  58.     batch->atomic = 0;
  59. }
  60.  
  61. static unsigned int
  62. intel_batchbuffer_space(struct intel_batchbuffer *batch)
  63. {
  64.     return (batch->size - BATCH_RESERVED) - (batch->ptr - batch->map);
  65. }
  66.  
  67.  
  68. struct intel_batchbuffer *
  69. intel_batchbuffer_new(struct intel_driver_data *intel, int flag, int buffer_size)
  70. {
  71.     struct intel_batchbuffer *batch = calloc(1, sizeof(*batch));
  72.     assert(flag == I915_EXEC_RENDER ||
  73.            flag == I915_EXEC_BSD ||
  74.            flag == I915_EXEC_BLT ||
  75.            flag == I915_EXEC_VEBOX);
  76.  
  77.    if (!buffer_size || buffer_size < BATCH_SIZE) {
  78.         buffer_size = BATCH_SIZE;
  79.    }
  80.  
  81.    /* the buffer size can't exceed 4M */
  82.    if (buffer_size > MAX_BATCH_SIZE) {
  83.         buffer_size = MAX_BATCH_SIZE;
  84.    }
  85.  
  86.     batch->intel = intel;
  87.     batch->flag = flag;
  88.     batch->run = drm_intel_bo_mrb_exec;
  89.  
  90.     if (IS_GEN6(intel->device_info) &&
  91.         flag == I915_EXEC_RENDER)
  92.         batch->wa_render_bo = dri_bo_alloc(intel->bufmgr,
  93.                                            "wa scratch",
  94.                                            4096,
  95.                                            4096);
  96.     else
  97.         batch->wa_render_bo = NULL;
  98.  
  99.     intel_batchbuffer_reset(batch, buffer_size);
  100.  
  101.     return batch;
  102. }
  103.  
  104. void intel_batchbuffer_free(struct intel_batchbuffer *batch)
  105. {
  106.     if (batch->map) {
  107.         dri_bo_unmap(batch->buffer);
  108.         batch->map = NULL;
  109.     }
  110.  
  111.     dri_bo_unreference(batch->buffer);
  112.     dri_bo_unreference(batch->wa_render_bo);
  113.     free(batch);
  114. }
  115.  
  116. void
  117. intel_batchbuffer_flush(struct intel_batchbuffer *batch)
  118. {
  119.     unsigned int used = batch->ptr - batch->map;
  120.  
  121.     if (used == 0) {
  122.         return;
  123.     }
  124.  
  125.     if ((used & 4) == 0) {
  126.         *(unsigned int*)batch->ptr = 0;
  127.         batch->ptr += 4;
  128.     }
  129.  
  130.     *(unsigned int*)batch->ptr = MI_BATCH_BUFFER_END;
  131.     batch->ptr += 4;
  132.     dri_bo_unmap(batch->buffer);
  133.     used = batch->ptr - batch->map;
  134.     batch->run(batch->buffer, used, 0, 0, 0, batch->flag);
  135.     intel_batchbuffer_reset(batch, batch->size);
  136. }
  137.  
  138. void
  139. intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, unsigned int x)
  140. {
  141.     assert(intel_batchbuffer_space(batch) >= 4);
  142.     *(unsigned int *)batch->ptr = x;
  143.     batch->ptr += 4;
  144. }
  145.  
  146. void
  147. intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch, dri_bo *bo,
  148.                                 uint32_t read_domains, uint32_t write_domains,
  149.                                 uint32_t delta)
  150. {
  151.     assert(batch->ptr - batch->map < batch->size);
  152.     dri_bo_emit_reloc(batch->buffer, read_domains, write_domains,
  153.                       delta, batch->ptr - batch->map, bo);
  154.     intel_batchbuffer_emit_dword(batch, bo->offset + delta);
  155. }
  156.  
  157. void
  158. intel_batchbuffer_require_space(struct intel_batchbuffer *batch,
  159.                                    unsigned int size)
  160. {
  161.     assert(size < batch->size - 8);
  162.  
  163.     if (intel_batchbuffer_space(batch) < size) {
  164.         intel_batchbuffer_flush(batch);
  165.     }
  166. }
  167.  
  168. void
  169. intel_batchbuffer_data(struct intel_batchbuffer *batch,
  170.                           void *data,
  171.                           unsigned int size)
  172. {
  173.     assert((size & 3) == 0);
  174.     intel_batchbuffer_require_space(batch, size);
  175.  
  176.     assert(batch->ptr);
  177.     memcpy(batch->ptr, data, size);
  178.     batch->ptr += size;
  179. }
  180.  
  181. void
  182. intel_batchbuffer_emit_mi_flush(struct intel_batchbuffer *batch)
  183. {
  184.     struct intel_driver_data *intel = batch->intel;
  185.  
  186.     if (IS_GEN6(intel->device_info) ||
  187.         IS_GEN7(intel->device_info) ||
  188.         IS_GEN8(intel->device_info)) {
  189.         if (batch->flag == I915_EXEC_RENDER) {
  190.             if (IS_GEN8(intel->device_info)) {
  191.                 BEGIN_BATCH(batch, 6);
  192.                 OUT_BATCH(batch, CMD_PIPE_CONTROL | (6 - 2));
  193.  
  194.                 OUT_BATCH(batch,
  195.                           CMD_PIPE_CONTROL_CS_STALL |
  196.                           CMD_PIPE_CONTROL_WC_FLUSH |
  197.                           CMD_PIPE_CONTROL_TC_FLUSH |
  198.                           CMD_PIPE_CONTROL_DC_FLUSH |
  199.                           CMD_PIPE_CONTROL_NOWRITE);
  200.                 OUT_BATCH(batch, 0); /* write address */
  201.                 OUT_BATCH(batch, 0);
  202.                 OUT_BATCH(batch, 0); /* write data */
  203.                 OUT_BATCH(batch, 0);
  204.                 ADVANCE_BATCH(batch);
  205.             } else if (IS_GEN6(intel->device_info)) {
  206.                 assert(batch->wa_render_bo);
  207.  
  208.                 BEGIN_BATCH(batch, 4 * 3);
  209.  
  210.                 OUT_BATCH(batch, CMD_PIPE_CONTROL | (4 - 2));
  211.                 OUT_BATCH(batch,
  212.                           CMD_PIPE_CONTROL_CS_STALL |
  213.                           CMD_PIPE_CONTROL_STALL_AT_SCOREBOARD);
  214.                 OUT_BATCH(batch, 0); /* address */
  215.                 OUT_BATCH(batch, 0); /* write data */
  216.  
  217.                 OUT_BATCH(batch, CMD_PIPE_CONTROL | (4 - 2));
  218.                 OUT_BATCH(batch, CMD_PIPE_CONTROL_WRITE_QWORD);
  219.                 OUT_RELOC(batch,
  220.                           batch->wa_render_bo,
  221.                           I915_GEM_DOMAIN_INSTRUCTION,
  222.                           I915_GEM_DOMAIN_INSTRUCTION,
  223.                           0);
  224.                 OUT_BATCH(batch, 0); /* write data */
  225.  
  226.                 /* now finally the _real flush */
  227.                 OUT_BATCH(batch, CMD_PIPE_CONTROL | (4 - 2));
  228.                 OUT_BATCH(batch,
  229.                           CMD_PIPE_CONTROL_WC_FLUSH |
  230.                           CMD_PIPE_CONTROL_TC_FLUSH |
  231.                           CMD_PIPE_CONTROL_NOWRITE);
  232.                 OUT_BATCH(batch, 0); /* write address */
  233.                 OUT_BATCH(batch, 0); /* write data */
  234.                 ADVANCE_BATCH(batch);
  235.             } else {
  236.                 BEGIN_BATCH(batch, 4);
  237.                 OUT_BATCH(batch, CMD_PIPE_CONTROL | (4 - 2));
  238.  
  239.                 OUT_BATCH(batch,
  240.                           CMD_PIPE_CONTROL_WC_FLUSH |
  241.                           CMD_PIPE_CONTROL_TC_FLUSH |
  242.                           CMD_PIPE_CONTROL_DC_FLUSH |
  243.                           CMD_PIPE_CONTROL_NOWRITE);
  244.                 OUT_BATCH(batch, 0); /* write address */
  245.                 OUT_BATCH(batch, 0); /* write data */
  246.                 ADVANCE_BATCH(batch);
  247.             }
  248.  
  249.         } else {
  250.             if (batch->flag == I915_EXEC_BLT) {
  251.                 BEGIN_BLT_BATCH(batch, 4);
  252.                 OUT_BLT_BATCH(batch, MI_FLUSH_DW);
  253.                 OUT_BLT_BATCH(batch, 0);
  254.                 OUT_BLT_BATCH(batch, 0);
  255.                 OUT_BLT_BATCH(batch, 0);
  256.                 ADVANCE_BLT_BATCH(batch);
  257.             }else if (batch->flag == I915_EXEC_VEBOX) {
  258.                 BEGIN_VEB_BATCH(batch, 4);
  259.                 OUT_VEB_BATCH(batch, MI_FLUSH_DW);
  260.                 OUT_VEB_BATCH(batch, 0);
  261.                 OUT_VEB_BATCH(batch, 0);
  262.                 OUT_VEB_BATCH(batch, 0);
  263.                 ADVANCE_VEB_BATCH(batch);
  264.             } else {
  265.                 assert(batch->flag == I915_EXEC_BSD);
  266.                 BEGIN_BCS_BATCH(batch, 4);
  267.                 OUT_BCS_BATCH(batch, MI_FLUSH_DW | MI_FLUSH_DW_VIDEO_PIPELINE_CACHE_INVALIDATE);
  268.                 OUT_BCS_BATCH(batch, 0);
  269.                 OUT_BCS_BATCH(batch, 0);
  270.                 OUT_BCS_BATCH(batch, 0);
  271.                 ADVANCE_BCS_BATCH(batch);
  272.             }
  273.         }
  274.     } else {
  275.         if (batch->flag == I915_EXEC_RENDER) {
  276.             BEGIN_BATCH(batch, 1);
  277.             OUT_BATCH(batch, MI_FLUSH | MI_FLUSH_STATE_INSTRUCTION_CACHE_INVALIDATE);
  278.             ADVANCE_BATCH(batch);              
  279.          } else {
  280.             assert(batch->flag == I915_EXEC_BSD);
  281.             BEGIN_BCS_BATCH(batch, 1);
  282.             OUT_BCS_BATCH(batch, MI_FLUSH | MI_FLUSH_STATE_INSTRUCTION_CACHE_INVALIDATE);
  283.             ADVANCE_BCS_BATCH(batch);
  284.         }
  285.     }
  286. }
  287.  
  288. void
  289. intel_batchbuffer_begin_batch(struct intel_batchbuffer *batch, int total)
  290. {
  291.     batch->emit_total = total * 4;
  292.     batch->emit_start = batch->ptr;
  293. }
  294.  
  295. void
  296. intel_batchbuffer_advance_batch(struct intel_batchbuffer *batch)
  297. {
  298.     assert(batch->emit_total == (batch->ptr - batch->emit_start));
  299. }
  300.  
  301. void
  302. intel_batchbuffer_check_batchbuffer_flag(struct intel_batchbuffer *batch, int flag)
  303. {
  304.     if (flag != I915_EXEC_RENDER &&
  305.         flag != I915_EXEC_BLT &&
  306.         flag != I915_EXEC_BSD &&
  307.         flag != I915_EXEC_VEBOX)
  308.         return;
  309.  
  310.     if (batch->flag == flag)
  311.         return;
  312.  
  313.     intel_batchbuffer_flush(batch);
  314.     batch->flag = flag;
  315. }
  316.  
  317. int
  318. intel_batchbuffer_check_free_space(struct intel_batchbuffer *batch, int size)
  319. {
  320.     return intel_batchbuffer_space(batch) >= size;
  321. }
  322.  
  323. static void
  324. intel_batchbuffer_start_atomic_helper(struct intel_batchbuffer *batch,
  325.                                       int flag,
  326.                                       unsigned int size)
  327. {
  328.     assert(!batch->atomic);
  329.     intel_batchbuffer_check_batchbuffer_flag(batch, flag);
  330.     intel_batchbuffer_require_space(batch, size);
  331.     batch->atomic = 1;
  332. }
  333.  
  334. void
  335. intel_batchbuffer_start_atomic(struct intel_batchbuffer *batch, unsigned int size)
  336. {
  337.     intel_batchbuffer_start_atomic_helper(batch, I915_EXEC_RENDER, size);
  338. }
  339.  
  340. void
  341. intel_batchbuffer_start_atomic_blt(struct intel_batchbuffer *batch, unsigned int size)
  342. {
  343.     intel_batchbuffer_start_atomic_helper(batch, I915_EXEC_BLT, size);
  344. }
  345.  
  346. void
  347. intel_batchbuffer_start_atomic_bcs(struct intel_batchbuffer *batch, unsigned int size)
  348. {
  349.     intel_batchbuffer_start_atomic_helper(batch, I915_EXEC_BSD, size);
  350. }
  351.  
  352. void
  353. intel_batchbuffer_start_atomic_veb(struct intel_batchbuffer *batch, unsigned int size)
  354. {
  355.     intel_batchbuffer_start_atomic_helper(batch, I915_EXEC_VEBOX, size);
  356. }
  357.  
  358.  
  359. void
  360. intel_batchbuffer_end_atomic(struct intel_batchbuffer *batch)
  361. {
  362.     assert(batch->atomic);
  363.     batch->atomic = 0;
  364. }
  365.  
  366. int
  367. intel_batchbuffer_used_size(struct intel_batchbuffer *batch)
  368. {
  369.     return batch->ptr - batch->map;
  370. }
  371.  
  372. void
  373. intel_batchbuffer_align(struct intel_batchbuffer *batch, unsigned int alignedment)
  374. {
  375.     int used = batch->ptr - batch->map;
  376.     int pad_size;
  377.  
  378.     assert((alignedment & 3) == 0);
  379.     pad_size = ALIGN(used, alignedment) - used;
  380.     assert((pad_size & 3) == 0);
  381.     assert(intel_batchbuffer_space(batch) >= pad_size);
  382.  
  383.     while (pad_size >= 4) {
  384.         intel_batchbuffer_emit_dword(batch, 0);
  385.         pad_size -= 4;
  386.     }
  387. }
  388.  
  389.