VkFormat color_attachment_formats[MAX_RTS];
VkFormat depth_attachment_format;
uint32_t render_components;
+ uint32_t multiview_mask;
};
static bool
ir3_find_sysval_regid(gs, SYSTEM_VALUE_GS_HEADER_IR3) :
regid(63, 0);
+ /* Note: we currently don't support multiview with tess or GS. If we did,
+ * and the HW actually works, then we'd have to somehow share this across
+ * stages. Note that the blob doesn't support this either.
+ */
+ const uint32_t viewid_regid =
+ ir3_find_sysval_regid(vs, SYSTEM_VALUE_VIEW_INDEX);
+
tu_cs_emit_pkt4(cs, REG_A6XX_VFD_CONTROL_1, 6);
tu_cs_emit(cs, A6XX_VFD_CONTROL_1_REGID4VTX(vertexid_regid) |
A6XX_VFD_CONTROL_1_REGID4INST(instanceid_regid) |
A6XX_VFD_CONTROL_1_REGID4PRIMID(primitiveid_regid) |
- 0xfc000000);
+ A6XX_VFD_CONTROL_1_REGID4VIEWID(viewid_regid));
tu_cs_emit(cs, A6XX_VFD_CONTROL_2_REGID_HSPATCHID(hs_patch_regid) |
A6XX_VFD_CONTROL_2_REGID_INVOCATIONID(hs_invocation_regid));
tu_cs_emit(cs, A6XX_VFD_CONTROL_3_REGID_DSPATCHID(ds_patch_regid) |
tu_cs_emit(cs, A6XX_VPC_CNTL_0_NUMNONPOSVAR(fs ? fs->total_in : 0) |
COND(fs && fs->total_in, A6XX_VPC_CNTL_0_VARYING) |
A6XX_VPC_CNTL_0_PRIMIDLOC(linkage.primid_loc) |
- A6XX_VPC_CNTL_0_VIEWIDLOC(0xff));
+ A6XX_VPC_CNTL_0_VIEWIDLOC(linkage.viewid_loc));
if (hs) {
shader_info *hs_info = &hs->shader->nir->info;
tu_cs_emit_pkt4(cs, REG_A6XX_PC_PRIMITIVE_CNTL_6, 1);
tu_cs_emit(cs, A6XX_PC_PRIMITIVE_CNTL_6_STRIDE_IN_VPC(vec4_size));
- tu_cs_emit_pkt4(cs, REG_A6XX_PC_MULTIVIEW_CNTL, 1);
- tu_cs_emit(cs, 0);
-
tu_cs_emit_pkt4(cs, REG_A6XX_SP_GS_PRIM_SIZE, 1);
tu_cs_emit(cs, vs->output_size);
}
tu6_emit_xs_config(cs, stage, xs, builder->shader_iova[stage]);
}
+ if (!binning_pass) {
+ uint32_t multiview_views = util_logbase2(builder->multiview_mask) + 1;
+ uint32_t multiview_cntl = builder->multiview_mask ?
+ A6XX_PC_MULTIVIEW_CNTL_ENABLE |
+ A6XX_PC_MULTIVIEW_CNTL_VIEWS(multiview_views) |
+ A6XX_PC_MULTIVIEW_CNTL_DISABLEMULTIPOS /* TODO multi-pos output */
+ : 0;
+
+ /* Copy what the blob does here. This will emit an extra 0x3f
+ * CP_EVENT_WRITE when multiview is disabled. I'm not exactly sure what
+ * this is working around yet.
+ */
+ tu_cs_emit_pkt7(cs, CP_REG_WRITE, 3);
+ tu_cs_emit(cs, CP_REG_WRITE_0_TRACKER(UNK_EVENT_WRITE));
+ tu_cs_emit(cs, REG_A6XX_PC_MULTIVIEW_CNTL);
+ tu_cs_emit(cs, multiview_cntl);
+
+ tu_cs_emit_pkt4(cs, REG_A6XX_VFD_MULTIVIEW_CNTL, 1);
+ tu_cs_emit(cs, multiview_cntl);
+
+ if (multiview_cntl &&
+ builder->device->physical_device->supports_multiview_mask) {
+ tu_cs_emit_pkt4(cs, REG_A6XX_PC_MULTIVIEW_MASK, 1);
+ tu_cs_emit(cs, builder->multiview_mask);
+ }
+ }
+
tu_cs_emit_pkt4(cs, REG_A6XX_SP_HS_UNKNOWN_A831, 1);
tu_cs_emit(cs, 0);
static uint32_t
tu6_gras_su_cntl(const VkPipelineRasterizationStateCreateInfo *rast_info,
- VkSampleCountFlagBits samples)
+ VkSampleCountFlagBits samples,
+ bool multiview)
{
uint32_t gras_su_cntl = 0;
if (samples > VK_SAMPLE_COUNT_1_BIT)
gras_su_cntl |= A6XX_GRAS_SU_CNTL_MSAA_ENABLE;
+ if (multiview) {
+ gras_su_cntl |=
+ A6XX_GRAS_SU_CNTL_UNK17 |
+ A6XX_GRAS_SU_CNTL_MULTIVIEW_ENABLE;
+ }
+
return gras_su_cntl;
}
continue;
struct tu_shader *shader =
- tu_shader_create(builder->device, stage, stage_info, builder->layout,
- builder->alloc);
+ tu_shader_create(builder->device, stage, stage_info, builder->multiview_mask,
+ builder->layout, builder->alloc);
if (!shader)
return VK_ERROR_OUT_OF_HOST_MEMORY;
A6XX_GRAS_SU_POINT_SIZE(1.0f));
pipeline->gras_su_cntl =
- tu6_gras_su_cntl(rast_info, builder->samples);
+ tu6_gras_su_cntl(rast_info, builder->samples, builder->multiview_mask != 0);
if (tu_pipeline_static_state(pipeline, &cs, VK_DYNAMIC_STATE_LINE_WIDTH, 2)) {
pipeline->gras_su_cntl |=
.layout = layout,
};
+ const struct tu_render_pass *pass =
+ tu_render_pass_from_handle(create_info->renderPass);
+ const struct tu_subpass *subpass =
+ &pass->subpasses[create_info->subpass];
+
+ builder->multiview_mask = subpass->multiview_mask;
+
builder->rasterizer_discard =
create_info->pRasterizationState->rasterizerDiscardEnable;
} else {
builder->samples = create_info->pMultisampleState->rasterizationSamples;
- const struct tu_render_pass *pass =
- tu_render_pass_from_handle(create_info->renderPass);
- const struct tu_subpass *subpass =
- &pass->subpasses[create_info->subpass];
-
const uint32_t a = subpass->depth_stencil_attachment.attachment;
builder->depth_attachment_format = (a != VK_ATTACHMENT_UNUSED) ?
pass->attachments[a].format : VK_FORMAT_UNDEFINED;
struct ir3_shader_key key = {};
struct tu_shader *shader =
- tu_shader_create(dev, MESA_SHADER_COMPUTE, stage_info, layout, pAllocator);
+ tu_shader_create(dev, MESA_SHADER_COMPUTE, stage_info, 0, layout, pAllocator);
if (!shader) {
result = VK_ERROR_OUT_OF_HOST_MEMORY;
goto fail;
/* Accessed via stg/ldg (not used with Vulkan?) */
.global_addr_format = nir_address_format_64bit_global,
+ /* ViewID is a sysval in geometry stages and an input in the FS */
+ .view_index_is_input = stage == MESA_SHADER_FRAGMENT,
.caps = {
.transform_feedback = true,
.tessellation = true,
tu_shader_create(struct tu_device *dev,
gl_shader_stage stage,
const VkPipelineShaderStageCreateInfo *stage_info,
+ unsigned multiview_mask,
struct tu_pipeline_layout *layout,
const VkAllocationCallbacks *alloc)
{
&(nir_input_attachment_options) {
.use_fragcoord_sysval = true,
.use_layer_id_sysval = false,
+ /* When using multiview rendering, we must use
+ * gl_ViewIndex as the layer id to pass to the texture
+ * sampling function. gl_Layer doesn't work when
+ * multiview is enabled.
+ */
+ .use_view_id_for_layer = multiview_mask != 0,
});
}
+ if (stage == MESA_SHADER_VERTEX && multiview_mask) {
+ NIR_PASS_V(nir, tu_nir_lower_multiview, multiview_mask, dev);
+ }
+
NIR_PASS_V(nir, nir_lower_explicit_io,
nir_var_mem_ubo | nir_var_mem_ssbo,
nir_address_format_vec2_index_32bit_offset);