#include <string.h>
#include <vulkan/vulkan_core.h>
+#include "compiler/shader_enums.h"
#include "hwdef/rogue_hw_utils.h"
+#include "pvr_device_info.h"
#include "pvr_hardcode.h"
#include "pvr_private.h"
#include "rogue/rogue.h"
* This should eventually be deleted as the compiler becomes more capable.
*/
+#define PVR_AXE_1_16M_BVNC PVR_BVNC_PACK(33, 15, 11, 3)
+#define PVR_GX6250_BVNC PVR_BVNC_PACK(4, 40, 2, 51)
+
enum pvr_hard_code_shader_type {
PVR_HARD_CODE_SHADER_TYPE_COMPUTE,
PVR_HARD_CODE_SHADER_TYPE_GRAPHICS,
};
-/* Applications for which the compiler is capable of generating valid shaders.
+/* Table indicating which demo and for which device the compiler is capable of
+ * generating valid shaders.
*/
-static const char *const compilable_progs[] = {
- "triangle",
+static struct {
+ const char *const name;
+ uint64_t bvncs[3];
+} compatiblity_table[] = {
+ {
+ .name = "triangle",
+ .bvncs = { PVR_GX6250_BVNC, },
+ },
};
static const struct pvr_hard_coding_data {
const char *const name;
+ uint64_t bvnc;
enum pvr_hard_code_shader_type type;
union {
} compute;
struct {
+ /* Mask of MESA_SHADER_* (gl_shader_stage). */
+ uint32_t flags;
+
struct rogue_shader_binary *const *const vert_shaders;
struct rogue_shader_binary *const *const frag_shaders;
} hard_coding_table[] = {
{
.name = "simple-compute",
+ .bvnc = PVR_GX6250_BVNC,
.type = PVR_HARD_CODE_SHADER_TYPE_COMPUTE,
.compute = {
},
};
-bool pvr_hard_code_shader_required(void)
+static inline uint64_t
+pvr_device_get_bvnc(const struct pvr_device_info *const dev_info)
+{
+ const struct pvr_device_ident *const ident = &dev_info->ident;
+
+ return PVR_BVNC_PACK(ident->b, ident->v, ident->n, ident->c);
+}
+
+bool pvr_hard_code_shader_required(const struct pvr_device_info *const dev_info)
{
const char *const program = util_get_process_name();
+ const uint64_t bvnc = pvr_device_get_bvnc(dev_info);
+
+ for (uint32_t i = 0; i < ARRAY_SIZE(compatiblity_table); i++) {
+ for (uint32_t j = 0; j < ARRAY_SIZE(compatiblity_table[0].bvncs); j++) {
+ if (bvnc != compatiblity_table[i].bvncs[j])
+ continue;
- for (uint32_t i = 0; i < ARRAY_SIZE(compilable_progs); i++) {
- if (strcmp(program, compilable_progs[i]) == 0)
- return false;
+ if (strcmp(program, compatiblity_table[i].name) == 0)
+ return false;
+ }
}
return true;
}
-static const struct pvr_hard_coding_data *pvr_get_hard_coding_data()
+static const struct pvr_hard_coding_data *
+pvr_get_hard_coding_data(const struct pvr_device_info *const dev_info)
{
const char *const program = util_get_process_name();
+ const uint64_t bvnc = pvr_device_get_bvnc(dev_info);
for (uint32_t i = 0; i < ARRAY_SIZE(hard_coding_table); i++) {
+ if (bvnc != hard_coding_table[i].bvnc)
+ continue;
+
if (strcmp(program, hard_coding_table[i].name) == 0)
return &hard_coding_table[i];
}
{
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();
+ const struct pvr_hard_coding_data *const data =
+ pvr_get_hard_coding_data(&device->pdevice->dev_info);
assert(data->type == PVR_HARD_CODE_SHADER_TYPE_COMPUTE);
&shader_state_out->bo);
}
-void pvr_hard_code_graphics_shaders(
- uint32_t pipeline_n,
- struct rogue_shader_binary **const vert_shader_out,
- struct rogue_shader_binary **const frag_shader_out)
+uint32_t
+pvr_hard_code_graphics_get_flags(const struct pvr_device_info *const dev_info)
{
- const struct pvr_hard_coding_data *const data = pvr_get_hard_coding_data();
+ const struct pvr_hard_coding_data *const data =
+ pvr_get_hard_coding_data(dev_info);
+
+ assert(data->type == PVR_HARD_CODE_SHADER_TYPE_GRAPHICS);
+
+ return data->graphics.flags;
+}
+
+void pvr_hard_code_graphics_shader(const struct pvr_device_info *const dev_info,
+ uint32_t pipeline_n,
+ gl_shader_stage stage,
+ struct rogue_shader_binary **const shader_out)
+{
+ const struct pvr_hard_coding_data *const data =
+ pvr_get_hard_coding_data(dev_info);
assert(data->type == PVR_HARD_CODE_SHADER_TYPE_GRAPHICS);
assert(pipeline_n < data->graphics.shader_count);
+ assert(data->graphics.flags & BITFIELD_BIT(stage));
+
+ mesa_logd("Hard coding %s stage shader for \"%s\" demo.",
+ _mesa_shader_stage_to_string(stage),
+ data->name);
- mesa_logd("Hard coding graphics pipeline for %s", data->name);
+ switch (stage) {
+ case MESA_SHADER_VERTEX:
+ *shader_out = data->graphics.vert_shaders[pipeline_n];
+ break;
- *vert_shader_out = data->graphics.vert_shaders[pipeline_n];
- *frag_shader_out = data->graphics.frag_shaders[pipeline_n];
+ case MESA_SHADER_FRAGMENT:
+ *shader_out = data->graphics.frag_shaders[pipeline_n];
+ break;
+
+ default:
+ unreachable("Unsupported stage.");
+ }
}
void pvr_hard_code_graphics_vertex_state(
+ const struct pvr_device_info *const dev_info,
uint32_t pipeline_n,
struct pvr_vertex_shader_state *const vert_state_out)
{
- const struct pvr_hard_coding_data *const data = pvr_get_hard_coding_data();
+ const struct pvr_hard_coding_data *const data =
+ pvr_get_hard_coding_data(dev_info);
assert(data->type == PVR_HARD_CODE_SHADER_TYPE_GRAPHICS);
assert(pipeline_n < data->graphics.shader_count);
+ assert(data->graphics.flags & BITFIELD_BIT(MESA_SHADER_VERTEX));
*vert_state_out = *data->graphics.vert_shader_states[0];
}
void pvr_hard_code_graphics_fragment_state(
+ const struct pvr_device_info *const dev_info,
uint32_t pipeline_n,
struct pvr_fragment_shader_state *const frag_state_out)
{
- const struct pvr_hard_coding_data *const data = pvr_get_hard_coding_data();
+ const struct pvr_hard_coding_data *const data =
+ pvr_get_hard_coding_data(dev_info);
assert(data->type == PVR_HARD_CODE_SHADER_TYPE_GRAPHICS);
assert(pipeline_n < data->graphics.shader_count);
+ assert(data->graphics.flags & BITFIELD_BIT(MESA_SHADER_FRAGMENT));
*frag_state_out = *data->graphics.frag_shader_states[0];
}
-void pvr_hard_code_graphics_inject_build_info(
+void pvr_hard_code_graphics_get_build_info(
+ const struct pvr_device_info *const dev_info,
uint32_t pipeline_n,
- struct rogue_build_ctx *ctx,
- struct pvr_explicit_constant_usage *const vert_common_data_out,
- struct pvr_explicit_constant_usage *const frag_common_data_out)
+ gl_shader_stage stage,
+ struct rogue_common_build_data *const common_build_data,
+ struct rogue_build_data *const build_data,
+ struct pvr_explicit_constant_usage *const explicit_const_usage)
{
- const struct pvr_hard_coding_data *const data = pvr_get_hard_coding_data();
+ const struct pvr_hard_coding_data *const data =
+ pvr_get_hard_coding_data(dev_info);
assert(data->type == PVR_HARD_CODE_SHADER_TYPE_GRAPHICS);
assert(pipeline_n < data->graphics.shader_count);
+ assert(data->graphics.flags & BITFIELD_BIT(stage));
+
+ switch (stage) {
+ case MESA_SHADER_VERTEX:
+ assert(
+ data->graphics.build_infos[pipeline_n]->vert_common_data.temps ==
+ data->graphics.vert_shader_states[pipeline_n]->stage_state.temps_count);
+
+ assert(data->graphics.build_infos[pipeline_n]->vert_common_data.coeffs ==
+ data->graphics.vert_shader_states[pipeline_n]
+ ->stage_state.coefficient_size);
- ctx->stage_data = data->graphics.build_infos[pipeline_n]->stage_data;
- ctx->common_data[MESA_SHADER_VERTEX] =
- data->graphics.build_infos[pipeline_n]->vert_common_data;
- ctx->common_data[MESA_SHADER_FRAGMENT] =
- data->graphics.build_infos[pipeline_n]->frag_common_data;
-
- assert(
- ctx->common_data[MESA_SHADER_VERTEX].temps ==
- data->graphics.vert_shader_states[pipeline_n]->stage_state.temps_count);
- assert(
- ctx->common_data[MESA_SHADER_FRAGMENT].temps ==
- data->graphics.frag_shader_states[pipeline_n]->stage_state.temps_count);
-
- assert(ctx->common_data[MESA_SHADER_VERTEX].coeffs ==
- data->graphics.vert_shader_states[pipeline_n]
- ->stage_state.coefficient_size);
- assert(ctx->common_data[MESA_SHADER_FRAGMENT].coeffs ==
- data->graphics.frag_shader_states[pipeline_n]
- ->stage_state.coefficient_size);
-
- *vert_common_data_out =
- data->graphics.build_infos[pipeline_n]->vert_explicit_conts_usage;
- *frag_common_data_out =
- data->graphics.build_infos[pipeline_n]->frag_explicit_conts_usage;
+ build_data->vs = data->graphics.build_infos[pipeline_n]->stage_data.vs;
+ *common_build_data =
+ data->graphics.build_infos[pipeline_n]->vert_common_data;
+ *explicit_const_usage =
+ data->graphics.build_infos[pipeline_n]->vert_explicit_conts_usage;
+
+ break;
+
+ case MESA_SHADER_FRAGMENT:
+ assert(
+ data->graphics.build_infos[pipeline_n]->frag_common_data.temps ==
+ data->graphics.frag_shader_states[pipeline_n]->stage_state.temps_count);
+
+ assert(data->graphics.build_infos[pipeline_n]->frag_common_data.coeffs ==
+ data->graphics.frag_shader_states[pipeline_n]
+ ->stage_state.coefficient_size);
+
+ build_data->fs = data->graphics.build_infos[pipeline_n]->stage_data.fs;
+ *common_build_data =
+ data->graphics.build_infos[pipeline_n]->frag_common_data;
+ *explicit_const_usage =
+ data->graphics.build_infos[pipeline_n]->frag_explicit_conts_usage;
+
+ break;
+
+ default:
+ unreachable("Unsupported stage.");
+ }
}
#include <stdint.h>
#include <vulkan/vulkan_core.h>
+#include "compiler/shader_enums.h"
#include "rogue/rogue_build_data.h"
/**
struct pvr_compute_pipeline_shader_state;
struct pvr_device;
struct pvr_fragment_shader_state;
+struct pvr_hard_coding_data;
struct pvr_vertex_shader_state;
struct pvr_explicit_constant_usage {
/* Returns true if the shader for the currently running program requires hard
* coded shaders.
*/
-bool pvr_hard_code_shader_required(void);
+bool pvr_hard_code_shader_required(const struct pvr_device_info *const dev_info);
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);
+/* Returns a mask of MESA_SHADER_* (gl_shader_stage) indicating which stage
+ * needs to be hard coded.
+ */
+uint32_t
+pvr_hard_code_graphics_get_flags(const struct pvr_device_info *const dev_info);
+
/* pipeline_n:
* The pipeline number. Each pipeline created requires unique hard
* coding so a pipeline number is necessary to identify which data to use.
* This pipeline number to request data for the first pipeline to be created
* is 0 and should be incremented for each subsequent pipeline.
*/
-void pvr_hard_code_graphics_shaders(
+void pvr_hard_code_graphics_shader(
+ const struct pvr_device_info *const dev_info,
uint32_t pipeline_n,
- struct rogue_shader_binary **const vert_shader_out,
- struct rogue_shader_binary **const frag_shader_out);
+ gl_shader_stage stage,
+ struct rogue_shader_binary **const shader_out);
void pvr_hard_code_graphics_vertex_state(
+ const struct pvr_device_info *const dev_info,
uint32_t pipeline_n,
- struct pvr_vertex_shader_state *vert_state);
+ struct pvr_vertex_shader_state *const vert_state_out);
void pvr_hard_code_graphics_fragment_state(
- uint32_t pipelien_n,
- struct pvr_fragment_shader_state *frag_state);
+ const struct pvr_device_info *const dev_info,
+ uint32_t pipeline_n,
+ struct pvr_fragment_shader_state *const frag_state_out);
-void pvr_hard_code_graphics_inject_build_info(
+void pvr_hard_code_graphics_get_build_info(
+ const struct pvr_device_info *const dev_info,
uint32_t pipeline_n,
- struct rogue_build_ctx *ctx,
- struct pvr_explicit_constant_usage *const vert_common_data_out,
- struct pvr_explicit_constant_usage *const frag_common_data_out);
+ gl_shader_stage stage,
+ struct rogue_common_build_data *const common_build_data,
+ struct rogue_build_data *const build_data,
+ struct pvr_explicit_constant_usage *const explicit_const_usage);
#endif /* PVR_HARDCODE_SHADERS_H */
uint32_t usc_temps;
VkResult result;
- if (pvr_hard_code_shader_required()) {
+ if (pvr_hard_code_shader_required(&device->pdevice->dev_info)) {
struct pvr_hard_code_compute_build_info build_info;
result = pvr_hard_code_compute_pipeline(device,
struct pvr_explicit_constant_usage frag_explicit_const_usage = {
.start_offset = 0,
};
- const bool requires_hard_coding = pvr_hard_code_shader_required();
static uint32_t hard_code_pipeline_n = 0;
const VkPipelineVertexInputStateCreateInfo *const vertex_input_state =
if (!ctx)
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
- if (requires_hard_coding) {
- pvr_hard_code_graphics_shaders(hard_code_pipeline_n,
- &ctx->binary[MESA_SHADER_VERTEX],
- &ctx->binary[MESA_SHADER_FRAGMENT]);
- } else {
- /* NIR middle-end translation. */
- for (gl_shader_stage stage = MESA_SHADER_FRAGMENT;
- stage > MESA_SHADER_NONE;
- stage--) {
- const VkPipelineShaderStageCreateInfo *create_info;
- size_t stage_index = gfx_pipeline->stage_indices[stage];
-
- /* Skip unused/inactive stages. */
- if (stage_index == ~0)
+ /* NIR middle-end translation. */
+ for (gl_shader_stage stage = MESA_SHADER_FRAGMENT; stage > MESA_SHADER_NONE;
+ stage--) {
+ const VkPipelineShaderStageCreateInfo *create_info;
+ size_t stage_index = gfx_pipeline->stage_indices[stage];
+
+ if (pvr_hard_code_shader_required(&device->pdevice->dev_info)) {
+ if (pvr_hard_code_graphics_get_flags(&device->pdevice->dev_info) &
+ BITFIELD_BIT(stage)) {
continue;
+ }
+ }
- create_info = &pCreateInfo->pStages[stage_index];
+ /* Skip unused/inactive stages. */
+ if (stage_index == ~0)
+ continue;
- /* SPIR-V to NIR. */
- ctx->nir[stage] = pvr_spirv_to_nir(ctx, stage, create_info);
- if (!ctx->nir[stage]) {
- ralloc_free(ctx);
- return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
- }
+ create_info = &pCreateInfo->pStages[stage_index];
+
+ /* SPIR-V to NIR. */
+ ctx->nir[stage] = pvr_spirv_to_nir(ctx, stage, create_info);
+ if (!ctx->nir[stage]) {
+ ralloc_free(ctx);
+ return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
}
+ }
- /* Pre-back-end analysis and optimization, driver data extraction. */
- /* TODO: Analyze and cull unused I/O between stages. */
- /* TODO: Allocate UBOs between stages;
- * pipeline->layout->set_{count,layout}.
- */
+ /* Pre-back-end analysis and optimization, driver data extraction. */
+ /* TODO: Analyze and cull unused I/O between stages. */
+ /* TODO: Allocate UBOs between stages;
+ * pipeline->layout->set_{count,layout}.
+ */
- /* Back-end translation. */
- for (gl_shader_stage stage = MESA_SHADER_FRAGMENT;
- stage > MESA_SHADER_NONE;
- stage--) {
- if (!ctx->nir[stage])
- continue;
+ /* Back-end translation. */
+ for (gl_shader_stage stage = MESA_SHADER_FRAGMENT; stage > MESA_SHADER_NONE;
+ stage--) {
+ if (pvr_hard_code_shader_required(&device->pdevice->dev_info) &&
+ pvr_hard_code_graphics_get_flags(&device->pdevice->dev_info) &
+ BITFIELD_BIT(stage)) {
+ const struct pvr_device_info *const dev_info =
+ &device->pdevice->dev_info;
+ struct pvr_explicit_constant_usage *explicit_const_usage;
+
+ switch (stage) {
+ case MESA_SHADER_VERTEX:
+ explicit_const_usage = &vert_explicit_const_usage;
+ break;
- ctx->rogue[stage] = pvr_nir_to_rogue(ctx, ctx->nir[stage]);
- if (!ctx->rogue[stage]) {
- ralloc_free(ctx);
- return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
- }
+ case MESA_SHADER_FRAGMENT:
+ explicit_const_usage = &frag_explicit_const_usage;
+ break;
- ctx->binary[stage] = pvr_rogue_to_binary(ctx, ctx->rogue[stage]);
- if (!ctx->binary[stage]) {
- ralloc_free(ctx);
- return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
+ default:
+ unreachable("Unsupported stage.");
}
+
+ pvr_hard_code_graphics_shader(dev_info,
+ hard_code_pipeline_n,
+ stage,
+ &ctx->binary[stage]);
+
+ pvr_hard_code_graphics_get_build_info(dev_info,
+ hard_code_pipeline_n,
+ stage,
+ &ctx->common_data[stage],
+ &ctx->stage_data,
+ explicit_const_usage);
+
+ continue;
+ }
+
+ if (!ctx->nir[stage])
+ continue;
+
+ ctx->rogue[stage] = pvr_nir_to_rogue(ctx, ctx->nir[stage]);
+ if (!ctx->rogue[stage]) {
+ ralloc_free(ctx);
+ return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
+ }
+
+ ctx->binary[stage] = pvr_rogue_to_binary(ctx, ctx->rogue[stage]);
+ if (!ctx->binary[stage]) {
+ ralloc_free(ctx);
+ return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
}
}
- if (requires_hard_coding) {
- pvr_hard_code_graphics_vertex_state(hard_code_pipeline_n,
+ if (pvr_hard_code_shader_required(&device->pdevice->dev_info) &&
+ pvr_hard_code_graphics_get_flags(&device->pdevice->dev_info) &
+ BITFIELD_BIT(MESA_SHADER_VERTEX)) {
+ pvr_hard_code_graphics_vertex_state(&device->pdevice->dev_info,
+ hard_code_pipeline_n,
&gfx_pipeline->vertex_shader_state);
} else {
pvr_vertex_state_init(gfx_pipeline,
if (result != VK_SUCCESS)
goto err_free_build_context;
- if (requires_hard_coding) {
+ if (pvr_hard_code_shader_required(&device->pdevice->dev_info) &&
+ pvr_hard_code_graphics_get_flags(&device->pdevice->dev_info) &
+ BITFIELD_BIT(MESA_SHADER_FRAGMENT)) {
pvr_hard_code_graphics_fragment_state(
+ &device->pdevice->dev_info,
hard_code_pipeline_n,
&gfx_pipeline->fragment_shader_state);
} else {
* case the optimization doesn't happen.
*/
- if (requires_hard_coding) {
- pvr_hard_code_graphics_inject_build_info(hard_code_pipeline_n,
- ctx,
- &vert_explicit_const_usage,
- &frag_explicit_const_usage);
- }
-
/* TODO: The programs we use are hard coded for now, but these should be
* selected dynamically.
*/