mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-06-21 08:08:24 +02:00
nvk: Merge tese/tesc state in the MME
Recent versions of vulkan have relaxed the requirements for the way
applications specify tess parameters with shader objects. Track the
state separately for tess eval and tess control so we can merge the
states in the MME.
See either:
* 60a4ad187c
* https://gitlab.khronos.org/vulkan/vulkan/-/merge_requests/7694
Fixes dEQP-VK.shader_object.tessellation.hlsl.* on VK CTS 1.4.5
Reviewed-by: Mary Guillemard <mary@mary.zone>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39571>
This commit is contained in:
parent
ad6a5a88d1
commit
99bc2d9775
6 changed files with 127 additions and 17 deletions
|
|
@ -298,6 +298,20 @@ impl ShaderBin {
|
|||
},
|
||||
}
|
||||
}
|
||||
ShaderStageInfo::TessellationInit(ts_info) => {
|
||||
nak_shader_info__bindgen_ty_1 {
|
||||
ts: nak_shader_info__bindgen_ty_1__bindgen_ty_3 {
|
||||
domain: 0,
|
||||
spacing: ts_info
|
||||
.common
|
||||
.spacing
|
||||
.map_or(0, |x| x as u8),
|
||||
ccw: ts_info.common.ccw,
|
||||
point_mode: ts_info.common.point_mode,
|
||||
_pad: Default::default(),
|
||||
},
|
||||
}
|
||||
}
|
||||
ShaderStageInfo::Tessellation(ts_info) => {
|
||||
nak_shader_info__bindgen_ty_1 {
|
||||
ts: nak_shader_info__bindgen_ty_1__bindgen_ty_3 {
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ fn init_info_from_nir(nak: &nak_compiler, nir: &nir_shader) -> ShaderInfo {
|
|||
ShaderStageInfo::TessellationInit(TessellationInitShaderInfo {
|
||||
per_patch_attribute_count: 6,
|
||||
threads_per_patch: info_tess.tcs_vertices_out,
|
||||
common: tess_common(info_tess),
|
||||
})
|
||||
}
|
||||
MESA_SHADER_TESS_EVAL => {
|
||||
|
|
|
|||
|
|
@ -9125,12 +9125,6 @@ impl Default for GeometryShaderInfo {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TessellationInitShaderInfo {
|
||||
pub per_patch_attribute_count: u8,
|
||||
pub threads_per_patch: u8,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum TessellationDomain {
|
||||
|
|
@ -9154,6 +9148,13 @@ pub struct TesselationCommonShaderInfo {
|
|||
pub point_mode: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TessellationInitShaderInfo {
|
||||
pub per_patch_attribute_count: u8,
|
||||
pub threads_per_patch: u8,
|
||||
pub common: TesselationCommonShaderInfo,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TessellationShaderInfo {
|
||||
pub domain: TessellationDomain,
|
||||
|
|
|
|||
|
|
@ -1615,6 +1615,8 @@ nvk_cmd_bind_graphics_shader(struct nvk_cmd_buffer *cmd,
|
|||
NVDEF(NV9097, SET_TESSELLATION_PARAMETERS, SPACING, spacing) | \
|
||||
flags
|
||||
|
||||
#define NVK_MME_FULL_TESS_STATE(ctrl, eval) (ctrl << 8) | (eval)
|
||||
|
||||
#define POINT_MODE_BIT 2
|
||||
#define CCW_BIT 3
|
||||
#define LOWER_LEFT_BIT 6
|
||||
|
|
@ -1624,7 +1626,8 @@ nvk_cmd_bind_graphics_shader(struct nvk_cmd_buffer *cmd,
|
|||
#define LOWER_LEFT BITFIELD_BIT(LOWER_LEFT_BIT)
|
||||
|
||||
uint32_t
|
||||
nvk_mme_tess_params(enum nak_ts_domain domain,
|
||||
nvk_mme_tess_params(mesa_shader_stage stage,
|
||||
enum nak_ts_domain domain,
|
||||
enum nak_ts_spacing spacing,
|
||||
bool ccw, bool point_mode)
|
||||
{
|
||||
|
|
@ -1637,10 +1640,20 @@ nvk_mme_tess_params(enum nak_ts_domain domain,
|
|||
params |= CCW;
|
||||
if (point_mode)
|
||||
params |= POINT_MODE;
|
||||
return nvk_mme_val_mask(params,
|
||||
DRF_SMASK(NV9097_SET_TESSELLATION_PARAMETERS_DOMAIN_TYPE) |
|
||||
DRF_SMASK(NV9097_SET_TESSELLATION_PARAMETERS_SPACING) |
|
||||
POINT_MODE | CCW);
|
||||
|
||||
uint16_t mask = DRF_SMASK(NV9097_SET_TESSELLATION_PARAMETERS_DOMAIN_TYPE) |
|
||||
DRF_SMASK(NV9097_SET_TESSELLATION_PARAMETERS_SPACING) |
|
||||
POINT_MODE | CCW;
|
||||
|
||||
if (stage == MESA_SHADER_TESS_CTRL) {
|
||||
assert(domain == 0);
|
||||
params <<= 8;
|
||||
mask <<= 8;
|
||||
} else {
|
||||
assert(stage == MESA_SHADER_TESS_EVAL);
|
||||
}
|
||||
|
||||
return nvk_mme_val_mask(params, mask);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
|
|
@ -1660,6 +1673,15 @@ nvk_mme_set_tess_params(struct mme_builder *b)
|
|||
mme_if(b, ine, params, old_params) {
|
||||
nvk_mme_store_scratch(b, TESS_PARAMS, params);
|
||||
|
||||
/* Merge tese and tesc state. The state space has been designed so we can
|
||||
* just OR then together - unspecified inputs are zero and where they're
|
||||
* both specifed we're guaranteed that they match by draw time.
|
||||
*/
|
||||
struct mme_value tesc = mme_merge(b, mme_zero(), params, 0, 8, 8);
|
||||
mme_or_to(b, params, params, tesc);
|
||||
mme_free_reg(b, tesc);
|
||||
|
||||
/* Compute primitives value */
|
||||
#define PRIMS(x) \
|
||||
mme_imm(NV9097_SET_TESSELLATION_PARAMETERS_OUTPUT_PRIMITIVES_##x)
|
||||
|
||||
|
|
@ -1708,8 +1730,21 @@ nvk_mme_set_tess_params(struct mme_builder *b)
|
|||
DRF_BITS(NV9097_SET_TESSELLATION_PARAMETERS_OUTPUT_PRIMITIVES), 0);
|
||||
mme_free_reg(b, prims);
|
||||
|
||||
mme_mthd(b, NV9097_SET_TESSELLATION_PARAMETERS);
|
||||
mme_emit(b, params);
|
||||
/* If the current state is never used in a draw, we can end up with
|
||||
* temporary invalid values while binding different shaders. Check
|
||||
* for this so we can avoid setting a state that will cause
|
||||
* context loss. This happens when `spacing == 3`. The same cannot
|
||||
* happen with `domain` because we never set it for TESS_CTRL.
|
||||
*/
|
||||
struct mme_value spacing =
|
||||
mme_merge(b, mme_zero(), params, 0,
|
||||
DRF_BITS(NV9097_SET_TESSELLATION_PARAMETERS_SPACING),
|
||||
DRF_LO(NV9097_SET_TESSELLATION_PARAMETERS_SPACING));
|
||||
|
||||
mme_if(b, ine, spacing, mme_imm(0x3)) {
|
||||
mme_mthd(b, NV9097_SET_TESSELLATION_PARAMETERS);
|
||||
mme_emit(b, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1824,6 +1859,62 @@ const struct nvk_mme_test_case nvk_mme_set_tess_params_tests[] = {{
|
|||
},
|
||||
{ }
|
||||
},
|
||||
}, {
|
||||
/* Test tese/tesc merge */
|
||||
.init = (struct nvk_mme_mthd_data[]) {
|
||||
{
|
||||
NVK_SET_MME_SCRATCH(TESS_PARAMS),
|
||||
NVK_MME_TESS_STATE(TRIANGLE, INTEGER, 0)
|
||||
},
|
||||
{ }
|
||||
},
|
||||
.params = (uint32_t[]) {
|
||||
NVK_MME_VAL_MASK(NVK_MME_FULL_TESS_STATE(
|
||||
NVDEF(NV9097, SET_TESSELLATION_PARAMETERS, DOMAIN_TYPE, TRIANGLE),
|
||||
NVDEF(NV9097, SET_TESSELLATION_PARAMETERS, SPACING, FRACTIONAL_ODD)
|
||||
), 0xffff)
|
||||
},
|
||||
.expected = (struct nvk_mme_mthd_data[]) {
|
||||
{
|
||||
NVK_SET_MME_SCRATCH(TESS_PARAMS),
|
||||
NVK_MME_FULL_TESS_STATE(
|
||||
NVDEF(NV9097, SET_TESSELLATION_PARAMETERS, DOMAIN_TYPE, TRIANGLE),
|
||||
NVDEF(NV9097, SET_TESSELLATION_PARAMETERS, SPACING, FRACTIONAL_ODD)
|
||||
)
|
||||
},
|
||||
{
|
||||
NV9097_SET_TESSELLATION_PARAMETERS,
|
||||
NVK_MME_TESS_PARAMS(TRIANGLE, FRACTIONAL_ODD, TRIANGLES_CW)
|
||||
},
|
||||
{ }
|
||||
},
|
||||
}, {
|
||||
/* Test skipping invalid spacing */
|
||||
.init = (struct nvk_mme_mthd_data[]) {
|
||||
{
|
||||
NVK_SET_MME_SCRATCH(TESS_PARAMS),
|
||||
NVK_MME_TESS_STATE(TRIANGLE, INTEGER, 0)
|
||||
},
|
||||
{ }
|
||||
},
|
||||
.params = (uint32_t[]) {
|
||||
NVK_MME_VAL_MASK(NVK_MME_FULL_TESS_STATE(
|
||||
NVDEF(NV9097, SET_TESSELLATION_PARAMETERS, DOMAIN_TYPE, TRIANGLE) |
|
||||
NVDEF(NV9097, SET_TESSELLATION_PARAMETERS, SPACING, FRACTIONAL_EVEN),
|
||||
NVDEF(NV9097, SET_TESSELLATION_PARAMETERS, SPACING, FRACTIONAL_ODD)
|
||||
), 0xffff)
|
||||
},
|
||||
.expected = (struct nvk_mme_mthd_data[]) {
|
||||
{
|
||||
NVK_SET_MME_SCRATCH(TESS_PARAMS),
|
||||
NVK_MME_FULL_TESS_STATE(
|
||||
NVDEF(NV9097, SET_TESSELLATION_PARAMETERS, DOMAIN_TYPE, TRIANGLE) |
|
||||
NVDEF(NV9097, SET_TESSELLATION_PARAMETERS, SPACING, FRACTIONAL_EVEN),
|
||||
NVDEF(NV9097, SET_TESSELLATION_PARAMETERS, SPACING, FRACTIONAL_ODD)
|
||||
)
|
||||
},
|
||||
{ }
|
||||
},
|
||||
}, {}};
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -249,7 +249,8 @@ void nvk_mme_set_conservative_raster_state(struct mme_builder *b);
|
|||
void nvk_mme_set_viewport_min_max_z(struct mme_builder *b);
|
||||
void nvk_mme_set_z_clamp(struct mme_builder *b);
|
||||
|
||||
uint32_t nvk_mme_tess_params(enum nak_ts_domain domain,
|
||||
uint32_t nvk_mme_tess_params(mesa_shader_stage stage,
|
||||
enum nak_ts_domain domain,
|
||||
enum nak_ts_spacing spacing,
|
||||
bool ccw, bool point_mode);
|
||||
uint32_t nvk_mme_anti_alias_min_sample_shading(float mss);
|
||||
|
|
|
|||
|
|
@ -631,7 +631,7 @@ nvk_max_shader_push_dw(const struct nvk_physical_device *pdev,
|
|||
|
||||
uint16_t max_dw_count = 8;
|
||||
|
||||
if (stage == MESA_SHADER_TESS_EVAL)
|
||||
if (stage == MESA_SHADER_TESS_CTRL || stage == MESA_SHADER_TESS_EVAL)
|
||||
max_dw_count += 2;
|
||||
|
||||
if (stage == MESA_SHADER_FRAGMENT)
|
||||
|
|
@ -686,10 +686,12 @@ nvk_shader_fill_push(struct nvk_device *dev,
|
|||
P_NVC397_SET_PIPELINE_BINDING(p, idx,
|
||||
nvk_pipeline_bind_group(shader->info.stage));
|
||||
|
||||
if (shader->info.stage == MESA_SHADER_TESS_EVAL) {
|
||||
if (shader->info.stage == MESA_SHADER_TESS_CTRL ||
|
||||
shader->info.stage == MESA_SHADER_TESS_EVAL) {
|
||||
max_dw_count += 2;
|
||||
P_1INC(p, NVB197, CALL_MME_MACRO(NVK_MME_SET_TESS_PARAMS));
|
||||
P_INLINE_DATA(p, nvk_mme_tess_params(shader->info.ts.domain,
|
||||
P_INLINE_DATA(p, nvk_mme_tess_params(shader->info.stage,
|
||||
shader->info.ts.domain,
|
||||
shader->info.ts.spacing,
|
||||
shader->info.ts.ccw,
|
||||
shader->info.ts.point_mode));
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue