summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIago Toral Quiroga <itoral@igalia.com>2020-06-18 11:06:00 +0200
committerMarge Bot <eric+marge@anholt.net>2020-10-13 21:21:31 +0000
commit67d5b0c91f8a0c96c25dfe2df52ca40125c07024 (patch)
tree3f3321566278afe25d2313371a265c65a2f06cbe
parent682cfd84d98c30cdc30ff76334c2f01c18e0441d (diff)
v3dv: support compute pipelines
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
-rw-r--r--src/broadcom/vulkan/v3dv_cmd_buffer.c19
-rw-r--r--src/broadcom/vulkan/v3dv_pipeline.c162
-rw-r--r--src/broadcom/vulkan/v3dv_private.h2
3 files changed, 175 insertions, 8 deletions
diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c
index edbf0e92f72..ea0eb5631ac 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -2694,6 +2694,7 @@ static void
bind_graphics_pipeline(struct v3dv_cmd_buffer *cmd_buffer,
struct v3dv_pipeline *pipeline)
{
+ assert(pipeline && !(pipeline->active_stages & VK_SHADER_STAGE_COMPUTE_BIT));
if (cmd_buffer->state.pipeline == pipeline)
return;
@@ -2724,6 +2725,19 @@ bind_graphics_pipeline(struct v3dv_cmd_buffer *cmd_buffer,
cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_PIPELINE;
}
+static void
+bind_compute_pipeline(struct v3dv_cmd_buffer *cmd_buffer,
+ struct v3dv_pipeline *pipeline)
+{
+ assert(pipeline && pipeline->active_stages == VK_SHADER_STAGE_COMPUTE_BIT);
+
+ if (cmd_buffer->state.pipeline == pipeline)
+ return;
+
+ cmd_buffer->state.pipeline = pipeline;
+ cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_PIPELINE;
+}
+
void
v3dv_CmdBindPipeline(VkCommandBuffer commandBuffer,
VkPipelineBindPoint pipelineBindPoint,
@@ -2734,7 +2748,7 @@ v3dv_CmdBindPipeline(VkCommandBuffer commandBuffer,
switch (pipelineBindPoint) {
case VK_PIPELINE_BIND_POINT_COMPUTE:
- assert(!"VK_PIPELINE_BIND_POINT_COMPUTE not supported yet");
+ bind_compute_pipeline(cmd_buffer, pipeline);
break;
case VK_PIPELINE_BIND_POINT_GRAPHICS:
@@ -3671,6 +3685,9 @@ cmd_buffer_pre_draw_split_job(struct v3dv_cmd_buffer *cmd_buffer)
static void
cmd_buffer_emit_pre_draw(struct v3dv_cmd_buffer *cmd_buffer)
{
+ assert(cmd_buffer->state.pipeline);
+ assert(!(cmd_buffer->state.pipeline->active_stages & VK_SHADER_STAGE_COMPUTE_BIT));
+
/* If the job is configured to flush on every draw call we need to create
* a new job now.
*/
diff --git a/src/broadcom/vulkan/v3dv_pipeline.c b/src/broadcom/vulkan/v3dv_pipeline.c
index 32addf496b8..d6d69f624f7 100644
--- a/src/broadcom/vulkan/v3dv_pipeline.c
+++ b/src/broadcom/vulkan/v3dv_pipeline.c
@@ -94,6 +94,9 @@ destroy_pipeline_stage(struct v3dv_device *device,
struct v3dv_pipeline_stage *p_stage,
const VkAllocationCallbacks *pAllocator)
{
+ if (!p_stage)
+ return;
+
hash_table_foreach(p_stage->cache, entry) {
struct v3dv_shader_variant *variant = entry->data;
@@ -125,6 +128,7 @@ v3dv_destroy_pipeline(struct v3dv_pipeline *pipeline,
destroy_pipeline_stage(device, pipeline->vs, pAllocator);
destroy_pipeline_stage(device, pipeline->vs_bin, pAllocator);
destroy_pipeline_stage(device, pipeline->fs, pAllocator);
+ destroy_pipeline_stage(device, pipeline->cs, pAllocator);
if (pipeline->default_attribute_values) {
v3dv_bo_free(device, pipeline->default_attribute_values);
@@ -821,7 +825,6 @@ shader_debug_output(const char *message, void *data)
static void
pipeline_populate_v3d_key(struct v3d_key *key,
- const VkGraphicsPipelineCreateInfo *pCreateInfo,
const struct v3dv_pipeline_stage *p_stage)
{
/* The following values are default values used at pipeline create, that
@@ -900,7 +903,7 @@ pipeline_populate_v3d_fs_key(struct v3d_fs_key *key,
{
memset(key, 0, sizeof(*key));
- pipeline_populate_v3d_key(&key->base, pCreateInfo, p_stage);
+ pipeline_populate_v3d_key(&key->base, p_stage);
const VkPipelineInputAssemblyStateCreateInfo *ia_info =
pCreateInfo->pInputAssemblyState;
@@ -1019,7 +1022,7 @@ pipeline_populate_v3d_vs_key(struct v3d_vs_key *key,
{
memset(key, 0, sizeof(*key));
- pipeline_populate_v3d_key(&key->base, pCreateInfo, p_stage);
+ pipeline_populate_v3d_key(&key->base, p_stage);
/* Vulkan doesn't appear to specify (anv does the same) */
key->clamp_color = false;
@@ -1067,6 +1070,12 @@ vs_cache_hash(const void *key)
return _mesa_hash_data(key, sizeof(struct v3d_vs_key));
}
+static uint32_t
+cs_cache_hash(const void *key)
+{
+ return _mesa_hash_data(key, sizeof(struct v3d_key));
+}
+
static bool
fs_cache_compare(const void *key1, const void *key2)
{
@@ -1079,6 +1088,12 @@ vs_cache_compare(const void *key1, const void *key2)
return memcmp(key1, key2, sizeof(struct v3d_vs_key)) == 0;
}
+static bool
+cs_cache_compare(const void *key1, const void *key2)
+{
+ return memcmp(key1, key2, sizeof(struct v3d_key)) == 0;
+}
+
static struct hash_table*
create_variant_cache(gl_shader_stage stage)
{
@@ -1087,6 +1102,8 @@ create_variant_cache(gl_shader_stage stage)
return _mesa_hash_table_create(NULL, vs_cache_hash, vs_cache_compare);
case MESA_SHADER_FRAGMENT:
return _mesa_hash_table_create(NULL, fs_cache_hash, fs_cache_compare);
+ case MESA_SHADER_COMPUTE:
+ return _mesa_hash_table_create(NULL, cs_cache_hash, cs_cache_compare);
default:
unreachable("not supported shader stage");
}
@@ -1155,6 +1172,9 @@ upload_assembly(struct v3dv_pipeline_stage *p_stage,
case MESA_SHADER_FRAGMENT:
name = "fragment_shader_assembly";
break;
+ case MESA_SHADER_COMPUTE:
+ name = "compute_shader_assembly";
+ break;
default:
unreachable("Stage not supported\n");
break;
@@ -1399,7 +1419,8 @@ pipeline_compile_graphics(struct v3dv_pipeline *pipeline,
* both. For the case of v3dv, it is more natural to have an id this way,
* as right now we are using it for debugging, not for shader-db.
*/
- p_stage->program_id = physical_device->next_program_id++;
+ p_stage->program_id =
+ p_atomic_inc_return(&physical_device->next_program_id);
p_stage->compiled_variant_count = 0;
p_stage->cache = create_variant_cache(stage);
@@ -1438,7 +1459,8 @@ pipeline_compile_graphics(struct v3dv_pipeline *pipeline,
p_stage->module = 0;
p_stage->nir = b.shader;
- p_stage->program_id = physical_device->next_program_id++;
+ p_stage->program_id =
+ p_atomic_inc_return(&physical_device->next_program_id);
p_stage->compiled_variant_count = 0;
p_stage->cache = create_variant_cache(MESA_SHADER_FRAGMENT);
@@ -2489,13 +2511,139 @@ v3dv_CreateGraphicsPipelines(VkDevice _device,
return result;
}
+static void
+shared_type_info(const struct glsl_type *type, unsigned *size, unsigned *align)
+{
+ assert(glsl_type_is_vector_or_scalar(type));
+
+ uint32_t comp_size = glsl_type_is_boolean(type)
+ ? 4 : glsl_get_bit_size(type) / 8;
+ unsigned length = glsl_get_vector_elements(type);
+ *size = comp_size * length,
+ *align = comp_size * (length == 3 ? 4 : length);
+}
+
+static void
+lower_cs_shared(struct nir_shader *nir)
+{
+ NIR_PASS_V(nir, nir_lower_vars_to_explicit_types,
+ nir_var_mem_shared, shared_type_info);
+ NIR_PASS_V(nir, nir_lower_explicit_io,
+ nir_var_mem_shared, nir_address_format_32bit_offset);
+}
+
+static VkResult
+pipeline_compile_compute(struct v3dv_pipeline *pipeline,
+ const VkComputePipelineCreateInfo *info,
+ const VkAllocationCallbacks *alloc)
+{
+ struct v3dv_device *device = pipeline->device;
+ struct v3dv_physical_device *physical_device =
+ &device->instance->physicalDevice;
+
+ const VkPipelineShaderStageCreateInfo *sinfo = &info->stage;
+ gl_shader_stage stage = vk_to_mesa_shader_stage(sinfo->stage);
+
+ struct v3dv_pipeline_stage *p_stage =
+ vk_zalloc2(&device->alloc, alloc, sizeof(*p_stage), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (!p_stage)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ p_stage->program_id = p_atomic_inc_return(&physical_device->next_program_id);
+ p_stage->compiled_variant_count = 0;
+ p_stage->cache = create_variant_cache(MESA_SHADER_COMPUTE);
+ p_stage->pipeline = pipeline;
+ p_stage->stage = stage;
+ p_stage->entrypoint = sinfo->pName;
+ p_stage->module = v3dv_shader_module_from_handle(sinfo->module);
+ p_stage->spec_info = sinfo->pSpecializationInfo;
+ p_stage->nir = shader_module_compile_to_nir(pipeline->device, p_stage);
+
+ pipeline->active_stages |= sinfo->stage;
+ st_nir_opts(p_stage->nir);
+ pipeline_lower_nir(pipeline, p_stage, pipeline->layout);
+ lower_cs_shared(p_stage->nir);
+
+ pipeline->cs = p_stage;
+
+ struct v3d_key *key = &p_stage->key.base;
+ memset(key, 0, sizeof(*key));
+ pipeline_populate_v3d_key(key, p_stage);
+
+ VkResult result;
+ p_stage->current_variant =
+ v3dv_get_shader_variant(p_stage, key, sizeof(*key), alloc, &result);
+ return result;
+}
+
+static VkResult
+compute_pipeline_init(struct v3dv_pipeline *pipeline,
+ struct v3dv_device *device,
+ const VkComputePipelineCreateInfo *info,
+ const VkAllocationCallbacks *alloc)
+{
+ V3DV_FROM_HANDLE(v3dv_pipeline_layout, layout, info->layout);
+
+ pipeline->device = device;
+ pipeline->layout = layout;
+
+ VkResult result = pipeline_compile_compute(pipeline, info, alloc);
+
+ return result;
+}
+
+static VkResult
+compute_pipeline_create(VkDevice _device,
+ VkPipelineCache _cache,
+ const VkComputePipelineCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkPipeline *pPipeline)
+{
+ V3DV_FROM_HANDLE(v3dv_device, device, _device);
+
+ struct v3dv_pipeline *pipeline;
+ VkResult result;
+
+ pipeline = vk_zalloc2(&device->alloc, pAllocator, sizeof(*pipeline), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (pipeline == NULL)
+ return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ result = compute_pipeline_init(pipeline, device, pCreateInfo, pAllocator);
+ if (result != VK_SUCCESS) {
+ v3dv_destroy_pipeline(pipeline, device, pAllocator);
+ return result;
+ }
+
+ *pPipeline = v3dv_pipeline_to_handle(pipeline);
+
+ return VK_SUCCESS;
+}
+
VkResult
-v3dv_CreateComputePipelines(VkDevice device,
+v3dv_CreateComputePipelines(VkDevice _device,
VkPipelineCache pipelineCache,
uint32_t createInfoCount,
const VkComputePipelineCreateInfo *pCreateInfos,
const VkAllocationCallbacks *pAllocator,
VkPipeline *pPipelines)
{
- unreachable("vkCreateComputePipelines not implemented");
+ VkResult result = VK_SUCCESS;
+
+ for (uint32_t i = 0; i < createInfoCount; i++) {
+ VkResult local_result;
+ local_result = compute_pipeline_create(_device,
+ pipelineCache,
+ &pCreateInfos[i],
+ pAllocator,
+ &pPipelines[i]);
+
+ if (local_result != VK_SUCCESS) {
+ result = local_result;
+ pPipelines[i] = VK_NULL_HANDLE;
+ }
+ }
+
+ return result;
}
diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h
index 5cbdc0b2c6b..13ba963456a 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -1150,6 +1150,7 @@ struct v3dv_shader_variant {
struct v3d_prog_data *base;
struct v3d_vs_prog_data *vs;
struct v3d_fs_prog_data *fs;
+ struct v3d_compute_prog_data *cs;
} prog_data;
/* FIXME: using one bo per shader. Eventually we would be interested on
@@ -1397,6 +1398,7 @@ struct v3dv_pipeline {
struct v3dv_pipeline_stage *vs;
struct v3dv_pipeline_stage *vs_bin;
struct v3dv_pipeline_stage *fs;
+ struct v3dv_pipeline_stage *cs;
struct v3dv_dynamic_state dynamic_state;