tu: Enable multi-position output
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6515>
This commit is contained in:
@@ -197,6 +197,7 @@ static const struct debug_control tu_debug_options[] = {
|
|||||||
{ "sysmem", TU_DEBUG_SYSMEM },
|
{ "sysmem", TU_DEBUG_SYSMEM },
|
||||||
{ "forcebin", TU_DEBUG_FORCEBIN },
|
{ "forcebin", TU_DEBUG_FORCEBIN },
|
||||||
{ "noubwc", TU_DEBUG_NOUBWC },
|
{ "noubwc", TU_DEBUG_NOUBWC },
|
||||||
|
{ "nomultipos", TU_DEBUG_NOMULTIPOS },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -15,11 +15,21 @@
|
|||||||
* one).
|
* one).
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
lower_multiview_mask(nir_function_impl *impl, uint32_t mask)
|
lower_multiview_mask(nir_shader *nir, uint32_t *mask)
|
||||||
{
|
{
|
||||||
|
nir_function_impl *impl = nir_shader_get_entrypoint(nir);
|
||||||
|
|
||||||
|
if (util_is_power_of_two_or_zero(*mask + 1)) {
|
||||||
|
nir_metadata_preserve(impl, nir_metadata_all);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
nir_builder b;
|
nir_builder b;
|
||||||
nir_builder_init(&b, impl);
|
nir_builder_init(&b, impl);
|
||||||
|
|
||||||
|
uint32_t old_mask = *mask;
|
||||||
|
*mask = BIT(util_logbase2(old_mask) + 1) - 1;
|
||||||
|
|
||||||
nir_foreach_block_reverse(block, impl) {
|
nir_foreach_block_reverse(block, impl) {
|
||||||
nir_foreach_instr_reverse(instr, block) {
|
nir_foreach_instr_reverse(instr, block) {
|
||||||
if (instr->type != nir_instr_type_intrinsic)
|
if (instr->type != nir_instr_type_intrinsic)
|
||||||
@@ -43,7 +53,7 @@ lower_multiview_mask(nir_function_impl *impl, uint32_t mask)
|
|||||||
|
|
||||||
/* ((1ull << gl_ViewIndex) & mask) != 0 */
|
/* ((1ull << gl_ViewIndex) & mask) != 0 */
|
||||||
nir_ssa_def *cmp =
|
nir_ssa_def *cmp =
|
||||||
nir_i2b(&b, nir_iand(&b, nir_imm_int(&b, mask),
|
nir_i2b(&b, nir_iand(&b, nir_imm_int(&b, old_mask),
|
||||||
nir_ishl(&b, nir_imm_int(&b, 1),
|
nir_ishl(&b, nir_imm_int(&b, 1),
|
||||||
nir_load_view_index(&b))));
|
nir_load_view_index(&b))));
|
||||||
|
|
||||||
@@ -61,16 +71,40 @@ lower_multiview_mask(nir_function_impl *impl, uint32_t mask)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
tu_nir_lower_multiview(nir_shader *nir, uint32_t mask, struct tu_device *dev)
|
tu_nir_lower_multiview(nir_shader *nir, uint32_t mask, bool *multi_pos_output,
|
||||||
|
struct tu_device *dev)
|
||||||
{
|
{
|
||||||
nir_function_impl *entrypoint = nir_shader_get_entrypoint(nir);
|
*multi_pos_output = false;
|
||||||
|
|
||||||
if (!dev->physical_device->supports_multiview_mask &&
|
bool progress = false;
|
||||||
!util_is_power_of_two_or_zero(mask + 1)) {
|
|
||||||
return lower_multiview_mask(entrypoint, mask);
|
if (!dev->physical_device->supports_multiview_mask)
|
||||||
|
NIR_PASS(progress, nir, lower_multiview_mask, &mask);
|
||||||
|
|
||||||
|
unsigned num_views = util_logbase2(mask) + 1;
|
||||||
|
|
||||||
|
/* Speculatively assign output locations so that we know num_outputs. We
|
||||||
|
* will assign output locations for real after this pass.
|
||||||
|
*/
|
||||||
|
unsigned num_outputs;
|
||||||
|
nir_assign_io_var_locations(nir, nir_var_shader_out, &num_outputs, MESA_SHADER_VERTEX);
|
||||||
|
|
||||||
|
/* In addition to the generic checks done by NIR, check that we don't
|
||||||
|
* overflow VPC with the extra copies of gl_Position.
|
||||||
|
*/
|
||||||
|
if (likely(!(dev->physical_device->instance->debug_flags & TU_DEBUG_NOMULTIPOS)) &&
|
||||||
|
num_outputs + (num_views - 1) <= 32 && nir_can_lower_multiview(nir)) {
|
||||||
|
*multi_pos_output = true;
|
||||||
|
|
||||||
|
/* It appears that the multiview mask is ignored when multi-position
|
||||||
|
* output is enabled, so we have to write 0 to inactive views ourselves.
|
||||||
|
*/
|
||||||
|
NIR_PASS(progress, nir, lower_multiview_mask, &mask);
|
||||||
|
|
||||||
|
NIR_PASS_V(nir, nir_lower_multiview, mask);
|
||||||
|
progress = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
nir_metadata_preserve(entrypoint, nir_metadata_all);
|
return progress;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -227,6 +227,7 @@ enum tu_debug_flags
|
|||||||
TU_DEBUG_SYSMEM = 1 << 4,
|
TU_DEBUG_SYSMEM = 1 << 4,
|
||||||
TU_DEBUG_FORCEBIN = 1 << 5,
|
TU_DEBUG_FORCEBIN = 1 << 5,
|
||||||
TU_DEBUG_NOUBWC = 1 << 6,
|
TU_DEBUG_NOUBWC = 1 << 6,
|
||||||
|
TU_DEBUG_NOMULTIPOS = 1 << 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tu_instance
|
struct tu_instance
|
||||||
@@ -1031,7 +1032,8 @@ struct tu_shader
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
tu_nir_lower_multiview(nir_shader *nir, uint32_t mask, struct tu_device *dev);
|
tu_nir_lower_multiview(nir_shader *nir, uint32_t mask, bool *multi_pos_output,
|
||||||
|
struct tu_device *dev);
|
||||||
|
|
||||||
nir_shader *
|
nir_shader *
|
||||||
tu_spirv_to_nir(struct tu_device *dev,
|
tu_spirv_to_nir(struct tu_device *dev,
|
||||||
|
@@ -761,7 +761,8 @@ tu_shader_create(struct tu_device *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nir->info.stage == MESA_SHADER_VERTEX && multiview_mask) {
|
if (nir->info.stage == MESA_SHADER_VERTEX && multiview_mask) {
|
||||||
NIR_PASS_V(nir, tu_nir_lower_multiview, multiview_mask, dev);
|
tu_nir_lower_multiview(nir, multiview_mask,
|
||||||
|
&shader->multi_pos_output, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
NIR_PASS_V(nir, nir_lower_explicit_io,
|
NIR_PASS_V(nir, nir_lower_explicit_io,
|
||||||
|
Reference in New Issue
Block a user