pvr: Change compute hard coding infrastructure.
authorKarmjit Mahil <Karmjit.Mahil@imgtec.com>
Wed, 1 Jun 2022 14:04:59 +0000 (15:04 +0100)
committerMarge Bot <emma+marge@anholt.net>
Mon, 20 Jun 2022 08:13:11 +0000 (08:13 +0000)
This commit changes the way in which the hard coding is done in
the compute pipeline to allow easier hard coding for demos other
than the simple-compute demo.

Signed-off-by: Karmjit Mahil <Karmjit.Mahil@imgtec.com>
Acked-by: Alyssa Rosenzweig <alyssa@collabora.com>
Reviewed-by: Frank Binns <frank.binns@imgtec.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16999>

src/imagination/vulkan/meson.build
src/imagination/vulkan/pvr_hardcode.c [new file with mode: 0644]
src/imagination/vulkan/pvr_hardcode.h [new file with mode: 0644]
src/imagination/vulkan/pvr_pipeline.c
src/imagination/vulkan/pvr_private.h
src/imagination/vulkan/usc/hardcoded_apps/pvr_simple_compute.h [moved from src/imagination/vulkan/usc/programs/pvr_usc_compute_shader.h with 95% similarity]

index 3b978dd..577f8e0 100644 (file)
@@ -43,6 +43,7 @@ pvr_files = files(
   'pvr_descriptor_set.c',
   'pvr_device.c',
   'pvr_formats.c',
+  'pvr_hardcode.c',
   'pvr_hw_pass.c',
   'pvr_image.c',
   'pvr_job_common.c',
diff --git a/src/imagination/vulkan/pvr_hardcode.c b/src/imagination/vulkan/pvr_hardcode.c
new file mode 100644 (file)
index 0000000..1091cf4
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright © 2022 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <vulkan/vulkan_core.h>
+
+#include "hwdef/rogue_hw_utils.h"
+#include "pvr_hardcode.h"
+#include "pvr_private.h"
+#include "rogue/rogue.h"
+#include "usc/hardcoded_apps/pvr_simple_compute.h"
+#include "util/macros.h"
+#include "util/u_process.h"
+
+/**
+ * \file pvr_hardcode.c
+ *
+ * \brief Contains hard coding functions.
+ * This should eventually be deleted as the compiler becomes more capable.
+ */
+
+/* Applications for which the compiler is capable of generating valid shaders.
+ */
+static const char *const compilable_progs[] = {
+   "triangle",
+};
+
+static const struct pvr_hard_coding_data {
+   const char *const name;
+
+   union {
+      struct {
+         const uint8_t *const shader;
+         size_t shader_size;
+
+         /* Note that the bo field will be unused. */
+         const struct pvr_compute_pipeline_shader_state shader_info;
+
+         const struct pvr_hard_code_compute_build_info build_info;
+      } compute;
+   };
+
+} hard_coding_table[] = {
+   {
+      .name = "simple-compute",
+      .compute = {
+         .shader = pvr_simple_compute_shader,
+         .shader_size = sizeof(pvr_simple_compute_shader),
+
+         .shader_info = {
+            .uses_atomic_ops = false,
+            .uses_barrier = false,
+            .uses_num_workgroups = false,
+
+            .const_shared_reg_count = 4,
+            .input_register_count = 8,
+            .work_size = 1 * 1 * 1,
+            .coefficient_register_count = 4,
+         },
+
+         .build_info = {
+            .ubo_data = { 0 },
+
+            .local_invocation_regs = { 0, 1 },
+            .work_group_regs = { 0, 1, 2 },
+            .barrier_reg = ROGUE_REG_UNUSED,
+            .usc_temps = 0,
+
+            .explicit_conts_usage = {
+               .start_offset = 0,
+            },
+         },
+      }
+   },
+};
+
+bool pvr_hard_code_shader_required(void)
+{
+   const char *const program = util_get_process_name();
+
+   for (uint32_t i = 0; i < ARRAY_SIZE(compilable_progs); i++) {
+      if (strcmp(program, compilable_progs[i]) == 0)
+         return false;
+   }
+
+   return true;
+}
+
+static const struct pvr_hard_coding_data *pvr_get_hard_coding_data()
+{
+   const char *const program = util_get_process_name();
+
+   for (uint32_t i = 0; i < ARRAY_SIZE(hard_coding_table); i++) {
+      if (strcmp(program, hard_coding_table[i].name) == 0)
+         return &hard_coding_table[i];
+   }
+
+   mesa_loge("Could not find hard coding data for %s", program);
+
+   return NULL;
+}
+
+VkResult pvr_hard_code_compute_pipeline(
+   struct pvr_device *const device,
+   struct pvr_compute_pipeline_shader_state *const shader_state_out,
+   struct pvr_hard_code_compute_build_info *const build_info_out)
+{
+   const uint32_t cache_line_size =
+      rogue_get_slc_cache_line_size(&device->pdevice->dev_info);
+   const struct pvr_hard_coding_data *const data = pvr_get_hard_coding_data();
+
+   mesa_logd("Hard coding compute pipeline for %s", data->name);
+
+   *build_info_out = data->compute.build_info;
+   *shader_state_out = data->compute.shader_info;
+
+   return pvr_gpu_upload_usc(device,
+                             data->compute.shader,
+                             data->compute.shader_size,
+                             cache_line_size,
+                             &shader_state_out->bo);
+}
diff --git a/src/imagination/vulkan/pvr_hardcode.h b/src/imagination/vulkan/pvr_hardcode.h
new file mode 100644 (file)
index 0000000..c663eb7
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2022 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef PVR_HARDCODE_SHADERS_H
+#define PVR_HARDCODE_SHADERS_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <vulkan/vulkan_core.h>
+
+#include "rogue/rogue_build_data.h"
+
+/**
+ * \file pvr_hardcode.h
+ *
+ * \brief Contains hard coding functions.
+ * This should eventually be deleted as the compiler becomes more capable.
+ */
+
+struct pvr_compute_pipeline_shader_state;
+struct pvr_device;
+
+struct pvr_explicit_constant_usage {
+   /* Hardware register number assigned to the explicit constant with the lower
+    * pre_assigned offset.
+    */
+   uint32_t start_offset;
+};
+
+struct pvr_hard_code_compute_build_info {
+   struct rogue_ubo_data ubo_data;
+
+   uint32_t local_invocation_regs[2];
+   uint32_t work_group_regs[3];
+   uint32_t barrier_reg;
+   uint32_t usc_temps;
+
+   struct pvr_explicit_constant_usage explicit_conts_usage;
+};
+
+/* Returns true if the shader for the currently running program requires hard
+ * coded shaders.
+ */
+bool pvr_hard_code_shader_required(void);
+
+VkResult pvr_hard_code_compute_pipeline(
+   struct pvr_device *const device,
+   struct pvr_compute_pipeline_shader_state *const shader_state_out,
+   struct pvr_hard_code_compute_build_info *const build_info_out);
+
+#endif /* PVR_HARDCODE_SHADERS_H */
index 9777210..e767868 100644 (file)
 #include "pvr_bo.h"
 #include "pvr_csb.h"
 #include "pvr_csb_enum_helpers.h"
+#include "pvr_hardcode.h"
 #include "pvr_pds.h"
 #include "pvr_private.h"
 #include "pvr_shader.h"
-#include "pvr_usc_compute_shader.h"
 #include "pvr_winsys.h"
 #include "rogue/rogue.h"
 #include "rogue/rogue_build_data.h"
 #include "vk_object.h"
 #include "vk_util.h"
 
-/* FIXME: Remove this when the compiler is hooked up. */
-/******************************************************************************
-   Hard coding
- ******************************************************************************/
-/* This section contains hard coding related structs. */
-
-struct pvr_explicit_constant_usage {
-   /* Hardware register number assigned to the explicit constant with the lower
-    * pre_assigned offset.
-    */
-   uint32_t start_offset;
-};
-
-static const struct {
-   uint32_t local_invocation_regs[2];
-
-   uint32_t work_group_regs[PVR_WORKGROUP_DIMENSIONS];
-
-   uint32_t barrier_reg;
-
-   uint32_t usc_temps;
-} pvr_pds_compute_program_params = {
-   .local_invocation_regs = { 0, 1 },
-
-   .work_group_regs = { 0, 1, 2 },
-
-   .barrier_reg = ROGUE_REG_UNUSED,
-
-   .usc_temps = 0,
-};
-
 /*****************************************************************************
    PDS functions
 *****************************************************************************/
@@ -1043,42 +1012,58 @@ static VkResult pvr_compute_pipeline_compile(
    const VkAllocationCallbacks *const allocator,
    struct pvr_compute_pipeline *const compute_pipeline)
 {
-   /* FIXME: Remove this hard coding. */
-   const struct pvr_explicit_constant_usage explicit_const_usage = {
-      .start_offset = 0,
-   };
-   const struct rogue_ubo_data uniform_program_ubo_data = { 0 };
-
-   const uint32_t cache_line_size =
-      rogue_get_slc_cache_line_size(&device->pdevice->dev_info);
    uint32_t work_group_input_regs[PVR_WORKGROUP_DIMENSIONS];
+   struct pvr_explicit_constant_usage explicit_const_usage;
    uint32_t local_input_regs[PVR_WORKGROUP_DIMENSIONS];
+   struct rogue_ubo_data ubo_data;
    uint32_t barrier_coefficient;
+   uint32_t usc_temps;
    VkResult result;
 
-   /* FIXME: Compile the shader. */
+   if (pvr_hard_code_shader_required()) {
+      struct pvr_hard_code_compute_build_info build_info;
 
-   /* FIXME: Remove this hard coding. */
-   compute_pipeline->state.shader.uses_atomic_ops = false;
-   compute_pipeline->state.shader.uses_barrier = false;
-   compute_pipeline->state.shader.uses_num_workgroups = false;
-   compute_pipeline->state.shader.const_shared_reg_count = 4;
-   compute_pipeline->state.shader.input_register_count = 8;
-   compute_pipeline->state.shader.work_size = 1 * 1 * 1;
-   compute_pipeline->state.shader.coefficient_register_count = 4;
+      result = pvr_hard_code_compute_pipeline(device,
+                                              &compute_pipeline->state.shader,
+                                              &build_info);
+      if (result != VK_SUCCESS)
+         return result;
 
-   result = pvr_gpu_upload_usc(device,
-                               pvr_usc_compute_shader,
-                               sizeof(pvr_usc_compute_shader),
-                               cache_line_size,
-                               &compute_pipeline->state.shader.bo);
-   if (result != VK_SUCCESS)
-      return result;
+      ubo_data = build_info.ubo_data;
+
+      /* We make sure that the compiler's unused reg value is compatible with
+       * the pds api.
+       */
+      STATIC_ASSERT(ROGUE_REG_UNUSED == PVR_PDS_COMPUTE_INPUT_REG_UNUSED);
+
+      barrier_coefficient = build_info.barrier_reg;
+
+      /* TODO: Maybe change the pds api to use pointers so we avoid the copy. */
+      local_input_regs[0] = build_info.local_invocation_regs[0];
+      local_input_regs[1] = build_info.local_invocation_regs[1];
+      /* This is not a mistake. We want to assign element 1 to 2. */
+      local_input_regs[2] = build_info.local_invocation_regs[1];
+
+      STATIC_ASSERT(
+         __same_type(work_group_input_regs, build_info.work_group_regs));
+      typed_memcpy(work_group_input_regs,
+                   build_info.work_group_regs,
+                   PVR_WORKGROUP_DIMENSIONS);
+
+      usc_temps = build_info.usc_temps;
+
+      explicit_const_usage = build_info.explicit_conts_usage;
+
+   } else {
+      /* FIXME: Compile and upload the shader. */
+      /* FIXME: Initialize the shader state and setup build info. */
+      abort();
+   };
 
    result = pvr_pds_uniform_program_create_and_upload(
       device,
       allocator,
-      &uniform_program_ubo_data,
+      &ubo_data,
       &explicit_const_usage,
       compute_pipeline->base.layout,
       PVR_STAGE_ALLOCATION_COMPUTE,
@@ -1087,35 +1072,13 @@ static VkResult pvr_compute_pipeline_compile(
    if (result != VK_SUCCESS)
       goto err_free_shader;
 
-   /* We make sure that the compiler's unused reg value is compatible with the
-    * pds api.
-    */
-   STATIC_ASSERT(ROGUE_REG_UNUSED == PVR_PDS_COMPUTE_INPUT_REG_UNUSED);
-
-   barrier_coefficient = pvr_pds_compute_program_params.barrier_reg;
-
-   /* TODO: Maybe change the pds api to use pointers so we avoid the copy. */
-   local_input_regs[0] =
-      pvr_pds_compute_program_params.local_invocation_regs[0];
-   local_input_regs[1] =
-      pvr_pds_compute_program_params.local_invocation_regs[1];
-   /* This is not a mistake. We want to assign element 1 to 2. */
-   local_input_regs[2] =
-      pvr_pds_compute_program_params.local_invocation_regs[1];
-
-   STATIC_ASSERT(__same_type(work_group_input_regs,
-                             pvr_pds_compute_program_params.work_group_regs));
-   typed_memcpy(work_group_input_regs,
-                pvr_pds_compute_program_params.work_group_regs,
-                PVR_WORKGROUP_DIMENSIONS);
-
    result = pvr_pds_compute_program_create_and_upload(
       device,
       allocator,
       local_input_regs,
       work_group_input_regs,
       barrier_coefficient,
-      pvr_pds_compute_program_params.usc_temps,
+      usc_temps,
       compute_pipeline->state.shader.bo->vma->dev_addr,
       &compute_pipeline->state.primary_program,
       &compute_pipeline->state.primary_program_info);
@@ -1137,7 +1100,7 @@ static VkResult pvr_compute_pipeline_compile(
          local_input_regs,
          work_group_input_regs,
          barrier_coefficient,
-         pvr_pds_compute_program_params.usc_temps,
+         usc_temps,
          compute_pipeline->state.shader.bo->vma->dev_addr,
          &compute_pipeline->state.primary_base_workgroup_variant_program);
       if (result != VK_SUCCESS)
index 4b687db..64130d7 100644 (file)
@@ -1037,7 +1037,10 @@ struct pvr_compute_pipeline {
    struct pvr_pipeline base;
 
    struct {
-      struct {
+      /* TODO: Change this to be an anonymous struct once the shader hardcoding
+       * is removed.
+       */
+      struct pvr_compute_pipeline_shader_state {
          /* Pointer to a buffer object that contains the shader binary. */
          struct pvr_bo *bo;
 
 
 /* Auto-generated file - don't edit */
 
-#ifndef PVR_USC_COMPUTE_SHADER_H
-#define PVR_USC_COMPUTE_SHADER_H
+#ifndef PVR_SIMPLE_COMPUTE_H
+#define PVR_SIMPLE_COMPUTE_H
 
 #include <stdint.h>
 
 /* clang-format off */
-uint8_t pvr_usc_compute_shader[] = {
+static const uint8_t pvr_simple_compute_shader[] = {
    0x44, 0x12, 0xd3, 0x3f,
    0x00, 0x00, 0x00, 0x24,
    0x46, 0x40, 0xf9, 0xb0,
@@ -99,4 +99,4 @@ uint8_t pvr_usc_compute_shader[] = {
 };
 /* clang-format on */
 
-#endif /* PVR_USC_COMPUTE_SHADER_H */
+#endif /* PVR_SIMPLE_COMPUTE_H */