Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2014 Broadcom
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21.  * IN THE SOFTWARE.
  22.  */
  23.  
  24. #ifdef USE_VC4_SIMULATOR
  25.  
  26. #include "util/u_memory.h"
  27. #include "util/ralloc.h"
  28.  
  29. #include "vc4_screen.h"
  30. #include "vc4_context.h"
  31. #include "kernel/vc4_drv.h"
  32. #include "vc4_simulator_validate.h"
  33. #include "simpenrose/simpenrose.h"
  34.  
  35. #define OVERFLOW_SIZE (32 * 1024 * 1024)
  36.  
  37. static struct drm_gem_cma_object *
  38. vc4_wrap_bo_with_cma(struct drm_device *dev, struct vc4_bo *bo)
  39. {
  40.         struct vc4_context *vc4 = dev->vc4;
  41.         struct vc4_screen *screen = vc4->screen;
  42.         struct drm_gem_cma_object *obj = CALLOC_STRUCT(drm_gem_cma_object);
  43.         uint32_t size = align(bo->size, 4096);
  44.  
  45.         obj->bo = bo;
  46.         obj->base.size = size;
  47.         obj->vaddr = screen->simulator_mem_base + dev->simulator_mem_next;
  48.         obj->paddr = simpenrose_hw_addr(obj->vaddr);
  49.  
  50.         dev->simulator_mem_next += size;
  51.         dev->simulator_mem_next = align(dev->simulator_mem_next, 4096);
  52.         assert(dev->simulator_mem_next <= screen->simulator_mem_size);
  53.  
  54.         return obj;
  55. }
  56.  
  57. struct drm_gem_cma_object *
  58. drm_gem_cma_create(struct drm_device *dev, size_t size)
  59. {
  60.         struct vc4_context *vc4 = dev->vc4;
  61.         struct vc4_screen *screen = vc4->screen;
  62.  
  63.         struct vc4_bo *bo = vc4_bo_alloc(screen, size, "simulator validate");
  64.         return vc4_wrap_bo_with_cma(dev, bo);
  65. }
  66.  
  67. static int
  68. vc4_simulator_pin_bos(struct drm_device *dev, struct vc4_exec_info *exec)
  69. {
  70.         struct drm_vc4_submit_cl *args = exec->args;
  71.         struct vc4_context *vc4 = dev->vc4;
  72.         struct vc4_bo **bos = vc4->bo_pointers.base;
  73.  
  74.         exec->bo_count = args->bo_handle_count;
  75.         exec->bo = calloc(exec->bo_count, sizeof(struct vc4_bo_exec_state));
  76.         for (int i = 0; i < exec->bo_count; i++) {
  77.                 struct vc4_bo *bo = bos[i];
  78.                 struct drm_gem_cma_object *obj = vc4_wrap_bo_with_cma(dev, bo);
  79.  
  80. #if 0
  81.                 fprintf(stderr, "bo hindex %d: %s\n", i, bo->name);
  82. #endif
  83.  
  84.                 vc4_bo_map(bo);
  85.                 memcpy(obj->vaddr, bo->map, bo->size);
  86.  
  87.                 exec->bo[i].bo = obj;
  88.         }
  89.         return 0;
  90. }
  91.  
  92. static int
  93. vc4_simulator_unpin_bos(struct vc4_exec_info *exec)
  94. {
  95.         for (int i = 0; i < exec->bo_count; i++) {
  96.                 struct drm_gem_cma_object *obj = exec->bo[i].bo;
  97.                 struct vc4_bo *bo = obj->bo;
  98.  
  99.                 memcpy(bo->map, obj->vaddr, bo->size);
  100.  
  101.                 free(obj);
  102.         }
  103.  
  104.         free(exec->bo);
  105.  
  106.         return 0;
  107. }
  108.  
  109. int
  110. vc4_simulator_flush(struct vc4_context *vc4, struct drm_vc4_submit_cl *args)
  111. {
  112.         struct vc4_screen *screen = vc4->screen;
  113.         struct vc4_surface *csurf = vc4_surface(vc4->framebuffer.cbufs[0]);
  114.         struct vc4_resource *ctex = csurf ? vc4_resource(csurf->base.texture) : NULL;
  115.         uint32_t winsys_stride = ctex ? ctex->bo->simulator_winsys_stride : 0;
  116.         uint32_t sim_stride = ctex ? ctex->slices[0].stride : 0;
  117.         uint32_t row_len = MIN2(sim_stride, winsys_stride);
  118.         struct vc4_exec_info exec;
  119.         struct drm_device local_dev = {
  120.                 .vc4 = vc4,
  121.                 .simulator_mem_next = OVERFLOW_SIZE,
  122.         };
  123.         struct drm_device *dev = &local_dev;
  124.         int ret;
  125.  
  126.         memset(&exec, 0, sizeof(exec));
  127.  
  128.         if (ctex && ctex->bo->simulator_winsys_map) {
  129. #if 0
  130.                 fprintf(stderr, "%dx%d %d %d %d\n",
  131.                         ctex->base.b.width0, ctex->base.b.height0,
  132.                         winsys_stride,
  133.                         sim_stride,
  134.                         ctex->bo->size);
  135. #endif
  136.  
  137.                 for (int y = 0; y < ctex->base.b.height0; y++) {
  138.                         memcpy(ctex->bo->map + y * sim_stride,
  139.                                ctex->bo->simulator_winsys_map + y * winsys_stride,
  140.                                row_len);
  141.                 }
  142.         }
  143.  
  144.         exec.args = args;
  145.  
  146.         ret = vc4_simulator_pin_bos(dev, &exec);
  147.         if (ret)
  148.                 return ret;
  149.  
  150.         ret = vc4_cl_validate(dev, &exec);
  151.         if (ret)
  152.                 return ret;
  153.  
  154.         if (exec.ct0ca != exec.ct0ea) {
  155.                 int bfc = simpenrose_do_binning(exec.ct0ca, exec.ct0ea);
  156.                 if (bfc != 1) {
  157.                         fprintf(stderr, "Binning returned %d flushes, should be 1.\n",
  158.                                 bfc);
  159.                         fprintf(stderr, "Relocated binning command list:\n");
  160.                         vc4_dump_cl(screen->simulator_mem_base + exec.ct0ca,
  161.                                     exec.ct0ea - exec.ct0ca, false);
  162.                         abort();
  163.                 }
  164.         }
  165.         int rfc = simpenrose_do_rendering(exec.ct1ca, exec.ct1ea);
  166.         if (rfc != 1) {
  167.                 fprintf(stderr, "Rendering returned %d frames, should be 1.\n",
  168.                         rfc);
  169.                 fprintf(stderr, "Relocated render command list:\n");
  170.                 vc4_dump_cl(screen->simulator_mem_base + exec.ct1ca,
  171.                             exec.ct1ea - exec.ct1ca, true);
  172.                 abort();
  173.         }
  174.  
  175.         ret = vc4_simulator_unpin_bos(&exec);
  176.         if (ret)
  177.                 return ret;
  178.  
  179.         vc4_bo_unreference(&exec.exec_bo->bo);
  180.         free(exec.exec_bo);
  181.  
  182.         if (ctex && ctex->bo->simulator_winsys_map) {
  183.                 for (int y = 0; y < ctex->base.b.height0; y++) {
  184.                         memcpy(ctex->bo->simulator_winsys_map + y * winsys_stride,
  185.                                ctex->bo->map + y * sim_stride,
  186.                                row_len);
  187.                 }
  188.         }
  189.  
  190.         return 0;
  191. }
  192.  
  193. void
  194. vc4_simulator_init(struct vc4_screen *screen)
  195. {
  196.         screen->simulator_mem_size = 256 * 1024 * 1024;
  197.         screen->simulator_mem_base = ralloc_size(screen,
  198.                                                  screen->simulator_mem_size);
  199.  
  200.         /* We supply our own memory so that we can have more aperture
  201.          * available (256MB instead of simpenrose's default 64MB).
  202.          */
  203.         simpenrose_init_hardware_supply_mem(screen->simulator_mem_base,
  204.                                             screen->simulator_mem_size);
  205.  
  206.         /* Carve out low memory for tile allocation overflow.  The kernel
  207.          * should be automatically handling overflow memory setup on real
  208.          * hardware, but for simulation we just get one shot to set up enough
  209.          * overflow memory before execution.  This overflow mem will be used
  210.          * up over the whole lifetime of simpenrose (not reused on each
  211.          * flush), so it had better be big.
  212.          */
  213.         simpenrose_supply_overflow_mem(0, OVERFLOW_SIZE);
  214. }
  215.  
  216. #endif /* USE_VC4_SIMULATOR */
  217.