/* The assembly BO is shared by all variants in the pipeline, so it can't
* be freed here and should be freed with the pipeline
*/
- if (variant->qpu_insts)
+ if (variant->qpu_insts) {
free(variant->qpu_insts);
+ variant->qpu_insts = NULL;
+ }
ralloc_free(variant->prog_data.base);
vk_free(&device->vk.alloc, variant);
}
return p_stage;
}
+/*
+ * Based on some creation flags we assume that the QPU would be needed later
+ * to gather further info. In that case we just keep the qput_insts around,
+ * instead of map/unmap the bo later.
+ */
+static bool
+pipeline_keep_qpu(struct v3dv_pipeline *pipeline)
+{
+ return pipeline->flags &
+ (VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR |
+ VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR);
+}
+
/**
* Returns false if it was not able to allocate or map the assembly bo memory.
*/
memcpy(bo->map + offset, variant->qpu_insts, variant->qpu_insts_size);
offset += variant->qpu_insts_size;
- /* We dont need qpu_insts anymore. */
- free(variant->qpu_insts);
- variant->qpu_insts = NULL;
+ if (!pipeline_keep_qpu(pipeline)) {
+ free(variant->qpu_insts);
+ variant->qpu_insts = NULL;
+ }
}
}
assert(total_size == offset);
VkResult result = VK_SUCCESS;
pipeline->device = device;
+ pipeline->flags = pCreateInfo->flags;
V3DV_FROM_HANDLE(v3dv_pipeline_layout, layout, pCreateInfo->layout);
pipeline->layout = layout;
return NULL;
}
- /* We expect the QPU BO to have been mapped before calling here */
- struct v3dv_bo *qpu_bo = pipeline->shared_data->assembly_bo;
- assert(qpu_bo && qpu_bo->map_size >= variant->assembly_offset +
- variant->qpu_insts_size);
-
*qpu_size = variant->qpu_insts_size;
- uint64_t *qpu = (uint64_t *)
- (((uint8_t *) qpu_bo->map) + variant->assembly_offset);
- return qpu;
+ return variant->qpu_insts;
}
/* FIXME: we use the same macro in various drivers, maybe move it to
pipeline->executables.mem_ctx);
/* Don't crash for failed/bogus pipelines */
- if (!pipeline->shared_data || !pipeline->shared_data->assembly_bo)
- return;
-
- /* Map the assembly BO so we can read the pipeline's QPU code */
- struct v3dv_bo *qpu_bo = pipeline->shared_data->assembly_bo;
-
- if (!v3dv_bo_map(pipeline->device, qpu_bo, qpu_bo->size)) {
- fprintf(stderr, "failed to map QPU buffer\n");
+ if (!pipeline->shared_data)
return;
- }
for (int s = BROADCOM_SHADER_VERTEX; s <= BROADCOM_SHADER_COMPUTE; s++) {
VkShaderStageFlags vk_stage =
if (!(vk_stage & pipeline->active_stages))
continue;
- nir_shader *nir = pipeline_get_nir(pipeline, s);
- char *nir_str = nir ?
- nir_shader_as_str(nir, pipeline->executables.mem_ctx) : NULL;
-
+ char *nir_str = NULL;
char *qpu_str = NULL;
- uint32_t qpu_size;
- uint64_t *qpu = pipeline_get_qpu(pipeline, s, &qpu_size);
- if (qpu) {
- uint32_t qpu_inst_count = qpu_size / sizeof(uint64_t);
- qpu_str = rzalloc_size(pipeline->executables.mem_ctx,
- qpu_inst_count * 96);
- size_t offset = 0;
- for (int i = 0; i < qpu_inst_count; i++) {
- const char *str = v3d_qpu_disasm(&pipeline->device->devinfo, qpu[i]);
- append(&qpu_str, &offset, "%s\n", str);
- ralloc_free((void *)str);
+
+ if (pipeline_keep_qpu(pipeline)) {
+ nir_shader *nir = pipeline_get_nir(pipeline, s);
+ nir_str = nir ?
+ nir_shader_as_str(nir, pipeline->executables.mem_ctx) : NULL;
+
+ uint32_t qpu_size;
+ uint64_t *qpu = pipeline_get_qpu(pipeline, s, &qpu_size);
+ if (qpu) {
+ uint32_t qpu_inst_count = qpu_size / sizeof(uint64_t);
+ qpu_str = rzalloc_size(pipeline->executables.mem_ctx,
+ qpu_inst_count * 96);
+ size_t offset = 0;
+ for (int i = 0; i < qpu_inst_count; i++) {
+ const char *str = v3d_qpu_disasm(&pipeline->device->devinfo, qpu[i]);
+ append(&qpu_str, &offset, "%s\n", str);
+ ralloc_free((void *)str);
+ }
}
}
util_dynarray_append(&pipeline->executables.data,
struct v3dv_pipeline_executable_data, data);
}
-
- v3dv_bo_unmap(pipeline->device, qpu_bo);
}
static const struct v3dv_pipeline_executable_data *
*/
uint32_t assembly_offset;
- /* Note: it is really likely that qpu_insts would be NULL, as it will be
- * used only temporarily, to upload it to the shared bo, as we compile the
- * different stages individually.
+ /* Note: don't assume qpu_insts to be always NULL or not-NULL. In general
+ * we will try to free it as soon as we upload it to the shared bo while we
+ * compile the different stages. But we can decide to keep it around based
+ * on some pipeline creation flags, like
+ * VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT.
*/
uint64_t *qpu_insts;
uint32_t qpu_insts_size;
struct v3dv_device *device;
VkShaderStageFlags active_stages;
+ VkPipelineCreateFlags flags;
struct v3dv_render_pass *pass;
struct v3dv_subpass *subpass;
struct {
void *mem_ctx;
- bool has_data;
struct util_dynarray data; /* Array of v3dv_pipeline_executable_data */
} executables;