dzn: Implement point coord

Since we don't support wide points, this isn't a useful feature, but the CTS
requires a particular point coord value for the single rasterized pixel, based
on where the original point coord fell within the pixel. Since we're not doing
a quad, we don't get free interpolation like the GL driver does, so split the
logic between vertex (transform point center into screen space) and pixel
(compute delta between current pixel/sample and point center).

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20400>
This commit is contained in:
Jesse Natalie
2022-12-20 11:25:36 -08:00
committed by Marge Bot
parent 03ce60ec7e
commit 9a991cc52e
6 changed files with 172 additions and 16 deletions

View File

@@ -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();

View File

@@ -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,

View File

@@ -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;
}
}

View File

@@ -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 {

View File

@@ -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 |=

View File

@@ -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) {