nvk: Support extended dynamic state for tessellation domain origin

The tessellation domain origin, type, prims and spacing are all pushed
together in SET_TESSELLATION_PARAMETERS. So to support domain origin as
dynamic we need to push all these together when the state is dynamically
changed or when a new tessellation shader is bound.
This is also needed for EXT_shader_object.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24872>
This commit is contained in:
George Ouzounoudis 2023-08-24 22:54:37 +03:00 committed by Faith Ekstrand
parent 1319cfb40d
commit 55c8f5e288
4 changed files with 44 additions and 32 deletions

View file

@ -930,6 +930,15 @@ nvk_cmd_bind_graphics_pipeline(struct nvk_cmd_buffer *cmd,
cmd->state.gfx.pipeline = pipeline;
vk_cmd_set_dynamic_graphics_state(&cmd->vk, &pipeline->dynamic);
/* When a pipeline with tess shaders is bound we need to re-upload the
* tessellation parameters at flush_ts_state, as the domain origin can be
* dynamic.
*/
if (nvk_shader_is_enabled(&pipeline->base.shaders[MESA_SHADER_TESS_EVAL])) {
BITSET_SET(cmd->vk.dynamic_graphics_state.dirty,
MESA_VK_DYNAMIC_TS_DOMAIN_ORIGIN);
}
struct nv_push *p = nvk_cmd_buffer_push(cmd, pipeline->push_dw_count);
nv_push_raw(p, pipeline->push_data, pipeline->push_dw_count);
}
@ -999,11 +1008,34 @@ nvk_flush_ts_state(struct nvk_cmd_buffer *cmd)
{
const struct vk_dynamic_graphics_state *dyn =
&cmd->vk.dynamic_graphics_state;
struct nv_push *p = nvk_cmd_buffer_push(cmd, 4);
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_TS_PATCH_CONTROL_POINTS)) {
struct nv_push *p = nvk_cmd_buffer_push(cmd, 2);
P_IMMD(p, NV9097, SET_PATCH, dyn->ts.patch_control_points);
}
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_TS_DOMAIN_ORIGIN)) {
const struct nvk_graphics_pipeline *pipeline= cmd->state.gfx.pipeline;
const struct nvk_shader *shader =
&pipeline->base.shaders[MESA_SHADER_TESS_EVAL];
if (nvk_shader_is_enabled(shader)) {
enum nak_ts_prims prims = shader->info.ts.prims;
/* When the origin is lower-left, we have to flip the winding order */
if (dyn->ts.domain_origin == VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT) {
if (prims == NAK_TS_PRIMS_TRIANGLES_CW)
prims = NAK_TS_PRIMS_TRIANGLES_CCW;
else if (prims == NAK_TS_PRIMS_TRIANGLES_CCW)
prims = NAK_TS_PRIMS_TRIANGLES_CW;
}
P_MTHD(p, NV9097, SET_TESSELLATION_PARAMETERS);
P_NV9097_SET_TESSELLATION_PARAMETERS(p, {
shader->info.ts.domain,
shader->info.ts.spacing,
prims
});
}
}
}
static void

View file

@ -113,27 +113,6 @@ static const uint32_t mesa_to_nv9097_shader_type[] = {
[MESA_SHADER_FRAGMENT] = NV9097_SET_PIPELINE_SHADER_TYPE_PIXEL,
};
static void
emit_tessellation_paramaters(struct nv_push *p,
const struct nvk_shader *shader,
const struct vk_tessellation_state *state)
{
enum nak_ts_prims prims = shader->info.ts.prims;
/* When the origin is lower-left, we have to flip the winding order */
if (state->domain_origin == VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT) {
if (prims == NAK_TS_PRIMS_TRIANGLES_CW)
prims = NAK_TS_PRIMS_TRIANGLES_CCW;
else if (prims == NAK_TS_PRIMS_TRIANGLES_CCW)
prims = NAK_TS_PRIMS_TRIANGLES_CW;
}
P_MTHD(p, NV9097, SET_TESSELLATION_PARAMETERS);
P_NV9097_SET_TESSELLATION_PARAMETERS(p, {
shader->info.ts.domain,
shader->info.ts.spacing,
prims
});
}
static void
merge_tess_info(struct shader_info *tes_info, struct shader_info *tcs_info)
{
@ -267,11 +246,11 @@ nvk_graphics_pipeline_create(struct nvk_device *dev,
uint32_t idx = mesa_to_nv9097_shader_type[stage];
P_IMMD(p, NV9097, SET_PIPELINE_SHADER(idx), {
.enable = shader->upload_size > 0,
.enable = nvk_shader_is_enabled(shader),
.type = mesa_to_nv9097_shader_type[stage],
});
if (shader->upload_size == 0)
if (!nvk_shader_is_enabled(shader))
continue;
if (stage != MESA_SHADER_FRAGMENT)
@ -294,6 +273,8 @@ nvk_graphics_pipeline_create(struct nvk_device *dev,
switch (stage) {
case MESA_SHADER_VERTEX:
case MESA_SHADER_GEOMETRY:
case MESA_SHADER_TESS_CTRL:
case MESA_SHADER_TESS_EVAL:
break;
case MESA_SHADER_FRAGMENT:
@ -329,13 +310,6 @@ nvk_graphics_pipeline_create(struct nvk_device *dev,
shader->info.fs.uses_sample_shading;
break;
case MESA_SHADER_TESS_CTRL:
break;
case MESA_SHADER_TESS_EVAL:
emit_tessellation_paramaters(p, shader, state.ts);
break;
default:
unreachable("Unsupported shader stage");
}

View file

@ -389,7 +389,7 @@ nvk_get_device_features(const struct nv_device_info *info,
.extendedDynamicState2PatchControlPoints = true,
/* VK_EXT_extended_dynamic_state3 */
.extendedDynamicState3TessellationDomainOrigin = false,
.extendedDynamicState3TessellationDomainOrigin = true,
.extendedDynamicState3DepthClampEnable = true,
.extendedDynamicState3PolygonMode = true,
.extendedDynamicState3RasterizationSamples = false,

View file

@ -64,6 +64,12 @@ nvk_shader_address(const struct nvk_shader *shader)
return shader->upload_addr + shader->upload_padding;
}
static inline bool
nvk_shader_is_enabled(const struct nvk_shader *shader)
{
return shader->upload_size > 0;
}
VkShaderStageFlags nvk_nak_stages(const struct nv_device_info *info);
uint64_t