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;
|
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
|
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();
|
glsl_type_singleton_init_or_ref();
|
||||||
|
|
||||||
if (prev_stage_nir) {
|
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(nir, dxil_spirv_nir_kill_undefined_varyings, prev_stage_nir);
|
||||||
NIR_PASS_V(prev_stage_nir, dxil_spirv_nir_kill_unused_outputs, nir);
|
NIR_PASS_V(prev_stage_nir, dxil_spirv_nir_kill_unused_outputs, nir);
|
||||||
|
|
||||||
nir->info.inputs_read =
|
nir->info.inputs_read =
|
||||||
dxil_reassign_driver_locations(nir, nir_var_shader_in,
|
dxil_reassign_driver_locations(nir, nir_var_shader_in,
|
||||||
prev_stage_nir->info.outputs_written);
|
prev_stage_nir->info.outputs_written);
|
||||||
|
|
||||||
prev_stage_nir->info.outputs_written =
|
prev_stage_nir->info.outputs_written =
|
||||||
dxil_reassign_driver_locations(prev_stage_nir, nir_var_shader_out,
|
dxil_reassign_driver_locations(prev_stage_nir, nir_var_shader_out,
|
||||||
nir->info.inputs_read);
|
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();
|
glsl_type_singleton_decref();
|
||||||
|
@@ -32,7 +32,8 @@ void
|
|||||||
dxil_spirv_nir_prep(nir_shader *nir);
|
dxil_spirv_nir_prep(nir_shader *nir);
|
||||||
|
|
||||||
void
|
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
|
void
|
||||||
dxil_spirv_nir_passes(nir_shader *nir,
|
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;
|
struct nir_shader_compiler_options nir_options;
|
||||||
|
|
||||||
static bool
|
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;
|
size_t file_size;
|
||||||
char *file_contents = os_read_file(filename, &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;
|
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 = {
|
struct spirv_to_nir_options spirv_opts = {
|
||||||
.caps = {
|
.caps = {
|
||||||
.draw_parameters = true,
|
.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);
|
dxil_spirv_nir_prep(shader->nir);
|
||||||
|
|
||||||
bool requires_runtime_data;
|
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)
|
if (debug)
|
||||||
nir_print_shader(shader->nir, stderr);
|
nir_print_shader(shader->nir, stderr);
|
||||||
@@ -200,6 +195,12 @@ main(int argc, char **argv)
|
|||||||
// have been already converted to zero-base.
|
// have been already converted to zero-base.
|
||||||
nir_options.lower_base_vertex = false;
|
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;
|
bool any_shaders = false;
|
||||||
while ((ch = getopt_long(argc, argv, "-s:e:o:m:x:vd", long_options, NULL)) !=
|
while ((ch = getopt_long(argc, argv, "-s:e:o:m:x:vd", long_options, NULL)) !=
|
||||||
-1) {
|
-1) {
|
||||||
@@ -232,7 +233,7 @@ main(int argc, char **argv)
|
|||||||
val_ver = DXIL_VALIDATOR_1_0 + atoi(optarg);
|
val_ver = DXIL_VALIDATOR_1_0 + atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (!compile_shader(optarg, shader_stage, &cur_shader))
|
if (!compile_shader(optarg, shader_stage, &cur_shader, &conf))
|
||||||
return 1;
|
return 1;
|
||||||
shaders[shader_stage] = cur_shader;
|
shaders[shader_stage] = cur_shader;
|
||||||
any_shaders = true;
|
any_shaders = true;
|
||||||
@@ -254,7 +255,7 @@ main(int argc, char **argv)
|
|||||||
for (int32_t prev = cur - 1; prev >= MESA_SHADER_VERTEX; --prev) {
|
for (int32_t prev = cur - 1; prev >= MESA_SHADER_VERTEX; --prev) {
|
||||||
if (!shaders[prev].nir)
|
if (!shaders[prev].nir)
|
||||||
continue;
|
continue;
|
||||||
dxil_spirv_nir_link(shaders[cur].nir, shaders[prev].nir);
|
dxil_spirv_nir_link(shaders[cur].nir, shaders[prev].nir, &conf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -112,6 +112,8 @@ struct dxil_spirv_vertex_runtime_data {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
uint32_t draw_id;
|
uint32_t draw_id;
|
||||||
|
float viewport_width;
|
||||||
|
float viewport_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum dxil_spirv_yz_flip_mode {
|
enum dxil_spirv_yz_flip_mode {
|
||||||
|
@@ -4518,7 +4518,10 @@ dzn_CmdBindPipeline(VkCommandBuffer commandBuffer,
|
|||||||
if (!gfx->vp.dynamic) {
|
if (!gfx->vp.dynamic) {
|
||||||
memcpy(cmdbuf->state.viewports, gfx->vp.desc,
|
memcpy(cmdbuf->state.viewports, gfx->vp.desc,
|
||||||
gfx->vp.count * sizeof(cmdbuf->state.viewports[0]));
|
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.dirty |= DZN_CMD_DIRTY_VIEWPORTS;
|
||||||
|
cmdbuf->state.bindpoint[pipelineBindPoint].dirty |= DZN_CMD_BINDPOINT_DIRTY_SYSVALS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gfx->scissor.dynamic) {
|
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.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) {
|
if (viewportCount) {
|
||||||
cmdbuf->state.dirty |= DZN_CMD_DIRTY_VIEWPORTS;
|
cmdbuf->state.dirty |= DZN_CMD_DIRTY_VIEWPORTS;
|
||||||
cmdbuf->state.bindpoint[VK_PIPELINE_BIND_POINT_GRAPHICS].dirty |=
|
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);
|
link_mask &= ~BITFIELD_BIT(stage);
|
||||||
gl_shader_stage prev_stage = util_last_bit(link_mask) - 1;
|
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);
|
assert(pipeline->templates.shaders[stage].nir);
|
||||||
dxil_spirv_nir_link(pipeline->templates.shaders[stage].nir,
|
dxil_spirv_nir_link(pipeline->templates.shaders[stage].nir,
|
||||||
prev_stage != MESA_SHADER_NONE ?
|
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) {
|
u_foreach_bit(stage, active_stage_mask) {
|
||||||
|
Reference in New Issue
Block a user