vkd3d: Be more robust with out of bounds clear/discard rects.
GravityBench ends up using ClearView with too large dimensions. This is a validation error in Vulkan, so just clamp the extents. To make full rect detection a bit more robust, do a range check instead of memcmp(). Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
parent
0a732a3b27
commit
27fdc39e67
|
@ -1956,18 +1956,25 @@ static bool d3d12_image_copy_writes_full_subresource(struct d3d12_resource *reso
|
||||||
return width == extent->width && height == extent->height && depth == extent->depth;
|
return width == extent->width && height == extent->height && depth == extent->depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool vk_rect_from_d3d12(const D3D12_RECT *rect, VkRect2D *vk_rect)
|
static bool vk_rect_from_d3d12(const D3D12_RECT *rect, VkRect2D *vk_rect, const D3D12_RECT *clamp_rect)
|
||||||
{
|
{
|
||||||
if (rect->top >= rect->bottom || rect->left >= rect->right)
|
D3D12_RECT clamped;
|
||||||
|
|
||||||
|
clamped.left = max(rect->left, clamp_rect->left);
|
||||||
|
clamped.right = min(rect->right, clamp_rect->right);
|
||||||
|
clamped.top = max(rect->top, clamp_rect->top);
|
||||||
|
clamped.bottom = min(rect->bottom, clamp_rect->bottom);
|
||||||
|
|
||||||
|
if (clamped.top >= clamped.bottom || clamped.left >= clamped.right)
|
||||||
{
|
{
|
||||||
WARN("Empty clear rect.\n");
|
WARN("Empty clear rect.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
vk_rect->offset.x = rect->left;
|
vk_rect->offset.x = clamped.left;
|
||||||
vk_rect->offset.y = rect->top;
|
vk_rect->offset.y = clamped.top;
|
||||||
vk_rect->extent.width = rect->right - rect->left;
|
vk_rect->extent.width = clamped.right - clamped.left;
|
||||||
vk_rect->extent.height = rect->bottom - rect->top;
|
vk_rect->extent.height = clamped.bottom - clamped.top;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2044,9 +2051,10 @@ static void d3d12_command_list_clear_attachment_inline(struct d3d12_command_list
|
||||||
D3D12_RECT full_rect;
|
D3D12_RECT full_rect;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
full_rect = d3d12_get_image_rect(resource, view->info.texture.miplevel_idx);
|
||||||
|
|
||||||
if (!rect_count)
|
if (!rect_count)
|
||||||
{
|
{
|
||||||
full_rect = d3d12_get_image_rect(resource, view->info.texture.miplevel_idx);
|
|
||||||
rect_count = 1;
|
rect_count = 1;
|
||||||
rects = &full_rect;
|
rects = &full_rect;
|
||||||
}
|
}
|
||||||
|
@ -2063,7 +2071,7 @@ static void d3d12_command_list_clear_attachment_inline(struct d3d12_command_list
|
||||||
|
|
||||||
for (i = 0; i < rect_count; i++)
|
for (i = 0; i < rect_count; i++)
|
||||||
{
|
{
|
||||||
if (vk_rect_from_d3d12(&rects[i], &vk_clear_rect.rect))
|
if (vk_rect_from_d3d12(&rects[i], &vk_clear_rect.rect, &full_rect))
|
||||||
{
|
{
|
||||||
VK_CALL(vkCmdClearAttachments(list->vk_command_buffer,
|
VK_CALL(vkCmdClearAttachments(list->vk_command_buffer,
|
||||||
1, &vk_clear_attachment, 1, &vk_clear_rect));
|
1, &vk_clear_attachment, 1, &vk_clear_rect));
|
||||||
|
@ -7344,6 +7352,12 @@ static void STDMETHODCALLTYPE d3d12_command_list_OMSetRenderTargets(d3d12_comman
|
||||||
d3d12_command_list_invalidate_current_pipeline(list, false);
|
d3d12_command_list_invalidate_current_pipeline(list, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool d3d12_rect_fully_covers_region(const D3D12_RECT *a, const D3D12_RECT *b)
|
||||||
|
{
|
||||||
|
return a->top <= b->top && a->bottom >= b->bottom &&
|
||||||
|
a->left <= b->left && a->right >= b->right;
|
||||||
|
}
|
||||||
|
|
||||||
static void d3d12_command_list_clear_attachment(struct d3d12_command_list *list, struct d3d12_resource *resource,
|
static void d3d12_command_list_clear_attachment(struct d3d12_command_list *list, struct d3d12_resource *resource,
|
||||||
struct vkd3d_view *view, VkImageAspectFlags clear_aspects, const VkClearValue *clear_value, UINT rect_count,
|
struct vkd3d_view *view, VkImageAspectFlags clear_aspects, const VkClearValue *clear_value, UINT rect_count,
|
||||||
const D3D12_RECT *rects)
|
const D3D12_RECT *rects)
|
||||||
|
@ -7359,7 +7373,7 @@ static void d3d12_command_list_clear_attachment(struct d3d12_command_list *list,
|
||||||
full_clear = !rect_count;
|
full_clear = !rect_count;
|
||||||
|
|
||||||
for (i = 0; i < rect_count && !full_clear; i++)
|
for (i = 0; i < rect_count && !full_clear; i++)
|
||||||
full_clear |= !memcmp(&rects[i], &full_rect, sizeof(full_rect));
|
full_clear = d3d12_rect_fully_covers_region(&rects[i], &full_rect);
|
||||||
|
|
||||||
if (full_clear)
|
if (full_clear)
|
||||||
rect_count = 0;
|
rect_count = 0;
|
||||||
|
@ -7882,7 +7896,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_DiscardResource(d3d12_command_l
|
||||||
full_rect = d3d12_get_image_rect(texture, vk_subresource.mipLevel);
|
full_rect = d3d12_get_image_rect(texture, vk_subresource.mipLevel);
|
||||||
|
|
||||||
for (i = 0; i < region->NumRects && !full_discard; i++)
|
for (i = 0; i < region->NumRects && !full_discard; i++)
|
||||||
full_discard = !memcmp(®ion->pRects[i], &full_rect, sizeof(full_rect));
|
full_discard = d3d12_rect_fully_covers_region(®ion->pRects[i], &full_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!full_discard)
|
if (!full_discard)
|
||||||
|
|
Loading…
Reference in New Issue