tests: Add a test for actual multisample loads.

The existing test loads from a single sample texture.
This commit is contained in:
Henri Verbeet 2024-10-21 00:21:00 +02:00
parent 072b45b972
commit aeae8322da
Notes: Henri Verbeet 2024-10-28 18:13:33 +01:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1225
9 changed files with 232 additions and 7 deletions

View File

@ -145,3 +145,56 @@ probe (0, 0) rgba (0.1, 0.2, 0.3, 0.4)
probe (1, 0) rgba (0.5, 0.7, 0.6, 0.8) probe (1, 0) rgba (0.5, 0.7, 0.6, 0.8)
probe (0, 1) rgba (0.6, 0.5, 0.2, 0.1) probe (0, 1) rgba (0.6, 0.5, 0.2, 0.1)
probe (1, 1) rgba (0.8, 0.0, 0.7, 1.0) probe (1, 1) rgba (0.8, 0.0, 0.7, 1.0)
% Test an actual multisample load
[require]
shader model >= 4.1
[rtv 0]
format r32g32b32a32-float
size (2dms, 4, 64, 64)
[srv 0]
format r32g32b32a32-float
size (2dms, 4, 64, 64)
[pixel shader]
float4 main(uint id : sv_sampleindex) : sv_target
{
return float4(1u << id, 0.25f, 0.5f, 1.0f);
}
[test]
clear rtv 0 0.0 0.0 0.0 0.0
todo(glsl | sm>=6) draw quad
probe (32, 32) rgba(3.75, 0.25, 0.5, 1.0)
copy rtv 0 srv 0
[rtv 0]
format r32g32b32a32-float
size (2d, 64, 64)
[pixel shader]
Texture2DMS<float4> t;
uint sample;
float4 main(float4 position : sv_position) : sv_target
{
float2 p = position.xy / 64.0f;
return t.Load(p, sample);
}
[test]
uniform 0 uint 0
todo(glsl) draw quad
todo(sm>=6) probe (32, 32) rgba(1.0, 0.25, 0.5, 1.0)
uniform 0 uint 1
todo(glsl) draw quad
todo(sm>=6) probe (32, 32) rgba(2.0, 0.25, 0.5, 1.0)
uniform 0 uint 2
todo(glsl) draw quad
todo(sm>=6) probe (32, 32) rgba(4.0, 0.25, 0.5, 1.0)
uniform 0 uint 3
todo(glsl) draw quad
todo(sm>=6) probe (32, 32) rgba(8.0, 0.25, 0.5, 1.0)

View File

@ -845,6 +845,30 @@ static void read_uint64_t2(const char **line, struct u64vec2 *v)
read_uint64(line, &v->y, true); read_uint64(line, &v->y, true);
} }
static struct resource *parse_resource_reference(struct shader_runner *runner, const char **const line)
{
enum resource_type type;
unsigned int slot = 0;
if (match_string(*line, "dsv", line))
type = RESOURCE_TYPE_DEPTH_STENCIL;
else if (match_string(*line, "rtv", line))
type = RESOURCE_TYPE_RENDER_TARGET;
else if (match_string(*line, "srv", line))
type = RESOURCE_TYPE_TEXTURE;
else if (match_string(*line, "uav", line))
type = RESOURCE_TYPE_UAV;
else if (match_string(*line, "vb", line))
type = RESOURCE_TYPE_VERTEX_BUFFER;
else
fatal_error("Malformed resource reference '%s'.\n", *line);
if (type != RESOURCE_TYPE_DEPTH_STENCIL)
read_uint(line, &slot, false);
return shader_runner_get_resource(runner, type, slot);
}
static void parse_test_directive(struct shader_runner *runner, const char *line) static void parse_test_directive(struct shader_runner *runner, const char *line)
{ {
bool skip_directive = false; bool skip_directive = false;
@ -1044,6 +1068,26 @@ static void parse_test_directive(struct shader_runner *runner, const char *line)
runner->last_render_failed = !runner->ops->draw(runner, topology, vertex_count, instance_count); runner->last_render_failed = !runner->ops->draw(runner, topology, vertex_count, instance_count);
} }
else if (match_string(line, "copy", &line))
{
struct resource *src, *dst;
if (!(src = parse_resource_reference(runner, &line)))
fatal_error("Undefined source resource.\n");
if (!(dst = parse_resource_reference(runner, &line)))
fatal_error("Undefined destination resource.\n");
if (src->desc.dimension != dst->desc.dimension
|| src->desc.texel_size != dst->desc.texel_size
|| src->desc.width != dst->desc.width
|| src->desc.height != dst->desc.height
|| src->desc.level_count != dst->desc.level_count
|| src->desc.sample_count != dst->desc.sample_count)
fatal_error("Resource dimensions don't match.\n");
if (!(runner->ops->copy(runner, src, dst)))
fatal_error("Failed to copy resource.\n");
}
else if (match_string(line, "probe", &line)) else if (match_string(line, "probe", &line))
{ {
unsigned int left, top, right, bottom, ulps, slot; unsigned int left, top, right, bottom, ulps, slot;

View File

@ -230,6 +230,7 @@ struct shader_runner_ops
void (*clear)(struct shader_runner *runner, struct resource *resource, const struct vec4 *clear_value); void (*clear)(struct shader_runner *runner, struct resource *resource, const struct vec4 *clear_value);
bool (*draw)(struct shader_runner *runner, D3D_PRIMITIVE_TOPOLOGY primitive_topology, unsigned int vertex_count, bool (*draw)(struct shader_runner *runner, D3D_PRIMITIVE_TOPOLOGY primitive_topology, unsigned int vertex_count,
unsigned int instance_count); unsigned int instance_count);
bool (*copy)(struct shader_runner *runner, struct resource *src, struct resource *dst);
bool (*dispatch)(struct shader_runner *runner, unsigned int x, unsigned int y, unsigned int z); bool (*dispatch)(struct shader_runner *runner, unsigned int x, unsigned int y, unsigned int z);
struct resource_readback *(*get_resource_readback)(struct shader_runner *runner, struct resource *resource); struct resource_readback *(*get_resource_readback)(struct shader_runner *runner, struct resource *resource);
void (*release_readback)(struct shader_runner *runner, struct resource_readback *rb); void (*release_readback)(struct shader_runner *runner, struct resource_readback *rb);

View File

@ -901,6 +901,17 @@ static bool d3d11_runner_draw(struct shader_runner *r,
return true; return true;
} }
static bool d3d11_runner_copy(struct shader_runner *r, struct resource *src, struct resource *dst)
{
struct d3d11_shader_runner *runner = d3d11_shader_runner(r);
struct d3d11_resource *s = d3d11_resource(src);
struct d3d11_resource *d = d3d11_resource(dst);
ID3D11DeviceContext_CopyResource(runner->immediate_context, d->resource, s->resource);
return true;
}
struct d3d11_resource_readback struct d3d11_resource_readback
{ {
struct resource_readback rb; struct resource_readback rb;
@ -1000,6 +1011,7 @@ static const struct shader_runner_ops d3d11_runner_ops =
.dispatch = d3d11_runner_dispatch, .dispatch = d3d11_runner_dispatch,
.clear = d3d11_runner_clear, .clear = d3d11_runner_clear,
.draw = d3d11_runner_draw, .draw = d3d11_runner_draw,
.copy = d3d11_runner_copy,
.get_resource_readback = d3d11_runner_get_resource_readback, .get_resource_readback = d3d11_runner_get_resource_readback,
.release_readback = d3d11_runner_release_readback, .release_readback = d3d11_runner_release_readback,
}; };

View File

@ -902,6 +902,33 @@ static bool d3d12_runner_draw(struct shader_runner *r,
return true; return true;
} }
static bool d3d12_runner_copy(struct shader_runner *r, struct resource *src, struct resource *dst)
{
struct d3d12_shader_runner *runner = d3d12_shader_runner(r);
struct test_context *context = &runner->test_context;
struct d3d12_resource *s = d3d12_resource(src);
struct d3d12_resource *d = d3d12_resource(dst);
D3D12_RESOURCE_STATES src_state, dst_state;
HRESULT hr;
src_state = resource_get_state(src);
dst_state = resource_get_state(dst);
transition_resource_state(context->list, s->resource, src_state, D3D12_RESOURCE_STATE_COPY_SOURCE);
transition_resource_state(context->list, d->resource, dst_state, D3D12_RESOURCE_STATE_COPY_DEST);
ID3D12GraphicsCommandList_CopyResource(context->list, d->resource, s->resource);
transition_resource_state(context->list, d->resource, D3D12_RESOURCE_STATE_COPY_DEST, dst_state);
transition_resource_state(context->list, s->resource, D3D12_RESOURCE_STATE_COPY_SOURCE, src_state);
hr = ID3D12GraphicsCommandList_Close(context->list);
ok(hr == S_OK, "Failed to close command list, hr %#x.\n", hr);
exec_command_list(context->queue, context->list);
wait_queue_idle(context->device, context->queue);
reset_command_list(context->list, context->allocator);
return true;
}
static struct resource_readback *d3d12_runner_get_resource_readback(struct shader_runner *r, struct resource *res) static struct resource_readback *d3d12_runner_get_resource_readback(struct shader_runner *r, struct resource *res)
{ {
struct d3d12_shader_runner *runner = d3d12_shader_runner(r); struct d3d12_shader_runner *runner = d3d12_shader_runner(r);
@ -933,6 +960,7 @@ static const struct shader_runner_ops d3d12_runner_ops =
.dispatch = d3d12_runner_dispatch, .dispatch = d3d12_runner_dispatch,
.clear = d3d12_runner_clear, .clear = d3d12_runner_clear,
.draw = d3d12_runner_draw, .draw = d3d12_runner_draw,
.copy = d3d12_runner_copy,
.get_resource_readback = d3d12_runner_get_resource_readback, .get_resource_readback = d3d12_runner_get_resource_readback,
.release_readback = d3d12_runner_release_readback, .release_readback = d3d12_runner_release_readback,
}; };

View File

@ -546,6 +546,11 @@ static bool d3d9_runner_draw(struct shader_runner *r,
return true; return true;
} }
static bool d3d9_runner_copy(struct shader_runner *r, struct resource *src, struct resource *dst)
{
return false;
}
struct d3d9_resource_readback struct d3d9_resource_readback
{ {
struct resource_readback rb; struct resource_readback rb;
@ -599,6 +604,7 @@ static const struct shader_runner_ops d3d9_runner_ops =
.dispatch = d3d9_runner_dispatch, .dispatch = d3d9_runner_dispatch,
.clear = d3d9_runner_clear, .clear = d3d9_runner_clear,
.draw = d3d9_runner_draw, .draw = d3d9_runner_draw,
.copy = d3d9_runner_copy,
.get_resource_readback = d3d9_runner_get_resource_readback, .get_resource_readback = d3d9_runner_get_resource_readback,
.release_readback = d3d9_runner_release_readback, .release_readback = d3d9_runner_release_readback,
}; };

View File

@ -113,6 +113,7 @@ static bool check_gl_extensions(struct gl_runner *runner)
{ {
"GL_ARB_clip_control", "GL_ARB_clip_control",
"GL_ARB_compute_shader", "GL_ARB_compute_shader",
"GL_ARB_copy_image",
"GL_ARB_sampler_objects", "GL_ARB_sampler_objects",
"GL_ARB_shader_image_load_store", "GL_ARB_shader_image_load_store",
"GL_ARB_texture_storage", "GL_ARB_texture_storage",
@ -1249,6 +1250,28 @@ static bool gl_runner_draw(struct shader_runner *r,
return true; return true;
} }
static bool gl_runner_copy(struct shader_runner *r, struct resource *src, struct resource *dst)
{
struct gl_resource *s = gl_resource(src);
struct gl_resource *d = gl_resource(dst);
GLenum target = GL_TEXTURE_2D;
unsigned int l, w, h;
if (src->desc.dimension == RESOURCE_DIMENSION_BUFFER)
return false;
if (src->desc.sample_count > 1)
target = GL_TEXTURE_2D_MULTISAMPLE;
for (l = 0; l < src->desc.level_count; ++l)
{
w = get_level_dimension(src->desc.width, l);
h = get_level_dimension(src->desc.height, l);
glCopyImageSubData(s->id, target, l, 0, 0, 0, d->id, target, l, 0, 0, 0, w, h, 1);
}
return true;
}
struct gl_resource_readback struct gl_resource_readback
{ {
struct resource_readback rb; struct resource_readback rb;
@ -1330,6 +1353,7 @@ static const struct shader_runner_ops gl_runner_ops =
.dispatch = gl_runner_dispatch, .dispatch = gl_runner_dispatch,
.clear = gl_runner_clear, .clear = gl_runner_clear,
.draw = gl_runner_draw, .draw = gl_runner_draw,
.copy = gl_runner_copy,
.get_resource_readback = gl_runner_get_resource_readback, .get_resource_readback = gl_runner_get_resource_readback,
.release_readback = gl_runner_release_readback, .release_readback = gl_runner_release_readback,
}; };

View File

@ -1256,6 +1256,66 @@ out:
return ret; return ret;
} }
static VkImageLayout resource_get_layout(struct resource *r)
{
if (r->desc.type == RESOURCE_TYPE_RENDER_TARGET)
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
if (r->desc.type == RESOURCE_TYPE_DEPTH_STENCIL)
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
if (r->desc.type == RESOURCE_TYPE_TEXTURE)
return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
return VK_IMAGE_LAYOUT_GENERAL;
}
static bool vulkan_runner_copy(struct shader_runner *r, struct resource *src, struct resource *dst)
{
struct vulkan_shader_runner *runner = vulkan_shader_runner(r);
const struct vulkan_test_context *context = &runner->context;
VkImageAspectFlags aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT;
struct vulkan_resource *s = vulkan_resource(src);
struct vulkan_resource *d = vulkan_resource(dst);
VkImageLayout src_layout, dst_layout;
VkImageCopy vk_image_copy;
unsigned int l;
if (src->desc.dimension == RESOURCE_DIMENSION_BUFFER)
return false;
if (src->desc.type == RESOURCE_TYPE_DEPTH_STENCIL)
aspect_mask = VK_IMAGE_ASPECT_DEPTH_BIT;
src_layout = resource_get_layout(src);
dst_layout = resource_get_layout(dst);
begin_command_buffer(context);
transition_image_layout(context, s->image, aspect_mask, src_layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
transition_image_layout(context, d->image, aspect_mask,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
vk_image_copy.srcSubresource = (VkImageSubresourceLayers){.aspectMask = aspect_mask, .layerCount = 1};
vk_image_copy.srcOffset = (VkOffset3D){.x = 0, .y = 0, .z = 0};
vk_image_copy.dstSubresource = vk_image_copy.srcSubresource;
vk_image_copy.dstOffset = vk_image_copy.srcOffset;
vk_image_copy.extent.depth = 1;
for (l = 0; l < src->desc.level_count; ++l)
{
vk_image_copy.srcSubresource.mipLevel = l;
vk_image_copy.dstSubresource.mipLevel = l;
vk_image_copy.extent.width = get_level_dimension(src->desc.width, l);
vk_image_copy.extent.height = get_level_dimension(src->desc.height, l);
VK_CALL(vkCmdCopyImage(context->cmd_buffer, s->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
d->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &vk_image_copy));
}
transition_image_layout(context, d->image, aspect_mask, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_layout);
transition_image_layout(context, s->image, aspect_mask, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, src_layout);
end_command_buffer(context);
return true;
}
struct vulkan_resource_readback struct vulkan_resource_readback
{ {
struct resource_readback rb; struct resource_readback rb;
@ -1300,13 +1360,7 @@ static struct resource_readback *vulkan_runner_get_resource_readback(struct shad
aspect_mask = (resource->r.desc.type == RESOURCE_TYPE_DEPTH_STENCIL) aspect_mask = (resource->r.desc.type == RESOURCE_TYPE_DEPTH_STENCIL)
? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
layout = resource_get_layout(res);
if (resource->r.desc.type == RESOURCE_TYPE_RENDER_TARGET)
layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
else if (resource->r.desc.type == RESOURCE_TYPE_DEPTH_STENCIL)
layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
else
layout = VK_IMAGE_LAYOUT_GENERAL;
begin_command_buffer(context); begin_command_buffer(context);
@ -1388,6 +1442,7 @@ static const struct shader_runner_ops vulkan_runner_ops =
.dispatch = vulkan_runner_dispatch, .dispatch = vulkan_runner_dispatch,
.clear = vulkan_runner_clear, .clear = vulkan_runner_clear,
.draw = vulkan_runner_draw, .draw = vulkan_runner_draw,
.copy = vulkan_runner_copy,
.get_resource_readback = vulkan_runner_get_resource_readback, .get_resource_readback = vulkan_runner_get_resource_readback,
.release_readback = vulkan_runner_release_readback, .release_readback = vulkan_runner_release_readback,
}; };
@ -1615,6 +1670,7 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner)
features.x = VK_TRUE features.x = VK_TRUE
ENABLE_FEATURE(fragmentStoresAndAtomics); ENABLE_FEATURE(fragmentStoresAndAtomics);
ENABLE_FEATURE(sampleRateShading);
ENABLE_FEATURE(shaderClipDistance); ENABLE_FEATURE(shaderClipDistance);
ENABLE_FEATURE(shaderImageGatherExtended); ENABLE_FEATURE(shaderImageGatherExtended);
ENABLE_FEATURE(shaderStorageImageWriteWithoutFormat); ENABLE_FEATURE(shaderStorageImageWriteWithoutFormat);

View File

@ -60,6 +60,7 @@ VK_DEVICE_PFN(vkCmdBindPipeline)
VK_DEVICE_PFN(vkCmdBindVertexBuffers) VK_DEVICE_PFN(vkCmdBindVertexBuffers)
VK_DEVICE_PFN(vkCmdClearAttachments) VK_DEVICE_PFN(vkCmdClearAttachments)
VK_DEVICE_PFN(vkCmdCopyBufferToImage) VK_DEVICE_PFN(vkCmdCopyBufferToImage)
VK_DEVICE_PFN(vkCmdCopyImage)
VK_DEVICE_PFN(vkCmdCopyImageToBuffer) VK_DEVICE_PFN(vkCmdCopyImageToBuffer)
VK_DEVICE_PFN(vkCmdDispatch) VK_DEVICE_PFN(vkCmdDispatch)
VK_DEVICE_PFN(vkCmdDraw) VK_DEVICE_PFN(vkCmdDraw)