vkd3d: Track depth-stencil image layouts over a command buffer.
Goal here is to avoid unnecessary image layout transitions when render passes toggle depth-stencil PSO states. Since we cannot know which states a resource is in, we have to be conservative, and assume that shader reads *could* happen. The best effort we can do is to detect when writes happen to a DSV resource. In this scenario, we can deduce that the aspect cannot be read, since DEPTH_WRITE | RESOURCE state is not allowed. To make the tracking somewhat sane, we only promote to OPTIMAL if an entire image's worth of subresources for a given aspect is transitioned. The common case for depth-stencil images is 1 mip / 1 layer anyways. Some other changes are required here: - Instead of common_layout for the depth image, we need to consult the command list, which might promote the layout to optimal. - We make use of render pass compatibility rules which state that we can change attachment reference layouts as well as initial/finalLayout. To make this change, a pipeline will fill in a vkd3d_render_pass_compat struct. - A command list has a dsv_plane_optimal_mask which keeps track of the plane aspects we have promoted to OPTIMAL, and we know cannot be read by shaders. The desired optimal mask is (existing optimal | PSO write). The initial existing optimal is inherited from the command list's tracker. - RTV/DSV/views no longer keep track of VkImageLayout. This is unnecessary since we always deduce image layout based on context. Overall, this shows a massive gain in HZD benchmark (RADV, 1440p ultimate, ~16% FPS on RX 6800). Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
parent
515ed7fbd1
commit
3915090c12
|
@ -56,6 +56,10 @@ static void d3d12_command_list_notify_decay_dsv_resource(struct d3d12_command_li
|
|||
static uint32_t d3d12_command_list_notify_dsv_writes(struct d3d12_command_list *list,
|
||||
struct d3d12_resource *resource, const struct vkd3d_view *view,
|
||||
uint32_t plane_write_mask);
|
||||
static void d3d12_command_list_notify_dsv_discard(struct d3d12_command_list *list,
|
||||
struct d3d12_resource *resource,
|
||||
uint32_t first_subresource, uint32_t subresource_count,
|
||||
uint32_t resource_subresource_count);
|
||||
static uint32_t d3d12_command_list_get_depth_stencil_resource_layout(const struct d3d12_command_list *list,
|
||||
const struct d3d12_resource *resource, uint32_t *plane_optimal_mask);
|
||||
static void d3d12_command_list_decay_optimal_dsv_resource(struct d3d12_command_list *list,
|
||||
|
@ -2246,6 +2250,36 @@ static uint32_t d3d12_command_list_notify_dsv_writes(struct d3d12_command_list *
|
|||
}
|
||||
}
|
||||
|
||||
static void d3d12_command_list_notify_dsv_discard(struct d3d12_command_list *list,
|
||||
struct d3d12_resource *resource,
|
||||
uint32_t first_subresource, uint32_t subresource_count,
|
||||
uint32_t resource_subresource_count)
|
||||
{
|
||||
if (subresource_count == resource_subresource_count)
|
||||
{
|
||||
d3d12_command_list_promote_dsv_resource(list, resource,
|
||||
VKD3D_DEPTH_PLANE_OPTIMAL | VKD3D_STENCIL_PLANE_OPTIMAL);
|
||||
}
|
||||
else if (resource->format->vk_aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
|
||||
{
|
||||
/* Can we at least discard a plane fully? */
|
||||
|
||||
if (first_subresource == 0 && subresource_count >= resource_subresource_count / 2)
|
||||
{
|
||||
if (resource->format->vk_aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT)
|
||||
d3d12_command_list_promote_dsv_resource(list, resource, VKD3D_DEPTH_PLANE_OPTIMAL);
|
||||
else if (resource->format->vk_aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||
d3d12_command_list_promote_dsv_resource(list, resource, VKD3D_STENCIL_PLANE_OPTIMAL);
|
||||
}
|
||||
else if (first_subresource <= resource_subresource_count / 2 &&
|
||||
first_subresource + subresource_count == resource_subresource_count)
|
||||
{
|
||||
if (resource->format->vk_aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||
d3d12_command_list_promote_dsv_resource(list, resource, VKD3D_STENCIL_PLANE_OPTIMAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void d3d12_command_list_notify_dsv_state(struct d3d12_command_list *list,
|
||||
struct d3d12_resource *resource, D3D12_RESOURCE_STATES state, UINT subresource)
|
||||
{
|
||||
|
@ -2363,6 +2397,7 @@ static void d3d12_command_list_clear_attachment_pass(struct d3d12_command_list *
|
|||
VkFramebuffer vk_framebuffer;
|
||||
VkRenderPass vk_render_pass;
|
||||
VkPipelineStageFlags stages;
|
||||
uint32_t plane_write_mask;
|
||||
bool separate_ds_layouts;
|
||||
VkAccessFlags access;
|
||||
VkExtent3D extent;
|
||||
|
@ -2388,7 +2423,7 @@ static void d3d12_command_list_clear_attachment_pass(struct d3d12_command_list *
|
|||
if (is_bound)
|
||||
attachment_desc.initialLayout = list->dsv_layout;
|
||||
else
|
||||
attachment_desc.initialLayout = resource->common_layout;
|
||||
attachment_desc.initialLayout = d3d12_command_list_get_depth_stencil_resource_layout(list, resource, NULL);
|
||||
|
||||
if (separate_ds_layouts)
|
||||
{
|
||||
|
@ -2399,19 +2434,34 @@ static void d3d12_command_list_clear_attachment_pass(struct d3d12_command_list *
|
|||
attachment_desc.pNext = &stencil_attachment_desc;
|
||||
}
|
||||
|
||||
attachment_desc.finalLayout = attachment_desc.initialLayout;
|
||||
stencil_attachment_desc.stencilFinalLayout = stencil_attachment_desc.stencilInitialLayout;
|
||||
/* We have proven a write, try to promote the image layout to something OPTIMAL. */
|
||||
plane_write_mask = 0;
|
||||
if (clear_aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
|
||||
plane_write_mask |= VKD3D_DEPTH_PLANE_OPTIMAL;
|
||||
if (clear_aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||
plane_write_mask |= VKD3D_STENCIL_PLANE_OPTIMAL;
|
||||
|
||||
attachment_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
attachment_desc.finalLayout = dsv_plane_optimal_mask_to_layout(
|
||||
d3d12_command_list_notify_dsv_writes(list, resource, view, plane_write_mask),
|
||||
resource->format->vk_aspect_mask);
|
||||
|
||||
if (separate_ds_layouts)
|
||||
{
|
||||
stencil_attachment_desc.stencilFinalLayout = vk_separate_stencil_layout(attachment_desc.finalLayout);
|
||||
attachment_desc.finalLayout = vk_separate_depth_layout(attachment_desc.finalLayout);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
attachment_desc.initialLayout = d3d12_resource_pick_layout(resource, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
attachment_desc.finalLayout = attachment_desc.initialLayout;
|
||||
}
|
||||
|
||||
attachment_ref.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
|
||||
attachment_ref.pNext = NULL;
|
||||
attachment_ref.attachment = 0;
|
||||
attachment_ref.layout = view->info.texture.vk_layout;
|
||||
attachment_ref.aspectMask = 0; /* input attachment aspect mask */
|
||||
|
||||
if (separate_ds_layouts)
|
||||
|
@ -2618,7 +2668,9 @@ static void d3d12_command_list_discard_attachment_barrier(struct d3d12_command_l
|
|||
{
|
||||
stages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||
access = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
layout = is_bound && list->dsv_layout ? list->dsv_layout : resource->common_layout;
|
||||
layout = is_bound && list->dsv_layout ?
|
||||
list->dsv_layout :
|
||||
d3d12_command_list_get_depth_stencil_resource_layout(list, resource, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2799,16 +2851,14 @@ static bool d3d12_resource_requires_shader_visibility_after_transition(
|
|||
new_layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
}
|
||||
|
||||
static VkPipelineStageFlags vk_render_pass_barrier_from_view(const struct vkd3d_view *view, const struct d3d12_resource *resource,
|
||||
static VkPipelineStageFlags vk_render_pass_barrier_from_view(struct d3d12_command_list *list,
|
||||
const struct vkd3d_view *view, const struct d3d12_resource *resource,
|
||||
enum vkd3d_render_pass_transition_mode mode, VkImageLayout layout, bool clear, VkImageMemoryBarrier *vk_barrier)
|
||||
{
|
||||
VkImageLayout outside_render_pass_layout;
|
||||
VkPipelineStageFlags stages;
|
||||
VkAccessFlags access;
|
||||
|
||||
if (!layout)
|
||||
layout = view->info.texture.vk_layout;
|
||||
|
||||
if (view->format->vk_aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
{
|
||||
stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
|
@ -2819,12 +2869,7 @@ static VkPipelineStageFlags vk_render_pass_barrier_from_view(const struct vkd3d_
|
|||
{
|
||||
stages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||
access = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
|
||||
/* SIMULTANEOUS + DEPTH is not allowed.
|
||||
* We cannot know if a resource is in DEPTH_READ or DEPTH_WRITE state up front, so
|
||||
* we map DEPTH_READ and DEPTH_WRITE to read-only, and transition in and out of depth write state
|
||||
* as required.
|
||||
* Common layout for depth images will be either read-only depth or read-write depth. */
|
||||
outside_render_pass_layout = resource->common_layout;
|
||||
outside_render_pass_layout = d3d12_command_list_get_depth_stencil_resource_layout(list, resource, NULL);
|
||||
}
|
||||
|
||||
vk_barrier->sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
|
@ -2920,8 +2965,8 @@ static void d3d12_command_list_emit_render_pass_transition(struct d3d12_command_
|
|||
if (mode == VKD3D_RENDER_PASS_TRANSITION_MODE_BEGIN)
|
||||
do_clear = d3d12_command_list_has_render_pass_rtv_clear(list, i);
|
||||
|
||||
if ((new_stages = vk_render_pass_barrier_from_view(rtv->view, rtv->resource,
|
||||
mode, VK_IMAGE_LAYOUT_UNDEFINED, do_clear, &vk_image_barriers[j])))
|
||||
if ((new_stages = vk_render_pass_barrier_from_view(list, rtv->view, rtv->resource,
|
||||
mode, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, do_clear, &vk_image_barriers[j])))
|
||||
{
|
||||
stage_mask |= new_stages;
|
||||
j++;
|
||||
|
@ -2930,19 +2975,29 @@ static void d3d12_command_list_emit_render_pass_transition(struct d3d12_command_
|
|||
|
||||
dsv = &list->dsv;
|
||||
|
||||
/* The dsv_layout is updated in d3d12_command_list_begin_render_pass(). */
|
||||
|
||||
if (dsv->view && list->dsv_layout)
|
||||
{
|
||||
if (mode == VKD3D_RENDER_PASS_TRANSITION_MODE_BEGIN)
|
||||
do_clear = d3d12_command_list_has_render_pass_dsv_clear(list);
|
||||
|
||||
if ((new_stages = vk_render_pass_barrier_from_view(dsv->view, dsv->resource,
|
||||
if ((new_stages = vk_render_pass_barrier_from_view(list, dsv->view, dsv->resource,
|
||||
mode, list->dsv_layout, do_clear, &vk_image_barriers[j])))
|
||||
{
|
||||
stage_mask |= new_stages;
|
||||
j++;
|
||||
}
|
||||
|
||||
/* We know for sure we will write something to these attachments now, so try to promote. */
|
||||
if (mode == VKD3D_RENDER_PASS_TRANSITION_MODE_BEGIN)
|
||||
d3d12_command_list_notify_dsv_writes(list, dsv->resource, dsv->view, list->dsv_plane_optimal_mask);
|
||||
}
|
||||
|
||||
/* Need to deduce DSV layouts again before we start a new render pass. */
|
||||
if (mode == VKD3D_RENDER_PASS_TRANSITION_MODE_END)
|
||||
list->dsv_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
/* Ignore VRS targets. They have to be in the appropriate resource state here. */
|
||||
|
||||
if (!j)
|
||||
|
@ -3606,11 +3661,12 @@ static VkAccessFlags vk_access_flags_all_possible_for_image(const struct d3d12_d
|
|||
return access;
|
||||
}
|
||||
|
||||
static void vk_access_and_stage_flags_from_d3d12_resource_state(const struct d3d12_device *device,
|
||||
static void vk_access_and_stage_flags_from_d3d12_resource_state(const struct d3d12_command_list *list,
|
||||
const struct d3d12_resource *resource, uint32_t state_mask, VkQueueFlags vk_queue_flags,
|
||||
VkPipelineStageFlags *stages, VkAccessFlags *access)
|
||||
{
|
||||
VkPipelineStageFlags queue_shader_stages = 0;
|
||||
struct d3d12_device *device = list->device;
|
||||
uint32_t unhandled_state = 0;
|
||||
|
||||
if (vk_queue_flags & VK_QUEUE_GRAPHICS_BIT)
|
||||
|
@ -3698,10 +3754,13 @@ static void vk_access_and_stage_flags_from_d3d12_resource_state(const struct d3d
|
|||
break;
|
||||
|
||||
case D3D12_RESOURCE_STATE_DEPTH_WRITE:
|
||||
/* If our default DS layout is attachment optimal, we will not perform implicit
|
||||
/* If our DS layout is attachment optimal in any way, we might not perform implicit
|
||||
* memory barriers as part of a render pass. */
|
||||
if (resource->common_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
|
||||
if (d3d12_command_list_get_depth_stencil_resource_layout(list, resource, NULL) !=
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL)
|
||||
{
|
||||
*access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
}
|
||||
/* fallthrough */
|
||||
case D3D12_RESOURCE_STATE_DEPTH_READ:
|
||||
*stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||
|
@ -4248,6 +4307,7 @@ static void d3d12_command_list_reset_api_state(struct d3d12_command_list *list,
|
|||
memset(&list->dsv, 0, sizeof(list->dsv));
|
||||
memset(&list->clear_state, 0, sizeof(list->clear_state));
|
||||
list->dsv_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
list->dsv_plane_optimal_mask = 0;
|
||||
list->fb_width = 0;
|
||||
list->fb_height = 0;
|
||||
list->fb_layer_count = 0;
|
||||
|
@ -4582,10 +4642,12 @@ static uint32_t d3d12_command_list_variant_flags(struct d3d12_command_list *list
|
|||
static bool d3d12_command_list_update_graphics_pipeline(struct d3d12_command_list *list)
|
||||
{
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
|
||||
const struct vkd3d_render_pass_compatibility *render_pass_compat;
|
||||
VkRenderPass vk_render_pass;
|
||||
uint32_t new_active_flags;
|
||||
VkPipeline vk_pipeline;
|
||||
uint32_t variant_flags;
|
||||
uint32_t i;
|
||||
|
||||
if (list->current_pipeline != VK_NULL_HANDLE)
|
||||
return true;
|
||||
|
@ -4600,27 +4662,50 @@ static bool d3d12_command_list_update_graphics_pipeline(struct d3d12_command_lis
|
|||
|
||||
/* 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, list->dsv.format, &vk_render_pass, &new_active_flags,
|
||||
&list->dynamic_state, list->dsv.format, &render_pass_compat, &new_active_flags,
|
||||
variant_flags)))
|
||||
{
|
||||
if (!(vk_pipeline = d3d12_pipeline_state_get_or_create_pipeline(list->state,
|
||||
&list->dynamic_state, list->dsv.format,
|
||||
&vk_render_pass, &new_active_flags, variant_flags)))
|
||||
&render_pass_compat, &new_active_flags, variant_flags)))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Try to match render passes so we can stay compatible. */
|
||||
for (i = 1, vk_render_pass = render_pass_compat->dsv_layouts[0];
|
||||
vk_render_pass != list->pso_render_pass && i < ARRAY_SIZE(render_pass_compat->dsv_layouts);
|
||||
i++)
|
||||
{
|
||||
vk_render_pass = render_pass_compat->dsv_layouts[i];
|
||||
}
|
||||
|
||||
/* The render pass cache ensures that we use the same Vulkan render pass
|
||||
* object for compatible render passes. */
|
||||
* object for compatible render passes.
|
||||
* If vk_render_pass == list->pso_render_pass, we know for certain
|
||||
* that the PSO does not add any write masks we didn't already account for. */
|
||||
if (list->pso_render_pass != vk_render_pass)
|
||||
{
|
||||
list->pso_render_pass = vk_render_pass;
|
||||
d3d12_command_list_invalidate_current_framebuffer(list);
|
||||
/* Don't end render pass if none is active, or otherwise
|
||||
* deferred clears are not going to work as intended. */
|
||||
if (list->current_render_pass || list->render_pass_suspended)
|
||||
d3d12_command_list_invalidate_current_render_pass(list);
|
||||
/* Only override this after ending the render pass. */
|
||||
list->dsv_layout = list->state->graphics.dsv_layout;
|
||||
|
||||
if (d3d12_command_list_has_depth_stencil_view(list))
|
||||
{
|
||||
/* Select new dsv_layout. Any new PSO write we didn't observe yet must be updated here. */
|
||||
list->dsv_plane_optimal_mask |= list->state->graphics.dsv_plane_optimal_mask;
|
||||
list->dsv_layout = dsv_plane_optimal_mask_to_layout(list->dsv_plane_optimal_mask,
|
||||
list->dsv.format->vk_aspect_mask);
|
||||
/* Pick render pass based on new plane optimal mask. */
|
||||
list->pso_render_pass = render_pass_compat->dsv_layouts[list->dsv_plane_optimal_mask];
|
||||
}
|
||||
else
|
||||
{
|
||||
list->pso_render_pass = render_pass_compat->dsv_layouts[0];
|
||||
list->dsv_plane_optimal_mask = 0;
|
||||
list->dsv_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
if (list->command_buffer_pipeline != vk_pipeline)
|
||||
|
@ -5258,6 +5343,22 @@ static void d3d12_command_list_update_dynamic_state(struct d3d12_command_list *l
|
|||
dyn_state->dirty_flags = 0;
|
||||
}
|
||||
|
||||
static void d3d12_command_list_promote_dsv_layout(struct d3d12_command_list *list)
|
||||
{
|
||||
/* If we know at this point that the image is DSV optimal in some way, promote the layout
|
||||
* so that we can select the appropriate render pass right away and ignore any
|
||||
* read-state shenanigans. If we cannot promote yet, the pipeline will override dsv_layout as required
|
||||
* by write enable bits. */
|
||||
if (list->dsv_layout == VK_IMAGE_LAYOUT_UNDEFINED &&
|
||||
list->state &&
|
||||
d3d12_command_list_has_depth_stencil_view(list) &&
|
||||
list->dsv.resource)
|
||||
{
|
||||
list->dsv_layout = d3d12_command_list_get_depth_stencil_resource_layout(list, list->dsv.resource,
|
||||
&list->dsv_plane_optimal_mask);
|
||||
}
|
||||
}
|
||||
|
||||
static bool d3d12_command_list_begin_render_pass(struct d3d12_command_list *list)
|
||||
{
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
|
||||
|
@ -5266,6 +5367,7 @@ static bool d3d12_command_list_begin_render_pass(struct d3d12_command_list *list
|
|||
VkRenderPassBeginInfo begin_desc;
|
||||
VkRenderPass vk_render_pass;
|
||||
|
||||
d3d12_command_list_promote_dsv_layout(list);
|
||||
if (!d3d12_command_list_update_graphics_pipeline(list))
|
||||
return false;
|
||||
if (!d3d12_command_list_update_current_framebuffer(list))
|
||||
|
@ -5826,7 +5928,6 @@ static void d3d12_command_list_copy_image(struct d3d12_command_list *list,
|
|||
memset(&dst_view_desc, 0, sizeof(dst_view_desc));
|
||||
dst_view_desc.image = dst_resource->res.vk_image;
|
||||
dst_view_desc.view_type = pipeline_key.view_type;
|
||||
dst_view_desc.layout = dst_layout;
|
||||
dst_view_desc.format = dst_format;
|
||||
dst_view_desc.miplevel_idx = region->dstSubresource.mipLevel;
|
||||
dst_view_desc.miplevel_count = 1;
|
||||
|
@ -5839,7 +5940,6 @@ static void d3d12_command_list_copy_image(struct d3d12_command_list *list,
|
|||
memset(&src_view_desc, 0, sizeof(src_view_desc));
|
||||
src_view_desc.image = src_resource->res.vk_image;
|
||||
src_view_desc.view_type = pipeline_key.view_type;
|
||||
src_view_desc.layout = src_layout;
|
||||
src_view_desc.format = src_format;
|
||||
src_view_desc.miplevel_idx = region->srcSubresource.mipLevel;
|
||||
src_view_desc.miplevel_count = 1;
|
||||
|
@ -5917,7 +6017,7 @@ static void d3d12_command_list_copy_image(struct d3d12_command_list *list,
|
|||
|
||||
vk_image_info.sampler = VK_NULL_HANDLE;
|
||||
vk_image_info.imageView = src_view->vk_image_view;
|
||||
vk_image_info.imageLayout = src_view_desc.layout;
|
||||
vk_image_info.imageLayout = src_layout;
|
||||
|
||||
vk_descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
vk_descriptor_write.pNext = NULL;
|
||||
|
@ -6684,7 +6784,7 @@ static bool d3d12_resource_may_alias_other_resources(struct d3d12_resource *reso
|
|||
}
|
||||
|
||||
static VkImageLayout vk_image_layout_from_d3d12_resource_state(
|
||||
const struct d3d12_resource *resource, D3D12_RESOURCE_STATES state)
|
||||
struct d3d12_command_list *list, const struct d3d12_resource *resource, D3D12_RESOURCE_STATES state)
|
||||
{
|
||||
/* Simultaneous access is always general, until we're forced to treat it differently in
|
||||
* a transfer, render pass, or similar. */
|
||||
|
@ -6710,10 +6810,17 @@ static VkImageLayout vk_image_layout_from_d3d12_resource_state(
|
|||
* VRS images also cannot be simultaneous access. */
|
||||
return VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
|
||||
|
||||
case D3D12_RESOURCE_STATE_DEPTH_WRITE:
|
||||
case D3D12_RESOURCE_STATE_DEPTH_READ:
|
||||
/* DEPTH_READ only is not a shader read state, and we treat WRITE and READ more or less the same. */
|
||||
if (list)
|
||||
return d3d12_command_list_get_depth_stencil_resource_layout(list, resource, NULL);
|
||||
else
|
||||
return resource->common_layout;
|
||||
|
||||
default:
|
||||
/* DEPTH write and read are treated the same until we know the layout for use in a render pass.
|
||||
* The common layout is one of the depth states otherwise.
|
||||
* For TRANSFER or RESOLVE states, we transition in and out of common state way. */
|
||||
/* For TRANSFER or RESOLVE states, we transition in and out of common state since we have to
|
||||
* handle implicit sync anyways and TRANSFER can decay/promote. */
|
||||
return resource->common_layout;
|
||||
}
|
||||
}
|
||||
|
@ -6892,18 +6999,24 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(d3d12_command_l
|
|||
continue;
|
||||
}
|
||||
|
||||
vk_access_and_stage_flags_from_d3d12_resource_state(list->device, preserve_resource,
|
||||
vk_access_and_stage_flags_from_d3d12_resource_state(list, preserve_resource,
|
||||
transition->StateBefore, list->vk_queue_flags, &transition_src_stage_mask,
|
||||
&transition_src_access);
|
||||
vk_access_and_stage_flags_from_d3d12_resource_state(list->device, preserve_resource,
|
||||
if (d3d12_resource_is_texture(preserve_resource))
|
||||
old_layout = vk_image_layout_from_d3d12_resource_state(list, preserve_resource, transition->StateBefore);
|
||||
|
||||
if (preserve_resource->desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)
|
||||
{
|
||||
/* If we enter DEPTH_WRITE or DEPTH_READ we can promote to optimal. */
|
||||
d3d12_command_list_notify_dsv_state(list, preserve_resource,
|
||||
transition->StateAfter, transition->Subresource);
|
||||
}
|
||||
|
||||
vk_access_and_stage_flags_from_d3d12_resource_state(list, preserve_resource,
|
||||
transition->StateAfter, list->vk_queue_flags, &transition_dst_stage_mask,
|
||||
&transition_dst_access);
|
||||
|
||||
if (d3d12_resource_is_texture(preserve_resource))
|
||||
{
|
||||
old_layout = vk_image_layout_from_d3d12_resource_state(preserve_resource, transition->StateBefore);
|
||||
new_layout = vk_image_layout_from_d3d12_resource_state(preserve_resource, transition->StateAfter);
|
||||
}
|
||||
new_layout = vk_image_layout_from_d3d12_resource_state(list, preserve_resource, transition->StateAfter);
|
||||
|
||||
if (old_layout != new_layout)
|
||||
{
|
||||
|
@ -6949,10 +7062,10 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(d3d12_command_l
|
|||
|
||||
assert(state_mask);
|
||||
|
||||
vk_access_and_stage_flags_from_d3d12_resource_state(list->device, preserve_resource,
|
||||
vk_access_and_stage_flags_from_d3d12_resource_state(list, preserve_resource,
|
||||
state_mask, list->vk_queue_flags, &batch.src_stage_mask,
|
||||
&batch.vk_memory_barrier.srcAccessMask);
|
||||
vk_access_and_stage_flags_from_d3d12_resource_state(list->device, preserve_resource,
|
||||
vk_access_and_stage_flags_from_d3d12_resource_state(list, preserve_resource,
|
||||
state_mask, list->vk_queue_flags, &batch.dst_stage_mask,
|
||||
&batch.vk_memory_barrier.dstAccessMask);
|
||||
|
||||
|
@ -6997,6 +7110,12 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(d3d12_command_l
|
|||
if (after && d3d12_resource_is_texture(after))
|
||||
{
|
||||
VkImageMemoryBarrier vk_alias_barrier;
|
||||
|
||||
/* An aliasing barrier discards to common layout.
|
||||
* We'll see a DiscardResource later anyways which should make the resource optimal. */
|
||||
if (after->desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)
|
||||
d3d12_command_list_notify_decay_dsv_resource(list, after);
|
||||
|
||||
vk_image_memory_barrier_for_after_aliasing_barrier(list->device, list->vk_queue_flags,
|
||||
after, &vk_alias_barrier);
|
||||
d3d12_command_list_barrier_batch_add_layout_transition(list, &batch, &vk_alias_barrier);
|
||||
|
@ -7642,6 +7761,9 @@ static void STDMETHODCALLTYPE d3d12_command_list_OMSetRenderTargets(d3d12_comman
|
|||
|
||||
memset(list->rtvs, 0, sizeof(list->rtvs));
|
||||
memset(&list->dsv, 0, sizeof(list->dsv));
|
||||
/* Need to deduce DSV layouts again. */
|
||||
list->dsv_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
list->dsv_plane_optimal_mask = 0;
|
||||
|
||||
for (i = 0; i < render_target_descriptor_count; ++i)
|
||||
{
|
||||
|
@ -7868,7 +7990,7 @@ static void d3d12_command_list_clear_uav(struct d3d12_command_list *list, const
|
|||
assert(args->has_view);
|
||||
image_info.sampler = VK_NULL_HANDLE;
|
||||
image_info.imageView = args->u.view->vk_image_view;
|
||||
image_info.imageLayout = args->u.view->info.texture.vk_layout;
|
||||
image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
write_set.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||
write_set.pImageInfo = &image_info;
|
||||
|
@ -8109,7 +8231,6 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewUint(d3
|
|||
|
||||
view_desc.image = resource_impl->res.vk_image;
|
||||
view_desc.view_type = base_view->info.texture.vk_view_type;
|
||||
view_desc.layout = base_view->info.texture.vk_layout;
|
||||
view_desc.format = uint_format;
|
||||
view_desc.miplevel_idx = base_view->info.texture.miplevel_idx;
|
||||
view_desc.miplevel_count = 1;
|
||||
|
@ -8186,6 +8307,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_DiscardResource(d3d12_command_l
|
|||
struct d3d12_resource *texture = unsafe_impl_from_ID3D12Resource(resource);
|
||||
unsigned int i, first_subresource, subresource_count;
|
||||
VkImageSubresourceLayers vk_subresource_layers;
|
||||
unsigned int resource_subresource_count;
|
||||
VkImageSubresource vk_subresource;
|
||||
D3D12_RECT full_rect;
|
||||
int attachment_idx;
|
||||
|
@ -8216,6 +8338,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_DiscardResource(d3d12_command_l
|
|||
|
||||
/* Assume that pRegion == NULL means that we should discard
|
||||
* the entire resource. This does not seem to be documented. */
|
||||
resource_subresource_count = d3d12_resource_get_sub_resource_count(texture);
|
||||
if (region)
|
||||
{
|
||||
first_subresource = region->FirstSubresource;
|
||||
|
@ -8224,7 +8347,15 @@ static void STDMETHODCALLTYPE d3d12_command_list_DiscardResource(d3d12_command_l
|
|||
else
|
||||
{
|
||||
first_subresource = 0;
|
||||
subresource_count = d3d12_resource_get_sub_resource_count(texture);
|
||||
subresource_count = resource_subresource_count;
|
||||
}
|
||||
|
||||
/* If we write to all subresources, we can promote the depth image to OPTIMAL since we know the resource
|
||||
* must be in OPTIMAL state. */
|
||||
if (texture->desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)
|
||||
{
|
||||
d3d12_command_list_notify_dsv_discard(list, texture,
|
||||
first_subresource, subresource_count, resource_subresource_count);
|
||||
}
|
||||
|
||||
/* We can't meaningfully discard sub-regions of an image. If rects
|
||||
|
@ -10385,7 +10516,7 @@ static void d3d12_command_queue_transition_pool_add_barrier(struct d3d12_command
|
|||
barrier->dstAccessMask = 0;
|
||||
barrier->oldLayout = d3d12_resource_is_cpu_accessible(resource)
|
||||
? VK_IMAGE_LAYOUT_PREINITIALIZED : VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
barrier->newLayout = vk_image_layout_from_d3d12_resource_state(resource, resource->initial_state);
|
||||
barrier->newLayout = vk_image_layout_from_d3d12_resource_state(NULL, resource, resource->initial_state);
|
||||
barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier->image = resource->res.vk_image;
|
||||
|
|
|
@ -667,7 +667,6 @@ static uint32_t vkd3d_view_entry_hash(const void *key)
|
|||
case VKD3D_VIEW_TYPE_IMAGE:
|
||||
hash = hash_uint64((uint64_t)k->u.texture.image);
|
||||
hash = hash_combine(hash, k->u.texture.view_type);
|
||||
hash = hash_combine(hash, k->u.texture.layout);
|
||||
hash = hash_combine(hash, (uintptr_t)k->u.texture.format);
|
||||
hash = hash_combine(hash, k->u.texture.miplevel_idx);
|
||||
hash = hash_combine(hash, k->u.texture.miplevel_count);
|
||||
|
@ -728,7 +727,6 @@ static bool vkd3d_view_entry_compare(const void *key, const struct hash_map_entr
|
|||
case VKD3D_VIEW_TYPE_IMAGE:
|
||||
return k->u.texture.image == e->key.u.texture.image &&
|
||||
k->u.texture.view_type == e->key.u.texture.view_type &&
|
||||
k->u.texture.layout == e->key.u.texture.layout &&
|
||||
k->u.texture.format == e->key.u.texture.format &&
|
||||
k->u.texture.miplevel_idx == e->key.u.texture.miplevel_idx &&
|
||||
k->u.texture.miplevel_count == e->key.u.texture.miplevel_count &&
|
||||
|
@ -3358,7 +3356,6 @@ static bool init_default_texture_view_desc(struct vkd3d_texture_view_desc *desc,
|
|||
|
||||
desc->aspect_mask = desc->format->vk_aspect_mask;
|
||||
desc->image = resource->res.vk_image;
|
||||
desc->layout = resource->common_layout;
|
||||
desc->miplevel_idx = 0;
|
||||
desc->miplevel_count = 1;
|
||||
desc->miplevel_clamp = 0.0f;
|
||||
|
@ -3459,7 +3456,6 @@ bool vkd3d_create_texture_view(struct d3d12_device *device, const struct vkd3d_t
|
|||
object->vk_image_view = vk_view;
|
||||
object->format = format;
|
||||
object->info.texture.vk_view_type = desc->view_type;
|
||||
object->info.texture.vk_layout = desc->layout;
|
||||
object->info.texture.miplevel_idx = desc->miplevel_idx;
|
||||
object->info.texture.layer_idx = desc->layer_idx;
|
||||
object->info.texture.layer_count = desc->layer_count;
|
||||
|
@ -3970,7 +3966,7 @@ static void vkd3d_create_texture_srv(struct d3d12_desc *descriptor,
|
|||
|
||||
descriptor_info.image.sampler = VK_NULL_HANDLE;
|
||||
descriptor_info.image.imageView = view ? view->vk_image_view : VK_NULL_HANDLE;
|
||||
descriptor_info.image.imageLayout = view ? view->info.texture.vk_layout : VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
descriptor_info.image.imageLayout = view ? resource->common_layout : VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
info_index = vkd3d_bindless_state_find_set_info_index(&device->bindless_state,
|
||||
VKD3D_BINDLESS_SET_SRV | VKD3D_BINDLESS_SET_IMAGE);
|
||||
|
@ -4245,9 +4241,6 @@ static void vkd3d_create_texture_uav(struct d3d12_desc *descriptor,
|
|||
return;
|
||||
}
|
||||
|
||||
/* UNORDERED_ACCESS is not the common layout, override it here. */
|
||||
key.u.texture.layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
if (desc)
|
||||
{
|
||||
switch (desc->ViewDimension)
|
||||
|
@ -4297,7 +4290,7 @@ static void vkd3d_create_texture_uav(struct d3d12_desc *descriptor,
|
|||
|
||||
descriptor_info.image.sampler = VK_NULL_HANDLE;
|
||||
descriptor_info.image.imageView = view ? view->vk_image_view : VK_NULL_HANDLE;
|
||||
descriptor_info.image.imageLayout = view ? view->info.texture.vk_layout : VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
descriptor_info.image.imageLayout = view ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
info_index = vkd3d_bindless_state_find_set_info_index(&device->bindless_state,
|
||||
VKD3D_BINDLESS_SET_UAV | VKD3D_BINDLESS_SET_IMAGE);
|
||||
|
@ -4658,7 +4651,6 @@ void d3d12_rtv_desc_create_rtv(struct d3d12_rtv_desc *rtv_desc, struct d3d12_dev
|
|||
}
|
||||
|
||||
key.view_type = VKD3D_VIEW_TYPE_IMAGE;
|
||||
key.u.texture.layout = d3d12_resource_pick_layout(resource, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
|
||||
if (desc)
|
||||
{
|
||||
|
@ -4733,24 +4725,6 @@ void d3d12_rtv_desc_create_rtv(struct d3d12_rtv_desc *rtv_desc, struct d3d12_dev
|
|||
rtv_desc->resource = resource;
|
||||
}
|
||||
|
||||
/* DSVs */
|
||||
static VkImageLayout d3d12_dsv_layout_from_flags(UINT flags)
|
||||
{
|
||||
const D3D12_DSV_FLAGS mask = D3D12_DSV_FLAG_READ_ONLY_DEPTH | D3D12_DSV_FLAG_READ_ONLY_STENCIL;
|
||||
|
||||
switch (flags & mask)
|
||||
{
|
||||
default: /* case 0: */
|
||||
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
case D3D12_DSV_FLAG_READ_ONLY_DEPTH:
|
||||
return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
case D3D12_DSV_FLAG_READ_ONLY_STENCIL:
|
||||
return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL;
|
||||
case D3D12_DSV_FLAG_READ_ONLY_DEPTH | D3D12_DSV_FLAG_READ_ONLY_STENCIL:
|
||||
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
|
||||
}
|
||||
}
|
||||
|
||||
void d3d12_rtv_desc_create_dsv(struct d3d12_rtv_desc *dsv_desc, struct d3d12_device *device,
|
||||
struct d3d12_resource *resource, const D3D12_DEPTH_STENCIL_VIEW_DESC *desc)
|
||||
{
|
||||
|
@ -4785,9 +4759,6 @@ void d3d12_rtv_desc_create_dsv(struct d3d12_rtv_desc *dsv_desc, struct d3d12_dev
|
|||
|
||||
if (desc)
|
||||
{
|
||||
key.u.texture.layout = d3d12_resource_pick_layout(resource,
|
||||
d3d12_dsv_layout_from_flags(desc->Flags));
|
||||
|
||||
switch (desc->ViewDimension)
|
||||
{
|
||||
case D3D12_DSV_DIMENSION_TEXTURE1D:
|
||||
|
@ -4826,8 +4797,6 @@ void d3d12_rtv_desc_create_dsv(struct d3d12_rtv_desc *dsv_desc, struct d3d12_dev
|
|||
/* Avoid passing down UINT32_MAX here since that makes framebuffer logic later rather awkward. */
|
||||
key.u.texture.layer_count = min(key.u.texture.layer_count, resource->desc.DepthOrArraySize - key.u.texture.layer_idx);
|
||||
}
|
||||
else
|
||||
key.u.texture.layout = d3d12_resource_pick_layout(resource, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
|
||||
assert(d3d12_resource_is_texture(resource));
|
||||
|
||||
|
|
|
@ -1851,7 +1851,7 @@ struct vkd3d_compiled_pipeline
|
|||
struct list entry;
|
||||
struct vkd3d_pipeline_key key;
|
||||
VkPipeline vk_pipeline;
|
||||
VkRenderPass vk_render_pass;
|
||||
struct vkd3d_render_pass_compatibility render_pass_compat;
|
||||
uint32_t dynamic_state_flags;
|
||||
};
|
||||
|
||||
|
@ -2673,10 +2673,12 @@ static unsigned int vkd3d_get_rt_format_swizzle(const struct vkd3d_format *forma
|
|||
|
||||
STATIC_ASSERT(sizeof(struct vkd3d_shader_transform_feedback_element) == sizeof(D3D12_SO_DECLARATION_ENTRY));
|
||||
|
||||
static HRESULT d3d12_graphics_pipeline_state_create_render_pass(
|
||||
static HRESULT d3d12_graphics_pipeline_state_create_render_pass_for_plane_mask(
|
||||
struct d3d12_graphics_pipeline_state *graphics, struct d3d12_device *device,
|
||||
const struct vkd3d_format *dynamic_dsv_format,
|
||||
VkRenderPass *vk_render_pass, VkImageLayout *dsv_layout,
|
||||
uint32_t plane_optimal_mask,
|
||||
VkRenderPass *vk_render_pass,
|
||||
uint32_t *out_plane_optimal_mask,
|
||||
uint32_t variant_flags)
|
||||
{
|
||||
VkFormat dsv_format = VK_FORMAT_UNDEFINED;
|
||||
|
@ -2705,21 +2707,35 @@ static HRESULT d3d12_graphics_pipeline_state_create_render_pass(
|
|||
|
||||
if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
|
||||
{
|
||||
if (graphics->ds_desc.depthTestEnable || graphics->ds_desc.depthBoundsTestEnable)
|
||||
if (plane_optimal_mask & VKD3D_DEPTH_PLANE_OPTIMAL)
|
||||
{
|
||||
key.flags |= VKD3D_RENDER_PASS_KEY_DEPTH_ENABLE | VKD3D_RENDER_PASS_KEY_DEPTH_WRITE;
|
||||
}
|
||||
else 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;
|
||||
plane_optimal_mask |= VKD3D_DEPTH_PLANE_OPTIMAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||
{
|
||||
if (graphics->ds_desc.stencilTestEnable)
|
||||
if (plane_optimal_mask & VKD3D_STENCIL_PLANE_OPTIMAL)
|
||||
{
|
||||
key.flags |= VKD3D_RENDER_PASS_KEY_STENCIL_ENABLE | VKD3D_RENDER_PASS_KEY_STENCIL_WRITE;
|
||||
}
|
||||
else 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;
|
||||
plane_optimal_mask |= VKD3D_STENCIL_PLANE_OPTIMAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2732,6 +2748,7 @@ static HRESULT d3d12_graphics_pipeline_state_create_render_pass(
|
|||
VKD3D_RENDER_PASS_KEY_DEPTH_ENABLE : 0;
|
||||
key.flags |= (key.flags & VKD3D_RENDER_PASS_KEY_STENCIL_WRITE) ?
|
||||
VKD3D_RENDER_PASS_KEY_DEPTH_WRITE : 0;
|
||||
plane_optimal_mask |= (plane_optimal_mask & VKD3D_STENCIL_PLANE_OPTIMAL) ? VKD3D_DEPTH_PLANE_OPTIMAL : 0;
|
||||
}
|
||||
|
||||
if (!(aspects & VK_IMAGE_ASPECT_STENCIL_BIT))
|
||||
|
@ -2740,6 +2757,7 @@ static HRESULT d3d12_graphics_pipeline_state_create_render_pass(
|
|||
VKD3D_RENDER_PASS_KEY_STENCIL_ENABLE : 0;
|
||||
key.flags |= (key.flags & VKD3D_RENDER_PASS_KEY_DEPTH_WRITE) ?
|
||||
VKD3D_RENDER_PASS_KEY_STENCIL_WRITE : 0;
|
||||
plane_optimal_mask |= (plane_optimal_mask & VKD3D_DEPTH_PLANE_OPTIMAL) ? VKD3D_STENCIL_PLANE_OPTIMAL : 0;
|
||||
}
|
||||
|
||||
key.vk_formats[key.attachment_count++] = dsv_format;
|
||||
|
@ -2755,12 +2773,41 @@ static HRESULT d3d12_graphics_pipeline_state_create_render_pass(
|
|||
|
||||
key.sample_count = graphics->ms_desc.rasterizationSamples;
|
||||
|
||||
if (dsv_layout)
|
||||
*dsv_layout = vkd3d_render_pass_get_depth_stencil_layout(&key);
|
||||
if (out_plane_optimal_mask)
|
||||
{
|
||||
/* Represents the aspects which the PSO will write to, i.e. DEPTH_WRITE state is required to
|
||||
* draw using this PSO. */
|
||||
*out_plane_optimal_mask = plane_optimal_mask;
|
||||
}
|
||||
|
||||
return vkd3d_render_pass_cache_find(&device->render_pass_cache, device, &key, vk_render_pass);
|
||||
}
|
||||
|
||||
static HRESULT d3d12_graphics_pipeline_state_create_render_pass(
|
||||
struct d3d12_graphics_pipeline_state *graphics, struct d3d12_device *device,
|
||||
const struct vkd3d_format *dynamic_dsv_format,
|
||||
struct vkd3d_render_pass_compatibility *render_pass_compat,
|
||||
uint32_t *out_plane_optimal_mask,
|
||||
uint32_t variant_flags)
|
||||
{
|
||||
uint32_t plane_optimal_mask;
|
||||
HRESULT hr;
|
||||
|
||||
for (plane_optimal_mask = 0; plane_optimal_mask < ARRAY_SIZE(render_pass_compat->dsv_layouts);
|
||||
plane_optimal_mask++)
|
||||
{
|
||||
if (FAILED(hr = d3d12_graphics_pipeline_state_create_render_pass_for_plane_mask(
|
||||
graphics, device, dynamic_dsv_format,
|
||||
plane_optimal_mask, &render_pass_compat->dsv_layouts[plane_optimal_mask],
|
||||
plane_optimal_mask == 0 ? out_plane_optimal_mask : NULL, variant_flags)))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static bool vk_blend_factor_needs_blend_constants(VkBlendFactor blend_factor)
|
||||
{
|
||||
return blend_factor == VK_BLEND_FACTOR_CONSTANT_COLOR ||
|
||||
|
@ -3440,7 +3487,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, NULL, &graphics->render_pass[i], &graphics->dsv_layout, i)))
|
||||
device, NULL, &graphics->render_pass[i], &graphics->dsv_plane_optimal_mask, i)))
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -3645,13 +3692,15 @@ enum VkPrimitiveTopology vk_topology_from_d3d12_topology(D3D12_PRIMITIVE_TOPOLOG
|
|||
}
|
||||
|
||||
static VkPipeline d3d12_pipeline_state_find_compiled_pipeline(struct d3d12_pipeline_state *state,
|
||||
const struct vkd3d_pipeline_key *key, VkRenderPass *vk_render_pass, uint32_t *dynamic_state_flags)
|
||||
const struct vkd3d_pipeline_key *key,
|
||||
const struct vkd3d_render_pass_compatibility **render_pass_compat,
|
||||
uint32_t *dynamic_state_flags)
|
||||
{
|
||||
const struct d3d12_graphics_pipeline_state *graphics = &state->graphics;
|
||||
VkPipeline vk_pipeline = VK_NULL_HANDLE;
|
||||
struct vkd3d_compiled_pipeline *current;
|
||||
|
||||
*vk_render_pass = VK_NULL_HANDLE;
|
||||
*render_pass_compat = NULL;
|
||||
|
||||
rw_spinlock_acquire_read(&state->lock);
|
||||
LIST_FOR_EACH_ENTRY(current, &graphics->compiled_fallback_pipelines, struct vkd3d_compiled_pipeline, entry)
|
||||
|
@ -3659,7 +3708,7 @@ static VkPipeline d3d12_pipeline_state_find_compiled_pipeline(struct d3d12_pipel
|
|||
if (!memcmp(¤t->key, key, sizeof(*key)))
|
||||
{
|
||||
vk_pipeline = current->vk_pipeline;
|
||||
*vk_render_pass = current->vk_render_pass;
|
||||
*render_pass_compat = ¤t->render_pass_compat;
|
||||
*dynamic_state_flags = current->dynamic_state_flags;
|
||||
break;
|
||||
}
|
||||
|
@ -3670,7 +3719,9 @@ static VkPipeline d3d12_pipeline_state_find_compiled_pipeline(struct d3d12_pipel
|
|||
}
|
||||
|
||||
static bool d3d12_pipeline_state_put_pipeline_to_cache(struct d3d12_pipeline_state *state,
|
||||
const struct vkd3d_pipeline_key *key, VkPipeline vk_pipeline, VkRenderPass vk_render_pass,
|
||||
const struct vkd3d_pipeline_key *key, VkPipeline vk_pipeline,
|
||||
const struct vkd3d_render_pass_compatibility *render_pass_compat,
|
||||
const struct vkd3d_render_pass_compatibility **out_render_pass_compat,
|
||||
uint32_t dynamic_state_flags)
|
||||
{
|
||||
struct d3d12_graphics_pipeline_state *graphics = &state->graphics;
|
||||
|
@ -3681,8 +3732,9 @@ static bool d3d12_pipeline_state_put_pipeline_to_cache(struct d3d12_pipeline_sta
|
|||
|
||||
compiled_pipeline->key = *key;
|
||||
compiled_pipeline->vk_pipeline = vk_pipeline;
|
||||
compiled_pipeline->vk_render_pass = vk_render_pass;
|
||||
compiled_pipeline->render_pass_compat = *render_pass_compat;
|
||||
compiled_pipeline->dynamic_state_flags = dynamic_state_flags;
|
||||
*out_render_pass_compat = &compiled_pipeline->render_pass_compat;
|
||||
|
||||
rw_spinlock_acquire_write(&state->lock);
|
||||
|
||||
|
@ -3705,7 +3757,8 @@ 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, const struct vkd3d_format *dsv_format, VkPipelineCache vk_cache,
|
||||
VkRenderPass *vk_render_pass, uint32_t *dynamic_state_flags, uint32_t variant_flags)
|
||||
struct vkd3d_render_pass_compatibility *render_pass_compat,
|
||||
uint32_t *dynamic_state_flags, uint32_t variant_flags)
|
||||
{
|
||||
VkVertexInputBindingDescription bindings[D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &state->device->vk_procs;
|
||||
|
@ -3806,10 +3859,11 @@ VkPipeline d3d12_pipeline_state_create_pipeline_variant(struct d3d12_pipeline_st
|
|||
}
|
||||
|
||||
if (FAILED(hr = d3d12_graphics_pipeline_state_create_render_pass(graphics, device, dsv_format,
|
||||
&pipeline_desc.renderPass, &graphics->dsv_layout, variant_flags)))
|
||||
render_pass_compat, &graphics->dsv_plane_optimal_mask, variant_flags)))
|
||||
return VK_NULL_HANDLE;
|
||||
|
||||
*vk_render_pass = pipeline_desc.renderPass;
|
||||
/* Any of these is fine from a compatibility PoV. */
|
||||
pipeline_desc.renderPass = render_pass_compat->dsv_layouts[0];
|
||||
|
||||
TRACE("Calling vkCreateGraphicsPipelines.\n");
|
||||
if ((vr = VK_CALL(vkCreateGraphicsPipelines(device->vk_device,
|
||||
|
@ -3860,7 +3914,8 @@ 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, const struct vkd3d_format *dsv_format,
|
||||
VkRenderPass *vk_render_pass, uint32_t *dynamic_state_flags, uint32_t variant_flags)
|
||||
const struct vkd3d_render_pass_compatibility **render_pass_compat,
|
||||
uint32_t *dynamic_state_flags, uint32_t variant_flags)
|
||||
{
|
||||
struct d3d12_graphics_pipeline_state *graphics = &state->graphics;
|
||||
|
||||
|
@ -3898,18 +3953,19 @@ VkPipeline d3d12_pipeline_state_get_pipeline(struct d3d12_pipeline_state *state,
|
|||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
*vk_render_pass = state->graphics.render_pass[variant_flags];
|
||||
*render_pass_compat = &state->graphics.render_pass[variant_flags];
|
||||
*dynamic_state_flags = state->graphics.dynamic_state_flags;
|
||||
return state->graphics.pipeline[variant_flags];
|
||||
}
|
||||
|
||||
VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_state *state,
|
||||
const struct vkd3d_dynamic_state *dyn_state, const struct vkd3d_format *dsv_format,
|
||||
VkRenderPass *vk_render_pass,
|
||||
const struct vkd3d_render_pass_compatibility **render_pass_compat,
|
||||
uint32_t *dynamic_state_flags, uint32_t variant_flags)
|
||||
{
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &state->device->vk_procs;
|
||||
struct d3d12_graphics_pipeline_state *graphics = &state->graphics;
|
||||
struct vkd3d_render_pass_compatibility new_render_pass_compat;
|
||||
struct d3d12_device *device = state->device;
|
||||
struct vkd3d_pipeline_key pipeline_key;
|
||||
uint32_t stride, stride_align_mask;
|
||||
|
@ -3958,7 +4014,7 @@ VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_sta
|
|||
|
||||
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,
|
||||
if ((vk_pipeline = d3d12_pipeline_state_find_compiled_pipeline(state, &pipeline_key, render_pass_compat,
|
||||
dynamic_state_flags)))
|
||||
{
|
||||
return vk_pipeline;
|
||||
|
@ -3968,7 +4024,7 @@ VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_sta
|
|||
FIXME("Extended dynamic state is supported, but compiling a fallback pipeline late!\n");
|
||||
|
||||
vk_pipeline = d3d12_pipeline_state_create_pipeline_variant(state,
|
||||
&pipeline_key, dsv_format, VK_NULL_HANDLE, vk_render_pass, dynamic_state_flags,
|
||||
&pipeline_key, dsv_format, VK_NULL_HANDLE, &new_render_pass_compat, dynamic_state_flags,
|
||||
variant_flags);
|
||||
|
||||
if (!vk_pipeline)
|
||||
|
@ -3977,11 +4033,15 @@ VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_sta
|
|||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (d3d12_pipeline_state_put_pipeline_to_cache(state, &pipeline_key, vk_pipeline, *vk_render_pass, *dynamic_state_flags))
|
||||
if (d3d12_pipeline_state_put_pipeline_to_cache(state, &pipeline_key, vk_pipeline, &new_render_pass_compat,
|
||||
render_pass_compat, *dynamic_state_flags))
|
||||
{
|
||||
return vk_pipeline;
|
||||
}
|
||||
|
||||
/* Other thread compiled the pipeline before us. */
|
||||
VK_CALL(vkDestroyPipeline(device->vk_device, vk_pipeline, NULL));
|
||||
vk_pipeline = d3d12_pipeline_state_find_compiled_pipeline(state, &pipeline_key, vk_render_pass, dynamic_state_flags);
|
||||
vk_pipeline = d3d12_pipeline_state_find_compiled_pipeline(state, &pipeline_key, render_pass_compat, dynamic_state_flags);
|
||||
if (!vk_pipeline)
|
||||
ERR("Could not get the pipeline compiled by other thread from the cache.\n");
|
||||
return vk_pipeline;
|
||||
|
|
|
@ -913,7 +913,6 @@ struct vkd3d_view
|
|||
struct
|
||||
{
|
||||
VkImageViewType vk_view_type;
|
||||
VkImageLayout vk_layout;
|
||||
unsigned int miplevel_idx;
|
||||
unsigned int layer_idx;
|
||||
unsigned int layer_count;
|
||||
|
@ -936,7 +935,6 @@ struct vkd3d_texture_view_desc
|
|||
{
|
||||
VkImage image;
|
||||
VkImageViewType view_type;
|
||||
VkImageLayout layout;
|
||||
VkImageAspectFlags aspect_mask;
|
||||
const struct vkd3d_format *format;
|
||||
unsigned int miplevel_idx;
|
||||
|
@ -1291,6 +1289,13 @@ enum vkd3d_graphics_pipeline_static_variant_flag
|
|||
VKD3D_GRAPHICS_PIPELINE_STATIC_VARIANT_LAST_BIT = (1u << 1),
|
||||
};
|
||||
|
||||
/* One render pass for each plane optimal mask. */
|
||||
#define VKD3D_RENDER_PASS_COMPATIBILITY_VARIANT_COUNT 4
|
||||
struct vkd3d_render_pass_compatibility
|
||||
{
|
||||
VkRenderPass dsv_layouts[VKD3D_RENDER_PASS_COMPATIBILITY_VARIANT_COUNT];
|
||||
};
|
||||
|
||||
enum vkd3d_plane_optimal_flag
|
||||
{
|
||||
VKD3D_DEPTH_PLANE_OPTIMAL = (1 << 0),
|
||||
|
@ -1324,8 +1329,8 @@ struct d3d12_graphics_pipeline_state
|
|||
unsigned int patch_vertex_count;
|
||||
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];
|
||||
uint32_t dsv_plane_optimal_mask;
|
||||
struct vkd3d_render_pass_compatibility render_pass[VKD3D_GRAPHICS_PIPELINE_STATIC_VARIANT_COUNT];
|
||||
|
||||
D3D12_INDEX_BUFFER_STRIP_CUT_VALUE index_buffer_strip_cut_value;
|
||||
VkPipelineRasterizationStateCreateInfo rs_desc;
|
||||
|
@ -1451,13 +1456,16 @@ HRESULT d3d12_pipeline_state_create(struct d3d12_device *device, VkPipelineBindP
|
|||
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, const struct vkd3d_format *dsv_format,
|
||||
VkRenderPass *vk_render_pass, uint32_t *dynamic_state_flags, uint32_t variant_flags);
|
||||
const struct vkd3d_render_pass_compatibility **render_pass_compat,
|
||||
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, const struct vkd3d_format *dsv_format,
|
||||
VkRenderPass *vk_render_pass, uint32_t *dynamic_state_flags, uint32_t variant_flags);
|
||||
const struct vkd3d_render_pass_compatibility **render_pass_compat,
|
||||
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, const struct vkd3d_format *dsv_format, VkPipelineCache vk_cache,
|
||||
VkRenderPass *vk_render_pass, uint32_t *dynamic_state_flags, uint32_t variant_flags);
|
||||
struct vkd3d_render_pass_compatibility *render_pass_compat,
|
||||
uint32_t *dynamic_state_flags, uint32_t variant_flags);
|
||||
struct d3d12_pipeline_state *unsafe_impl_from_ID3D12PipelineState(ID3D12PipelineState *iface);
|
||||
|
||||
/* ID3D12PipelineLibrary */
|
||||
|
@ -1754,6 +1762,7 @@ struct d3d12_command_list
|
|||
struct d3d12_rtv_desc rtvs[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT];
|
||||
struct d3d12_rtv_desc dsv;
|
||||
struct vkd3d_clear_state clear_state;
|
||||
uint32_t dsv_plane_optimal_mask;
|
||||
VkImageLayout dsv_layout;
|
||||
unsigned int fb_width;
|
||||
unsigned int fb_height;
|
||||
|
|
Loading…
Reference in New Issue