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:
@@ -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();
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
@@ -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 |=
|
||||
|
@@ -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) {
|
||||
|
Reference in New Issue
Block a user