spirv: Implement the new ray-tracing storage classes

The SPV_KHR_ray_tracing extension adds 6 new storage classes which is a
bit on the ridiculous side.  In order to avoid adding that many variable
modes to NIR, we make a few simplifying assumptions:

 1. CallableData and RayPayload data actually lives on the stack
    somewhere, presumably in the caller's stack.  We assume that these
    are no different from global variables and use nir_var_shader_temp
    for them.  We still need a separate storage class for the incoming
    variants but only so we can figure out which one the incoming one
    is and lower it to something useful.

 2. There's no difference between incoming CallableData and RayPaolad
    data.  We can use a single storage class for both.

 3. ShaderRecordBuffer data is just a global memory access.  This lets
    us avoid NIR variables entirely and just fetch the pointer via the
    shader_record_ptr system value and it's accessed using a 64-bit
    global memory pointer.

Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6479>
This commit is contained in:
Jason Ekstrand
2020-07-29 15:06:34 -05:00
committed by Marge Bot
parent 84a8ca1db8
commit 6b8fd65e84
4 changed files with 60 additions and 1 deletions

View File

@@ -675,6 +675,7 @@ system_value("ray_hit_kind", 1)
system_value("ray_flags", 1)
system_value("ray_geometry_index", 1)
system_value("ray_instance_custom_index", 1)
system_value("shader_record_ptr", 1, bit_sizes=[64])
# Driver-specific viewport scale/offset parameters.
#

View File

@@ -846,6 +846,7 @@ vtn_type_needs_explicit_layout(struct vtn_builder *b, enum vtn_variable_mode mod
case vtn_variable_mode_phys_ssbo:
case vtn_variable_mode_ubo:
case vtn_variable_mode_push_constant:
case vtn_variable_mode_shader_record:
return true;
default:

View File

@@ -494,6 +494,12 @@ enum vtn_variable_mode {
vtn_variable_mode_output,
vtn_variable_mode_image,
vtn_variable_mode_accel_struct,
vtn_variable_mode_call_data,
vtn_variable_mode_call_data_in,
vtn_variable_mode_ray_payload,
vtn_variable_mode_ray_payload_in,
vtn_variable_mode_hit_attrib,
vtn_variable_mode_shader_record,
};
struct vtn_pointer {

View File

@@ -410,6 +410,16 @@ vtn_pointer_dereference(struct vtn_builder *b,
tail = nir_build_deref_cast(&b->nb, desc, nir_mode,
vtn_type_get_nir_type(b, type, base->mode),
base->ptr_type->stride);
} else if (base->mode == vtn_variable_mode_shader_record) {
/* For ShaderRecordBufferKHR variables, we don't have a nir_variable.
* It's just a fancy handle around a pointer to the shader record for
* the current shader.
*/
tail = nir_build_deref_cast(&b->nb, nir_load_shader_record_ptr(&b->nb),
nir_var_mem_constant,
vtn_type_get_nir_type(b, base->type,
base->mode),
0 /* ptr_as_array stride */);
} else {
assert(base->var && base->var->var);
tail = nir_build_deref_var(&b->nb, base->var->var);
@@ -1325,6 +1335,9 @@ var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
} else if (vtn_var->mode == vtn_variable_mode_input ||
vtn_var->mode == vtn_variable_mode_output) {
location += vtn_var->patch ? VARYING_SLOT_PATCH0 : VARYING_SLOT_VAR0;
} else if (vtn_var->mode == vtn_variable_mode_call_data ||
vtn_var->mode == vtn_variable_mode_ray_payload) {
/* This location is fine as-is */
} else if (vtn_var->mode != vtn_variable_mode_uniform) {
vtn_warn("Location must be on input, output, uniform, sampler or "
"image variable");
@@ -1463,6 +1476,31 @@ vtn_storage_class_to_mode(struct vtn_builder *b,
mode = vtn_variable_mode_image;
nir_mode = nir_var_mem_ubo;
break;
case SpvStorageClassCallableDataKHR:
mode = vtn_variable_mode_call_data;
nir_mode = nir_var_shader_temp;
break;
case SpvStorageClassIncomingCallableDataKHR:
mode = vtn_variable_mode_call_data_in;
nir_mode = nir_var_shader_call_data;
break;
case SpvStorageClassRayPayloadKHR:
mode = vtn_variable_mode_ray_payload;
nir_mode = nir_var_shader_temp;
break;
case SpvStorageClassIncomingRayPayloadKHR:
mode = vtn_variable_mode_ray_payload_in;
nir_mode = nir_var_shader_call_data;
break;
case SpvStorageClassHitAttributeKHR:
mode = vtn_variable_mode_hit_attrib;
nir_mode = nir_var_ray_hit_attrib;
break;
case SpvStorageClassShaderRecordBufferKHR:
mode = vtn_variable_mode_shader_record;
nir_mode = nir_var_mem_constant;
break;
case SpvStorageClassGeneric:
mode = vtn_variable_mode_generic;
nir_mode = nir_var_mem_generic;
@@ -1501,6 +1539,7 @@ vtn_mode_to_address_format(struct vtn_builder *b, enum vtn_variable_mode mode)
case vtn_variable_mode_cross_workgroup:
return b->options->global_addr_format;
case vtn_variable_mode_shader_record:
case vtn_variable_mode_constant:
return b->options->constant_addr_format;
@@ -1518,6 +1557,11 @@ vtn_mode_to_address_format(struct vtn_builder *b, enum vtn_variable_mode mode)
case vtn_variable_mode_input:
case vtn_variable_mode_output:
case vtn_variable_mode_image:
case vtn_variable_mode_call_data:
case vtn_variable_mode_call_data_in:
case vtn_variable_mode_ray_payload:
case vtn_variable_mode_ray_payload_in:
case vtn_variable_mode_hit_attrib:
return nir_address_format_logical;
}
@@ -1760,6 +1804,11 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
case vtn_variable_mode_uniform:
case vtn_variable_mode_atomic_counter:
case vtn_variable_mode_constant:
case vtn_variable_mode_call_data:
case vtn_variable_mode_call_data_in:
case vtn_variable_mode_ray_payload:
case vtn_variable_mode_ray_payload_in:
case vtn_variable_mode_hit_attrib:
/* For these, we create the variable normally */
var->var = rzalloc(b->shader, nir_variable);
var->var->name = ralloc_strdup(var->var, val->name);
@@ -1885,6 +1934,7 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
}
case vtn_variable_mode_accel_struct:
case vtn_variable_mode_shader_record:
/* These don't need actual variables. */
break;
@@ -1945,7 +1995,8 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
nir_shader_add_variable(b->shader, var->var);
} else {
vtn_assert(vtn_pointer_is_external_block(b, val->pointer) ||
var->mode == vtn_variable_mode_accel_struct);
var->mode == vtn_variable_mode_accel_struct ||
var->mode == vtn_variable_mode_shader_record);
}
}