tu: Split out viewport faking from per-view viewports
For VK_VALVE_fragment_density_map_layered, we need to split out whether to enable per-view viewports and whether viewport 0 should be splatted to all viewports. We also have to split this out for VK_QCOM_multiview_per_view_viewport, where the splatting needs to be disabled. To avoid conflicts between them, plumb through "fake_single_viewport" which will be needed for the former extension and needs to be modified for the latter extension. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35594>
This commit is contained in:
@@ -4491,8 +4491,11 @@ tu_CmdBindPipeline(VkCommandBuffer commandBuffer,
|
||||
pipeline->shaders[MESA_SHADER_FRAGMENT]->fs.has_fdm;
|
||||
}
|
||||
|
||||
if (pipeline->program.per_view_viewport != cmd->state.per_view_viewport) {
|
||||
if (pipeline->program.per_view_viewport != cmd->state.per_view_viewport ||
|
||||
pipeline->program.fake_single_viewport != cmd->state.fake_single_viewport) {
|
||||
cmd->state.per_view_viewport = pipeline->program.per_view_viewport;
|
||||
cmd->state.fake_single_viewport =
|
||||
pipeline->program.fake_single_viewport;
|
||||
cmd->state.dirty |= TU_CMD_DIRTY_PER_VIEW_VIEWPORT;
|
||||
}
|
||||
|
||||
|
||||
@@ -289,6 +289,13 @@ struct tu_render_pass_state
|
||||
bool has_zpass_done_sample_count_write_in_rp;
|
||||
bool disable_gmem;
|
||||
bool sysmem_single_prim_mode;
|
||||
|
||||
/* This is set if, at any point in the render pass, we were not able to
|
||||
* duplicate the viewport per-view due to the user using multiple viewports
|
||||
* and instead we used the state from view 0 to transform each viewport. If
|
||||
* this happens at any point then all views must contain the same FDM
|
||||
* fragment size.
|
||||
*/
|
||||
bool shared_viewport;
|
||||
|
||||
/* Track whether conditional predicate for COND_REG_EXEC is changed in draw_cs */
|
||||
@@ -447,7 +454,10 @@ struct tu_cmd_state
|
||||
uint32_t max_vbs_bound;
|
||||
|
||||
bool has_fdm;
|
||||
/* See tu_pipeline::per_view_viewport */
|
||||
bool per_view_viewport;
|
||||
/* See tu_pipeline::fake_single_viewport */
|
||||
bool fake_single_viewport;
|
||||
|
||||
/* saved states to re-emit in TU_CMD_DIRTY_DRAW_STATE case */
|
||||
struct tu_draw_state dynamic_state[TU_DYNAMIC_STATE_COUNT];
|
||||
|
||||
@@ -2321,6 +2321,7 @@ tu_emit_program_state(struct tu_cs *sub_cs,
|
||||
!last_shader->writes_viewport &&
|
||||
shaders[MESA_SHADER_FRAGMENT]->fs.has_fdm &&
|
||||
dev->physical_device->info->a6xx.has_per_view_viewport;
|
||||
prog->fake_single_viewport = prog->per_view_viewport;
|
||||
prog->writes_shading_rate = last_shader->writes_shading_rate;
|
||||
prog->reads_shading_rate = fs->reads_shading_rate;
|
||||
prog->accesses_smask = fs->reads_smask || fs->writes_smask;
|
||||
@@ -2552,7 +2553,10 @@ tu6_emit_viewport(struct tu_cs *cs,
|
||||
struct apply_viewport_state {
|
||||
struct vk_viewport_state vp;
|
||||
struct vk_rasterization_state rs;
|
||||
/* See tu_render_pass_state::shared_viewport */
|
||||
bool share_scale;
|
||||
/* See tu_pipeline::fake_single_viewport */
|
||||
bool fake_single_viewport;
|
||||
};
|
||||
|
||||
/* It's a hardware restriction that the window offset (i.e. common_bin_offset)
|
||||
@@ -2609,15 +2613,14 @@ fdm_apply_viewports(struct tu_cmd_buffer *cmd, struct tu_cs *cs, void *data,
|
||||
* same across all views, we can pick any view. However the number
|
||||
* of viewports and number of views is not guaranteed the same, so we
|
||||
* need to pick the 0'th view which always exists to be safe.
|
||||
*
|
||||
* Conversly, if we're not using shared scaling then the rasterizer in
|
||||
* the original pipeline is using only the first viewport, so we need to
|
||||
* replicate it across all viewports.
|
||||
*/
|
||||
VkExtent2D frag_area = state->share_scale ? frag_areas[0] : frag_areas[i];
|
||||
VkRect2D bin = state->share_scale ? bins[0] : bins[i];
|
||||
/* Implement fake_single_viewport by replicating viewport 0 across all
|
||||
* views.
|
||||
*/
|
||||
VkViewport viewport =
|
||||
state->share_scale ? state->vp.viewports[i] : state->vp.viewports[0];
|
||||
state->fake_single_viewport ? state->vp.viewports[0] : state->vp.viewports[i];
|
||||
if (frag_area.width == 1 && frag_area.height == 1 &&
|
||||
common_bin_offset.x == bin.offset.x &&
|
||||
common_bin_offset.y == bin.offset.y) {
|
||||
@@ -2653,6 +2656,7 @@ tu6_emit_viewport_fdm(struct tu_cs *cs, struct tu_cmd_buffer *cmd,
|
||||
.vp = *vp,
|
||||
.rs = *rs,
|
||||
.share_scale = !cmd->state.per_view_viewport,
|
||||
.fake_single_viewport = cmd->state.fake_single_viewport,
|
||||
};
|
||||
if (!state.share_scale)
|
||||
state.vp.viewport_count = num_views;
|
||||
@@ -2722,7 +2726,7 @@ fdm_apply_scissors(struct tu_cmd_buffer *cmd, struct tu_cs *cs, void *data,
|
||||
VkExtent2D frag_area = state->share_scale ? frag_areas[0] : frag_areas[i];
|
||||
VkRect2D bin = state->share_scale ? bins[0] : bins[i];
|
||||
VkRect2D scissor =
|
||||
state->share_scale ? state->vp.scissors[i] : state->vp.scissors[0];
|
||||
state->fake_single_viewport ? state->vp.scissors[0] : state->vp.scissors[i];
|
||||
|
||||
/* Transform the scissor following the viewport. It's unclear how this
|
||||
* is supposed to handle cases where the scissor isn't aligned to the
|
||||
@@ -2765,6 +2769,7 @@ tu6_emit_scissor_fdm(struct tu_cs *cs, struct tu_cmd_buffer *cmd,
|
||||
struct apply_viewport_state state = {
|
||||
.vp = *vp,
|
||||
.share_scale = !cmd->state.per_view_viewport,
|
||||
.fake_single_viewport = cmd->state.fake_single_viewport,
|
||||
};
|
||||
if (!state.share_scale)
|
||||
state.vp.scissor_count = num_views;
|
||||
|
||||
@@ -109,7 +109,18 @@ struct tu_program_state
|
||||
|
||||
unsigned dynamic_descriptor_offsets[MAX_SETS];
|
||||
|
||||
/* Whether the per-view-viewport feature should be enabled in HW. This
|
||||
* implicitly adds gl_ViewIndex to gl_ViewportIndex so that from a HW
|
||||
* point of view (but not necessarily the user's point of view!) there
|
||||
* is a viewport per view.
|
||||
*/
|
||||
bool per_view_viewport;
|
||||
/* If per_view_viewport is true and this is true, the app has provided
|
||||
* a single viewport and we need to fake it by duplicating the viewport
|
||||
* across views before transforming each viewport separately using FDM
|
||||
* state.
|
||||
*/
|
||||
bool fake_single_viewport;
|
||||
bool writes_shading_rate;
|
||||
bool reads_shading_rate;
|
||||
bool accesses_smask;
|
||||
|
||||
Reference in New Issue
Block a user