Merge branch 'review/vulkan-common-heap' into 'main'

Draft: vulkan,nir,spirv: descriptor heap

See merge request mesa/mesa!39477
This commit is contained in:
Lionel Landwerlin 2026-03-11 04:58:11 +00:00
commit 6ecf398eea
41 changed files with 2247 additions and 119 deletions

View file

@ -2119,7 +2119,7 @@ radv_get_physical_device_properties(struct radv_physical_device *pdev)
.imageViewCaptureReplayDescriptorDataSize = 1,
.samplerCaptureReplayDescriptorDataSize = 4,
.accelerationStructureCaptureReplayDescriptorDataSize = 1,
.samplerDescriptorSize = RADV_SAMPLER_DESC_SIZE,
.EDBsamplerDescriptorSize = RADV_SAMPLER_DESC_SIZE,
.combinedImageSamplerDescriptorSize = radv_get_combined_image_sampler_desc_size(pdev),
.sampledImageDescriptorSize = radv_get_sampled_image_desc_size(pdev),
.storageImageDescriptorSize = RADV_STORAGE_IMAGE_DESC_SIZE,

View file

@ -2566,6 +2566,10 @@ nir_intrinsic_from_system_value(gl_system_value val)
return nir_intrinsic_load_warp_id_arm;
case SYSTEM_VALUE_WARP_MAX_ID_ARM:
return nir_intrinsic_load_warp_max_id_arm;
case SYSTEM_VALUE_SAMPLER_HEAP_PTR:
return nir_intrinsic_load_sampler_heap_ptr;
case SYSTEM_VALUE_RESOURCE_HEAP_PTR:
return nir_intrinsic_load_resource_heap_ptr;
default:
return nir_num_intrinsics;
}
@ -2752,6 +2756,10 @@ nir_system_value_from_intrinsic(nir_intrinsic_op intrin)
return SYSTEM_VALUE_WARP_ID_ARM;
case nir_intrinsic_load_warp_max_id_arm:
return SYSTEM_VALUE_WARP_MAX_ID_ARM;
case nir_intrinsic_load_sampler_heap_ptr:
return SYSTEM_VALUE_SAMPLER_HEAP_PTR;
case nir_intrinsic_load_resource_heap_ptr:
return SYSTEM_VALUE_RESOURCE_HEAP_PTR;
default:
UNREACHABLE("intrinsic doesn't produce a system value");
}
@ -2947,6 +2955,7 @@ nir_chase_binding(nir_src rsrc)
res.var = deref->var;
res.desc_set = deref->var->data.descriptor_set;
res.binding = deref->var->data.binding;
res.resource_type = deref->var->data.resource_type;
return res;
} else if (deref->deref_type == nir_deref_type_array && is_image) {
if (res.num_indices == ARRAY_SIZE(res.indices))
@ -3037,6 +3046,7 @@ nir_chase_binding(nir_src rsrc)
res.success = true;
res.desc_set = nir_intrinsic_desc_set(intrin);
res.binding = nir_intrinsic_binding(intrin);
res.resource_type = nir_intrinsic_resource_type(intrin);
res.num_indices = 1;
res.indices[0] = intrin->src[0];
return res;
@ -3571,6 +3581,8 @@ nir_tex_instr_src_type(const nir_tex_instr *instr, unsigned src)
case nir_tex_src_texture_2_handle:
case nir_tex_src_sampler_2_handle:
case nir_tex_src_block_size:
case nir_tex_src_texture_heap_offset:
case nir_tex_src_sampler_heap_offset:
return nir_type_uint;
case nir_num_tex_src_types:

View file

@ -712,10 +712,13 @@ typedef struct nir_variable {
*/
unsigned access : 9;
/* VkSpirvResourceTypeFlagBitsKHR bit index that this variable would have. */
unsigned resource_type : 9;
/**
* Descriptor set binding for sampler or UBO.
*/
unsigned descriptor_set : 5;
unsigned descriptor_set;
#define NIR_VARIABLE_NO_INDEX ~0
@ -1832,19 +1835,6 @@ nir_deref_instr_parent(const nir_deref_instr *instr)
return nir_src_as_deref(instr->parent);
}
static inline nir_variable *
nir_deref_instr_get_variable(const nir_deref_instr *instr)
{
while (instr->deref_type != nir_deref_type_var) {
if (instr->deref_type == nir_deref_type_cast)
return NULL;
instr = nir_deref_instr_parent(instr);
}
return instr->var;
}
bool nir_deref_instr_has_indirect(nir_deref_instr *instr);
bool nir_deref_instr_is_known_out_of_bounds(nir_deref_instr *instr);
@ -1972,12 +1962,6 @@ typedef struct nir_intrinsic_instr {
nir_src src[];
} nir_intrinsic_instr;
static inline nir_variable *
nir_intrinsic_get_var(const nir_intrinsic_instr *intrin, unsigned i)
{
return nir_deref_instr_get_variable(nir_src_as_deref(intrin->src[i]));
}
typedef enum {
/* Memory ordering. */
NIR_MEMORY_ACQUIRE = 1 << 0,
@ -2363,6 +2347,12 @@ typedef enum nir_tex_src_type {
*/
nir_tex_src_sampler_handle,
/** Texture descriptor heap offset (in bytes) */
nir_tex_src_texture_heap_offset,
/** Sampler descriptor heap offset (in bytes) */
nir_tex_src_sampler_heap_offset,
/** Tex src intrinsic
*
* This is an intrinsic used before function inlining i.e. before we know
@ -2594,6 +2584,12 @@ typedef struct nir_tex_instr {
*/
bool sampler_non_uniform;
/** True if this texture instruction uses an embedded sampler.
*
* In this case, sampler_index is the index in embedded sampler table.
*/
bool embedded_sampler;
/** True if the offset is not dynamically uniform */
bool offset_non_uniform;
@ -3165,6 +3161,7 @@ typedef struct nir_binding {
nir_variable *var;
unsigned desc_set;
unsigned binding;
unsigned resource_type;
unsigned num_indices;
nir_src indices[4];
bool read_first_invocation;
@ -4113,6 +4110,26 @@ nir_shader_get_function_for_name(const nir_shader *shader, const char *name)
return NULL;
}
static inline nir_variable *
nir_deref_instr_get_variable(const nir_deref_instr *instr)
{
while (instr->deref_type != nir_deref_type_var) {
if (instr->deref_type == nir_deref_type_cast &&
!nir_def_is_deref(instr->parent.ssa))
return NULL;
instr = nir_deref_instr_parent(instr);
}
return instr->var;
}
static inline nir_variable *
nir_intrinsic_get_var(const nir_intrinsic_instr *intrin, unsigned i)
{
return nir_deref_instr_get_variable(nir_src_as_deref(intrin->src[i]));
}
/*
* After all functions are forcibly inlined, these passes remove redundant
* functions from a shader and library respectively.
@ -6193,6 +6210,7 @@ bool nir_has_non_uniform_access(nir_shader *shader, enum nir_lower_non_uniform_a
bool nir_opt_non_uniform_access(nir_shader *shader);
bool nir_lower_non_uniform_access(nir_shader *shader,
const nir_lower_non_uniform_access_options *options);
bool nir_tag_non_uniform_accesses(nir_shader *shader);
typedef struct nir_lower_idiv_options {
/* Whether 16-bit floating point arithmetic should be allowed in 8-bit

View file

@ -423,6 +423,7 @@ clone_tex(clone_state *state, const nir_tex_instr *tex)
ntex->texture_non_uniform = tex->texture_non_uniform;
ntex->sampler_non_uniform = tex->sampler_non_uniform;
ntex->offset_non_uniform = tex->offset_non_uniform;
ntex->embedded_sampler = tex->embedded_sampler;
ntex->backend_flags = tex->backend_flags;

View file

@ -364,6 +364,8 @@ visit_intrinsic(nir_intrinsic_instr *instr, struct divergence_state *state)
case nir_intrinsic_load_ray_query_global_intel:
case nir_intrinsic_load_call_return_address_amd:
case nir_intrinsic_load_indirect_address_intel:
case nir_intrinsic_load_sampler_heap_ptr:
case nir_intrinsic_load_resource_heap_ptr:
is_divergent = false;
break;
@ -653,9 +655,11 @@ visit_intrinsic(nir_intrinsic_instr *instr, struct divergence_state *state)
case nir_intrinsic_image_samples_identical:
case nir_intrinsic_image_deref_samples_identical:
case nir_intrinsic_bindless_image_samples_identical:
case nir_intrinsic_image_heap_samples_identical:
case nir_intrinsic_image_fragment_mask_load_amd:
case nir_intrinsic_image_deref_fragment_mask_load_amd:
case nir_intrinsic_bindless_image_fragment_mask_load_amd:
case nir_intrinsic_image_heap_fragment_mask_load_amd:
is_divergent = (src_divergent(instr->src[0], state) &&
(nir_intrinsic_access(instr) & ACCESS_NON_UNIFORM)) ||
src_divergent(instr->src[1], state) ||
@ -674,9 +678,11 @@ visit_intrinsic(nir_intrinsic_instr *instr, struct divergence_state *state)
case nir_intrinsic_image_load:
case nir_intrinsic_image_deref_load:
case nir_intrinsic_bindless_image_load:
case nir_intrinsic_image_heap_load:
case nir_intrinsic_image_sparse_load:
case nir_intrinsic_image_deref_sparse_load:
case nir_intrinsic_bindless_image_sparse_load:
case nir_intrinsic_image_heap_sparse_load:
is_divergent = (src_divergent(instr->src[0], state) &&
(nir_intrinsic_access(instr) & ACCESS_NON_UNIFORM)) ||
src_divergent(instr->src[1], state) ||
@ -734,20 +740,27 @@ visit_intrinsic(nir_intrinsic_instr *instr, struct divergence_state *state)
case nir_intrinsic_image_levels:
case nir_intrinsic_image_deref_levels:
case nir_intrinsic_bindless_image_levels:
case nir_intrinsic_image_heap_levels:
case nir_intrinsic_image_samples:
case nir_intrinsic_image_deref_samples:
case nir_intrinsic_bindless_image_samples:
case nir_intrinsic_image_heap_samples:
case nir_intrinsic_image_size:
case nir_intrinsic_image_deref_size:
case nir_intrinsic_bindless_image_size:
case nir_intrinsic_image_heap_size:
case nir_intrinsic_image_descriptor_amd:
case nir_intrinsic_image_deref_descriptor_amd:
case nir_intrinsic_image_heap_descriptor_amd:
case nir_intrinsic_bindless_image_descriptor_amd:
case nir_intrinsic_strict_wqm_coord_amd:
case nir_intrinsic_copy_deref:
case nir_intrinsic_vulkan_resource_index:
case nir_intrinsic_vulkan_resource_reindex:
case nir_intrinsic_load_vulkan_descriptor:
case nir_intrinsic_load_heap_descriptor:
case nir_intrinsic_load_resource_heap_data:
case nir_intrinsic_global_addr_to_descriptor:
case nir_intrinsic_load_input_attachment_target_pan:
case nir_intrinsic_load_input_attachment_conv_pan:
case nir_intrinsic_load_converted_mem_pan:
@ -761,6 +774,7 @@ visit_intrinsic(nir_intrinsic_instr *instr, struct divergence_state *state)
case nir_intrinsic_load_sample_positions_amd:
case nir_intrinsic_image_deref_load_param_intel:
case nir_intrinsic_image_load_raw_intel:
case nir_intrinsic_load_buffer_ptr_deref:
case nir_intrinsic_get_ubo_size:
case nir_intrinsic_load_ssbo_address:
case nir_intrinsic_load_global_bounded:
@ -902,6 +916,8 @@ visit_intrinsic(nir_intrinsic_instr *instr, struct divergence_state *state)
case nir_intrinsic_image_atomic_swap:
case nir_intrinsic_bindless_image_atomic:
case nir_intrinsic_bindless_image_atomic_swap:
case nir_intrinsic_image_heap_atomic:
case nir_intrinsic_image_heap_atomic_swap:
case nir_intrinsic_shared_atomic:
case nir_intrinsic_shared_atomic_swap:
case nir_intrinsic_shared_atomic_nv:

View file

@ -396,6 +396,7 @@ intrinsic_is_bindless(nir_intrinsic_instr *instr)
case nir_intrinsic_bindless_image_atomic_swap:
case nir_intrinsic_bindless_image_descriptor_amd:
case nir_intrinsic_bindless_image_format:
case nir_intrinsic_bindless_image_levels:
case nir_intrinsic_bindless_image_load:
case nir_intrinsic_bindless_image_load_raw_intel:
case nir_intrinsic_bindless_image_order:
@ -413,6 +414,36 @@ intrinsic_is_bindless(nir_intrinsic_instr *instr)
return false;
}
static bool
intrinsic_is_heap(nir_intrinsic_instr *instr)
{
switch (instr->intrinsic) {
case nir_intrinsic_global_addr_to_descriptor:
case nir_intrinsic_image_heap_atomic:
case nir_intrinsic_image_heap_atomic_swap:
case nir_intrinsic_image_heap_descriptor_amd:
case nir_intrinsic_image_heap_format:
case nir_intrinsic_image_heap_levels:
case nir_intrinsic_image_heap_load:
case nir_intrinsic_image_heap_load_raw_intel:
case nir_intrinsic_image_heap_order:
case nir_intrinsic_image_heap_samples:
case nir_intrinsic_image_heap_samples_identical:
case nir_intrinsic_image_heap_size:
case nir_intrinsic_image_heap_sparse_load:
case nir_intrinsic_image_heap_store:
case nir_intrinsic_image_heap_store_raw_intel:
case nir_intrinsic_load_buffer_ptr_deref:
case nir_intrinsic_load_heap_descriptor:
case nir_intrinsic_load_resource_heap_data:
case nir_intrinsic_load_sampler_heap_ptr:
return true;
default:
break;
}
return false;
}
static void
gather_intrinsic_info(nir_intrinsic_instr *instr, nir_shader *shader)
{
@ -883,6 +914,7 @@ gather_intrinsic_info(nir_intrinsic_instr *instr, nir_shader *shader)
}
default:
shader->info.use_descriptor_heap |= intrinsic_is_heap(instr);
shader->info.uses_bindless |= intrinsic_is_bindless(instr);
if (nir_intrinsic_writes_external_memory(instr))
shader->info.writes_memory = true;
@ -920,7 +952,10 @@ gather_intrinsic_info(nir_intrinsic_instr *instr, nir_shader *shader)
instr->intrinsic == nir_intrinsic_bindless_image_size ||
instr->intrinsic == nir_intrinsic_bindless_image_samples ||
instr->intrinsic == nir_intrinsic_get_ubo_size ||
instr->intrinsic == nir_intrinsic_get_ssbo_size)
instr->intrinsic == nir_intrinsic_get_ssbo_size ||
instr->intrinsic == nir_intrinsic_image_heap_levels ||
instr->intrinsic == nir_intrinsic_image_heap_size ||
instr->intrinsic == nir_intrinsic_image_heap_samples)
shader->info.uses_resource_info_query = true;
break;
}
@ -941,6 +976,13 @@ gather_tex_info(nir_tex_instr *instr, nir_shader *shader)
nir_tex_instr_src_index(instr, nir_tex_src_sampler_handle) != -1)
shader->info.uses_bindless = true;
if (nir_tex_instr_src_index(instr, nir_tex_src_texture_heap_offset) != -1 ||
nir_tex_instr_src_index(instr, nir_tex_src_sampler_heap_offset) != -1)
shader->info.use_descriptor_heap = true;
if (instr->embedded_sampler)
shader->info.uses_embedded_samplers = true;
if (!nir_tex_instr_is_query(instr) &&
(instr->sampler_dim == GLSL_SAMPLER_DIM_SUBPASS ||
instr->sampler_dim == GLSL_SAMPLER_DIM_SUBPASS_MS))
@ -1023,6 +1065,7 @@ nir_shader_gather_info(nir_shader *shader, nir_function_impl *entrypoint)
shader->info.bit_sizes_float = 0;
shader->info.bit_sizes_int = 0;
shader->info.uses_bindless = false;
shader->info.uses_embedded_samplers = false;
nir_foreach_variable_with_modes(var, shader, nir_var_image | nir_var_uniform) {
if (var->data.bindless)

View file

@ -278,6 +278,7 @@ pack_tex(const nir_tex_instr *instr)
PACK(instr->skip_helpers, 1);
PACK(instr->texture_non_uniform, 1);
PACK(instr->sampler_non_uniform, 1);
PACK(instr->embedded_sampler, 1);
PACK(instr->offset_non_uniform, 1);
#undef PACK

View file

@ -245,6 +245,9 @@ index("unsigned", "offset_shift_nv")
# The Vulkan descriptor type for a vulkan_resource_[re]index intrinsic.
index("unsigned", "desc_type")
# The Vulkan descriptor type according to VkSpirvResourceTypeFlagsKHR.
index("unsigned", "resource_type")
# The nir_alu_type of input data to a store or conversion
index("nir_alu_type", "src_type")
@ -816,6 +819,8 @@ def image(name, src_comp=[], extra_indices=[], **kwargs):
indices=[IMAGE_DIM, IMAGE_ARRAY, FORMAT, ACCESS, RANGE_BASE] + extra_indices, **kwargs)
intrinsic("bindless_image_" + name, src_comp=[-1] + src_comp,
indices=[IMAGE_DIM, IMAGE_ARRAY, FORMAT, ACCESS] + extra_indices, **kwargs)
intrinsic("image_heap_" + name, src_comp=[1] + src_comp,
indices=[IMAGE_DIM, IMAGE_ARRAY, FORMAT, ACCESS] + extra_indices, **kwargs)
image("load", src_comp=[4, 1, 1], extra_indices=[DEST_TYPE], dest_comp=0, flags=[CAN_ELIMINATE])
image("sparse_load", src_comp=[4, 1, 1], extra_indices=[DEST_TYPE], dest_comp=0, flags=[CAN_ELIMINATE])
@ -859,7 +864,7 @@ image("fragment_mask_load_amd", src_comp=[4], dest_comp=1, bit_sizes=[32], flags
# corresponds to the tuple (set, binding, index) and computes an index
# corresponding to tuple (set, binding, idx + src1).
intrinsic("vulkan_resource_index", src_comp=[1], dest_comp=0,
indices=[DESC_SET, BINDING, DESC_TYPE],
indices=[DESC_SET, BINDING, DESC_TYPE, RESOURCE_TYPE],
flags=[CAN_ELIMINATE, CAN_REORDER])
intrinsic("vulkan_resource_reindex", src_comp=[0, 1], dest_comp=0,
indices=[DESC_TYPE], flags=[CAN_ELIMINATE, CAN_REORDER])
@ -1436,6 +1441,21 @@ intrinsic("cmat_insert", src_comp=[-1, 1, -1, 1])
intrinsic("cmat_copy", src_comp=[-1, -1])
intrinsic("cmat_transpose", src_comp=[-1, -1])
# VK_KHR_descriptor_heap
system_value("sampler_heap_ptr", 1, bit_sizes=[64])
system_value("resource_heap_ptr", 1, bit_sizes=[64])
# src[] = { deref }.
load("buffer_ptr_deref", [-1], [ACCESS, RESOURCE_TYPE],
flags=[CAN_ELIMINATE, CAN_REORDER])
# src[] = { offset }.
load("heap_descriptor", [1], [RESOURCE_TYPE], [CAN_ELIMINATE, CAN_REORDER])
# src[] = { offset }.
load("resource_heap_data", [1], [ALIGN_MUL, ALIGN_OFFSET],
flags=[CAN_ELIMINATE, CAN_REORDER])
# src[] = { addr }.
intrinsic("global_addr_to_descriptor", src_comp=[1], dest_comp=0,
indices=[RESOURCE_TYPE], flags=[CAN_ELIMINATE, CAN_REORDER])
# Select an output vertex in a poly GS. Takes the stream-local vertex ID.
intrinsic("select_vertex_poly", src_comp=[1], indices=[STREAM_ID])

View file

@ -1094,10 +1094,11 @@ nir_get_io_offset_src(nir_intrinsic_instr *instr)
return idx >= 0 ? &instr->src[idx] : NULL;
}
#define IMG_CASE(name) \
case nir_intrinsic_image_##name: \
case nir_intrinsic_image_deref_##name: \
case nir_intrinsic_bindless_image_##name
#define IMG_CASE(name) \
case nir_intrinsic_image_##name: \
case nir_intrinsic_image_deref_##name: \
case nir_intrinsic_bindless_image_##name: \
case nir_intrinsic_image_heap_##name
/**
* Return the index or handle source number for a load/store intrinsic or -1

View file

@ -245,6 +245,7 @@ lower_non_uniform_tex_access(struct nu_state *state, nir_tex_instr *tex,
case nir_tex_src_texture_handle:
case nir_tex_src_texture_deref:
case nir_tex_src_texture_2_deref:
case nir_tex_src_texture_heap_offset:
if (!tex->texture_non_uniform)
continue;
if (!(opts->types & base_access_type))
@ -257,6 +258,7 @@ lower_non_uniform_tex_access(struct nu_state *state, nir_tex_instr *tex,
case nir_tex_src_sampler_handle:
case nir_tex_src_sampler_deref:
case nir_tex_src_sampler_2_deref:
case nir_tex_src_sampler_heap_offset:
if (!tex->sampler_non_uniform)
continue;
if (!(opts->types & base_access_type))
@ -424,6 +426,16 @@ nir_lower_non_uniform_access_impl(nir_function_impl *impl,
case nir_intrinsic_image_deref_atomic_swap:
case nir_intrinsic_image_deref_samples_identical:
case nir_intrinsic_image_deref_fragment_mask_load_amd:
case nir_intrinsic_image_heap_load:
case nir_intrinsic_image_heap_sparse_load:
case nir_intrinsic_image_heap_store:
case nir_intrinsic_image_heap_atomic:
case nir_intrinsic_image_heap_atomic_swap:
case nir_intrinsic_image_heap_levels:
case nir_intrinsic_image_heap_size:
case nir_intrinsic_image_heap_samples:
case nir_intrinsic_image_heap_samples_identical:
case nir_intrinsic_image_heap_fragment_mask_load_amd:
if ((options->types & nir_lower_non_uniform_image_access) &&
lower_non_uniform_access_intrin(&state, intrin, 0, nir_lower_non_uniform_image_access))
progress = true;

View file

@ -376,6 +376,7 @@ sample_plane(nir_builder *b, nir_tex_instr *tex, int plane,
plane_tex->dest_type = nir_type_float | tex->def.bit_size;
plane_tex->coord_components = 2;
plane_tex->embedded_sampler = tex->embedded_sampler;
plane_tex->texture_index = tex->texture_index;
plane_tex->sampler_index = tex->sampler_index;
plane_tex->can_speculate = tex->can_speculate;
@ -937,6 +938,7 @@ lower_tex_to_txd(nir_builder *b, nir_tex_instr *tex)
txd->sampler_dim = tex->sampler_dim;
txd->dest_type = tex->dest_type;
txd->coord_components = tex->coord_components;
txd->embedded_sampler = tex->embedded_sampler;
txd->texture_index = tex->texture_index;
txd->sampler_index = tex->sampler_index;
txd->is_array = tex->is_array;
@ -980,6 +982,7 @@ lower_txb_to_txl(nir_builder *b, nir_tex_instr *tex)
txl->sampler_dim = tex->sampler_dim;
txl->dest_type = tex->dest_type;
txl->coord_components = tex->coord_components;
txl->embedded_sampler = tex->embedded_sampler;
txl->texture_index = tex->texture_index;
txl->sampler_index = tex->sampler_index;
txl->is_array = tex->is_array;
@ -1237,6 +1240,7 @@ lower_tg4_offsets(nir_builder *b, nir_tex_instr *tex)
tex_copy->is_gather_implicit_lod = tex->is_gather_implicit_lod;
tex_copy->component = tex->component;
tex_copy->dest_type = tex->dest_type;
tex_copy->embedded_sampler = tex->embedded_sampler;
tex_copy->texture_index = tex->texture_index;
tex_copy->sampler_index = tex->sampler_index;
tex_copy->backend_flags = tex->backend_flags;

View file

@ -24,10 +24,21 @@
#include "nir.h"
#include "nir_builder.h"
#include "vulkan/vulkan_core.h"
static bool
is_ubo_intrinsic(nir_intrinsic_instr *intrin)
{
return intrin->intrinsic == nir_intrinsic_load_ubo;
switch (intrin->intrinsic) {
case nir_intrinsic_load_ubo:
return true;
case nir_intrinsic_load_buffer_ptr_deref:
return nir_intrinsic_resource_type(intrin) == VK_SPIRV_RESOURCE_TYPE_UNIFORM_BUFFER_BIT_EXT;
default:
return false;
}
}
static bool
@ -40,6 +51,10 @@ is_ssbo_intrinsic(nir_intrinsic_instr *intrin)
case nir_intrinsic_ssbo_atomic_swap:
return true;
case nir_intrinsic_load_buffer_ptr_deref:
return nir_intrinsic_resource_type(intrin) == VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT ||
nir_intrinsic_resource_type(intrin) == VK_SPIRV_RESOURCE_TYPE_READ_WRITE_STORAGE_BUFFER_BIT_EXT;
default:
return false;
}
@ -87,6 +102,31 @@ is_image_query_intrinsic(nir_intrinsic_instr *intrin)
case nir_intrinsic_image_deref_size:
case nir_intrinsic_image_deref_samples:
case nir_intrinsic_image_deref_levels:
case nir_intrinsic_image_deref_fragment_mask_load_amd:
case nir_intrinsic_image_heap_load:
case nir_intrinsic_image_heap_sparse_load:
case nir_intrinsic_image_heap_store:
case nir_intrinsic_image_heap_atomic:
case nir_intrinsic_image_heap_atomic_swap:
case nir_intrinsic_image_heap_size:
case nir_intrinsic_image_heap_samples:
case nir_intrinsic_image_heap_levels:
case nir_intrinsic_image_heap_fragment_mask_load_amd:
return true;
default:
return false;
}
}
static bool
is_deref_intrinsic(nir_intrinsic_instr *intrin)
{
switch (intrin->intrinsic) {
case nir_intrinsic_load_deref:
case nir_intrinsic_store_deref:
case nir_intrinsic_deref_atomic:
case nir_intrinsic_deref_atomic_swap:
return true;
default:
@ -209,6 +249,7 @@ opt_non_uniform_tex_access(nir_tex_instr *tex)
case nir_tex_src_texture_offset:
case nir_tex_src_texture_handle:
case nir_tex_src_texture_deref:
case nir_tex_src_texture_heap_offset:
if (tex->texture_non_uniform && !nir_src_is_divergent(&tex->src[i].src)) {
tex->texture_non_uniform = false;
progress = true;
@ -218,6 +259,7 @@ opt_non_uniform_tex_access(nir_tex_instr *tex)
case nir_tex_src_sampler_offset:
case nir_tex_src_sampler_handle:
case nir_tex_src_sampler_deref:
case nir_tex_src_sampler_heap_offset:
if (tex->sampler_non_uniform && !nir_src_is_divergent(&tex->src[i].src)) {
tex->sampler_non_uniform = false;
progress = true;
@ -292,3 +334,122 @@ nir_opt_non_uniform_access(nir_shader *shader)
return progress;
}
static bool
tag_non_uniform_tex_access(nir_tex_instr *tex)
{
bool progress = false;
for (unsigned i = 0; i < tex->num_srcs; i++) {
switch (tex->src[i].src_type) {
case nir_tex_src_texture_offset:
case nir_tex_src_texture_handle:
case nir_tex_src_texture_deref:
case nir_tex_src_texture_heap_offset:
if (nir_src_is_divergent(&tex->src[i].src)) {
tex->texture_non_uniform = true;
progress = true;
}
break;
case nir_tex_src_sampler_offset:
case nir_tex_src_sampler_handle:
case nir_tex_src_sampler_deref:
case nir_tex_src_sampler_heap_offset:
if (nir_src_is_divergent(&tex->src[i].src)) {
tex->sampler_non_uniform = true;
progress = true;
}
break;
case nir_tex_src_offset:
if (nir_src_is_divergent(&tex->src[i].src)) {
tex->offset_non_uniform = true;
progress = true;
}
break;
default:
break;
}
}
return progress;
}
static bool
tag_non_uniform_access_intrin(nir_intrinsic_instr *intrin, unsigned handle_src)
{
if (has_non_uniform_access_intrin(intrin))
return false;
if (!nir_src_is_divergent(&intrin->src[handle_src]))
return false;
nir_intrinsic_set_access(intrin, nir_intrinsic_access(intrin) | ACCESS_NON_UNIFORM);
return true;
}
static bool
tag_non_uniform_deref_intrin(nir_intrinsic_instr *intrin)
{
nir_deref_instr *deref = nir_def_as_deref(intrin->src[0].ssa);
if (!nir_deref_mode_is_one_of(deref,
nir_var_mem_ubo |
nir_var_mem_ssbo))
return false;
assert(deref);
while (deref &&
deref->deref_type != nir_deref_type_var &&
deref->deref_type != nir_deref_type_cast)
deref = nir_deref_instr_parent(deref);
assert(deref);
if (!nir_src_is_divergent(&deref->parent))
return false;
nir_intrinsic_set_access(intrin, nir_intrinsic_access(intrin) | ACCESS_NON_UNIFORM);
return true;
}
static bool
nir_tag_non_uniform_access_instr(nir_builder *b, nir_instr *instr, UNUSED void *user_data)
{
switch (instr->type) {
case nir_instr_type_tex:
return tag_non_uniform_tex_access(nir_instr_as_tex(instr));
case nir_instr_type_intrinsic: {
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
if (is_ubo_intrinsic(intrin) || is_ssbo_intrinsic(intrin) ||
is_image_access_intrinsic(intrin) || is_image_query_intrinsic(intrin) ||
intrin->intrinsic == nir_intrinsic_get_ssbo_size)
return tag_non_uniform_access_intrin(intrin, nir_get_io_index_src_number(intrin));
if (is_deref_intrinsic(intrin))
return tag_non_uniform_deref_intrin(intrin);
break;
}
default:
/* Nothing to do */
break;
}
return false;
}
bool
nir_tag_non_uniform_accesses(nir_shader *shader)
{
nir_divergence_analysis(shader);
return nir_shader_instructions_pass(shader,
nir_tag_non_uniform_access_instr,
nir_metadata_live_defs |
nir_metadata_instr_index |
nir_metadata_control_flow, NULL);
}

View file

@ -1238,6 +1238,33 @@ vulkan_descriptor_type_name(VkDescriptorType type)
}
}
static const char *
vk_spirv_resource_type_name(VkSpirvResourceTypeFlagBitsEXT type)
{
switch (type) {
case VK_SPIRV_RESOURCE_TYPE_SAMPLER_BIT_EXT:
return "sampler";
case VK_SPIRV_RESOURCE_TYPE_SAMPLED_IMAGE_BIT_EXT:
return "texture";
case VK_SPIRV_RESOURCE_TYPE_READ_ONLY_IMAGE_BIT_EXT:
return "RO-image";
case VK_SPIRV_RESOURCE_TYPE_READ_WRITE_IMAGE_BIT_EXT:
return "RW-image";
case VK_SPIRV_RESOURCE_TYPE_COMBINED_SAMPLED_IMAGE_BIT_EXT:
return "texture+sampler";
case VK_SPIRV_RESOURCE_TYPE_UNIFORM_BUFFER_BIT_EXT:
return "UBO";
case VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT:
return "RO-SSBO";
case VK_SPIRV_RESOURCE_TYPE_READ_WRITE_STORAGE_BUFFER_BIT_EXT:
return "RW-SSBO";
case VK_SPIRV_RESOURCE_TYPE_ACCELERATION_STRUCTURE_BIT_EXT:
return "accel-struct";
default:
return "unknown";
}
}
static void
print_alu_type(nir_alu_type type, print_state *state)
{
@ -1425,6 +1452,13 @@ print_intrinsic_instr(nir_intrinsic_instr *instr, print_state *state)
break;
}
case NIR_INTRINSIC_RESOURCE_TYPE: {
VkSpirvResourceTypeFlagBitsEXT res_type =
nir_intrinsic_resource_type(instr);
fprintf(fp, "resource_type=%s", vk_spirv_resource_type_name(res_type));
break;
}
case NIR_INTRINSIC_SRC_TYPE: {
fprintf(fp, "src_type=");
print_alu_type(nir_intrinsic_src_type(instr), state);
@ -2075,6 +2109,12 @@ print_tex_instr(nir_tex_instr *instr, print_state *state)
case nir_tex_src_box_size:
fprintf(fp, "(box_size)");
break;
case nir_tex_src_texture_heap_offset:
fprintf(fp, "(texture_heap_offset)");
break;
case nir_tex_src_sampler_heap_offset:
fprintf(fp, "(sampler_heap_offset)");
break;
case nir_tex_src_plane:
fprintf(fp, "(plane)");
break;
@ -2918,6 +2958,7 @@ print_shader_info(const struct shader_info *info, FILE *fp)
print_nz_bool(fp, "flrp_lowered", info->flrp_lowered);
print_nz_bool(fp, "io_lowered", info->io_lowered);
print_nz_bool(fp, "writes_memory", info->writes_memory);
print_nz_bool(fp, "use_descriptor_heap", info->use_descriptor_heap);
print_nz_unsigned(fp, "derivative_group", info->derivative_group);
switch (info->stage) {

View file

@ -1374,10 +1374,11 @@ union packed_tex_data {
unsigned texture_non_uniform : 1;
unsigned sampler_non_uniform : 1;
unsigned offset_non_uniform : 1;
unsigned embedded_sampler : 1;
unsigned array_is_lowered_cube : 1;
unsigned is_gather_implicit_lod : 1;
unsigned can_speculate : 1;
unsigned unused : 3; /* Mark unused for valgrind. */
unsigned unused : 2; /* Mark unused for valgrind. */
} u;
};
@ -1415,6 +1416,7 @@ write_tex(write_ctx *ctx, const nir_tex_instr *tex)
.u.texture_non_uniform = tex->texture_non_uniform,
.u.sampler_non_uniform = tex->sampler_non_uniform,
.u.offset_non_uniform = tex->offset_non_uniform,
.u.embedded_sampler = tex->embedded_sampler,
.u.array_is_lowered_cube = tex->array_is_lowered_cube,
.u.is_gather_implicit_lod = tex->is_gather_implicit_lod,
.u.can_speculate = tex->can_speculate,
@ -1456,6 +1458,7 @@ read_tex(read_ctx *ctx, union packed_instr header)
tex->texture_non_uniform = packed.u.texture_non_uniform;
tex->sampler_non_uniform = packed.u.sampler_non_uniform;
tex->offset_non_uniform = packed.u.offset_non_uniform;
tex->embedded_sampler = packed.u.embedded_sampler;
tex->array_is_lowered_cube = packed.u.array_is_lowered_cube;
tex->is_gather_implicit_lod = packed.u.is_gather_implicit_lod;
tex->can_speculate = packed.u.can_speculate;

View file

@ -459,6 +459,8 @@ gl_system_value_name(gl_system_value sysval)
ENUM(SYSTEM_VALUE_CORE_MAX_ID_ARM),
ENUM(SYSTEM_VALUE_WARP_ID_ARM),
ENUM(SYSTEM_VALUE_WARP_MAX_ID_ARM),
ENUM(SYSTEM_VALUE_SAMPLER_HEAP_PTR),
ENUM(SYSTEM_VALUE_RESOURCE_HEAP_PTR),
};
STATIC_ASSERT(ARRAY_SIZE(names) == SYSTEM_VALUE_MAX);
return NAME(sysval);

View file

@ -969,6 +969,10 @@ typedef enum
SYSTEM_VALUE_WARP_ID_ARM,
SYSTEM_VALUE_WARP_MAX_ID_ARM,
/* SPV_KHR_sampler_heap */
SYSTEM_VALUE_SAMPLER_HEAP_PTR,
SYSTEM_VALUE_RESOURCE_HEAP_PTR,
SYSTEM_VALUE_MAX /**< Number of values */
} gl_system_value;

View file

@ -276,6 +276,9 @@ typedef struct shader_info {
/* Whether ARB_bindless_texture ops or variables are used */
bool uses_bindless : 1;
/* Number of embedded samplers used by this shader */
bool uses_embedded_samplers : 1;
/**
* Shared memory types have explicit layout set. Used for
* SPV_KHR_workgroup_storage_explicit_layout.
@ -335,7 +338,12 @@ typedef struct shader_info {
* generate NaNs, and the only way the GPU saw one was to possibly feed it
* in as a uniform.
*/
bool use_legacy_math_rules;
bool use_legacy_math_rules:1;
/**
* Whether the shader uses descriptor heaps
*/
bool use_descriptor_heap:1;
/*
* Arrangement of invocations used to calculate derivatives in

View file

@ -111,6 +111,16 @@ struct spirv_to_nir_options {
*/
uint32_t min_ssbo_alignment;
/* These must be identical to the values set in
* VkPhysicalDeviceDescriptorHeapPropertiesEXT
*/
uint32_t sampler_descriptor_size;
uint32_t sampler_descriptor_alignment;
uint32_t image_descriptor_size;
uint32_t image_descriptor_alignment;
uint32_t buffer_descriptor_size;
uint32_t buffer_descriptor_alignment;
const nir_shader *clc_shader;
struct {

View file

@ -81,6 +81,7 @@ static const struct spirv_capabilities implemented_capabilities = {
.DenormFlushToZero = true,
.DenormPreserve = true,
.DerivativeControl = true,
.DescriptorHeapEXT = true,
.DeviceGroup = true,
.DotProduct = true,
.DotProductBFloat16AccVALVE = true,
@ -465,6 +466,7 @@ vtn_base_type_to_string(enum vtn_base_type t)
CASE(function);
CASE(event);
CASE(cooperative_matrix);
CASE(buffer);
}
#undef CASE
UNREACHABLE("unknown base type");
@ -679,6 +681,69 @@ spirv_to_gl_access_qualifier(struct vtn_builder *b,
}
}
static nir_deref_instr *
clone_deref_chain_for_mode(struct vtn_builder *b,
nir_def *value,
nir_variable_mode mode,
const glsl_type *type,
enum pipe_format image_format)
{
assert(nir_def_is_deref(value));
nir_deref_instr *deref = nir_def_as_deref(value);
if (deref->modes & mode)
return deref;
nir_deref_path path;
nir_deref_path_init(&path, deref, NULL);
nir_deref_instr *r = NULL;
for (unsigned i = 0; path.path[i] != NULL; i++) {
nir_deref_instr *d = path.path[i];
switch (d->deref_type) {
case nir_deref_type_var: {
nir_variable *var = nir_variable_clone(d->var, b->shader);
var->type = type;
var->data.mode = mode;
if (glsl_type_is_image(type))
var->data.image.format = image_format;
nir_shader_add_variable(b->shader, var);
r = nir_build_deref_var(&b->nb, var);
r->modes = mode;
break;
}
case nir_deref_type_array:
r = nir_build_deref_array(&b->nb, r, d->arr.index.ssa);
break;
case nir_deref_type_ptr_as_array:
r = nir_build_deref_ptr_as_array(&b->nb, r, d->arr.index.ssa);
break;
case nir_deref_type_struct:
r = nir_build_deref_struct(&b->nb, r, d->strct.index);
break;
case nir_deref_type_cast:
r = nir_build_deref_cast_with_alignment(&b->nb, &r->def, mode,
d->type,
d->cast.ptr_stride,
d->cast.align_mul,
d->cast.align_offset);
break;
default:
UNREACHABLE("invalid type");
return NULL;
}
}
nir_deref_path_finish(&path);
return r;
}
static nir_deref_instr *
vtn_get_image(struct vtn_builder *b, uint32_t value_id,
enum gl_access_qualifier *access)
@ -687,10 +752,13 @@ vtn_get_image(struct vtn_builder *b, uint32_t value_id,
vtn_assert(type->base_type == vtn_base_type_image);
if (access)
*access |= spirv_to_gl_access_qualifier(b, type->access_qualifier);
nir_variable_mode mode = glsl_type_is_image(type->glsl_image) ?
nir_var_image : nir_var_uniform;
return nir_build_deref_cast(&b->nb, vtn_get_nir_ssa(b, value_id),
mode, type->glsl_image, 0);
nir_def *value = &clone_deref_chain_for_mode(
b, vtn_get_nir_ssa(b, value_id), mode,
type->glsl_image, type->image_format)->def;
return nir_build_deref_cast(&b->nb, value, mode, type->glsl_image, 0);
}
static void
@ -708,8 +776,11 @@ vtn_get_sampler(struct vtn_builder *b, uint32_t value_id)
{
struct vtn_type *type = vtn_get_value_type(b, value_id);
vtn_assert(type->base_type == vtn_base_type_sampler);
return nir_build_deref_cast(&b->nb, vtn_get_nir_ssa(b, value_id),
nir_var_uniform, glsl_bare_sampler_type(), 0);
nir_def *value = &clone_deref_chain_for_mode(
b, vtn_get_nir_ssa(b, value_id), nir_var_uniform,
glsl_bare_sampler_type(), PIPE_FORMAT_NONE)->def;
return nir_build_deref_cast(&b->nb, value, nir_var_uniform,
glsl_bare_sampler_type(), 0);
}
nir_def *
@ -736,6 +807,11 @@ vtn_get_sampled_image(struct vtn_builder *b, uint32_t value_id)
struct vtn_type *type = vtn_get_value_type(b, value_id);
vtn_assert(type->base_type == vtn_base_type_sampled_image);
nir_def *si_vec2 = vtn_get_nir_ssa(b, value_id);
nir_alu_instr *si_alu_vec2 = nir_def_as_alu(si_vec2);
assert(si_alu_vec2->src[0].swizzle[0] == 0);
assert(si_alu_vec2->src[1].swizzle[0] == 0);
nir_def *image = si_alu_vec2->src[0].src.ssa;
nir_def *sampler = si_alu_vec2->src[1].src.ssa;
/* Even though this is a sampled image, we can end up here with a storage
* image because OpenCL doesn't distinguish between the two.
@ -745,11 +821,17 @@ vtn_get_sampled_image(struct vtn_builder *b, uint32_t value_id)
nir_var_image : nir_var_uniform;
struct vtn_sampled_image si = { NULL, };
si.image = nir_build_deref_cast(&b->nb, nir_channel(&b->nb, si_vec2, 0),
image_mode, image_type, 0);
si.sampler = nir_build_deref_cast(&b->nb, nir_channel(&b->nb, si_vec2, 1),
nir_var_uniform,
glsl_bare_sampler_type(), 0);
si.image = nir_build_deref_cast(
&b->nb,
&clone_deref_chain_for_mode(
b, image, image_mode, image_type, type->image_format)->def,
image_mode, image_type, 0);
si.sampler = nir_build_deref_cast(
&b->nb,
&clone_deref_chain_for_mode(
b, sampler, nir_var_uniform, glsl_bare_sampler_type(), PIPE_FORMAT_NONE)->def,
nir_var_uniform,
glsl_bare_sampler_type(), 0);
return si;
}
@ -1127,6 +1209,7 @@ vtn_handle_decoration(struct vtn_builder *b, SpvOp opcode,
case SpvOpDecorate:
case SpvOpDecorateId:
case SpvOpMemberDecorate:
case SpvOpMemberDecorateIdEXT:
case SpvOpDecorateString:
case SpvOpMemberDecorateString:
case SpvOpExecutionMode:
@ -1141,6 +1224,7 @@ vtn_handle_decoration(struct vtn_builder *b, SpvOp opcode,
dec->scope = VTN_DEC_DECORATION;
break;
case SpvOpMemberDecorate:
case SpvOpMemberDecorateIdEXT:
case SpvOpMemberDecorateString:
dec->scope = VTN_DEC_STRUCT_MEMBER0 + *(w++);
vtn_fail_if(dec->scope < VTN_DEC_STRUCT_MEMBER0, /* overflow */
@ -1269,6 +1353,9 @@ vtn_types_compatible(struct vtn_builder *b,
case vtn_base_type_cooperative_matrix:
return t1->type == t2->type;
case vtn_base_type_buffer:
return t1->storage_class == t2->storage_class;
case vtn_base_type_array:
return t1->length == t2->length &&
vtn_types_compatible(b, t1->array_element, t2->array_element);
@ -1330,6 +1417,7 @@ vtn_type_copy(struct vtn_builder *b, struct vtn_type *src)
case vtn_base_type_accel_struct:
case vtn_base_type_ray_query:
case vtn_base_type_cooperative_matrix:
case vtn_base_type_buffer:
/* Nothing more to do */
break;
@ -1370,6 +1458,10 @@ vtn_type_needs_explicit_layout(struct vtn_builder *b, struct vtn_type *type,
*/
return b->shader->info.has_transform_feedback_varyings;
case vtn_variable_mode_uniform:
/* These are used for descriptor heaps in Vulkan */
return b->options->environment == NIR_SPIRV_VULKAN;
case vtn_variable_mode_ssbo:
case vtn_variable_mode_phys_ssbo:
case vtn_variable_mode_ubo:
@ -1525,6 +1617,8 @@ array_stride_decoration_cb(struct vtn_builder *b,
vtn_fail_if(dec->operands[0] == 0, "ArrayStride must be non-zero");
type->stride = dec->operands[0];
}
} else if (dec->decoration == SpvDecorationArrayStrideIdEXT) {
type->stride = vtn_constant_uint(b, dec->operands[0]);
}
}
@ -1590,6 +1684,12 @@ struct_member_decoration_cb(struct vtn_builder *b,
ctx->type->offsets[member] = dec->operands[0];
ctx->fields[member].offset = dec->operands[0];
break;
case SpvDecorationOffsetIdEXT: {
uint32_t offset = vtn_constant_uint(b, dec->operands[0]);
ctx->type->offsets[member] = offset;
ctx->fields[member].offset = offset;
break;
}
case SpvDecorationMatrixStride:
/* Handled as a second pass */
break;
@ -1770,6 +1870,7 @@ type_decoration_cb(struct vtn_builder *b,
switch (dec->decoration) {
case SpvDecorationArrayStride:
case SpvDecorationArrayStrideIdEXT:
vtn_assert(type->base_type == vtn_base_type_array ||
type->base_type == vtn_base_type_pointer);
break;
@ -1808,6 +1909,7 @@ type_decoration_cb(struct vtn_builder *b,
case SpvDecorationXfbBuffer:
case SpvDecorationXfbStride:
case SpvDecorationUserSemantic:
case SpvDecorationOffsetIdEXT:
vtn_warn("Decoration only allowed for struct members: %s",
spirv_decoration_to_string(dec->decoration));
break;
@ -2438,6 +2540,21 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
val->type->type = b->shader->info.cs.ptr_size == 64 ? glsl_int64_t_type() : glsl_int_type();
break;
case SpvOpTypeBufferEXT: {
SpvStorageClass storage_class = w[2];
vtn_fail_if(storage_class != SpvStorageClassUniform &&
storage_class != SpvStorageClassStorageBuffer,
"Storage Class must be Uniform or StorageBuffer.");
const nir_address_format addr_format = vtn_mode_to_address_format(b,
vtn_storage_class_to_mode(b, storage_class, NULL, NULL));
val->type->base_type = vtn_base_type_buffer;
val->type->storage_class = storage_class;
val->type->type = nir_address_format_to_glsl_type(addr_format);
break;
}
case SpvOpTypeDeviceEvent:
case SpvOpTypeReserveId:
case SpvOpTypeQueue:
@ -3014,6 +3131,37 @@ vtn_handle_constant(struct vtn_builder *b, SpvOp opcode,
val->is_null_constant = true;
break;
case SpvOpConstantSizeOfEXT: {
vtn_fail_if(val->type->type != glsl_uint_type() &&
val->type->type != glsl_int_type(),
"Result Type must be a 32-bit integer type scalar.");
struct vtn_type *type = vtn_get_type(b, w[3]);
switch (type->base_type) {
case vtn_base_type_image:
val->constant->values[0].u32 =
align(b->options->image_descriptor_size,
b->options->image_descriptor_alignment);
break;
case vtn_base_type_sampler:
val->constant->values[0].u32 =
align(b->options->sampler_descriptor_size,
b->options->sampler_descriptor_alignment);
break;
case vtn_base_type_accel_struct:
case vtn_base_type_buffer:
val->constant->values[0].u32 =
align(b->options->buffer_descriptor_size,
b->options->buffer_descriptor_alignment);
break;
default:
vtn_fail("Type must be an OpTypeBufferKHR, OpTypeImage, "
"OpTypeAccelerationStructureKHR, OpTypeTensorARM, or "
"OpTypeSampler instruction.");
}
break;
}
default:
vtn_fail_with_opcode("Unhandled opcode", opcode);
}
@ -4163,6 +4311,22 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode,
val->image->sample = vtn_get_nir_ssa(b, w[5]);
val->image->lod = nir_imm_int(&b->nb, 0);
return;
} else if (opcode == SpvOpUntypedImageTexelPointerEXT) {
struct vtn_type *type = vtn_get_value_type(b, w[3]);
struct vtn_value *val =
vtn_push_value(b, w[2], vtn_value_type_image_pointer);
val->image = vtn_alloc(b, struct vtn_image_pointer);
val->image->image = nir_build_deref_cast(
&b->nb,
&clone_deref_chain_for_mode(
b, vtn_get_nir_ssa(b, w[4]), nir_var_image, type->glsl_image, type->image_format)->def,
nir_var_image,
type->glsl_image, 0);
val->image->coord = get_image_coord(b, w[5]);
val->image->sample = vtn_get_nir_ssa(b, w[6]);
val->image->lod = nir_imm_int(&b->nb, 0);
return;
}
struct vtn_image_pointer image;
@ -5368,6 +5532,10 @@ vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode,
spirv_capability_to_string(cap));
break;
case SpvCapabilityDescriptorHeapEXT:
b->shader->info.use_descriptor_heap = true;
break;
default:
vtn_fail_if(!spirv_capabilities_get(&implemented_capabilities, cap),
"Unimplemented SPIR-V capability: %s (%u)",
@ -5461,6 +5629,7 @@ vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode,
case SpvOpDecorate:
case SpvOpDecorateId:
case SpvOpMemberDecorate:
case SpvOpMemberDecorateIdEXT:
case SpvOpGroupDecorate:
case SpvOpGroupMemberDecorate:
case SpvOpDecorateString:
@ -6010,11 +6179,8 @@ vtn_handle_execution_mode_id(struct vtn_builder *b, struct vtn_value *entry_poin
}
static bool
vtn_handle_variable_or_type_instruction(struct vtn_builder *b, SpvOp opcode,
const uint32_t *w, unsigned count)
spv_op_is_preamble(SpvOp opcode)
{
vtn_set_instruction_result_type(b, opcode, w, count);
switch (opcode) {
case SpvOpSource:
case SpvOpSourceContinued:
@ -6032,13 +6198,29 @@ vtn_handle_variable_or_type_instruction(struct vtn_builder *b, SpvOp opcode,
case SpvOpDecorate:
case SpvOpDecorateId:
case SpvOpMemberDecorate:
case SpvOpMemberDecorateIdEXT:
case SpvOpGroupDecorate:
case SpvOpGroupMemberDecorate:
case SpvOpDecorateString:
case SpvOpMemberDecorateString:
vtn_fail("Invalid opcode types and variables section");
break;
return true;
default:
return false;
}
}
static bool
vtn_handle_variable_or_type_instruction(struct vtn_builder *b, SpvOp opcode,
const uint32_t *w, unsigned count)
{
vtn_fail_if(spv_op_is_preamble(opcode),
"Invalid opcode in the types and variables section: %s",
spirv_op_to_string(opcode));
vtn_set_instruction_result_type(b, opcode, w, count);
switch (opcode) {
case SpvOpTypeVoid:
case SpvOpTypeBool:
case SpvOpTypeInt:
@ -6064,6 +6246,7 @@ vtn_handle_variable_or_type_instruction(struct vtn_builder *b, SpvOp opcode,
case SpvOpTypeRayQueryKHR:
case SpvOpTypeCooperativeMatrixKHR:
case SpvOpTypeUntypedPointerKHR:
case SpvOpTypeBufferEXT:
vtn_handle_type(b, opcode, w, count);
break;
@ -6079,6 +6262,7 @@ vtn_handle_variable_or_type_instruction(struct vtn_builder *b, SpvOp opcode,
case SpvOpSpecConstantComposite:
case SpvOpSpecConstantCompositeReplicateEXT:
case SpvOpSpecConstantOp:
case SpvOpConstantSizeOfEXT:
vtn_handle_constant(b, opcode, w, count);
break;
@ -6639,6 +6823,7 @@ vtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode,
case SpvOpUntypedInBoundsAccessChainKHR:
case SpvOpUntypedInBoundsPtrAccessChainKHR:
case SpvOpUntypedArrayLengthKHR:
case SpvOpBufferPointerEXT:
vtn_handle_variables(b, opcode, w, count);
break;
@ -6681,6 +6866,7 @@ vtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode,
case SpvOpImageTexelPointer:
case SpvOpImageQueryFormat:
case SpvOpImageQueryOrder:
case SpvOpUntypedImageTexelPointerEXT:
vtn_handle_image(b, opcode, w, count);
break;

View file

@ -297,6 +297,7 @@ enum vtn_base_type {
vtn_base_type_function,
vtn_base_type_event,
vtn_base_type_cooperative_matrix,
vtn_base_type_buffer,
};
struct vtn_type {
@ -364,7 +365,7 @@ struct vtn_type {
bool packed:1;
};
/* Members for pointer types */
/* Members for pointer and buffer types */
struct {
/* For regular pointers, the vtn_type of the object pointed to;
* for untyped pointers it must be NULL.

View file

@ -260,6 +260,7 @@ vtn_variable_resource_index(struct vtn_builder *b, struct vtn_variable *var,
nir_intrinsic_set_desc_set(instr, var->descriptor_set);
nir_intrinsic_set_binding(instr, var->binding);
nir_intrinsic_set_desc_type(instr, vk_desc_type_for_mode(b, var->mode));
nir_intrinsic_set_resource_type(instr, var->var->data.resource_type);
nir_address_format addr_format = vtn_mode_to_address_format(b, var->mode);
nir_def_init(&instr->instr, &instr->def,
@ -1339,6 +1340,15 @@ vtn_get_builtin_location(struct vtn_builder *b,
set_mode_system_value(b, mode);
break;
case SpvBuiltInSamplerHeapEXT:
vtn_assert(*mode == nir_var_uniform);
*location = SYSTEM_VALUE_SAMPLER_HEAP_PTR;
break;
case SpvBuiltInResourceHeapEXT:
vtn_assert(*mode == nir_var_uniform);
*location = SYSTEM_VALUE_RESOURCE_HEAP_PTR;
break;
default:
vtn_fail("Unsupported builtin: %s (%u)",
spirv_builtin_to_string(builtin), builtin);
@ -1459,6 +1469,7 @@ apply_var_decoration(struct vtn_builder *b,
case SpvDecorationArrayStride:
case SpvDecorationGLSLShared:
case SpvDecorationGLSLPacked:
case SpvDecorationArrayStrideIdEXT:
break; /* These can apply to a type but we don't care about them */
case SpvDecorationBinding:
@ -1786,6 +1797,13 @@ vtn_storage_class_to_mode(struct vtn_builder *b,
nir_mode = nir_var_mem_global;
break;
case SpvStorageClassUniformConstant:
/* This can happen with descriptor heaps and it's UBO */
if (interface_type == NULL) {
mode = vtn_variable_mode_uniform;
nir_mode = nir_var_uniform;
break;
}
/* interface_type is only NULL when OpTypeForwardPointer is used and
* OpTypeForwardPointer can only be used for struct types, not images or
* acceleration structures.
@ -1793,8 +1811,7 @@ vtn_storage_class_to_mode(struct vtn_builder *b,
if (interface_type)
interface_type = vtn_type_without_array(interface_type);
if (interface_type &&
interface_type->base_type == vtn_base_type_image &&
if (interface_type->base_type == vtn_base_type_image &&
glsl_type_is_image(interface_type->glsl_image)) {
mode = vtn_variable_mode_image;
nir_mode = nir_var_image;
@ -2452,6 +2469,43 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
/* Propagate access flags from the OpVariable decorations. */
val->pointer->access |= var->access;
switch (without_array->base_type) {
case vtn_base_type_image:
if (glsl_type_is_image(without_array->glsl_image)) {
if (var->access & ACCESS_NON_WRITEABLE)
var->var->data.resource_type = VK_SPIRV_RESOURCE_TYPE_READ_ONLY_IMAGE_BIT_EXT;
else
var->var->data.resource_type = VK_SPIRV_RESOURCE_TYPE_READ_WRITE_IMAGE_BIT_EXT;
} else {
var->var->data.resource_type = VK_SPIRV_RESOURCE_TYPE_SAMPLED_IMAGE_BIT_EXT;
}
break;
case vtn_base_type_sampler:
var->var->data.resource_type = VK_SPIRV_RESOURCE_TYPE_SAMPLER_BIT_EXT;
break;
case vtn_base_type_sampled_image:
var->var->data.resource_type = VK_SPIRV_RESOURCE_TYPE_COMBINED_SAMPLED_IMAGE_BIT_EXT;
break;
case vtn_base_type_accel_struct:
var->var->data.resource_type = VK_SPIRV_RESOURCE_TYPE_ACCELERATION_STRUCTURE_BIT_EXT;
break;
default:
switch (var->mode) {
case vtn_variable_mode_ubo:
var->var->data.resource_type = VK_SPIRV_RESOURCE_TYPE_UNIFORM_BUFFER_BIT_EXT;
break;
case vtn_variable_mode_ssbo:
if (var->access & ACCESS_NON_WRITEABLE)
var->var->data.resource_type = VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT;
else
var->var->data.resource_type = VK_SPIRV_RESOURCE_TYPE_READ_WRITE_STORAGE_BUFFER_BIT_EXT;
break;
default:
break;
}
break;
}
if ((var->mode == vtn_variable_mode_input ||
var->mode == vtn_variable_mode_output) &&
var->var->members) {
@ -2693,6 +2747,38 @@ vtn_cast_pointer(struct vtn_builder *b, struct vtn_pointer *p,
return casted;
}
static void
buffer_ptr_decoration_cb(struct vtn_builder *b, struct vtn_value *val,
int member, const struct vtn_decoration *dec,
void *void_access)
{
enum gl_access_qualifier *access = void_access;
vtn_assert(member == -1);
switch (dec->decoration) {
case SpvDecorationNonReadable:
*access |= ACCESS_NON_READABLE;
break;
case SpvDecorationNonWritable:
*access |= ACCESS_NON_WRITEABLE;
break;
case SpvDecorationRestrict:
*access |= ACCESS_RESTRICT;
break;
case SpvDecorationAliased:
*access &= ~ACCESS_RESTRICT;
break;
case SpvDecorationVolatile:
*access |= ACCESS_VOLATILE;
break;
case SpvDecorationCoherent:
*access |= ACCESS_COHERENT;
break;
default:
vtn_fail_with_decoration("Unhandled decoration", dec->decoration);
}
}
void
vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
const uint32_t *w, unsigned count)
@ -2710,7 +2796,13 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
const bool untyped = opcode == SpvOpUntypedVariableKHR;
struct vtn_type *ptr_type = vtn_get_type(b, w[1]);
struct vtn_type *data_type = untyped ? vtn_get_type(b, w[4]) : ptr_type->pointed;
struct vtn_type *data_type =
untyped && count > 4 ? vtn_get_type(b, w[4]) : ptr_type->pointed;
if (data_type == NULL) {
data_type = vtn_zalloc(b, struct vtn_type);
data_type->base_type = vtn_base_type_void;
data_type->type = glsl_void_type();
}
SpvStorageClass storage_class = w[3];
@ -2946,6 +3038,62 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
break;
}
case SpvOpBufferPointerEXT: {
struct vtn_type *res_type = vtn_get_type(b, w[1]);
struct vtn_value *val = vtn_untyped_value(b, w[1]);
struct vtn_value *src_val = vtn_value(b, w[3], vtn_value_type_pointer);
struct vtn_pointer *src = vtn_value_to_pointer(b, src_val);
vtn_fail_if(res_type->base_type != vtn_base_type_pointer,
"Result Type must be a pointer type");
enum gl_access_qualifier access = 0;
vtn_foreach_decoration(b, val, buffer_ptr_decoration_cb, &access);
VkSpirvResourceTypeFlagBitsEXT resource_type;
switch (res_type->storage_class) {
case SpvStorageClassUniform:
case SpvStorageClassUniformConstant:
resource_type = VK_SPIRV_RESOURCE_TYPE_UNIFORM_BUFFER_BIT_EXT;
break;
case SpvStorageClassStorageBuffer:
if (access & ACCESS_NON_WRITEABLE)
resource_type = VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT;
else
resource_type = VK_SPIRV_RESOURCE_TYPE_READ_WRITE_STORAGE_BUFFER_BIT_EXT;
break;
default:
vtn_fail("Result Type must be a pointer type with a Storage Class "
"of Uniform or StorageBuffer.");
}
const nir_address_format addr_format = vtn_mode_to_address_format(b,
vtn_storage_class_to_mode(b, res_type->storage_class, NULL, NULL));
unsigned num_components = nir_address_format_num_components(addr_format);
unsigned bit_size = nir_address_format_bit_size(addr_format);
struct vtn_type *buffer_type = vtn_zalloc(b, struct vtn_type);
buffer_type->base_type = vtn_base_type_buffer;
buffer_type->storage_class = res_type->storage_class;
buffer_type->type = nir_address_format_to_glsl_type(addr_format);
/* buffer is always an untyped pointer */
src = vtn_cast_pointer(b, src, buffer_type);
/* We know the alignment from the API */
src = vtn_align_pointer(b, src, b->options->buffer_descriptor_alignment);
nir_deref_instr *src_deref = vtn_pointer_to_deref(b, src);
nir_def *ptr = nir_load_buffer_ptr_deref(&b->nb, num_components, bit_size,
&src_deref->def,
.access = access,
.resource_type = resource_type);
vtn_push_pointer(b, w[2], vtn_pointer_from_ssa(b, ptr, res_type));
break;
}
case SpvOpStore: {
struct vtn_value *dest_val = vtn_pointer_value(b, w[1]);
struct vtn_pointer *dest = vtn_value_to_pointer(b, dest_val);

View file

@ -1389,7 +1389,7 @@ tu_get_properties(struct tu_physical_device *pdevice,
props->samplerCaptureReplayDescriptorDataSize = 0;
props->accelerationStructureCaptureReplayDescriptorDataSize = 0;
/* Note: these sizes must match descriptor_size() */
props->samplerDescriptorSize = FDL6_TEX_CONST_DWORDS * 4;
props->EDBsamplerDescriptorSize = FDL6_TEX_CONST_DWORDS * 4;
props->combinedImageSamplerDescriptorSize = 2 * FDL6_TEX_CONST_DWORDS * 4;
props->sampledImageDescriptorSize = FDL6_TEX_CONST_DWORDS * 4;
props->storageImageDescriptorSize = FDL6_TEX_CONST_DWORDS * 4;
@ -1535,7 +1535,7 @@ tu_get_properties(struct tu_physical_device *pdevice,
props->conservativeRasterizationPostDepthCoverage = false;
/* VK_EXT_fragment_density_map_offset */
props->fragmentDensityOffsetGranularity = (VkExtent2D) {
props->fragmentDensityOffsetGranularity = (VkExtent2D) {
TU_FDM_OFFSET_GRANULARITY, TU_FDM_OFFSET_GRANULARITY
};

View file

@ -1230,7 +1230,7 @@ lvp_get_properties(const struct lvp_physical_device *device, struct vk_propertie
.imageViewCaptureReplayDescriptorDataSize = 0,
.samplerCaptureReplayDescriptorDataSize = 0,
.accelerationStructureCaptureReplayDescriptorDataSize = 0,
.samplerDescriptorSize = sizeof(struct lp_descriptor),
.EDBsamplerDescriptorSize = sizeof(struct lp_descriptor),
.combinedImageSamplerDescriptorSize = sizeof(struct lp_descriptor),
.sampledImageDescriptorSize = sizeof(struct lp_descriptor),
.storageImageDescriptorSize = sizeof(struct lp_descriptor),

View file

@ -1714,7 +1714,7 @@ get_properties(const struct anv_physical_device *pdevice,
*/
props->accelerationStructureCaptureReplayDescriptorDataSize = 0;
props->samplerDescriptorSize = ANV_SAMPLER_STATE_SIZE;
props->EDBsamplerDescriptorSize = ANV_SAMPLER_STATE_SIZE;
props->combinedImageSamplerDescriptorSize = align(ANV_SURFACE_STATE_SIZE + ANV_SAMPLER_STATE_SIZE,
ANV_SURFACE_STATE_SIZE);
props->sampledImageDescriptorSize = ANV_SURFACE_STATE_SIZE;

View file

@ -1102,7 +1102,7 @@ nvk_get_device_properties(const struct nvk_instance *instance,
.samplerCaptureReplayDescriptorDataSize =
sizeof(struct nvk_sampler_capture),
.accelerationStructureCaptureReplayDescriptorDataSize = 0, // todo
.samplerDescriptorSize = sizeof(struct nvk_sampled_image_descriptor),
.EDBsamplerDescriptorSize = sizeof(struct nvk_sampled_image_descriptor),
.combinedImageSamplerDescriptorSize = sizeof(struct nvk_sampled_image_descriptor),
.sampledImageDescriptorSize = sizeof(struct nvk_sampled_image_descriptor),
.storageImageDescriptorSize = sizeof(struct nvk_storage_image_descriptor),

View file

@ -262,6 +262,7 @@ vulkan_runtime_files = files(
'vk_meta_draw_rects.c',
'vk_nir.c',
'vk_nir_convert_ycbcr.c',
'vk_nir_lower_descriptor_heaps.c',
'vk_pipeline.c',
'vk_pipeline_cache.c',
'vk_shader.c',

View file

@ -86,6 +86,23 @@ vk_buffer_range(const struct vk_buffer *buffer,
}
}
static inline VkDeviceAddressRangeEXT
vk_buffer_address_range(const struct vk_buffer *buffer,
VkDeviceSize offset, VkDeviceSize range)
{
/* Since we're returning a size along with the address, it's safe for this
* helper to automatically handle null descriptor cases by returning a zero
* address and size.
*/
if (buffer == NULL || range == 0)
return (VkDeviceAddressRangeEXT) { .size = 0 };
return (VkDeviceAddressRangeEXT) {
.address = vk_buffer_address(buffer, offset),
.size = vk_buffer_range(buffer, offset, range),
};
}
#ifdef __cplusplus
}
#endif

View file

@ -636,6 +636,23 @@ vk_common_DeviceWaitIdle(VkDevice _device)
return VK_SUCCESS;
}
VKAPI_ATTR VkResult VKAPI_CALL
vk_common_RegisterCustomBorderColorEXT(VkDevice device,
const VkSamplerCustomBorderColorCreateInfoEXT* pBorderColor,
VkBool32 requestIndex,
uint32_t *pIndex)
{
if (requestIndex)
*pIndex = 0;
return VK_SUCCESS;
}
VKAPI_ATTR void VKAPI_CALL
vk_common_UnregisterCustomBorderColorEXT(VkDevice device,
uint32_t index)
{ }
VkResult
vk_device_copy_semaphore_payloads(struct vk_device *device,
uint32_t wait_semaphore_count,

View file

@ -96,4 +96,6 @@
*/
#define MESA_VK_MAX_MULTIVIEW_VIEW_COUNT 32
#define MESA_VK_MAX_CUSTOM_BORDER_COLOR ~0
#endif /* VK_LIMITS_H */

View file

@ -136,6 +136,19 @@ vk_spirv_to_nir(struct vk_device *device,
spirv_options_local.debug.func = spirv_nir_debug;
spirv_options_local.debug.private_data = (void *)device;
spirv_options_local.sampler_descriptor_size =
device->physical->properties.samplerDescriptorSize;
spirv_options_local.sampler_descriptor_alignment =
device->physical->properties.samplerDescriptorAlignment;
spirv_options_local.image_descriptor_size =
device->physical->properties.imageDescriptorSize;
spirv_options_local.image_descriptor_alignment =
device->physical->properties.imageDescriptorAlignment;
spirv_options_local.buffer_descriptor_size =
device->physical->properties.bufferDescriptorSize;
spirv_options_local.buffer_descriptor_alignment =
device->physical->properties.bufferDescriptorAlignment;
uint32_t num_spec_entries = 0;
struct nir_spirv_specialization *spec_entries =
vk_spec_info_to_nir_spirv(spec_info, &num_spec_entries);

View file

@ -151,19 +151,33 @@ struct ycbcr_state {
nir_builder *builder;
nir_def *image_size;
nir_tex_instr *origin_tex;
nir_deref_instr *tex_deref;
nir_tex_src tex_handle;
const struct vk_ycbcr_conversion_state *conversion;
const struct vk_format_ycbcr_info *format_ycbcr_info;
};
/* TODO: we should probably replace this with a push constant/uniform. */
static nir_def *
get_texture_size(struct ycbcr_state *state, nir_deref_instr *texture)
get_texture_size(struct ycbcr_state *state)
{
if (!state->image_size) {
nir_builder *b = state->builder;
state->image_size = nir_i2f32(b, nir_txs(b, .texture_deref = texture));
}
if (state->image_size)
return state->image_size;
nir_builder *b = state->builder;
nir_tex_instr *tex = nir_tex_instr_create(b->shader, 1);
tex->op = nir_texop_txs;
tex->sampler_dim = state->origin_tex->sampler_dim,
tex->is_array = state->origin_tex->is_array,
tex->is_shadow = state->origin_tex->is_shadow,
tex->dest_type = nir_type_int32;
tex->src[0] = state->tex_handle;
nir_def_init(&tex->instr, &tex->def, nir_tex_instr_dest_size(tex), 32);
nir_builder_instr_insert(b, &tex->instr);
state->image_size = nir_i2f32(b, &tex->def);
return state->image_size;
}
@ -185,7 +199,7 @@ implicit_downsampled_coords(struct ycbcr_state *state,
{
nir_builder *b = state->builder;
const struct vk_ycbcr_conversion_state *conversion = state->conversion;
nir_def *image_size = get_texture_size(state, state->tex_deref);
nir_def *image_size = get_texture_size(state);
nir_def *comp[4] = { NULL, };
int c;
@ -247,6 +261,7 @@ create_plane_tex_instr_implicit(struct ycbcr_state *state,
tex->is_new_style_shadow = old_tex->is_new_style_shadow;
tex->component = old_tex->component;
tex->embedded_sampler = old_tex->embedded_sampler;
tex->texture_index = old_tex->texture_index;
tex->sampler_index = old_tex->sampler_index;
tex->is_array = old_tex->is_array;
@ -294,25 +309,40 @@ lower_ycbcr_tex_instr(nir_builder *b, nir_tex_instr *tex, void *_state)
tex->op == nir_texop_lod)
return false;
int deref_src_idx = nir_tex_instr_src_index(tex, nir_tex_src_texture_deref);
assert(deref_src_idx >= 0);
nir_deref_instr *deref = nir_src_as_deref(tex->src[deref_src_idx].src);
nir_tex_src tex_handle;
const struct vk_ycbcr_conversion_state *conversion;
if (tex->embedded_sampler) {
const int heap_src_idx =
nir_tex_instr_src_index(tex, nir_tex_src_texture_heap_offset);
tex_handle = tex->src[heap_src_idx];
nir_variable *var = nir_deref_instr_get_variable(deref);
uint32_t set = var->data.descriptor_set;
uint32_t binding = var->data.binding;
assert(tex->texture_index == 0);
unsigned array_index = 0;
if (deref->deref_type != nir_deref_type_var) {
assert(deref->deref_type == nir_deref_type_array);
if (!nir_src_is_const(deref->arr.index))
conversion = state->cb(state->cb_data,
VK_NIR_YCBCR_SET_IMMUTABLE_SAMPLERS,
tex->sampler_index, 0);
} else {
const int deref_src_idx =
nir_tex_instr_src_index(tex, nir_tex_src_texture_deref);
if (deref_src_idx < 0)
return false;
array_index = nir_src_as_uint(deref->arr.index);
}
const struct vk_ycbcr_conversion_state *conversion =
state->cb(state->cb_data, set, binding, array_index);
tex_handle = tex->src[deref_src_idx];
nir_deref_instr *deref = nir_src_as_deref(tex_handle.src);
nir_variable *var = nir_deref_instr_get_variable(deref);
uint32_t set = var->data.descriptor_set;
uint32_t binding = var->data.binding;
assert(tex->texture_index == 0);
unsigned array_index = 0;
if (deref->deref_type != nir_deref_type_var) {
assert(deref->deref_type == nir_deref_type_array);
if (!nir_src_is_const(deref->arr.index))
return false;
array_index = nir_src_as_uint(deref->arr.index);
}
conversion = state->cb(state->cb_data, set, binding, array_index);
}
if (conversion == NULL)
return false;
@ -357,7 +387,7 @@ lower_ycbcr_tex_instr(nir_builder *b, nir_tex_instr *tex, void *_state)
struct ycbcr_state tex_state = {
.builder = b,
.origin_tex = tex,
.tex_deref = deref,
.tex_handle = tex_handle,
.conversion = conversion,
.format_ycbcr_info = format_ycbcr_info,
};

View file

@ -40,6 +40,12 @@ nir_convert_ycbcr_to_rgb(nir_builder *b,
struct vk_ycbcr_conversion;
/** Passed as the set parameter to nir_vk_ycbcr_conversion_lookup_cb() to
* indicate that embedded samplers are being used and that binding is the
* index in the embedded sampler table.
*/
#define VK_NIR_YCBCR_SET_IMMUTABLE_SAMPLERS UINT32_MAX
typedef const struct vk_ycbcr_conversion_state *
(*nir_vk_ycbcr_conversion_lookup_cb)(const void *data, uint32_t set,
uint32_t binding, uint32_t array_index);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,86 @@
/*
* Copyright © 2024 Valve Corporation
* SPDX-License-Identifier: MIT
*/
#ifndef VK_NIR_LOWER_DESCRIPTOR_HEAP_MAPPINGS
#define VK_NIR_LOWER_DESCRIPTOR_HEAP_MAPPINGS
#include "nir.h"
#include <vulkan/vulkan_core.h>
#include "util/mesa-blake3.h"
static inline const VkDescriptorSetAndBindingMappingEXT *
vk_descriptor_heap_mapping(const VkShaderDescriptorSetAndBindingMappingInfoEXT *info,
uint32_t set, uint32_t binding,
VkSpirvResourceTypeFlagBitsEXT resource_type)
{
assert(util_is_power_of_two_nonzero(resource_type));
for (uint32_t i = 0; i < info->mappingCount; i++) {
const VkDescriptorSetAndBindingMappingEXT *mapping = &info->pMappings[i];
const uint32_t begin_binding = mapping->firstBinding;
const uint32_t end_binding =
(mapping->firstBinding + mapping->bindingCount) < mapping->firstBinding ?
UINT32_MAX : (mapping->firstBinding + mapping->bindingCount - 1) ;
if (mapping->descriptorSet == set &&
binding >= begin_binding && binding <= end_binding &&
mapping->resourceMask & resource_type)
return mapping;
}
return NULL;
}
static inline const VkSamplerCreateInfo *
vk_descriptor_heap_embedded_sampler(const VkDescriptorSetAndBindingMappingEXT *mapping)
{
switch (mapping->source) {
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT:
return mapping->sourceData.constantOffset.pEmbeddedSampler;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT:
return mapping->sourceData.pushIndex.pEmbeddedSampler;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_EXT:
return mapping->sourceData.indirectIndex.pEmbeddedSampler;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT:
return mapping->sourceData.indirectIndexArray.pEmbeddedSampler;
case VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_SHADER_RECORD_INDEX_EXT:
return mapping->sourceData.shaderRecordIndex.pEmbeddedSampler;
default:
return NULL;
}
}
void vk_hash_descriptor_heap_mappings(
const VkShaderDescriptorSetAndBindingMappingInfoEXT *info,
blake3_hash blake3_out);
nir_def *
vk_build_descriptor_heap_offset(nir_builder *b,
const VkDescriptorSetAndBindingMappingEXT *mapping,
VkSpirvResourceTypeFlagBitsEXT resource_type,
uint32_t binding, nir_def *index,
bool is_sampler);
nir_def *
vk_build_descriptor_heap_address(nir_builder *b,
const VkDescriptorSetAndBindingMappingEXT *mapping,
uint32_t binding, nir_def *index);
struct vk_sampler_state_array {
struct vk_sampler_state *samplers;
uint32_t sampler_count;
};
static inline void
vk_sampler_state_array_finish(struct vk_sampler_state_array *arr)
{
free(arr->samplers);
}
bool vk_nir_lower_descriptor_heaps(
nir_shader *nir,
const VkShaderDescriptorSetAndBindingMappingInfoEXT *mapping,
struct vk_sampler_state_array *embedded_samplers_out);
#endif

View file

@ -324,3 +324,34 @@ vk_common_GetPhysicalDeviceToolProperties(VkPhysicalDevice physicalDevice,
return vk_outarray_status(&out);
}
VKAPI_ATTR VkDeviceSize VKAPI_CALL
vk_common_GetPhysicalDeviceDescriptorSizeEXT(VkPhysicalDevice physicalDevice,
VkDescriptorType descriptorType)
{
VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
switch (descriptorType) {
case VK_DESCRIPTOR_TYPE_SAMPLER:
return pdevice->properties.samplerDescriptorSize;
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
case VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM:
case VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM:
return pdevice->properties.imageDescriptorSize;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
return pdevice->properties.bufferDescriptorSize;
default:
UNREACHABLE("Invalid descriptor type in GetPhysicalDeviceDescriptorSizeEXT");
return 0;
}
}

View file

@ -31,9 +31,11 @@
#include "vk_graphics_state.h"
#include "vk_log.h"
#include "vk_nir.h"
#include "vk_nir_lower_descriptor_heaps.h"
#include "vk_physical_device.h"
#include "vk_physical_device_features.h"
#include "vk_pipeline_layout.h"
#include "vk_sampler.h"
#include "vk_shader.h"
#include "vk_shader_module.h"
#include "vk_util.h"
@ -296,6 +298,16 @@ vk_pipeline_hash_shader_stage_blake3(VkPipelineCreateFlags2KHR pipeline_flags,
info->pSpecializationInfo->dataSize);
}
const VkShaderDescriptorSetAndBindingMappingInfoEXT *desc_map =
vk_find_struct_const(info->pNext,
SHADER_DESCRIPTOR_SET_AND_BINDING_MAPPING_INFO_EXT);
if (desc_map != NULL) {
blake3_hash desc_map_blake3;
vk_hash_descriptor_heap_mappings(desc_map, desc_map_blake3);
_mesa_blake3_update(&ctx, desc_map_blake3, sizeof(desc_map_blake3));
}
uint32_t req_subgroup_size = get_required_subgroup_size(info);
_mesa_blake3_update(&ctx, &req_subgroup_size, sizeof(req_subgroup_size));
@ -700,6 +712,9 @@ struct vk_pipeline_precomp_shader {
/* Tessellation info if the shader is a tessellation shader */
struct vk_pipeline_tess_info tess;
uint32_t embedded_sampler_count;
struct vk_sampler_state *embedded_samplers;
struct blob nir_blob;
};
@ -730,7 +745,9 @@ static struct vk_pipeline_precomp_shader *
vk_pipeline_precomp_shader_create(struct vk_device *device,
const void *key_data, size_t key_size,
const struct vk_pipeline_robustness_state *rs,
nir_shader *nir)
nir_shader *nir,
const uint32_t embedded_sampler_count,
const struct vk_sampler_state *embedded_samplers)
{
struct blob blob;
blob_init(&blob);
@ -740,10 +757,12 @@ vk_pipeline_precomp_shader_create(struct vk_device *device,
if (blob.out_of_memory)
goto fail_blob;
struct vk_pipeline_precomp_shader *shader =
vk_zalloc(&device->alloc, sizeof(*shader), 8,
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
if (shader == NULL)
VK_MULTIALLOC(ma);
VK_MULTIALLOC_DECL(&ma, struct vk_pipeline_precomp_shader, shader, 1);
VK_MULTIALLOC_DECL(&ma, struct vk_sampler_state, samplers,
embedded_sampler_count);
if (!vk_multialloc_zalloc(&ma, &device->alloc,
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE))
goto fail_blob;
assert(sizeof(shader->cache_key) == key_size);
@ -759,6 +778,11 @@ vk_pipeline_precomp_shader_create(struct vk_device *device,
vk_pipeline_gather_nir_tess_info(nir, &shader->tess);
shader->embedded_sampler_count = embedded_sampler_count;
shader->embedded_samplers = samplers;
for (uint32_t i = 0; i < embedded_sampler_count; i++)
shader->embedded_samplers[i] = embedded_samplers[i];
shader->nir_blob = blob;
return shader;
@ -779,6 +803,10 @@ vk_pipeline_precomp_shader_serialize(struct vk_pipeline_cache_object *obj,
blob_write_uint32(blob, shader->stage);
blob_write_bytes(blob, &shader->rs, sizeof(shader->rs));
blob_write_bytes(blob, &shader->tess, sizeof(shader->tess));
blob_write_uint32(blob, shader->embedded_sampler_count);
blob_write_bytes(blob, shader->embedded_samplers,
shader->embedded_sampler_count *
sizeof(*shader->embedded_samplers));
blob_write_uint64(blob, shader->nir_blob.size);
blob_write_bytes(blob, shader->nir_blob.data, shader->nir_blob.size);
@ -790,10 +818,36 @@ vk_pipeline_precomp_shader_deserialize(struct vk_device *device,
const void *key_data, size_t key_size,
struct blob_reader *blob)
{
struct vk_pipeline_precomp_shader *shader =
vk_zalloc(&device->alloc, sizeof(*shader), 8,
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
if (shader == NULL)
const mesa_shader_stage stage = blob_read_uint32(blob);
struct vk_pipeline_robustness_state rs;
blob_copy_bytes(blob, &rs, sizeof(rs));
struct vk_pipeline_tess_info tess;
blob_copy_bytes(blob, &tess, sizeof(tess));
const uint32_t embedded_sampler_count = blob_read_uint32(blob);
const struct vk_sampler_state *embedded_samplers =
blob_read_bytes(blob, embedded_sampler_count *
sizeof(*embedded_samplers));
blake3_hash blake3;
blob_copy_bytes(blob, blake3, sizeof(blake3));
uint64_t nir_size = blob_read_uint64(blob);
if (blob->overrun || nir_size > SIZE_MAX)
return NULL;
const void *nir_data = blob_read_bytes(blob, nir_size);
if (blob->overrun)
return NULL;
VK_MULTIALLOC(ma);
VK_MULTIALLOC_DECL(&ma, struct vk_pipeline_precomp_shader, shader, 1);
VK_MULTIALLOC_DECL(&ma, struct vk_sampler_state, samplers,
embedded_sampler_count);
if (!vk_multialloc_zalloc(&ma, &device->alloc,
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE))
return NULL;
assert(sizeof(shader->cache_key) == key_size);
@ -804,28 +858,25 @@ vk_pipeline_precomp_shader_deserialize(struct vk_device *device,
shader->cache_key,
sizeof(shader->cache_key));
shader->stage = blob_read_uint32(blob);
blob_copy_bytes(blob, &shader->rs, sizeof(shader->rs));
blob_copy_bytes(blob, &shader->tess, sizeof(shader->tess));
shader->stage = stage;
shader->rs = rs;
shader->tess = tess;
uint64_t nir_size = blob_read_uint64(blob);
if (blob->overrun || nir_size > SIZE_MAX)
goto fail_shader;
shader->embedded_sampler_count = embedded_sampler_count;
shader->embedded_samplers = samplers;
for (uint32_t i = 0; i < embedded_sampler_count; i++)
shader->embedded_samplers[i] = embedded_samplers[i];
const void *nir_data = blob_read_bytes(blob, nir_size);
if (blob->overrun)
goto fail_shader;
memcpy(shader->cache_key, blake3, sizeof(blake3));
blob_init(&shader->nir_blob);
blob_write_bytes(&shader->nir_blob, nir_data, nir_size);
if (shader->nir_blob.out_of_memory)
goto fail_nir_blob;
goto fail_cache_obj;
return &shader->cache_obj;
fail_nir_blob:
blob_finish(&shader->nir_blob);
fail_shader:
fail_cache_obj:
vk_pipeline_cache_object_finish(&shader->cache_obj);
vk_free(&device->alloc, shader);
@ -957,10 +1008,26 @@ vk_pipeline_precompile_shader(struct vk_device *device,
if (ops->preprocess_nir != NULL)
ops->preprocess_nir(device->physical, nir, &rs);
const VkShaderDescriptorSetAndBindingMappingInfoEXT *desc_map =
vk_find_struct_const(info->pNext,
SHADER_DESCRIPTOR_SET_AND_BINDING_MAPPING_INFO_EXT);
struct vk_sampler_state_array embedded_samplers;
bool heaps_progress = false;
NIR_PASS(heaps_progress, nir, vk_nir_lower_descriptor_heaps,
desc_map, &embedded_samplers);
if (heaps_progress) {
nir->info.use_descriptor_heap = true;
NIR_PASS(_, nir, nir_remove_dead_variables,
nir_var_uniform | nir_var_image, NULL);
NIR_PASS(_, nir, nir_opt_dce);
}
stage->precomp =
vk_pipeline_precomp_shader_create(device, stage->precomp_key,
sizeof(stage->precomp_key),
&rs, nir);
&rs, nir,
embedded_samplers.sampler_count,
embedded_samplers.samplers);
ralloc_free(nir);
if (stage->precomp == NULL)
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
@ -1782,6 +1849,8 @@ vk_graphics_pipeline_compile_shaders(struct vk_device *device,
.robustness = &stage->precomp->rs,
.set_layout_count = compile_info->set_layout_count,
.set_layouts = compile_info->set_layouts,
.embedded_sampler_count = stage->precomp->embedded_sampler_count,
.embedded_samplers = stage->precomp->embedded_samplers,
.push_constant_range_count = push_range != NULL,
.push_constant_ranges = push_range != NULL ? push_range : NULL,
};
@ -2348,11 +2417,13 @@ vk_get_compute_pipeline_compile_info(struct vk_pipeline_stage *stage,
features_blake3);
_mesa_blake3_update(&blake3_ctx, features_blake3, sizeof(features_blake3));
for (uint32_t i = 0; i < pipeline_layout->set_count; i++) {
if (pipeline_layout->set_layouts[i] != NULL) {
_mesa_blake3_update(&blake3_ctx,
pipeline_layout->set_layouts[i]->blake3,
sizeof(pipeline_layout->set_layouts[i]->blake3));
if (pipeline_layout != NULL) {
for (uint32_t i = 0; i < pipeline_layout->set_count; i++) {
if (pipeline_layout->set_layouts[i] != NULL) {
_mesa_blake3_update(&blake3_ctx,
pipeline_layout->set_layouts[i]->blake3,
sizeof(pipeline_layout->set_layouts[i]->blake3));
}
}
}
if (push_range != NULL)
@ -2415,8 +2486,10 @@ vk_pipeline_compile_compute_stage(struct vk_device *device,
.next_stage_mask = 0,
.nir = nir,
.robustness = &stage->precomp->rs,
.set_layout_count = pipeline_layout->set_count,
.set_layouts = pipeline_layout->set_layouts,
.set_layout_count = pipeline_layout ? pipeline_layout->set_count : 0,
.set_layouts = pipeline_layout ? pipeline_layout->set_layouts : NULL,
.embedded_sampler_count = stage->precomp->embedded_sampler_count,
.embedded_samplers = stage->precomp->embedded_samplers,
.push_constant_range_count = push_range != NULL,
.push_constant_ranges = push_range != NULL ? push_range : NULL,
};
@ -2798,8 +2871,8 @@ hash_rt_parameters(struct mesa_blake3 *blake3_ctx,
_mesa_blake3_update(blake3_ctx, &shader_flags, sizeof(shader_flags));
_mesa_blake3_update(blake3_ctx, &rt_flags, sizeof(rt_flags));
for (uint32_t i = 0; i < pipeline_layout->set_count; i++) {
if (pipeline_layout->set_layouts[i] != NULL) {
if (pipeline_layout != NULL) {
for (uint32_t i = 0; i < pipeline_layout->set_count; i++) {
_mesa_blake3_update(blake3_ctx,
pipeline_layout->set_layouts[i]->blake3,
sizeof(pipeline_layout->set_layouts[i]->blake3));
@ -3209,8 +3282,10 @@ vk_pipeline_compile_rt_shader(struct vk_device *device,
.next_stage_mask = 0,
.nir = nir,
.robustness = &stage->precomp->rs,
.set_layout_count = pipeline_layout->set_count,
.set_layouts = pipeline_layout->set_layouts,
.set_layout_count = pipeline_layout != NULL ? pipeline_layout->set_count : 0,
.set_layouts = pipeline_layout != NULL ? pipeline_layout->set_layouts : NULL,
.embedded_sampler_count = stage->precomp->embedded_sampler_count,
.embedded_samplers = stage->precomp->embedded_samplers,
.push_constant_range_count = push_range != NULL,
.push_constant_ranges = push_range != NULL ? push_range : NULL,
};
@ -3319,8 +3394,10 @@ vk_pipeline_compile_rt_shader_group(struct vk_device *device,
.next_stage_mask = 0,
.nir = vk_pipeline_precomp_shader_get_nir(precomp, nir_options),
.robustness = &precomp->rs,
.set_layout_count = pipeline_layout->set_count,
.set_layouts = pipeline_layout->set_layouts,
.set_layout_count = pipeline_layout != NULL ? pipeline_layout->set_count : 0,
.set_layouts = pipeline_layout != NULL ? pipeline_layout->set_layouts : NULL,
.embedded_sampler_count = precomp->embedded_sampler_count,
.embedded_samplers = precomp->embedded_samplers,
.push_constant_range_count = push_range != NULL,
.push_constant_ranges = push_range != NULL ? push_range : NULL,
};

View file

@ -25,6 +25,7 @@
#include "vk_sampler.h"
#include "vk_device.h"
#include "vk_format.h"
#include "vk_limits.h"
#include "vk_util.h"
#include "vk_ycbcr_conversion.h"
@ -121,6 +122,7 @@ vk_sampler_state_init(struct vk_sampler_state *state,
if (!vk_border_color_is_custom(pCreateInfo->borderColor))
state->border_color_value = vk_border_color_value(pCreateInfo->borderColor);
state->reduction_mode = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE;
state->border_color_index = MESA_VK_MAX_CUSTOM_BORDER_COLOR;
vk_foreach_struct_const(ext, pCreateInfo->pNext) {
switch (ext->sType) {
@ -173,6 +175,12 @@ vk_sampler_state_init(struct vk_sampler_state *state,
break;
}
case VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_INDEX_CREATE_INFO_EXT: {
const VkSamplerCustomBorderColorIndexCreateInfoEXT *bc_info = (void *)ext;
state->border_color_index = bc_info->index;
break;
}
default:
break;
}

View file

@ -90,6 +90,11 @@ struct vk_sampler_state {
*/
VkClearColorValue border_color_value;
/**
* VkSamplerCustomBorderColorIndexCreateInfo::index.
*/
uint32_t border_color_index;
/** VkSamplerBorderColorComponentMappingCreateInfoEXT::components */
VkComponentMapping border_color_component_mapping;

View file

@ -29,6 +29,7 @@
#include "vk_descriptor_set_layout.h"
#include "vk_device.h"
#include "vk_nir.h"
#include "vk_nir_lower_descriptor_heaps.h"
#include "vk_physical_device.h"
#include "vk_physical_device_features.h"
#include "vk_pipeline.h"
@ -245,7 +246,8 @@ cmp_stage_idx(const void *_a, const void *_b)
static nir_shader *
vk_shader_to_nir(struct vk_device *device,
const VkShaderCreateInfoEXT *info,
const struct vk_pipeline_robustness_state *rs)
const struct vk_pipeline_robustness_state *rs,
struct vk_sampler_state_array *embedded_samplers_out)
{
const struct vk_device_shader_ops *ops = device->shader_ops;
@ -274,6 +276,20 @@ vk_shader_to_nir(struct vk_device *device,
if (ops->preprocess_nir != NULL)
ops->preprocess_nir(device->physical, nir, rs);
const VkShaderDescriptorSetAndBindingMappingInfoEXT *desc_map =
vk_find_struct_const(info->pNext,
SHADER_DESCRIPTOR_SET_AND_BINDING_MAPPING_INFO_EXT);
bool heaps_progress = false;
NIR_PASS(heaps_progress, nir, vk_nir_lower_descriptor_heaps,
desc_map, embedded_samplers_out);
if (heaps_progress) {
nir->info.use_descriptor_heap = true;
NIR_PASS(_, nir, nir_remove_dead_variables,
nir_var_uniform | nir_var_image, NULL);
NIR_PASS(_, nir, nir_opt_dce);
}
return nir;
}
@ -286,6 +302,7 @@ vk_shader_compile_info_init(struct vk_shader_compile_info *info,
struct set_layouts *set_layouts,
const VkShaderCreateInfoEXT *vk_info,
const struct vk_pipeline_robustness_state *rs,
const struct vk_sampler_state_array *es,
nir_shader *nir)
{
for (uint32_t sl = 0; sl < vk_info->setLayoutCount; sl++) {
@ -301,6 +318,8 @@ vk_shader_compile_info_init(struct vk_shader_compile_info *info,
.robustness = rs,
.set_layout_count = vk_info->setLayoutCount,
.set_layouts = set_layouts->set_layouts,
.embedded_sampler_count = es->sampler_count,
.embedded_samplers = es->samplers,
.push_constant_range_count = vk_info->pushConstantRangeCount,
.push_constant_ranges = vk_info->pPushConstantRanges,
};
@ -600,8 +619,10 @@ vk_common_CreateShadersEXT(VkDevice _device,
.idx = i,
};
} else {
struct vk_sampler_state_array embedded_samplers = {};
nir_shader *nir = vk_shader_to_nir(device, vk_info,
&vk_robustness_disabled);
&vk_robustness_disabled,
&embedded_samplers);
if (nir == NULL) {
result = vk_errorf(device, VK_ERROR_UNKNOWN,
"Failed to compile shader to NIR");
@ -611,12 +632,16 @@ vk_common_CreateShadersEXT(VkDevice _device,
struct vk_shader_compile_info info;
struct set_layouts set_layouts;
vk_shader_compile_info_init(&info, &set_layouts,
vk_info, &vk_robustness_disabled, nir);
vk_info, &vk_robustness_disabled,
&embedded_samplers, nir);
struct vk_shader *shader;
result = vk_compile_shaders(device, 1, &info,
NULL /* state */, NULL /* features */,
pAllocator, &shader);
vk_sampler_state_array_finish(&embedded_samplers);
if (result != VK_SUCCESS)
break;
@ -636,6 +661,7 @@ vk_common_CreateShadersEXT(VkDevice _device,
if (linked_count > 0) {
struct set_layouts set_layouts[VK_MAX_LINKED_SHADER_STAGES];
struct vk_shader_compile_info infos[VK_MAX_LINKED_SHADER_STAGES];
struct vk_sampler_state_array embedded_samplers[VK_MAX_LINKED_SHADER_STAGES];
VkResult result = VK_SUCCESS;
/* Sort so we guarantee the driver always gets them in-order */
@ -643,12 +669,14 @@ vk_common_CreateShadersEXT(VkDevice _device,
/* Memset for easy error handling */
memset(infos, 0, sizeof(infos));
memset(embedded_samplers, 0, sizeof(embedded_samplers));
for (uint32_t l = 0; l < linked_count; l++) {
const VkShaderCreateInfoEXT *vk_info = &pCreateInfos[linked[l].idx];
nir_shader *nir = vk_shader_to_nir(device, vk_info,
&vk_robustness_disabled);
&vk_robustness_disabled,
&embedded_samplers[l]);
if (nir == NULL) {
result = vk_errorf(device, VK_ERROR_UNKNOWN,
"Failed to compile shader to NIR");
@ -656,7 +684,8 @@ vk_common_CreateShadersEXT(VkDevice _device,
}
vk_shader_compile_info_init(&infos[l], &set_layouts[l],
vk_info, &vk_robustness_disabled, nir);
vk_info, &vk_robustness_disabled,
&embedded_samplers[l], nir);
}
if (result == VK_SUCCESS) {
@ -675,6 +704,9 @@ vk_common_CreateShadersEXT(VkDevice _device,
}
}
for (uint32_t l = 0; l < linked_count; l++)
vk_sampler_state_array_finish(&embedded_samplers[l]);
if (first_fail_or_success == VK_SUCCESS)
first_fail_or_success = result;
}

View file

@ -46,6 +46,7 @@ struct vk_features;
struct vk_physical_device;
struct vk_pipeline;
struct vk_pipeline_robustness_state;
struct vk_sampler_state;
bool vk_validate_shader_binaries(void);
@ -94,6 +95,9 @@ struct vk_shader_compile_info {
uint32_t set_layout_count;
struct vk_descriptor_set_layout * const *set_layouts;
uint32_t embedded_sampler_count;
const struct vk_sampler_state* embedded_samplers;
uint32_t push_constant_range_count;
const VkPushConstantRange *push_constant_ranges;
};

View file

@ -58,6 +58,7 @@ RENAMED_PROPERTIES = {
("SubgroupProperties", "supportedStages"): "subgroupSupportedStages",
("SubgroupProperties", "supportedOperations"): "subgroupSupportedOperations",
("SubgroupProperties", "quadOperationsInAllStages"): "subgroupQuadOperationsInAllStages",
("DescriptorBufferPropertiesEXT", "samplerDescriptorSize"): "EDBsamplerDescriptorSize",
}
OUT_ARRAYS = {