v3dv: allow to create shader modules from NIR

This will come in handy when the driver needs to generate its own shaders,
such as for partial clears.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
This commit is contained in:
Iago Toral Quiroga 2020-03-31 12:52:06 +02:00 committed by Marge Bot
parent f47d0829cb
commit c6dca4c529
2 changed files with 35 additions and 16 deletions

View file

@ -51,11 +51,13 @@ v3dv_CreateShaderModule(VkDevice _device,
assert(pCreateInfo->flags == 0);
module = vk_alloc2(&device->alloc, pAllocator,
sizeof(*module) + pCreateInfo->codeSize, 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
sizeof(*module) + pCreateInfo->codeSize, 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (module == NULL)
return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
module->nir = NULL;
module->size = pCreateInfo->codeSize;
memcpy(module->data, pCreateInfo->pCode, module->size);
@ -77,6 +79,13 @@ v3dv_DestroyShaderModule(VkDevice _device,
if (!module)
return;
/* NIR modules (which are only created internally by the driver) are not
* dynamically allocated so we should never call this for them.
* Instead the driver is responsible for freeing the NIR code when it is
* no longer needed.
*/
assert(module->nir == NULL);
vk_free2(&device->alloc, pAllocator, module);
}
@ -329,22 +338,28 @@ shader_module_compile_to_nir(struct v3dv_device *device,
nir_shader *nir;
const nir_shader_compiler_options *nir_options = &v3dv_nir_options;
uint32_t *spirv = (uint32_t *) stage->module->data;
assert(stage->module->size % 4 == 0);
if (!stage->module->nir) {
uint32_t *spirv = (uint32_t *) stage->module->data;
assert(stage->module->size % 4 == 0);
if (V3D_DEBUG & V3D_DEBUG_DUMP_SPIRV)
v3dv_print_spirv(stage->module->data, stage->module->size, stderr);
if (V3D_DEBUG & V3D_DEBUG_DUMP_SPIRV)
v3dv_print_spirv(stage->module->data, stage->module->size, stderr);
uint32_t num_spec_entries = 0;
struct nir_spirv_specialization *spec_entries = NULL;
uint32_t num_spec_entries = 0;
struct nir_spirv_specialization *spec_entries = NULL;
const struct spirv_to_nir_options spirv_options = default_spirv_options;
nir = spirv_to_nir(spirv, stage->module->size / 4,
spec_entries, num_spec_entries,
stage->stage, stage->entrypoint,
&spirv_options, nir_options);
const struct spirv_to_nir_options spirv_options = default_spirv_options;
nir = spirv_to_nir(spirv, stage->module->size / 4,
spec_entries, num_spec_entries,
stage->stage, stage->entrypoint,
&spirv_options, nir_options);
nir_validate_shader(nir, "after spirv_to_nir");
free(spec_entries);
} else {
nir = stage->module->nir;
nir_validate_shader(nir, "nir module");
}
assert(nir->info.stage == stage->stage);
nir_validate_shader(nir, "after spirv_to_nir");
if (V3D_DEBUG & (V3D_DEBUG_NIR |
v3d_debug_flag_for_shader_stage(stage->stage))) {
@ -355,8 +370,6 @@ shader_module_compile_to_nir(struct v3dv_device *device,
fprintf(stderr, "\n");
}
free(spec_entries);
/* We have to lower away local variable initializers right before we
* inline functions. That way they get properly initialized at the top
* of the function and not at the top of its caller.

View file

@ -765,6 +765,12 @@ struct v3dv_event {
};
struct v3dv_shader_module {
/* A NIR shader. We create NIR modules for shaders that are generated
* internally by the driver.
*/
struct nir_shader *nir;
/* A SPIR-V shader */
unsigned char sha1[20];
uint32_t size;
char data[0];