vkd3d: Normalize depth-stencil layouts if only one aspect is used.

Avoid using the separate layouts if we're only using formats with one
aspects. This makes it more likely to match layouts with common layout,
and we can avoid awkward transition barriers.

Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
Hans-Kristian Arntzen 2021-06-10 12:25:31 +02:00
parent 014a3c0b94
commit 02398c4eef
3 changed files with 73 additions and 33 deletions

View File

@ -4204,7 +4204,6 @@ static bool d3d12_command_list_update_graphics_pipeline(struct d3d12_command_lis
uint32_t new_active_flags;
VkPipeline vk_pipeline;
uint32_t variant_flags;
VkFormat dsv_format;
if (list->current_pipeline != VK_NULL_HANDLE)
return true;
@ -4215,17 +4214,15 @@ static bool d3d12_command_list_update_graphics_pipeline(struct d3d12_command_lis
return false;
}
dsv_format = list->dsv.format ? list->dsv.format->vk_format : VK_FORMAT_UNDEFINED;
variant_flags = d3d12_command_list_variant_flags(list);
/* Try to grab the pipeline we compiled ahead of time. If we cannot do so, fall back. */
if (!(vk_pipeline = d3d12_pipeline_state_get_pipeline(list->state,
&list->dynamic_state, dsv_format, &vk_render_pass, &new_active_flags,
&list->dynamic_state, list->dsv.format, &vk_render_pass, &new_active_flags,
variant_flags)))
{
if (!(vk_pipeline = d3d12_pipeline_state_get_or_create_pipeline(list->state,
&list->dynamic_state, dsv_format,
&list->dynamic_state, list->dsv.format,
&vk_render_pass, &new_active_flags, variant_flags)))
return false;
}

View File

@ -2628,35 +2628,73 @@ STATIC_ASSERT(sizeof(struct vkd3d_shader_transform_feedback_element) == sizeof(D
static HRESULT d3d12_graphics_pipeline_state_create_render_pass(
struct d3d12_graphics_pipeline_state *graphics, struct d3d12_device *device,
VkFormat dynamic_dsv_format, VkRenderPass *vk_render_pass, VkImageLayout *dsv_layout,
const struct vkd3d_format *dynamic_dsv_format,
VkRenderPass *vk_render_pass, VkImageLayout *dsv_layout,
uint32_t variant_flags)
{
VkFormat dsv_format = VK_FORMAT_UNDEFINED;
struct vkd3d_render_pass_key key;
VkFormat dsv_format;
VkImageAspectFlags aspects = 0;
unsigned int i;
memcpy(key.vk_formats, graphics->rtv_formats, sizeof(graphics->rtv_formats));
key.attachment_count = graphics->rt_count;
key.flags = 0;
if (!(dsv_format = graphics->dsv_format) && (graphics->null_attachment_mask & dsv_attachment_mask(graphics)))
dsv_format = dynamic_dsv_format;
if (graphics->dsv_format)
{
dsv_format = graphics->dsv_format->vk_format;
aspects = graphics->dsv_format->vk_aspect_mask;
}
else if (dynamic_dsv_format && (graphics->null_attachment_mask & dsv_attachment_mask(graphics)))
{
dsv_format = dynamic_dsv_format->vk_format;
aspects = dynamic_dsv_format->vk_aspect_mask;
}
if (dsv_format)
{
assert(graphics->ds_desc.front.writeMask == graphics->ds_desc.back.writeMask);
if (graphics->ds_desc.depthTestEnable || graphics->ds_desc.depthBoundsTestEnable)
if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
{
key.flags |= VKD3D_RENDER_PASS_KEY_DEPTH_ENABLE;
if (graphics->ds_desc.depthWriteEnable)
key.flags |= VKD3D_RENDER_PASS_KEY_DEPTH_WRITE;
if (graphics->ds_desc.depthTestEnable || graphics->ds_desc.depthBoundsTestEnable)
{
key.flags |= VKD3D_RENDER_PASS_KEY_DEPTH_ENABLE;
if (graphics->ds_desc.depthWriteEnable)
key.flags |= VKD3D_RENDER_PASS_KEY_DEPTH_WRITE;
}
}
if (graphics->ds_desc.stencilTestEnable)
if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
{
key.flags |= VKD3D_RENDER_PASS_KEY_STENCIL_ENABLE;
if (graphics->ds_desc.front.writeMask != 0)
key.flags |= VKD3D_RENDER_PASS_KEY_STENCIL_WRITE;
if (graphics->ds_desc.stencilTestEnable)
{
key.flags |= VKD3D_RENDER_PASS_KEY_STENCIL_ENABLE;
if (graphics->ds_desc.front.writeMask != 0)
key.flags |= VKD3D_RENDER_PASS_KEY_STENCIL_WRITE;
}
}
/* If our format does not have both aspects, use same state across the aspects so that we are more likely
* to match one of our common formats, DS_READ_ONLY or DS_OPTIMAL.
* Otherwise, we are very likely to hit the DS write / stencil read layout. */
if (!(aspects & VK_IMAGE_ASPECT_DEPTH_BIT))
{
key.flags |= (key.flags & VKD3D_RENDER_PASS_KEY_STENCIL_ENABLE) ?
VKD3D_RENDER_PASS_KEY_DEPTH_ENABLE : 0;
key.flags |= (key.flags & VKD3D_RENDER_PASS_KEY_STENCIL_WRITE) ?
VKD3D_RENDER_PASS_KEY_DEPTH_WRITE : 0;
}
if (!(aspects & VK_IMAGE_ASPECT_STENCIL_BIT))
{
key.flags |= (key.flags & VKD3D_RENDER_PASS_KEY_DEPTH_ENABLE) ?
VKD3D_RENDER_PASS_KEY_STENCIL_ENABLE : 0;
key.flags |= (key.flags & VKD3D_RENDER_PASS_KEY_DEPTH_WRITE) ?
VKD3D_RENDER_PASS_KEY_STENCIL_WRITE : 0;
}
key.vk_formats[key.attachment_count++] = dsv_format;
}
@ -2941,19 +2979,18 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
graphics->ds_desc.depthTestEnable = VK_FALSE;
}
graphics->dsv_format = VK_FORMAT_UNDEFINED;
graphics->dsv_format = NULL;
if (graphics->ds_desc.depthTestEnable || graphics->ds_desc.stencilTestEnable || graphics->ds_desc.depthBoundsTestEnable)
{
if (desc->dsv_format == DXGI_FORMAT_UNKNOWN)
{
WARN("DSV format is DXGI_FORMAT_UNKNOWN.\n");
graphics->dsv_format = VK_FORMAT_UNDEFINED;
graphics->null_attachment_mask |= dsv_attachment_mask(graphics);
}
else if ((format = vkd3d_get_format(device, desc->dsv_format, true)))
{
if (format->vk_aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
graphics->dsv_format = format->vk_format;
graphics->dsv_format = format;
else
FIXME("Format %#x is not depth/stencil format.\n", format->dxgi_format);
}
@ -3356,7 +3393,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
continue;
if (FAILED(hr = d3d12_graphics_pipeline_state_create_render_pass(graphics,
device, 0, &graphics->render_pass[i], &graphics->dsv_layout, i)))
device, NULL, &graphics->render_pass[i], &graphics->dsv_layout, i)))
goto fail;
}
}
@ -3635,7 +3672,7 @@ static bool d3d12_pipeline_state_put_pipeline_to_cache(struct d3d12_pipeline_sta
}
VkPipeline d3d12_pipeline_state_create_pipeline_variant(struct d3d12_pipeline_state *state,
const struct vkd3d_pipeline_key *key, VkFormat dsv_format, VkPipelineCache vk_cache,
const struct vkd3d_pipeline_key *key, const struct vkd3d_format *dsv_format, VkPipelineCache vk_cache,
VkRenderPass *vk_render_pass, uint32_t *dynamic_state_flags, uint32_t variant_flags)
{
VkVertexInputBindingDescription bindings[D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
@ -3731,7 +3768,10 @@ VkPipeline d3d12_pipeline_state_create_pipeline_variant(struct d3d12_pipeline_st
/* A workaround for SottR, which creates pipelines with DSV_UNKNOWN, but still insists on using a depth buffer.
* If we notice that the base pipeline's DSV format does not match the dynamic DSV format, we fall-back to create a new render pass. */
if (graphics->dsv_format != dsv_format && (graphics->null_attachment_mask & dsv_attachment_mask(graphics)))
TRACE("Compiling %p with fallback DSV format %#x.\n", state, dsv_format);
{
TRACE("Compiling %p with fallback DSV format %#x.\n", state,
dsv_format ? dsv_format->vk_format : VK_FORMAT_UNDEFINED);
}
if (FAILED(hr = d3d12_graphics_pipeline_state_create_render_pass(graphics, device, dsv_format,
&pipeline_desc.renderPass, &graphics->dsv_layout, variant_flags)))
@ -3777,7 +3817,7 @@ static bool d3d12_pipeline_state_can_use_dynamic_stride(struct d3d12_pipeline_st
}
VkPipeline d3d12_pipeline_state_get_pipeline(struct d3d12_pipeline_state *state,
const struct vkd3d_dynamic_state *dyn_state, VkFormat dsv_format,
const struct vkd3d_dynamic_state *dyn_state, const struct vkd3d_format *dsv_format,
VkRenderPass *vk_render_pass, uint32_t *dynamic_state_flags, uint32_t variant_flags)
{
struct d3d12_graphics_pipeline_state *graphics = &state->graphics;
@ -3786,12 +3826,14 @@ VkPipeline d3d12_pipeline_state_get_pipeline(struct d3d12_pipeline_state *state,
return VK_NULL_HANDLE;
/* Unknown DSV format workaround. */
if ((dsv_format != graphics->dsv_format) && (graphics->dsv_format != VK_FORMAT_UNDEFINED ||
state->graphics.ds_desc.depthTestEnable || state->graphics.ds_desc.stencilTestEnable ||
if ((dsv_format != graphics->dsv_format) && (graphics->dsv_format ||
state->graphics.ds_desc.depthTestEnable ||
state->graphics.ds_desc.stencilTestEnable ||
state->graphics.ds_desc.depthBoundsTestEnable))
{
TRACE("DSV format mismatch, expected %u, got %u, buggy application!\n",
graphics->dsv_format, dsv_format);
graphics->dsv_format ? graphics->dsv_format->vk_format : VK_FORMAT_UNDEFINED,
dsv_format ? dsv_format->vk_format : VK_FORMAT_UNDEFINED);
return VK_NULL_HANDLE;
}
@ -3820,7 +3862,8 @@ VkPipeline d3d12_pipeline_state_get_pipeline(struct d3d12_pipeline_state *state,
}
VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_state *state,
const struct vkd3d_dynamic_state *dyn_state, VkFormat dsv_format, VkRenderPass *vk_render_pass,
const struct vkd3d_dynamic_state *dyn_state, const struct vkd3d_format *dsv_format,
VkRenderPass *vk_render_pass,
uint32_t *dynamic_state_flags, uint32_t variant_flags)
{
const struct vkd3d_vk_device_procs *vk_procs = &state->device->vk_procs;
@ -3871,7 +3914,7 @@ VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_sta
}
}
pipeline_key.dsv_format = dsv_format;
pipeline_key.dsv_format = dsv_format ? dsv_format->vk_format : VK_FORMAT_UNDEFINED;
if ((vk_pipeline = d3d12_pipeline_state_find_compiled_pipeline(state, &pipeline_key, vk_render_pass,
dynamic_state_flags)))

View File

@ -1310,7 +1310,7 @@ struct d3d12_graphics_pipeline_state
unsigned int rt_count;
unsigned int null_attachment_mask;
unsigned int patch_vertex_count;
VkFormat dsv_format;
const struct vkd3d_format *dsv_format;
VkFormat rtv_formats[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT];
VkImageLayout dsv_layout;
VkRenderPass render_pass[VKD3D_GRAPHICS_PIPELINE_STATIC_VARIANT_COUNT];
@ -1437,13 +1437,13 @@ bool d3d12_pipeline_state_has_replaced_shaders(struct d3d12_pipeline_state *stat
HRESULT d3d12_pipeline_state_create(struct d3d12_device *device, VkPipelineBindPoint bind_point,
const struct d3d12_pipeline_state_desc *desc, struct d3d12_pipeline_state **state);
VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_state *state,
const struct vkd3d_dynamic_state *dyn_state, VkFormat dsv_format,
const struct vkd3d_dynamic_state *dyn_state, const struct vkd3d_format *dsv_format,
VkRenderPass *vk_render_pass, uint32_t *dynamic_state_flags, uint32_t variant_flags);
VkPipeline d3d12_pipeline_state_get_pipeline(struct d3d12_pipeline_state *state,
const struct vkd3d_dynamic_state *dyn_state, VkFormat dsv_format,
const struct vkd3d_dynamic_state *dyn_state, const struct vkd3d_format *dsv_format,
VkRenderPass *vk_render_pass, uint32_t *dynamic_state_flags, uint32_t variant_flags);
VkPipeline d3d12_pipeline_state_create_pipeline_variant(struct d3d12_pipeline_state *state,
const struct vkd3d_pipeline_key *key, VkFormat dsv_format, VkPipelineCache vk_cache,
const struct vkd3d_pipeline_key *key, const struct vkd3d_format *dsv_format, VkPipelineCache vk_cache,
VkRenderPass *vk_render_pass, uint32_t *dynamic_state_flags, uint32_t variant_flags);
struct d3d12_pipeline_state *unsafe_impl_from_ID3D12PipelineState(ID3D12PipelineState *iface);