From 9a44a390008cba42bac45bbef5039f1b67db0dfa Mon Sep 17 00:00:00 2001 From: Beliefzh Date: Tue, 24 Jun 2025 14:44:58 +0800 Subject: [PATCH 1/9] =?UTF-8?q?CTS=E9=83=A8=E5=88=86=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=201=E3=80=81=E6=94=AF=E6=8C=81Geome?= =?UTF-8?q?tryShader=202=E3=80=81=E6=94=AF=E6=8C=81texture=5Flod=203?= =?UTF-8?q?=E3=80=81=E6=94=AF=E6=8C=81ComputeShader=204=E3=80=81=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E6=B5=B7=E6=80=9D=E7=BA=B9=E7=90=86=E8=BD=AC=E6=8D=A2?= =?UTF-8?q?=E7=B2=BE=E5=BA=A6=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Beliefzh --- src/gallium/auxiliary/nir/tgsi_to_nir.c | 8 + src/gallium/auxiliary/tgsi/tgsi_ureg.c | 95 ++++-- src/gallium/auxiliary/tgsi/tgsi_ureg.h | 6 + src/gallium/auxiliary/util/u_simple_shaders.c | 7 +- .../drivers/zink/nir_to_spirv/nir_to_spirv.c | 312 ++++++++++++++++++ src/gallium/drivers/zink/zink_screen.c | 1 + src/gallium/include/pipe/p_shader_tokens.h | 2 +- src/mesa/state_tracker/st_extensions.c | 2 +- 8 files changed, 397 insertions(+), 36 deletions(-) diff --git a/src/gallium/auxiliary/nir/tgsi_to_nir.c b/src/gallium/auxiliary/nir/tgsi_to_nir.c index 457a9bd513c..2510cb6a070 100644 --- a/src/gallium/auxiliary/nir/tgsi_to_nir.c +++ b/src/gallium/auxiliary/nir/tgsi_to_nir.c @@ -384,6 +384,14 @@ ttn_emit_declaration(struct ttn_compile *c) var->data.location = FRAG_RESULT_COLOR; else var->data.location = FRAG_RESULT_DATA0 + semantic_index; + switch (decl->Declaration.ValueType) { + case TGSI_RETURN_TYPE_SINT: + var->type = glsl_ivec4_type(); + break; + case TGSI_RETURN_TYPE_UINT: + var->type = glsl_uvec4_type(); + break; + } } break; } diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c index fdbc37220d0..c15e1aa5ecd 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c @@ -144,6 +144,7 @@ struct ureg_program unsigned last; unsigned array_id; bool invariant; + unsigned value_type; /* = TGSI_RETURN_TYPE_* */ } output[UREG_MAX_OUTPUT]; unsigned nr_outputs, nr_output_regs; @@ -502,6 +503,17 @@ ureg_DECL_output(struct ureg_program *ureg, 0, 1); } +struct ureg_dst +ureg_DECL_output_typed(struct ureg_program *ureg, + enum tgsi_semantic name, + unsigned index, + enum tgsi_return_type value_type) +{ + struct ureg_dst dst = ureg_DECL_output(ureg, name, index); + ureg->output[ureg->nr_outputs - 1].value_type = value_type; + return dst; +} + struct ureg_dst ureg_DECL_output_array(struct ureg_program *ureg, enum tgsi_semantic semantic_name, @@ -1511,16 +1523,17 @@ ureg_memory_insn(struct ureg_program *ureg, static void -emit_decl_semantic(struct ureg_program *ureg, - unsigned file, - unsigned first, - unsigned last, - enum tgsi_semantic semantic_name, - unsigned semantic_index, - unsigned streams, - unsigned usage_mask, - unsigned array_id, - bool invariant) +emit_decl_semantic_typed(struct ureg_program *ureg, + unsigned file, + unsigned first, + unsigned last, + enum tgsi_semantic semantic_name, + unsigned semantic_index, + unsigned streams, + unsigned usage_mask, + unsigned array_id, + bool invariant, + enum tgsi_return_type value_type) { union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, array_id ? 4 : 3); @@ -1532,6 +1545,7 @@ emit_decl_semantic(struct ureg_program *ureg, out[0].decl.Semantic = 1; out[0].decl.Array = array_id != 0; out[0].decl.Invariant = invariant; + out[0].decl.ValueType = value_type; out[1].value = 0; out[1].decl_range.First = first; @@ -1551,6 +1565,23 @@ emit_decl_semantic(struct ureg_program *ureg, } } +static void +emit_decl_semantic(struct ureg_program *ureg, + unsigned file, + unsigned first, + unsigned last, + enum tgsi_semantic semantic_name, + unsigned semantic_index, + unsigned streams, + unsigned usage_mask, + unsigned array_id, + bool invariant) +{ + emit_decl_semantic_typed(ureg, file, first, last, + semantic_name, semantic_index, streams, usage_mask, array_id, + invariant, TGSI_RETURN_TYPE_UNKNOWN); +} + static void emit_decl_atomic_2d(struct ureg_program *ureg, unsigned first, @@ -1895,16 +1926,16 @@ static void emit_decls( struct ureg_program *ureg ) } else { if (ureg->supports_any_inout_decl_range) { for (i = 0; i < ureg->nr_inputs; i++) { - emit_decl_semantic(ureg, - TGSI_FILE_INPUT, - ureg->input[i].first, - ureg->input[i].last, - ureg->input[i].semantic_name, - ureg->input[i].semantic_index, - 0, - TGSI_WRITEMASK_XYZW, - ureg->input[i].array_id, - false); + emit_decl_semantic_typed(ureg, + TGSI_FILE_INPUT, + ureg->input[i].first, + ureg->input[i].last, + ureg->input[i].semantic_name, + ureg->input[i].semantic_index, + 0, + TGSI_WRITEMASK_XYZW, + ureg->input[i].array_id, + false); } } else { @@ -1950,22 +1981,24 @@ static void emit_decls( struct ureg_program *ureg ) ureg->output[i].streams, ureg->output[i].usage_mask, ureg->output[i].array_id, - ureg->output[i].invariant); + ureg->output[i].invariant, + ureg->output[i].value_type); } } else { for (i = 0; i < ureg->nr_outputs; i++) { for (j = ureg->output[i].first; j <= ureg->output[i].last; j++) { - emit_decl_semantic(ureg, - TGSI_FILE_OUTPUT, - j, j, - ureg->output[i].semantic_name, - ureg->output[i].semantic_index + - (j - ureg->output[i].first), - ureg->output[i].streams, - ureg->output[i].usage_mask, - 0, - ureg->output[i].invariant); + emit_decl_semantic_type(ureg, + TGSI_FILE_OUTPUT, + j, j, + ureg->output[i].semantic_name, + ureg->output[i].semantic_index + + (j - ureg->output[i].first), + ureg->output[i].streams, + ureg->output[i].usage_mask, + 0, + ureg->output[i].invariant, + ureg->output[i].value_type); } } } diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h index 76efe956fcd..6c6995fcf04 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.h +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h @@ -254,6 +254,12 @@ ureg_DECL_output(struct ureg_program *, enum tgsi_semantic semantic_name, unsigned semantic_index); +struct ureg_dst +ureg_DECL_output_type(struct ureg_program *, + enum tgsi_semantic semantic_name, + unsigned semantic_index, + enum tgsi_return_type value_type); + struct ureg_dst ureg_DECL_output_array(struct ureg_program *ureg, enum tgsi_semantic semantic_name, diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c index 9ecb041bdd9..c94e8ec247f 100644 --- a/src/gallium/auxiliary/util/u_simple_shaders.c +++ b/src/gallium/auxiliary/util/u_simple_shaders.c @@ -273,9 +273,10 @@ util_make_fragment_tex_shader(struct pipe_context *pipe, TGSI_SEMANTIC_GENERIC, 0, TGSI_INTERPOLATE_LINEAR ); - out = ureg_DECL_output( ureg, - TGSI_SEMANTIC_COLOR, - 0 ); + out = ureg_DECL_output_type( ureg, + TGSI_SEMANTIC_COLOR, + 0, + dtype); temp = ureg_DECL_temporary(ureg); diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c index fa626382927..c721569fff7 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c +++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c @@ -113,6 +113,14 @@ struct ntv_context { SpvId discard_func; SpvId float_array_type[2]; + + bool use_gl_per_vertex; + SpvId per_vertex_block_type[2]; + SpvId per_vertex_in; + SpvId per_vertex_out; + SpvId float_array_1_type; + int gl_in_num_vertices[3]; + int gl_out_num_vertices; }; static SpvId @@ -787,9 +795,156 @@ emit_interpolation(struct ntv_context *ctx, SpvId var_id, } } +enum per_vertex_member { + PV_MEMBER_POSITION = 0, + PV_MEMBER_POINT_SIZE = 1, + PV_MEMBER_CLIP_DISTANCE = 2, + PV_MEMBER_CULL_DISTANCE = 3, + PV_MEMBER_COUNT = 4 +} + +static inline bool +stage_has_per_vertex_input(gl_shader_stage stage) +{ + return stage == MESA_SHADER_TESS_CTRL || + stage == MESA_SHADER_TESS_EVAL || + stage == MESA_SHADER_GEOMETRY; +} + +static inline bool +stage_has_per_vertex_output(gl_shader_stage stage) +{ + return stage == MESA_SHADER_VERTEX || + stage == MESA_SHADER_TESS_CTRL || + stage == MESA_SHADER_TESS_EVAL || + stage == MESA_SHADER_GEOMETRY; +} + +static inline bool +stage_has_per_vertex(struct ntv_context *ctx) +{ + return ctx->use_gl_per_vertex && + (stage_has_per_vertex_input(ctx->stage) || + stage_has_per_vertex_output(ctx->stage)); +} + +static bool +is_per_vertex_builtin(struct ntv_context *ctx, nir_variable *var) +{ + if (var->data.mode != nir_var_shader_in && + var->data.mode != nir_var_shader_out) + return false; + + if (var->data.mode == nir_var_shader_in && + ctx->stage == MESA_SHADER_VERTEX) { + return false; + } + + if (ctx->stage == MESA_SHADER_FRAGMENT) + return false; + + switch (var->data.location) { + case VARYING_SLOT_POS: + case VARYING_SLOT_PSIZ: + case VARYING_SLOT_CLIP_DIST0: + case VARYING_SLOT_CULL_DIST0: + return true; + default + return false; + } +} + +static enum per_vertex_member +location_to_per_vertex_member(unsigned location) +{ + switch (location) { + case VARYING_SLOT_POS: + return PV_MEMBER_POSITION; + case VARYING_SLOT_PSIZ: + return PV_MEMBER_POINT_SIZE; + case VARYING_SLOT_CLIP_DIST0: + return PV_MEMBER_CLIP_DISTANCE; + case VARYING_SLOT_CULL_DIST0: + return PV_MEMBER_CULL_DISTANCE; + default: + unreachable("not a per-vertex builtin"); + } +} + +static SpvId +get_per_vertex_member_type(struct ntv_context *ctx, uint32_t last_member_idx) +{ + switch (member_idx) { + case PV_MEMBER_POSITION: + return get_glsl_type(ctx, glsl_vec4_type()); + case PV_MEMBER_POINT_SIZE: + return get_glsl_type(ctx, glsl_float_type()); + case PV_MEMBER_CLIP_DISTANCE: + case PV_MEMBER_CULL_DISTANCE: + // Use cached type or create it once + if (ctx->float_array_1_type == 0) { + SpvId float_type = get_glsl_type(ctx, glsl_float_type()); + SpvId array_size = spirv_builder_const_uint(&ctx->builder, 32, 6); + ctx->float_array_1_type = spirv_builder_type_array(&ctx->builder, float_type, array_size); + } + return ctx->float_array_1_type; + default: + unreachable("invalid per-vertex member"); + } +} + +static SpvId +create_per_vertex_block_type(struct ntv_context *ctx, bool in) +{ + int index = in ? 0 : 1; + if (ctx->per_vertex_block_type[index] != 0) + return ctx->per_vertex_block_type[index]; + + SpvId vec4_tpye = get_glsl_type(ctx, glsl_vec4_type()); + SpvId float_type = get_glsl_type(ctx, glsl_float_type()); + SpvId float_array_type = get_per_vertex_member_type(ctx, PV_MEMBER_CLIP_DISTANCE); + + SpvId member_types[PV_MEMBER_COUNT] = { + [PV_MEMBER_POSITION] = vec4_tpye, + [PV_MEMBER_POINT_SIZE] = float_type, + [PV_MEMBER_CLIP_DISTANCE] = float_array_type, + [PV_MEMBER_CULL_DISTANCE] = float_array_type // Same type as clip distance + }; + + SpvId block_type = spirv_builder_type_struct(&ctx->builder, member_types, PV_MEMBER_COUNT); + + spirv_builder_emit_member_name(&ctx->builder, block_type, PV_MEMBER_POSITION, "gl_Position"); + spirv_builder_emit_member_builtin(&ctx->builder, block_type, PV_MEMBER_POSITION, + SpvbuiltInPosition); + + spirv_builder_emit_member_name(&ctx->builder, block_type, PV_MEMBER_POINT_SIZE, "gl_PointSize"); + spirv_builder_emit_member_builtin(&ctx->builder, block_type, PV_MEMBER_POINT_SIZE, + SpvbuiltInPointSize); + + spirv_builder_emit_member_name(&ctx->builder, block_type, PV_MEMBER_CLIP_DISTANCE, "gl_ClipDistance"); + spirv_builder_emit_member_builtin(&ctx->builder, block_type, PV_MEMBER_CLIP_DISTANCE, + SpvbuiltInClipDistance); + + spirv_builder_emit_member_name(&ctx->builder, block_type, PV_MEMBER_CULL_DISTANCE, "gl_CullDistance"); + spirv_builder_emit_member_builtin(&ctx->builder, block_type, PV_MEMBER_CULL_DISTANCE, + SpvbuiltInCullDistance); + + spirv_builder_emit_name(&ctx->builder, block_type, in ? "gl_PerVertex_0" : "gl_PerVertex"); + spirv_builder_emit_decoration(&ctx->builder, block_type, SpvDecorationBlock); + + ctx->per_vertex_block_type[index] = block_type; + + return block_type; +} + static void emit_input(struct ntv_context *ctx, struct nir_variable *var) { + if (stage_has_per_vertex(ctx) && is_per_vertex_builtin(ctx, var)) { + if (glsl_type_is_array(var->type)) + ctx->gl_in_num_vertices[ctx->stage - 1] = glsl_get_length(var->typr); + return; + } SpvId var_id = input_var_init(ctx, var); if (ctx->stage == MESA_SHADER_VERTEX) spirv_builder_emit_location(&ctx->builder, var_id, @@ -851,6 +1006,11 @@ emit_input(struct ntv_context *ctx, struct nir_variable *var) static void emit_output(struct ntv_context *ctx, struct nir_variable *var) { + if (stage_has_per_vertex(ctx) && is_per_vertex_builtin(ctx, var)) { + if (glsl_type_is_array(var->type)) + ctx->gl_out_num_vertices[ctx->stage - 1] = glsl_get_length(var->typr); + return; + } SpvId var_type = get_glsl_type(ctx, var->type); /* SampleMask is always an array in spirv */ @@ -3995,9 +4155,110 @@ emit_jump(struct ntv_context *ctx, nir_jump_instr *jump) } } +// Detect if this is a gl_PerVertex access chain and build the complete access +static bool +try_emit_gl_per_vertex_access(struct ntv_context *ctx, nir_deref_instr *deref) +{ + if (!stage_has_per_vertex(ctx)) + return false; + + // Walk up the dereference chain to find components + nir_deref_instr *cur = deref; + nir_deref_instr* array_derefs[2] = {NULL, NULL}; + int num_array_derefs = 0; + nir_deref_instr *struct_deref = NULL; + nir_variable *root_var = NULL; + + // Walk up the chain: current -> parent -> parent... + while (cur) { + switch (cur->deref_type) { + case nir_deref_type_var: + root_var = cur->var; + cur = NULL; // End of chain + break; + case nir_deref_type_array: + if (num_array_derefs >= 2) + return false; + array_derefs[num_array_derefs++] = cur; + cur = nir_deref_instr_parent(cur); + break; + case nir_deref_type_struct: + if (!struct_deref) struct_deref = cur; + cur = nir_deref_instr_parent(cur); + break; + default: + return false; // Unsupported dereference type + } + } + + // Check if this is a gl_PerVertex builtin access + if (!root_var || !is_per_vertex_builtin(ctx, root_var)) + return false; + + // Validate stage compatibility + bool is_output = (root_var->data.mode == nir_var_shader_out); + if (is_output && !stage_has_per_vertex_output(ctx->stage)) + return false; + if (!is_output && !stage_has_per_vertex_input(ctx->stage)) + return false; + + // Build the SPIR-V access chain + SpvId base = is_output ? ctx->per_vertex_out : ctx->per_vertex_in; + SpvId indices[3] = {0, 0, 0}; // Max: [array_index, struct_member, ...] + int num_indices = 0; + + // Add array index if present (for gl_in[i] or gl_out[i]) + bool is_access_per_vertex_array = is_output ? (ctx->stage == MESA_SHADER_TESS_CTRL) : true; + if (is_access_per_vertex_array && num_array_derefs > 0 && array_derefs[num_array_derefs - 1]) { + nir_deref_instr* array_deref = array_derefs[num_array_derefs - 1]; + nir_alu_type itype; + SpvId array_index = get_src(ctx, &array_deref->arr.index, &itype); + if (itype == nir_type_float) + array_index = emit_bitcast(ctx, get_uvec_type(ctx, 32, 1), array_index); + indices[num_indices++] = array_index; + } + + // Add struct member index (always present for gl_PerVertex) + enum per_vertex_member member = location_to_per_vertex_member(root_var->data.location); + SpvId member_index = spirv_builder_const_uint(&ctx->builder, 32, member); + indices[num_indices++] = member_index; + + // Add array index if present (for gl_ClipDistance[i]) + bool is_access_clip_distance = is_access_per_vertex_array ? num_array_derefs > 1 : num_array_derefs > 0; + if (is_access_clip_distance && array_derefs[0]) { + nir_deref_instr* array_deref = array_derefs[0]; + nir_alu_type itype; + SpvId array_index = get_src(ctx, &array_deref->arr.index, &itype); + if (itype == nir_type_float) + array_index = emit_bitcast(ctx, get_uvec_type(ctx, 32, 1), array_index); + indices[num_indices++] = array_index; + } + + // Determine result type and storage class + SpvId member_type = get_per_vertex_member_type(ctx, member); + if (is_access_per_vertex_array) { + member_type = num_array_derefs <= 0 ? ctx->per_vertex_block_type[is_output ? 1 : 0] : + (num_array_derefs > 1 ? get_glsl_type(ctx, glsl_float_type()) : member_type); + } else { + member_type = num_array_derefs > 0 ? get_glsl_type(ctx, glsl_float_type()) : member_type; + } + + SpvStorageClass storage_class = get_storage_class(root_var); + SpvId ptr_type = spirv_builder_type_pointer(&ctx->builder, storage_class, member_type); + + // Generate the access chain + SpvId result = spirv_builder_emit_access_chain(&ctx->builder, ptr_type, base, indices, num_indices); + store_def(ctx, deref->def.index, result, get_nir_alu_type(deref->type)); + + return true; +} + static void emit_deref_var(struct ntv_context *ctx, nir_deref_instr *deref) { + if (try_emit_gl_per_vertex_access(ctx, deref)) + return; + assert(deref->deref_type == nir_deref_type_var); struct hash_entry *he = _mesa_hash_table_search(ctx->vars, deref->var); @@ -4404,6 +4665,51 @@ get_spacing(enum gl_tess_spacing spacing) } } +static void +setup_per_vertex_blocks(struct ntv_context *ctx) +{ + SpvId block_type_in = create_per_vertex_block_type(ctx, true); + SpvId block_type_out = create_per_vertex_block_type(ctx, false); + + if (stage_has_per_vertex_input(ctx->stage)) { + SpvId input_type = block_type_in; + + if (ctx->stage == MESA_SHADER_GEOMETRY || + ctx->stage == MESA_SHADER_TESS_CTRL || + ctx->stage == MESA_SHADER_TESS_EVAL) { + // gl_in[]: array of gl_PerVertex + uint32_t input_vertices = MAX2(ctx->gl_in_num_vertices[ctx->stage - 1], 1); + + SpvId array_size = spirv_builder_const_uint(&ctx->builder, 32, input_vertices); + input_type = spirv_builder_type_array(&ctx->builder, block_type_in, array_size); + } + + SpvId ptr_type = spirv_builder_type_pointer(&ctx->builder, SpvStorageClassInput, input_type); + SpvId var_id = spirv_builder_emit_var(&ctx->builder, ptr_type, SpvStorageClassInput); + spirv_builder_emit_name(&ctx->builder, var_id, "gl_in"); + ctx->per_vertex_in = var_id; + ctx->entry_ifaces[ctx->num_entry_ifaces++] = var_id; + } + + if (stage_has_per_vertex_output(ctx->stage)) { + SpvId output_type = block_type_out; + + // Tessellation control shaders need gl_out[] as an array + if (ctx->stage == MESA_SHADER_TESS_CTRL) { + uint32_t output_vertices = MAX2(ctx->gl_out_num_vertices, 1); + SpvId array_size = spirv_builder_const_uint(&ctx->builder, 32, output_vertices); + output_type = spirv_builder_type_array(&ctx->builder, block_type_out, array_size); + } + + SpvId ptr_type = spirv_builder_type_pointer(&ctx->builder, SpvStorageClassOutput, output_type); + SpvId var_id = spirv_builder_emit_var(&ctx->builder, ptr_type, SpvStorageClassOutput); + spirv_builder_emit_name(&ctx->builder, var_id, "gl_out"); + + ctx->per_vertex_out = var_id; + ctx->entry_ifaces[ctx->num_entry_ifaces++] = var_id; + } +} + struct spirv_shader * nir_to_spirv(struct nir_shader *s, const struct zink_shader_info *sinfo, const struct zink_screen *screen) { @@ -4572,6 +4878,9 @@ nir_to_spirv(struct nir_shader *s, const struct zink_shader_info *sinfo, const s ctx.vars = _mesa_hash_table_create(ctx.mem_ctx, _mesa_hash_pointer, _mesa_key_pointer_equal); + // TODO: set this on a per driver basis + ctx.use_gl_per_vertex = true; + nir_foreach_variable_with_modes(var, s, nir_var_mem_push_const) input_var_init(&ctx, var); @@ -4589,6 +4898,9 @@ nir_to_spirv(struct nir_shader *s, const struct zink_shader_info *sinfo, const s emit_output(&ctx, var); } + if (ctx.use_gl_per_vertex) + setup_per_vertex_blocks(&ctx); + uint32_t tcs_vertices_out_word = 0; unsigned ubo_counter[2] = {0}; diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index 274908d5528..a0709d094fe 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -857,6 +857,7 @@ zink_init_screen_caps(struct zink_screen *screen) caps->allow_glthread_buffer_subdata_opt = true; caps->nir_samplers_as_deref = true; caps->call_finalize_nir_in_linker = true; + caps->texture_shadow_lod = true; caps->draw_vertex_state = screen->info.have_EXT_vertex_input_dynamic_state; diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h index 170c5e4082b..8491f3ede60 100644 --- a/src/gallium/include/pipe/p_shader_tokens.h +++ b/src/gallium/include/pipe/p_shader_tokens.h @@ -134,7 +134,7 @@ struct tgsi_declaration unsigned Array : 1; /**< extra array info? */ unsigned Atomic : 1; /**< atomic only? for TGSI_FILE_BUFFER */ unsigned MemType : 2; /**< TGSI_MEMORY_TYPE_x for TGSI_FILE_MEMORY */ - unsigned Padding : 3; + unsigned ValueType : 3; /**< TGSI_RETURN_TYPE_x */ }; struct tgsi_declaration_range diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 7ce1828d303..bc413d5b92e 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -1689,7 +1689,7 @@ void st_init_extensions(struct pipe_screen *screen, } extensions->ARB_compute_shader = - max_threads_per_block >= 1024 && + max_threads_per_block >= 512 && extensions->ARB_shader_image_load_store && extensions->ARB_shader_atomic_counters; -- Gitee From 8d622db852335cd205be8abb0003738bb8a7b288 Mon Sep 17 00:00:00 2001 From: Beliefzh Date: Tue, 24 Jun 2025 14:44:58 +0800 Subject: [PATCH 2/9] =?UTF-8?q?CTS=E9=83=A8=E5=88=86=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=201=E3=80=81=E6=94=AF=E6=8C=81Geome?= =?UTF-8?q?tryShader=202=E3=80=81=E6=94=AF=E6=8C=81texture=5Flod=203?= =?UTF-8?q?=E3=80=81=E6=94=AF=E6=8C=81ComputeShader=204=E3=80=81=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E6=B5=B7=E6=80=9D=E7=BA=B9=E7=90=86=E8=BD=AC=E6=8D=A2?= =?UTF-8?q?=E7=B2=BE=E5=BA=A6=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Beliefzh --- src/gallium/auxiliary/nir/tgsi_to_nir.c | 8 + src/gallium/auxiliary/tgsi/tgsi_build.c | 2 +- src/gallium/auxiliary/tgsi/tgsi_ureg.c | 93 ++++-- src/gallium/auxiliary/tgsi/tgsi_ureg.h | 6 + src/gallium/auxiliary/util/u_simple_shaders.c | 6 +- .../drivers/zink/nir_to_spirv/nir_to_spirv.c | 314 ++++++++++++++++++ src/gallium/drivers/zink/zink_screen.c | 1 + src/gallium/include/pipe/p_shader_tokens.h | 2 +- 8 files changed, 397 insertions(+), 35 deletions(-) diff --git a/src/gallium/auxiliary/nir/tgsi_to_nir.c b/src/gallium/auxiliary/nir/tgsi_to_nir.c index 457a9bd513c..a09b07dfd49 100644 --- a/src/gallium/auxiliary/nir/tgsi_to_nir.c +++ b/src/gallium/auxiliary/nir/tgsi_to_nir.c @@ -385,6 +385,14 @@ ttn_emit_declaration(struct ttn_compile *c) else var->data.location = FRAG_RESULT_DATA0 + semantic_index; } + switch (decl->Declaration.ValueType) { + case TGSI_RETURN_TYPE_SINT: + var->type = glsl_ivec4_type(); + break; + case TGSI_RETURN_TYPE_UINT: + var->type = glsl_uvec4_type(); + break; + } break; } case TGSI_SEMANTIC_POSITION: diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.c b/src/gallium/auxiliary/tgsi/tgsi_build.c index 6c573fc6f4b..d36017a3adc 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_build.c +++ b/src/gallium/auxiliary/tgsi/tgsi_build.c @@ -112,7 +112,7 @@ tgsi_default_declaration( void ) declaration.Array = 0; declaration.Atomic = 0; declaration.MemType = TGSI_MEMORY_TYPE_GLOBAL; - declaration.Padding = 0; + declaration.ValueType = TGSI_RETURN_TYPE_UNKNOWN; return declaration; } diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c index fdbc37220d0..6c621af54f8 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c @@ -144,6 +144,7 @@ struct ureg_program unsigned last; unsigned array_id; bool invariant; + unsigned value_type; /* = TGSI_RETURN_TYPE_* */ } output[UREG_MAX_OUTPUT]; unsigned nr_outputs, nr_output_regs; @@ -502,6 +503,17 @@ ureg_DECL_output(struct ureg_program *ureg, 0, 1); } +struct ureg_dst +ureg_DECL_output_typed(struct ureg_program *ureg, + enum tgsi_semantic name, + unsigned index, + enum tgsi_return_type value_type) +{ + struct ureg_dst dst = ureg_DECL_output(ureg, name, index); + ureg->output[ureg->nr_outputs - 1].value_type = value_type; + return dst; +} + struct ureg_dst ureg_DECL_output_array(struct ureg_program *ureg, enum tgsi_semantic semantic_name, @@ -1511,16 +1523,17 @@ ureg_memory_insn(struct ureg_program *ureg, static void -emit_decl_semantic(struct ureg_program *ureg, - unsigned file, - unsigned first, - unsigned last, - enum tgsi_semantic semantic_name, - unsigned semantic_index, - unsigned streams, - unsigned usage_mask, - unsigned array_id, - bool invariant) +emit_decl_semantic_typed(struct ureg_program *ureg, + unsigned file, + unsigned first, + unsigned last, + enum tgsi_semantic semantic_name, + unsigned semantic_index, + unsigned streams, + unsigned usage_mask, + unsigned array_id, + bool invariant, + enum tgsi_return_type value_type) { union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, array_id ? 4 : 3); @@ -1532,6 +1545,7 @@ emit_decl_semantic(struct ureg_program *ureg, out[0].decl.Semantic = 1; out[0].decl.Array = array_id != 0; out[0].decl.Invariant = invariant; + out[0].decl.ValueType = value_type; out[1].value = 0; out[1].decl_range.First = first; @@ -1551,6 +1565,23 @@ emit_decl_semantic(struct ureg_program *ureg, } } +static void +emit_decl_semantic(struct ureg_program *ureg, + unsigned file, + unsigned first, + unsigned last, + enum tgsi_semantic semantic_name, + unsigned semantic_index, + unsigned streams, + unsigned usage_mask, + unsigned array_id, + bool invariant) +{ + emit_decl_semantic_typed(ureg, file, first, last, + semantic_name, semantic_index, streams, usage_mask, array_id, + invariant, TGSI_RETURN_TYPE_UNKNOWN); +} + static void emit_decl_atomic_2d(struct ureg_program *ureg, unsigned first, @@ -1941,31 +1972,33 @@ static void emit_decls( struct ureg_program *ureg ) if (ureg->supports_any_inout_decl_range) { for (i = 0; i < ureg->nr_outputs; i++) { - emit_decl_semantic(ureg, - TGSI_FILE_OUTPUT, - ureg->output[i].first, - ureg->output[i].last, - ureg->output[i].semantic_name, - ureg->output[i].semantic_index, - ureg->output[i].streams, - ureg->output[i].usage_mask, - ureg->output[i].array_id, - ureg->output[i].invariant); + emit_decl_semantic_typed(ureg, + TGSI_FILE_OUTPUT, + ureg->output[i].first, + ureg->output[i].last, + ureg->output[i].semantic_name, + ureg->output[i].semantic_index, + ureg->output[i].streams, + ureg->output[i].usage_mask, + ureg->output[i].array_id, + ureg->output[i].invariant, + ureg->output[i].value_type); } } else { for (i = 0; i < ureg->nr_outputs; i++) { for (j = ureg->output[i].first; j <= ureg->output[i].last; j++) { - emit_decl_semantic(ureg, - TGSI_FILE_OUTPUT, - j, j, - ureg->output[i].semantic_name, - ureg->output[i].semantic_index + - (j - ureg->output[i].first), - ureg->output[i].streams, - ureg->output[i].usage_mask, - 0, - ureg->output[i].invariant); + emit_decl_semantic_typed(ureg, + TGSI_FILE_OUTPUT, + j, j, + ureg->output[i].semantic_name, + ureg->output[i].semantic_index + + (j - ureg->output[i].first), + ureg->output[i].streams, + ureg->output[i].usage_mask, + 0, + ureg->output[i].invariant, + ureg->output[i].value_type); } } } diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h index 76efe956fcd..15cf5feb10d 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.h +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h @@ -254,6 +254,12 @@ ureg_DECL_output(struct ureg_program *, enum tgsi_semantic semantic_name, unsigned semantic_index); +struct ureg_dst +ureg_DECL_output_typed(struct ureg_program *, + enum tgsi_semantic semantic_name, + unsigned semantic_index, + enum tgsi_return_type value_type); + struct ureg_dst ureg_DECL_output_array(struct ureg_program *ureg, enum tgsi_semantic semantic_name, diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c index 9ecb041bdd9..bb43b165acb 100644 --- a/src/gallium/auxiliary/util/u_simple_shaders.c +++ b/src/gallium/auxiliary/util/u_simple_shaders.c @@ -273,9 +273,9 @@ util_make_fragment_tex_shader(struct pipe_context *pipe, TGSI_SEMANTIC_GENERIC, 0, TGSI_INTERPOLATE_LINEAR ); - out = ureg_DECL_output( ureg, - TGSI_SEMANTIC_COLOR, - 0 ); + out = ureg_DECL_output_typed( ureg, + TGSI_SEMANTIC_COLOR, + 0, dtype); temp = ureg_DECL_temporary(ureg); diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c index fa626382927..844d1aa7bf5 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c +++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c @@ -113,6 +113,14 @@ struct ntv_context { SpvId discard_func; SpvId float_array_type[2]; + + bool use_gl_per_vertex; + SpvId per_vertex_block_type[2]; + SpvId per_vertex_in; + SpvId per_vertex_out; + SpvId float_array_1_type; + int gl_in_num_vertices[3]; + int gl_out_num_vertices; }; static SpvId @@ -787,9 +795,157 @@ emit_interpolation(struct ntv_context *ctx, SpvId var_id, } } +enum per_vertex_member { + PV_MEMBER_POSITION = 0, + PV_MEMBER_POINT_SIZE = 1, + PV_MEMBER_CLIP_DISTANCE = 2, + PV_MEMBER_CULL_DISTANCE = 3, + PV_MEMBER_COUNT = 4 +}; + +static inline bool +stage_has_per_vertex_input(gl_shader_stage stage) +{ + return stage == MESA_SHADER_TESS_CTRL || + stage == MESA_SHADER_TESS_EVAL || + stage == MESA_SHADER_GEOMETRY; +} + +static inline bool +stage_has_per_vertex_output(gl_shader_stage stage) +{ + return stage == MESA_SHADER_VERTEX || + stage == MESA_SHADER_TESS_CTRL || + stage == MESA_SHADER_TESS_EVAL || + stage == MESA_SHADER_GEOMETRY; +} + +static inline bool +stage_has_per_vertex(struct ntv_context *ctx) +{ + return ctx->use_gl_per_vertex && + (stage_has_per_vertex_input(ctx->stage) || + stage_has_per_vertex_output(ctx->stage)); +} + +static bool +is_per_vertex_builtin(struct ntv_context *ctx, nir_variable *var) +{ + if (var->data.mode != nir_var_shader_in && + var->data.mode != nir_var_shader_out) + return false; + + if (var->data.mode == nir_var_shader_in && + ctx->stage == MESA_SHADER_VERTEX) { + return false; + } + + if (ctx->stage == MESA_SHADER_FRAGMENT) + return false; + + switch (var->data.location) { + case VARYING_SLOT_POS: + case VARYING_SLOT_PSIZ: + case VARYING_SLOT_CLIP_DIST0: + case VARYING_SLOT_CULL_DIST0: + return true; + default: + return false; + } +} + +static enum per_vertex_member +location_to_per_vertex_member(unsigned location) +{ + switch (location) { + case VARYING_SLOT_POS: + return PV_MEMBER_POSITION; + case VARYING_SLOT_PSIZ: + return PV_MEMBER_POINT_SIZE; + case VARYING_SLOT_CLIP_DIST0: + return PV_MEMBER_CLIP_DISTANCE; + case VARYING_SLOT_CULL_DIST0: + return PV_MEMBER_CULL_DISTANCE; + default: + unreachable("not a per-vertex builtin"); + } +} + +static SpvId +get_per_vertex_member_type(struct ntv_context *ctx, uint32_t member_idx) +{ + switch (member_idx) { + case PV_MEMBER_POSITION: + return get_glsl_type(ctx, glsl_vec4_type()); + case PV_MEMBER_POINT_SIZE: + return get_glsl_type(ctx, glsl_float_type()); + case PV_MEMBER_CLIP_DISTANCE: + case PV_MEMBER_CULL_DISTANCE: + // Use cached type or create it once + if (ctx->float_array_1_type == 0) { + SpvId float_type = get_glsl_type(ctx, glsl_float_type()); + SpvId array_size = spirv_builder_const_uint(&ctx->builder, 32, 6); + ctx->float_array_1_type = spirv_builder_type_array(&ctx->builder, float_type, array_size); + } + return ctx->float_array_1_type; + default: + unreachable("invalid per-vertex member"); + } +} + +static SpvId +create_per_vertex_block_type(struct ntv_context *ctx, bool in) +{ + int index = in ? 0 : 1; + if (ctx->per_vertex_block_type[index] != 0) + return ctx->per_vertex_block_type[index]; + + SpvId vec4_type = get_glsl_type(ctx, glsl_vec4_type()); + SpvId float_type = get_glsl_type(ctx, glsl_float_type()); + SpvId float_array_type = get_per_vertex_member_type(ctx, PV_MEMBER_CLIP_DISTANCE); + + SpvId member_types[PV_MEMBER_COUNT] = { + [PV_MEMBER_POSITION] = vec4_type, + [PV_MEMBER_POINT_SIZE] = float_type, + [PV_MEMBER_CLIP_DISTANCE] = float_array_type, + [PV_MEMBER_CULL_DISTANCE] = float_array_type // Same type as clip distance + }; + + SpvId block_type = spirv_builder_type_struct(&ctx->builder, member_types, PV_MEMBER_COUNT); + + spirv_builder_emit_member_name(&ctx->builder, block_type, PV_MEMBER_POSITION, "gl_Position"); + spirv_builder_emit_member_builtin(&ctx->builder, block_type, PV_MEMBER_POSITION, + SpvBuiltInPosition); + + spirv_builder_emit_member_name(&ctx->builder, block_type, PV_MEMBER_POINT_SIZE, "gl_PointSize"); + spirv_builder_emit_member_builtin(&ctx->builder, block_type, PV_MEMBER_POINT_SIZE, + SpvBuiltInPointSize); + + spirv_builder_emit_member_name(&ctx->builder, block_type, PV_MEMBER_CLIP_DISTANCE, "gl_ClipDistance"); + spirv_builder_emit_member_builtin(&ctx->builder, block_type, PV_MEMBER_CLIP_DISTANCE, + SpvBuiltInClipDistance); + + spirv_builder_emit_member_name(&ctx->builder, block_type, PV_MEMBER_CULL_DISTANCE, "gl_CullDistance"); + spirv_builder_emit_member_builtin(&ctx->builder, block_type, PV_MEMBER_CULL_DISTANCE, + SpvBuiltInCullDistance); + + spirv_builder_emit_name(&ctx->builder, block_type, in ? "gl_PerVertex_0" : "gl_PerVertex"); + spirv_builder_emit_decoration(&ctx->builder, block_type, SpvDecorationBlock); + + ctx->per_vertex_block_type[index] = block_type; + + return block_type; +} + static void emit_input(struct ntv_context *ctx, struct nir_variable *var) { + if (stage_has_per_vertex(ctx) && is_per_vertex_builtin(ctx, var)) { + if (glsl_type_is_array(var->type)) + ctx->gl_in_num_vertices[ctx->stage - 1] = glsl_get_length(var->type); + return; + } + SpvId var_id = input_var_init(ctx, var); if (ctx->stage == MESA_SHADER_VERTEX) spirv_builder_emit_location(&ctx->builder, var_id, @@ -851,6 +1007,12 @@ emit_input(struct ntv_context *ctx, struct nir_variable *var) static void emit_output(struct ntv_context *ctx, struct nir_variable *var) { + if (stage_has_per_vertex(ctx) && is_per_vertex_builtin(ctx, var)) { + if (glsl_type_is_array(var->type)) + ctx->gl_out_num_vertices = glsl_get_length(var->type); + return; + } + SpvId var_type = get_glsl_type(ctx, var->type); /* SampleMask is always an array in spirv */ @@ -3995,6 +4157,104 @@ emit_jump(struct ntv_context *ctx, nir_jump_instr *jump) } } +// Detect if this is a gl_PerVertex access chain and build the complete access +static bool +try_emit_gl_per_vertex_access(struct ntv_context *ctx, nir_deref_instr *deref) +{ + if (!stage_has_per_vertex(ctx)) + return false; + + // Walk up the dereference chain to find components + nir_deref_instr *cur = deref; + nir_deref_instr* array_derefs[2] = {NULL, NULL}; + int num_array_derefs = 0; + nir_deref_instr *struct_deref = NULL; + nir_variable *root_var = NULL; + + // Walk up the chain: current -> parent -> parent... + while (cur) { + switch (cur->deref_type) { + case nir_deref_type_var: + root_var = cur->var; + cur = NULL; // End of chain + break; + case nir_deref_type_array: + if (num_array_derefs >= 2) + return false; + array_derefs[num_array_derefs++] = cur; + cur = nir_deref_instr_parent(cur); + break; + case nir_deref_type_struct: + if (!struct_deref) struct_deref = cur; + cur = nir_deref_instr_parent(cur); + break; + default: + return false; // Unsupported dereference type + } + } + + // Check if this is a gl_PerVertex builtin access + if (!root_var || !is_per_vertex_builtin(ctx, root_var)) + return false; + + // Validate stage compatibility + bool is_output = (root_var->data.mode == nir_var_shader_out); + if (is_output && !stage_has_per_vertex_output(ctx->stage)) + return false; + if (!is_output && !stage_has_per_vertex_input(ctx->stage)) + return false; + + // Build the SPIR-V access chain + SpvId base = is_output ? ctx->per_vertex_out : ctx->per_vertex_in; + SpvId indices[3] = {0, 0, 0}; // Max: [array_index, struct_member, ...] + int num_indices = 0; + + // Add array index if present (for gl_in[i] or gl_out[i]) + bool is_access_per_vertex_array = is_output ? (ctx->stage == MESA_SHADER_TESS_CTRL) : true; + if (is_access_per_vertex_array && num_array_derefs > 0 && array_derefs[num_array_derefs - 1]) { + nir_deref_instr* array_deref = array_derefs[num_array_derefs - 1]; + nir_alu_type itype; + SpvId array_index = get_src(ctx, &array_deref->arr.index, &itype); + if (itype == nir_type_float) + array_index = emit_bitcast(ctx, get_uvec_type(ctx, 32, 1), array_index); + indices[num_indices++] = array_index; + } + + // Add struct member index (always present for gl_PerVertex) + enum per_vertex_member member = location_to_per_vertex_member(root_var->data.location); + SpvId member_index = spirv_builder_const_uint(&ctx->builder, 32, member); + indices[num_indices++] = member_index; + + // Add array index if present (for gl_ClipDistance[i]) + bool is_access_clip_distance = is_access_per_vertex_array ? num_array_derefs > 1 : num_array_derefs > 0; + if (is_access_clip_distance && array_derefs[0]) { + nir_deref_instr* array_deref = array_derefs[0]; + nir_alu_type itype; + SpvId array_index = get_src(ctx, &array_deref->arr.index, &itype); + if (itype == nir_type_float) + array_index = emit_bitcast(ctx, get_uvec_type(ctx, 32, 1), array_index); + indices[num_indices++] = array_index; + } + + // Determine result type and storage class + SpvId member_type = get_per_vertex_member_type(ctx, member); + if (is_access_per_vertex_array) { + member_type = num_array_derefs <= 0 ? ctx->per_vertex_block_type[is_output ? 1 : 0] : + (num_array_derefs > 1 ? get_glsl_type(ctx, glsl_float_type()) : member_type); + } else { + member_type = num_array_derefs > 0 ? get_glsl_type(ctx, glsl_float_type()) : member_type; + } + + SpvStorageClass storage_class = get_storage_class(root_var); + SpvId ptr_type = spirv_builder_type_pointer(&ctx->builder, storage_class, member_type); + + // Generate the access chain + SpvId result = spirv_builder_emit_access_chain(&ctx->builder, ptr_type, base, indices, num_indices); + store_def(ctx, deref->def.index, result, get_nir_alu_type(deref->type)); + + return true; +} + static void emit_deref_var(struct ntv_context *ctx, nir_deref_instr *deref) { @@ -4120,6 +4380,9 @@ emit_deref_struct(struct ntv_context *ctx, nir_deref_instr *deref) static void emit_deref(struct ntv_context *ctx, nir_deref_instr *deref) { + if (try_emit_gl_per_vertex_access(ctx, deref)) + return; + switch (deref->deref_type) { case nir_deref_type_var: emit_deref_var(ctx, deref); @@ -4404,6 +4667,51 @@ get_spacing(enum gl_tess_spacing spacing) } } +static void +setup_per_vertex_blocks(struct ntv_context *ctx) +{ + SpvId block_type_in = create_per_vertex_block_type(ctx, true); + SpvId block_type_out = create_per_vertex_block_type(ctx, false); + + if (stage_has_per_vertex_input(ctx->stage)) { + SpvId input_type = block_type_in; + + if (ctx->stage == MESA_SHADER_GEOMETRY || + ctx->stage == MESA_SHADER_TESS_CTRL || + ctx->stage == MESA_SHADER_TESS_EVAL) { + // gl_in[]: array of gl_PerVertex + uint32_t input_vertices = MAX2(ctx->gl_in_num_vertices[ctx->stage - 1], 1); + + SpvId array_size = spirv_builder_const_uint(&ctx->builder, 32, input_vertices); + input_type = spirv_builder_type_array(&ctx->builder, block_type_in, array_size); + } + + SpvId ptr_type = spirv_builder_type_pointer(&ctx->builder, SpvStorageClassInput, input_type); + SpvId var_id = spirv_builder_emit_var(&ctx->builder, ptr_type, SpvStorageClassInput); + spirv_builder_emit_name(&ctx->builder, var_id, "gl_in"); + ctx->per_vertex_in = var_id; + ctx->entry_ifaces[ctx->num_entry_ifaces++] = var_id; + } + + if (stage_has_per_vertex_output(ctx->stage)) { + SpvId output_type = block_type_out; + + // Tessellation control shaders need gl_out[] as an array + if (ctx->stage == MESA_SHADER_TESS_CTRL) { + uint32_t output_vertices = MAX2(ctx->gl_out_num_vertices, 1); + SpvId array_size = spirv_builder_const_uint(&ctx->builder, 32, output_vertices); + output_type = spirv_builder_type_array(&ctx->builder, block_type_out, array_size); + } + + SpvId ptr_type = spirv_builder_type_pointer(&ctx->builder, SpvStorageClassOutput, output_type); + SpvId var_id = spirv_builder_emit_var(&ctx->builder, ptr_type, SpvStorageClassOutput); + spirv_builder_emit_name(&ctx->builder, var_id, "gl_out"); + + ctx->per_vertex_out = var_id; + ctx->entry_ifaces[ctx->num_entry_ifaces++] = var_id; + } +} + struct spirv_shader * nir_to_spirv(struct nir_shader *s, const struct zink_shader_info *sinfo, const struct zink_screen *screen) { @@ -4572,6 +4880,9 @@ nir_to_spirv(struct nir_shader *s, const struct zink_shader_info *sinfo, const s ctx.vars = _mesa_hash_table_create(ctx.mem_ctx, _mesa_hash_pointer, _mesa_key_pointer_equal); + // TODO: set this on a per driver basis + ctx.use_gl_per_vertex = true; + nir_foreach_variable_with_modes(var, s, nir_var_mem_push_const) input_var_init(&ctx, var); @@ -4589,6 +4900,9 @@ nir_to_spirv(struct nir_shader *s, const struct zink_shader_info *sinfo, const s emit_output(&ctx, var); } + if (ctx.use_gl_per_vertex) + setup_per_vertex_blocks(&ctx); + uint32_t tcs_vertices_out_word = 0; unsigned ubo_counter[2] = {0}; diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index 274908d5528..a0709d094fe 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -857,6 +857,7 @@ zink_init_screen_caps(struct zink_screen *screen) caps->allow_glthread_buffer_subdata_opt = true; caps->nir_samplers_as_deref = true; caps->call_finalize_nir_in_linker = true; + caps->texture_shadow_lod = true; caps->draw_vertex_state = screen->info.have_EXT_vertex_input_dynamic_state; diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h index 170c5e4082b..8491f3ede60 100644 --- a/src/gallium/include/pipe/p_shader_tokens.h +++ b/src/gallium/include/pipe/p_shader_tokens.h @@ -134,7 +134,7 @@ struct tgsi_declaration unsigned Array : 1; /**< extra array info? */ unsigned Atomic : 1; /**< atomic only? for TGSI_FILE_BUFFER */ unsigned MemType : 2; /**< TGSI_MEMORY_TYPE_x for TGSI_FILE_MEMORY */ - unsigned Padding : 3; + unsigned ValueType : 3; /**< TGSI_RETURN_TYPE_x */ }; struct tgsi_declaration_range -- Gitee From b534303089f90b183c83b3fb30096319f7c241df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=98=E5=B4=87=E6=98=8E?= Date: Tue, 24 Jun 2025 13:43:09 +0000 Subject: [PATCH 3/9] update src/gallium/auxiliary/util/u_simple_shaders.c. --- src/gallium/auxiliary/util/u_simple_shaders.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c index 81a2a7512b4..bb43b165acb 100644 --- a/src/gallium/auxiliary/util/u_simple_shaders.c +++ b/src/gallium/auxiliary/util/u_simple_shaders.c @@ -273,16 +273,9 @@ util_make_fragment_tex_shader(struct pipe_context *pipe, TGSI_SEMANTIC_GENERIC, 0, TGSI_INTERPOLATE_LINEAR ); -<<<<<<< HEAD out = ureg_DECL_output_typed( ureg, TGSI_SEMANTIC_COLOR, 0, dtype); -======= - out = ureg_DECL_output_type( ureg, - TGSI_SEMANTIC_COLOR, - 0, - dtype); ->>>>>>> 9a44a390008cba42bac45bbef5039f1b67db0dfa temp = ureg_DECL_temporary(ureg); -- Gitee From f21291a7a9317def25de93f867f9a760ac46af1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=98=E5=B4=87=E6=98=8E?= Date: Tue, 24 Jun 2025 13:44:23 +0000 Subject: [PATCH 4/9] update src/gallium/auxiliary/tgsi/tgsi_ureg.h. --- src/gallium/auxiliary/tgsi/tgsi_ureg.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h index 8637cee17bd..15cf5feb10d 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.h +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h @@ -255,17 +255,10 @@ ureg_DECL_output(struct ureg_program *, unsigned semantic_index); struct ureg_dst -<<<<<<< HEAD ureg_DECL_output_typed(struct ureg_program *, enum tgsi_semantic semantic_name, unsigned semantic_index, enum tgsi_return_type value_type); -======= -ureg_DECL_output_type(struct ureg_program *, - enum tgsi_semantic semantic_name, - unsigned semantic_index, - enum tgsi_return_type value_type); ->>>>>>> 9a44a390008cba42bac45bbef5039f1b67db0dfa struct ureg_dst ureg_DECL_output_array(struct ureg_program *ureg, -- Gitee From cc068d5b442f40d2d9f08cc33095cf20b2e1ad76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=98=E5=B4=87=E6=98=8E?= Date: Tue, 24 Jun 2025 14:36:09 +0000 Subject: [PATCH 5/9] update src/gallium/auxiliary/tgsi/tgsi_ureg.c. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 战崇明 --- src/gallium/auxiliary/tgsi/tgsi_ureg.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c index 051fbccde5a..8ca3e7fd6ca 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c @@ -1926,16 +1926,16 @@ static void emit_decls( struct ureg_program *ureg ) } else { if (ureg->supports_any_inout_decl_range) { for (i = 0; i < ureg->nr_inputs; i++) { - emit_decl_semantic_typed(ureg, - TGSI_FILE_INPUT, - ureg->input[i].first, - ureg->input[i].last, - ureg->input[i].semantic_name, - ureg->input[i].semantic_index, - 0, - TGSI_WRITEMASK_XYZW, - ureg->input[i].array_id, - false); + emit_decl_semantic(ureg, + TGSI_FILE_INPUT, + ureg->input[i].first, + ureg->input[i].last, + ureg->input[i].semantic_name, + ureg->input[i].semantic_index, + 0, + TGSI_WRITEMASK_XYZW, + ureg->input[i].array_id, + false); } } else { -- Gitee From 3c932cf680ca38e5d0274ae6d07291bb624707e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=98=E5=B4=87=E6=98=8E?= Date: Tue, 24 Jun 2025 14:49:00 +0000 Subject: [PATCH 6/9] update src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c. --- .../drivers/zink/nir_to_spirv/nir_to_spirv.c | 48 ------------------- 1 file changed, 48 deletions(-) diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c index bed5482c4c3..28a9ff44f1c 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c +++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c @@ -4258,9 +4258,6 @@ try_emit_gl_per_vertex_access(struct ntv_context *ctx, nir_deref_instr *deref) static void emit_deref_var(struct ntv_context *ctx, nir_deref_instr *deref) { - if (try_emit_gl_per_vertex_access(ctx, deref)) - return; - assert(deref->deref_type == nir_deref_type_var); struct hash_entry *he = _mesa_hash_table_search(ctx->vars, deref->var); @@ -4670,51 +4667,6 @@ get_spacing(enum gl_tess_spacing spacing) } } -static void -setup_per_vertex_blocks(struct ntv_context *ctx) -{ - SpvId block_type_in = create_per_vertex_block_type(ctx, true); - SpvId block_type_out = create_per_vertex_block_type(ctx, false); - - if (stage_has_per_vertex_input(ctx->stage)) { - SpvId input_type = block_type_in; - - if (ctx->stage == MESA_SHADER_GEOMETRY || - ctx->stage == MESA_SHADER_TESS_CTRL || - ctx->stage == MESA_SHADER_TESS_EVAL) { - // gl_in[]: array of gl_PerVertex - uint32_t input_vertices = MAX2(ctx->gl_in_num_vertices[ctx->stage - 1], 1); - - SpvId array_size = spirv_builder_const_uint(&ctx->builder, 32, input_vertices); - input_type = spirv_builder_type_array(&ctx->builder, block_type_in, array_size); - } - - SpvId ptr_type = spirv_builder_type_pointer(&ctx->builder, SpvStorageClassInput, input_type); - SpvId var_id = spirv_builder_emit_var(&ctx->builder, ptr_type, SpvStorageClassInput); - spirv_builder_emit_name(&ctx->builder, var_id, "gl_in"); - ctx->per_vertex_in = var_id; - ctx->entry_ifaces[ctx->num_entry_ifaces++] = var_id; - } - - if (stage_has_per_vertex_output(ctx->stage)) { - SpvId output_type = block_type_out; - - // Tessellation control shaders need gl_out[] as an array - if (ctx->stage == MESA_SHADER_TESS_CTRL) { - uint32_t output_vertices = MAX2(ctx->gl_out_num_vertices, 1); - SpvId array_size = spirv_builder_const_uint(&ctx->builder, 32, output_vertices); - output_type = spirv_builder_type_array(&ctx->builder, block_type_out, array_size); - } - - SpvId ptr_type = spirv_builder_type_pointer(&ctx->builder, SpvStorageClassOutput, output_type); - SpvId var_id = spirv_builder_emit_var(&ctx->builder, ptr_type, SpvStorageClassOutput); - spirv_builder_emit_name(&ctx->builder, var_id, "gl_out"); - - ctx->per_vertex_out = var_id; - ctx->entry_ifaces[ctx->num_entry_ifaces++] = var_id; - } -} - struct spirv_shader * nir_to_spirv(struct nir_shader *s, const struct zink_shader_info *sinfo, const struct zink_screen *screen) { -- Gitee From ca0eef28ecd46709f441ca3c7a0e7c2181a66d54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=98=E5=B4=87=E6=98=8E?= Date: Tue, 24 Jun 2025 15:01:43 +0000 Subject: [PATCH 7/9] update src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c. --- .../drivers/zink/nir_to_spirv/nir_to_spirv.c | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c index 28a9ff44f1c..f0a56a724a2 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c +++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c @@ -4667,6 +4667,51 @@ get_spacing(enum gl_tess_spacing spacing) } } +static void +setup_per_vertex_blocks(struct ntv_context *ctx) +{ + SpvId block_type_in = create_per_vertex_block_type(ctx, true); + SpvId block_type_out = create_per_vertex_block_type(ctx, false); + + if (stage_has_per_vertex_input(ctx->stage)) { + SpvId input_type = block_type_in; + + if (ctx->stage == MESA_SHADER_GEOMETRY || + ctx->stage == MESA_SHADER_TESS_CTRL || + ctx->stage == MESA_SHADER_TESS_EVAL) { + // gl_in[]: array of gl_PerVertex + uint32_t input_vertices = MAX2(ctx->gl_in_num_vertices[ctx->stage - 1], 1); + + SpvId array_size = spirv_builder_const_uint(&ctx->builder, 32, input_vertices); + input_type = spirv_builder_type_array(&ctx->builder, block_type_in, array_size); + } + + SpvId ptr_type = spirv_builder_type_pointer(&ctx->builder, SpvStorageClassInput, input_type); + SpvId var_id = spirv_builder_emit_var(&ctx->builder, ptr_type, SpvStorageClassInput); + spirv_builder_emit_name(&ctx->builder, var_id, "gl_in"); + ctx->per_vertex_in = var_id; + ctx->entry_ifaces[ctx->num_entry_ifaces++] = var_id; + } + + if (stage_has_per_vertex_output(ctx->stage)) { + SpvId output_type = block_type_out; + + // Tessellation control shaders need gl_out[] as an array + if (ctx->stage == MESA_SHADER_TESS_CTRL) { + uint32_t output_vertices = MAX2(ctx->gl_out_num_vertices, 1); + SpvId array_size = spirv_builder_const_uint(&ctx->builder, 32, output_vertices); + output_type = spirv_builder_type_array(&ctx->builder, block_type_out, array_size); + } + + SpvId ptr_type = spirv_builder_type_pointer(&ctx->builder, SpvStorageClassOutput, output_type); + SpvId var_id = spirv_builder_emit_var(&ctx->builder, ptr_type, SpvStorageClassOutput); + spirv_builder_emit_name(&ctx->builder, var_id, "gl_out"); + + ctx->per_vertex_out = var_id; + ctx->entry_ifaces[ctx->num_entry_ifaces++] = var_id; + } +} + struct spirv_shader * nir_to_spirv(struct nir_shader *s, const struct zink_shader_info *sinfo, const struct zink_screen *screen) { -- Gitee From 318e4058789e202a26fcf7384fbd4bf6701ef36b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=98=E5=B4=87=E6=98=8E?= Date: Tue, 24 Jun 2025 15:01:43 +0000 Subject: [PATCH 8/9] update src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c. Signed-off-by: Beliefzh --- .../drivers/zink/nir_to_spirv/nir_to_spirv.c | 45 +++++++++++++++++++ .../drivers/zink/nir_to_spirv/spirv_builder.c | 22 +++++++++ .../drivers/zink/nir_to_spirv/spirv_builder.h | 8 ++++ 3 files changed, 75 insertions(+) diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c index 28a9ff44f1c..f0a56a724a2 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c +++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c @@ -4667,6 +4667,51 @@ get_spacing(enum gl_tess_spacing spacing) } } +static void +setup_per_vertex_blocks(struct ntv_context *ctx) +{ + SpvId block_type_in = create_per_vertex_block_type(ctx, true); + SpvId block_type_out = create_per_vertex_block_type(ctx, false); + + if (stage_has_per_vertex_input(ctx->stage)) { + SpvId input_type = block_type_in; + + if (ctx->stage == MESA_SHADER_GEOMETRY || + ctx->stage == MESA_SHADER_TESS_CTRL || + ctx->stage == MESA_SHADER_TESS_EVAL) { + // gl_in[]: array of gl_PerVertex + uint32_t input_vertices = MAX2(ctx->gl_in_num_vertices[ctx->stage - 1], 1); + + SpvId array_size = spirv_builder_const_uint(&ctx->builder, 32, input_vertices); + input_type = spirv_builder_type_array(&ctx->builder, block_type_in, array_size); + } + + SpvId ptr_type = spirv_builder_type_pointer(&ctx->builder, SpvStorageClassInput, input_type); + SpvId var_id = spirv_builder_emit_var(&ctx->builder, ptr_type, SpvStorageClassInput); + spirv_builder_emit_name(&ctx->builder, var_id, "gl_in"); + ctx->per_vertex_in = var_id; + ctx->entry_ifaces[ctx->num_entry_ifaces++] = var_id; + } + + if (stage_has_per_vertex_output(ctx->stage)) { + SpvId output_type = block_type_out; + + // Tessellation control shaders need gl_out[] as an array + if (ctx->stage == MESA_SHADER_TESS_CTRL) { + uint32_t output_vertices = MAX2(ctx->gl_out_num_vertices, 1); + SpvId array_size = spirv_builder_const_uint(&ctx->builder, 32, output_vertices); + output_type = spirv_builder_type_array(&ctx->builder, block_type_out, array_size); + } + + SpvId ptr_type = spirv_builder_type_pointer(&ctx->builder, SpvStorageClassOutput, output_type); + SpvId var_id = spirv_builder_emit_var(&ctx->builder, ptr_type, SpvStorageClassOutput); + spirv_builder_emit_name(&ctx->builder, var_id, "gl_out"); + + ctx->per_vertex_out = var_id; + ctx->entry_ifaces[ctx->num_entry_ifaces++] = var_id; + } +} + struct spirv_shader * nir_to_spirv(struct nir_shader *s, const struct zink_shader_info *sinfo, const struct zink_screen *screen) { diff --git a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c index 83ec238d4d1..d90508342b3 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c +++ b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c @@ -412,6 +412,28 @@ spirv_builder_emit_member_offset(struct spirv_builder *b, SpvId target, args, ARRAY_SIZE(args)); } +void +spirv_builder_emit_member_builtin(struct spirv_builder *b, SpvId target, + uint32_t member, SpvBuiltIn builtin) +{ + uint32_t args[] = { builtin }; + emit_member_decoration(b, target, member, SpvDecorationBiltin, + args, ARRAY_SIZE(args)); +} + +void +spirv_builder_emit_member_name(struct spirv_builder *b, SpvId struct_name, + unsigned member, const char *name) +{ + size_t pos = b->debug_names.num_words; + spirv_buffer_prepare(&b->debug_names, b->mem_ctx, 3); + spirv_buffer_emit_word(&b->debug_names, SpvOpMemberName); + spirv_buffer_emit_word(&b->debug_names, struct_name); + spirv_buffer_emit_word(&b->debug_names, member); + int len = spirv_buffer_emit_string(&b->debug_names, b->mem_ctx, name); + b->debug_names.words[pos] |= (3 + len) << 16; +} + SpvId spirv_builder_emit_undef(struct spirv_builder *b, SpvId result_type) { diff --git a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h index 2456d2a1bf3..73facbe8d63 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h +++ b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h @@ -165,6 +165,14 @@ void spirv_builder_emit_member_offset(struct spirv_builder *b, SpvId target, uint32_t member, uint32_t offset); +void +spirv_builder_emit_member_builtin(struct spirv_builder *b, SpvId target, + uint32_t member, SpvBuiltIn builtin); + +void +spirv_builder_emit_member_name(struct spirv_builder *b, SpvId struct_name, + unsigned member, const char *name); + void spirv_builder_emit_entry_point(struct spirv_builder *b, SpvExecutionModel exec_model, SpvId entry_point, -- Gitee From c38e723668fa9df0484d238d174895e0d03eab59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=98=E5=B4=87=E6=98=8E?= Date: Wed, 25 Jun 2025 07:00:44 +0000 Subject: [PATCH 9/9] update src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c. --- src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c index d90508342b3..f02ffda1caa 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c +++ b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c @@ -417,7 +417,7 @@ spirv_builder_emit_member_builtin(struct spirv_builder *b, SpvId target, uint32_t member, SpvBuiltIn builtin) { uint32_t args[] = { builtin }; - emit_member_decoration(b, target, member, SpvDecorationBiltin, + emit_member_decoration(b, target, member, SpvDecorationBuiltin, args, ARRAY_SIZE(args)); } -- Gitee