memcpy(&local_key, &p_stage->key.fs, sizeof(struct v3d_fs_key));
if (cmd_buffer_populate_v3d_key(&local_key.base, cmd_buffer)) {
+ VkResult vk_result;
variant = v3dv_get_shader_variant(p_stage, &local_key.base,
- sizeof(struct v3d_fs_key));
+ sizeof(struct v3d_fs_key),
+ &cmd_buffer->device->alloc,
+ &vk_result);
+ /* At this point we are not creating a vulkan object to return to the
+ * API user, so we can't really return back a OOM error
+ */
+ assert(variant);
if (p_stage->current_variant != variant) {
p_stage->current_variant = variant;
memcpy(&local_key, &p_stage->key.vs, sizeof(struct v3d_vs_key));
if (cmd_buffer_populate_v3d_key(&local_key.base, cmd_buffer)) {
+ VkResult vk_result;
variant = v3dv_get_shader_variant(p_stage, &local_key.base,
- sizeof(struct v3d_vs_key));
+ sizeof(struct v3d_vs_key),
+ &cmd_buffer->device->alloc,
+ &vk_result);
+ /* At this point we are not creating a vulkan object to return to the
+ * API user, so we can't really return back a OOM error
+ */
+ assert(variant);
if (p_stage->current_variant != variant) {
p_stage->current_variant = variant;
memcpy(&local_key, &p_stage->key.vs, sizeof(struct v3d_vs_key));
if (cmd_buffer_populate_v3d_key(&local_key.base, cmd_buffer)) {
+ VkResult vk_result;
variant = v3dv_get_shader_variant(p_stage, &local_key.base,
- sizeof(struct v3d_vs_key));
+ sizeof(struct v3d_vs_key),
+ &cmd_buffer->device->alloc,
+ &vk_result);
+
+ /* At this point we are not creating a vulkan object to return to the
+ * API user, so we can't really return back a OOM error
+ */
+ assert(variant);
if (p_stage->current_variant != variant) {
p_stage->current_variant = variant;
vk_free2(&device->alloc, pAllocator, p_stage);
}
-void
-v3dv_DestroyPipeline(VkDevice _device,
- VkPipeline _pipeline,
- const VkAllocationCallbacks *pAllocator)
+static void
+v3dv_destroy_pipeline(struct v3dv_pipeline *pipeline,
+ struct v3dv_device *device,
+ const VkAllocationCallbacks *pAllocator)
{
- V3DV_FROM_HANDLE(v3dv_device, device, _device);
- V3DV_FROM_HANDLE(v3dv_pipeline, pipeline, _pipeline);
-
if (!pipeline)
return;
vk_free2(&device->alloc, pAllocator, pipeline);
}
+void
+v3dv_DestroyPipeline(VkDevice _device,
+ VkPipeline _pipeline,
+ const VkAllocationCallbacks *pAllocator)
+{
+ V3DV_FROM_HANDLE(v3dv_device, device, _device);
+ V3DV_FROM_HANDLE(v3dv_pipeline, pipeline, _pipeline);
+
+ if (!pipeline)
+ return;
+
+ v3dv_destroy_pipeline(pipeline, device, pAllocator);
+}
+
static const struct spirv_to_nir_options default_spirv_options = {
.caps = { false },
.ubo_addr_format = nir_address_format_32bit_index_offset,
* 4096, so that would allow to use less memory.
*
* For now one-bo per-assembly would work.
+ *
+ * Returns false if it was not able to allocate or map the assembly bo memory.
*/
-static void
+static bool
upload_assembly(struct v3dv_pipeline_stage *p_stage,
struct v3dv_shader_variant *variant,
const void *data,
struct v3dv_bo *bo = v3dv_bo_alloc(device, size, name);
if (!bo) {
fprintf(stderr, "failed to allocate memory for shader\n");
- abort();
+ return false;
}
bool ok = v3dv_bo_map(device, bo, size);
if (!ok) {
fprintf(stderr, "failed to map source shader buffer\n");
- abort();
+ return false;
}
memcpy(bo->map, data, size);
v3dv_bo_unmap(device, bo);
variant->assembly_bo = bo;
+
+ return true;
}
/* For a given key, it returns the compiled version of the shader. If it was
* already compiled, it gets it from the p_stage cache, if not it compiles is
* through the v3d compiler
+ *
+ * If the method returns NULL it means that it was not able to allocate the
+ * resources for the variant. out_vk_result would return which OOM applies.
*/
struct v3dv_shader_variant*
v3dv_get_shader_variant(struct v3dv_pipeline_stage *p_stage,
struct v3d_key *key,
- size_t key_size)
+ size_t key_size,
+ const VkAllocationCallbacks *pAllocator,
+ VkResult *out_vk_result)
{
struct hash_table *ht = p_stage->cache;
struct hash_entry *entry = _mesa_hash_table_search(ht, key);
- if (entry)
+ if (entry) {
+ *out_vk_result = VK_SUCCESS;
return entry->data;
+ }
struct v3dv_device *device = p_stage->pipeline->device;
struct v3dv_shader_variant *variant =
vk_zalloc(&device->alloc, sizeof(*variant), 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (variant == NULL) {
+ *out_vk_result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ return NULL;
+ }
+
struct v3dv_physical_device *physical_device =
&p_stage->pipeline->device->instance->physicalDevice;
const struct v3d_compiler *compiler = physical_device->compiler;
gl_shader_stage_name(p_stage->stage),
p_stage->program_id);
} else {
- upload_assembly(p_stage, variant, qpu_insts, qpu_insts_size);
+ if (!upload_assembly(p_stage, variant, qpu_insts, qpu_insts_size)) {
+ free(qpu_insts);
+ vk_free2(&device->alloc, pAllocator, variant);
+
+ *out_vk_result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ return NULL;
+ }
}
free(qpu_insts);
/* FIXME: pending provide scratch space for register spilling */
assert(variant->prog_data.base->spill_size == 0);
+ *out_vk_result = VK_SUCCESS;
return variant;
}
*/
struct v3d_vs_key *key = &pipeline->vs->key.vs;
pipeline_populate_v3d_vs_key(key, pCreateInfo, pipeline->vs);
+ VkResult vk_result;
pipeline->vs->current_variant =
- v3dv_get_shader_variant(pipeline->vs, &key->base, sizeof(*key));
+ v3dv_get_shader_variant(pipeline->vs, &key->base, sizeof(*key),
+ pAllocator, &vk_result);
+ if (vk_result != VK_SUCCESS)
+ return vk_result;
key = &pipeline->vs_bin->key.vs;
pipeline_populate_v3d_vs_key(key, pCreateInfo, pipeline->vs_bin);
pipeline->vs_bin->current_variant =
- v3dv_get_shader_variant(pipeline->vs_bin, &key->base, sizeof(*key));
+ v3dv_get_shader_variant(pipeline->vs_bin, &key->base, sizeof(*key),
+ pAllocator, &vk_result);
+ if (vk_result != VK_SUCCESS)
+ return vk_result;
+
break;
}
case MESA_SHADER_FRAGMENT: {
lower_fs_io(p_stage->nir);
+ VkResult vk_result;
p_stage->current_variant =
- v3dv_get_shader_variant(p_stage, &key->base, sizeof(*key));
+ v3dv_get_shader_variant(p_stage, &key->base, sizeof(*key),
+ pAllocator, &vk_result);
+ if (vk_result != VK_SUCCESS)
+ return vk_result;
break;
}
return attr_type;
}
-static void
+static bool
create_default_attribute_values(struct v3dv_pipeline *pipeline,
const VkPipelineVertexInputStateCreateInfo *vi_info)
{
if (!pipeline->default_attribute_values) {
fprintf(stderr, "failed to allocate memory for the default "
"attribute values\n");
+ return false;
}
}
pipeline->default_attribute_values, size);
if (!ok) {
fprintf(stderr, "failed to map default attribute values buffer\n");
- abort();
+ return false;
}
uint32_t *attrs = pipeline->default_attribute_values->map;
}
v3dv_bo_unmap(pipeline->device, pipeline->default_attribute_values);
+
+ return true;
}
static void
pipeline->va_count++;
}
}
- create_default_attribute_values(pipeline, vi_info);
+
+ if (!create_default_attribute_values(pipeline, vi_info))
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
return result;
}
pAllocator);
if (result != VK_SUCCESS) {
- vk_free2(&device->alloc, pAllocator, pipeline);
+ v3dv_destroy_pipeline(pipeline, device, pAllocator);
return result;
}