diff --git a/src/microsoft/spirv_to_dxil/dxil_spirv_nir.c b/src/microsoft/spirv_to_dxil/dxil_spirv_nir.c index 30704833830..a5709c1a4c5 100644 --- a/src/microsoft/spirv_to_dxil/dxil_spirv_nir.c +++ b/src/microsoft/spirv_to_dxil/dxil_spirv_nir.c @@ -604,24 +604,163 @@ dxil_spirv_nir_kill_unused_outputs(nir_shader *shader, return progress; } +struct lower_pntc_data { + const struct dxil_spirv_runtime_conf *conf; + nir_variable *pntc; +}; + +static bool +write_pntc_with_pos(nir_builder *b, nir_instr *instr, void *_data) +{ + struct lower_pntc_data *data = (struct lower_pntc_data *)_data; + if (instr->type != nir_instr_type_intrinsic) + return false; + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + if (intr->intrinsic != nir_intrinsic_store_deref) + return false; + nir_variable *var = nir_intrinsic_get_var(intr, 0); + if (!var || var->data.location != VARYING_SLOT_POS) + return false; + + nir_ssa_def *pos = intr->src[1].ssa; + + unsigned offset = + offsetof(struct dxil_spirv_vertex_runtime_data, viewport_width) - 4; + static_assert(offsetof(struct dxil_spirv_vertex_runtime_data, viewport_width) % 16 == 4, + "Doing vector unpacking with this assumption"); + nir_address_format ubo_format = nir_address_format_32bit_index_offset; + + b->cursor = nir_before_instr(instr); + nir_ssa_def *index = nir_vulkan_resource_index( + b, nir_address_format_num_components(ubo_format), + nir_address_format_bit_size(ubo_format), + nir_imm_int(b, 0), + .desc_set = data->conf->runtime_data_cbv.register_space, + .binding = data->conf->runtime_data_cbv.base_shader_register, + .desc_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + + nir_ssa_def *load_desc = nir_load_vulkan_descriptor( + b, nir_address_format_num_components(ubo_format), + nir_address_format_bit_size(ubo_format), + index, .desc_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + + nir_ssa_def *transform = nir_channels(b, + build_load_ubo_dxil(b, + nir_channel(b, load_desc, 0), + nir_imm_int(b, offset), 4, 32), + 0x6); + nir_ssa_def *point_center_in_clip = nir_fmul(b, nir_channels(b, pos, 0x3), nir_frcp(b, nir_channel(b, pos, 3))); + nir_ssa_def *point_center = + nir_fmul(b, nir_fadd_imm(b, + nir_fmul(b, point_center_in_clip, + nir_vec2(b, nir_imm_float(b, 0.5), nir_imm_float(b, -0.5f))), + 0.5), transform); + nir_store_var(b, data->pntc, nir_pad_vec4(b, point_center), 0xf); + return true; +} + +static void +dxil_spirv_write_pntc(nir_shader *nir, const struct dxil_spirv_runtime_conf *conf) +{ + struct lower_pntc_data data = { .conf = conf }; + data.pntc = nir_variable_create(nir, nir_var_shader_out, glsl_vec4_type(), "gl_PointCoord"); + data.pntc->data.location = VARYING_SLOT_PNTC; + nir_shader_instructions_pass(nir, write_pntc_with_pos, + nir_metadata_block_index | + nir_metadata_dominance | + nir_metadata_loop_analysis, + &data); + nir->info.outputs_written |= VARYING_BIT_PNTC; + + /* Add the runtime data var if it's not already there */ + nir_binding binding = { + .binding = conf->runtime_data_cbv.base_shader_register, + .desc_set = conf->runtime_data_cbv.register_space, + .success = true, + }; + nir_variable *ubo_var = nir_get_binding_variable(nir, binding); + if (!ubo_var) + add_runtime_data_var(nir, conf->runtime_data_cbv.register_space, conf->runtime_data_cbv.base_shader_register); +} + +static bool +lower_pntc_read(nir_builder *b, nir_instr *instr, void *data) +{ + if (instr->type != nir_instr_type_intrinsic) + return false; + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + if (intr->intrinsic != nir_intrinsic_load_deref) + return false; + nir_variable *var = nir_intrinsic_get_var(intr, 0); + if (!var || var->data.location != VARYING_SLOT_PNTC) + return false; + + nir_ssa_def *point_center = &intr->dest.ssa; + nir_variable *pos_var = (nir_variable *)data; + + b->cursor = nir_after_instr(instr); + + nir_ssa_def *pos; + if (var->data.sample == pos_var->data.sample) + pos = nir_load_var(b, pos_var); + else if (var->data.sample) + pos = nir_interp_deref_at_sample(b, 4, 32, + &nir_build_deref_var(b, pos_var)->dest.ssa, + nir_load_sample_id(b)); + else + pos = nir_interp_deref_at_offset(b, 4, 32, + &nir_build_deref_var(b, pos_var)->dest.ssa, + nir_vec2(b, nir_imm_float(b, 0), nir_imm_float(b, 0))); + + nir_ssa_def *pntc = nir_fadd_imm(b, + nir_fsub(b, nir_channels(b, pos, 0x3), nir_channels(b, point_center, 0x3)), + 0.5); + nir_ssa_def_rewrite_uses_after(point_center, pntc, pntc->parent_instr); + return true; +} + +static void +dxil_spirv_compute_pntc(nir_shader *nir) +{ + nir_variable *pos = nir_find_variable_with_location(nir, nir_var_shader_in, VARYING_SLOT_POS); + if (!pos) { + pos = nir_variable_create(nir, nir_var_shader_in, glsl_vec4_type(), "gl_FragCoord"); + pos->data.location = VARYING_SLOT_POS; + pos->data.sample = nir_find_variable_with_location(nir, nir_var_shader_in, VARYING_SLOT_PNTC)->data.sample; + } + nir_shader_instructions_pass(nir, lower_pntc_read, + nir_metadata_block_index | + nir_metadata_dominance | + nir_metadata_loop_analysis, + pos); +} + void -dxil_spirv_nir_link(nir_shader *nir, nir_shader *prev_stage_nir) +dxil_spirv_nir_link(nir_shader *nir, nir_shader *prev_stage_nir, + const struct dxil_spirv_runtime_conf *conf) { glsl_type_singleton_init_or_ref(); if (prev_stage_nir) { + if (nir->info.stage == MESA_SHADER_FRAGMENT) { + nir->info.clip_distance_array_size = prev_stage_nir->info.clip_distance_array_size; + + if (nir->info.inputs_read & VARYING_BIT_PNTC) { + NIR_PASS_V(prev_stage_nir, dxil_spirv_write_pntc, conf); + NIR_PASS_V(nir, dxil_spirv_compute_pntc); + } + } + NIR_PASS_V(nir, dxil_spirv_nir_kill_undefined_varyings, prev_stage_nir); NIR_PASS_V(prev_stage_nir, dxil_spirv_nir_kill_unused_outputs, nir); nir->info.inputs_read = dxil_reassign_driver_locations(nir, nir_var_shader_in, prev_stage_nir->info.outputs_written); + prev_stage_nir->info.outputs_written = dxil_reassign_driver_locations(prev_stage_nir, nir_var_shader_out, nir->info.inputs_read); - - if (nir->info.stage == MESA_SHADER_FRAGMENT) - nir->info.clip_distance_array_size = prev_stage_nir->info.clip_distance_array_size; } glsl_type_singleton_decref(); diff --git a/src/microsoft/spirv_to_dxil/dxil_spirv_nir.h b/src/microsoft/spirv_to_dxil/dxil_spirv_nir.h index 26ee3e9d8f7..3531d2aef1c 100644 --- a/src/microsoft/spirv_to_dxil/dxil_spirv_nir.h +++ b/src/microsoft/spirv_to_dxil/dxil_spirv_nir.h @@ -32,7 +32,8 @@ void dxil_spirv_nir_prep(nir_shader *nir); void -dxil_spirv_nir_link(nir_shader *nir, nir_shader *prev_stage_nir); +dxil_spirv_nir_link(nir_shader *nir, nir_shader *prev_stage_nir, + const struct dxil_spirv_runtime_conf *conf); void dxil_spirv_nir_passes(nir_shader *nir, diff --git a/src/microsoft/spirv_to_dxil/spirv2dxil.c b/src/microsoft/spirv_to_dxil/spirv2dxil.c index a468f308b23..2598551468e 100644 --- a/src/microsoft/spirv_to_dxil/spirv2dxil.c +++ b/src/microsoft/spirv_to_dxil/spirv2dxil.c @@ -80,7 +80,8 @@ enum dxil_shader_model shader_model = SHADER_MODEL_6_2; struct nir_shader_compiler_options nir_options; static bool -compile_shader(const char *filename, gl_shader_stage shader_stage, struct shader *shader) +compile_shader(const char *filename, gl_shader_stage shader_stage, struct shader *shader, + struct dxil_spirv_runtime_conf *conf) { size_t file_size; char *file_contents = os_read_file(filename, &file_size); @@ -98,12 +99,6 @@ compile_shader(const char *filename, gl_shader_stage shader_stage, struct shader size_t word_count = file_size / WORD_SIZE; - struct dxil_spirv_runtime_conf conf; - memset(&conf, 0, sizeof(conf)); - conf.runtime_data_cbv.base_shader_register = 0; - conf.runtime_data_cbv.register_space = 31; - conf.zero_based_vertex_instance_id = true; - struct spirv_to_nir_options spirv_opts = { .caps = { .draw_parameters = true, @@ -135,7 +130,7 @@ compile_shader(const char *filename, gl_shader_stage shader_stage, struct shader dxil_spirv_nir_prep(shader->nir); bool requires_runtime_data; - dxil_spirv_nir_passes(shader->nir, &conf, &requires_runtime_data); + dxil_spirv_nir_passes(shader->nir, conf, &requires_runtime_data); if (debug) nir_print_shader(shader->nir, stderr); @@ -200,6 +195,12 @@ main(int argc, char **argv) // have been already converted to zero-base. nir_options.lower_base_vertex = false; + struct dxil_spirv_runtime_conf conf; + memset(&conf, 0, sizeof(conf)); + conf.runtime_data_cbv.base_shader_register = 0; + conf.runtime_data_cbv.register_space = 31; + conf.zero_based_vertex_instance_id = true; + bool any_shaders = false; while ((ch = getopt_long(argc, argv, "-s:e:o:m:x:vd", long_options, NULL)) != -1) { @@ -232,7 +233,7 @@ main(int argc, char **argv) val_ver = DXIL_VALIDATOR_1_0 + atoi(optarg); break; case 1: - if (!compile_shader(optarg, shader_stage, &cur_shader)) + if (!compile_shader(optarg, shader_stage, &cur_shader, &conf)) return 1; shaders[shader_stage] = cur_shader; any_shaders = true; @@ -254,7 +255,7 @@ main(int argc, char **argv) for (int32_t prev = cur - 1; prev >= MESA_SHADER_VERTEX; --prev) { if (!shaders[prev].nir) continue; - dxil_spirv_nir_link(shaders[cur].nir, shaders[prev].nir); + dxil_spirv_nir_link(shaders[cur].nir, shaders[prev].nir, &conf); break; } } diff --git a/src/microsoft/spirv_to_dxil/spirv_to_dxil.h b/src/microsoft/spirv_to_dxil/spirv_to_dxil.h index 8160f1cae9d..8a602dc1ba7 100644 --- a/src/microsoft/spirv_to_dxil/spirv_to_dxil.h +++ b/src/microsoft/spirv_to_dxil/spirv_to_dxil.h @@ -112,6 +112,8 @@ struct dxil_spirv_vertex_runtime_data { }; }; uint32_t draw_id; + float viewport_width; + float viewport_height; }; enum dxil_spirv_yz_flip_mode { diff --git a/src/microsoft/vulkan/dzn_cmd_buffer.c b/src/microsoft/vulkan/dzn_cmd_buffer.c index 7a504cd6b86..db6cb22222d 100644 --- a/src/microsoft/vulkan/dzn_cmd_buffer.c +++ b/src/microsoft/vulkan/dzn_cmd_buffer.c @@ -4518,7 +4518,10 @@ dzn_CmdBindPipeline(VkCommandBuffer commandBuffer, if (!gfx->vp.dynamic) { memcpy(cmdbuf->state.viewports, gfx->vp.desc, gfx->vp.count * sizeof(cmdbuf->state.viewports[0])); + cmdbuf->state.sysvals.gfx.viewport_width = cmdbuf->state.viewports[0].Width; + cmdbuf->state.sysvals.gfx.viewport_height = cmdbuf->state.viewports[0].Height; cmdbuf->state.dirty |= DZN_CMD_DIRTY_VIEWPORTS; + cmdbuf->state.bindpoint[pipelineBindPoint].dirty |= DZN_CMD_BINDPOINT_DIRTY_SYSVALS; } if (!gfx->scissor.dynamic) { @@ -4621,6 +4624,9 @@ dzn_CmdSetViewport(VkCommandBuffer commandBuffer, cmdbuf->state.sysvals.gfx.yz_flip_mask &= ~BITFIELD_BIT(vp); } + cmdbuf->state.sysvals.gfx.viewport_width = cmdbuf->state.viewports[0].Width; + cmdbuf->state.sysvals.gfx.viewport_height = cmdbuf->state.viewports[0].Height; + if (viewportCount) { cmdbuf->state.dirty |= DZN_CMD_DIRTY_VIEWPORTS; cmdbuf->state.bindpoint[VK_PIPELINE_BIND_POINT_GRAPHICS].dirty |= diff --git a/src/microsoft/vulkan/dzn_pipeline.c b/src/microsoft/vulkan/dzn_pipeline.c index b9221a00f91..757743f37d3 100644 --- a/src/microsoft/vulkan/dzn_pipeline.c +++ b/src/microsoft/vulkan/dzn_pipeline.c @@ -823,10 +823,17 @@ dzn_graphics_pipeline_compile_shaders(struct dzn_device *device, link_mask &= ~BITFIELD_BIT(stage); gl_shader_stage prev_stage = util_last_bit(link_mask) - 1; + struct dxil_spirv_runtime_conf conf = { + .runtime_data_cbv = { + .register_space = DZN_REGISTER_SPACE_SYSVALS, + .base_shader_register = 0, + }}; + assert(pipeline->templates.shaders[stage].nir); dxil_spirv_nir_link(pipeline->templates.shaders[stage].nir, prev_stage != MESA_SHADER_NONE ? - pipeline->templates.shaders[prev_stage].nir : NULL); + pipeline->templates.shaders[prev_stage].nir : NULL, + &conf); } u_foreach_bit(stage, active_stage_mask) {