mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
tests: Implement multisampling in the Vulkan renderer.
This commit is contained in:
parent
fe21318b5f
commit
737967604e
Notes:
Henri Verbeet
2024-07-11 00:41:24 +02:00
Approved-by: Giovanni Mascellani (@giomasce) Approved-by: Henri Verbeet (@hverbeet) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/924
@ -939,6 +939,14 @@ static void parse_test_directive(struct shader_runner *runner, const char *line)
|
|||||||
if (!runner->vs_source)
|
if (!runner->vs_source)
|
||||||
runner->vs_source = strdup(vs_source);
|
runner->vs_source = strdup(vs_source);
|
||||||
|
|
||||||
|
runner->sample_count = 1;
|
||||||
|
for (i = 0; i < runner->resource_count; ++i)
|
||||||
|
{
|
||||||
|
if (runner->resources[i]->desc.type == RESOURCE_TYPE_RENDER_TARGET
|
||||||
|
|| runner->resources[i]->desc.type == RESOURCE_TYPE_DEPTH_STENCIL)
|
||||||
|
runner->sample_count = max(runner->sample_count, runner->resources[i]->desc.sample_count);
|
||||||
|
}
|
||||||
|
|
||||||
runner->last_render_failed = !runner->ops->draw(runner, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, 3, 1);
|
runner->last_render_failed = !runner->ops->draw(runner, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, 3, 1);
|
||||||
}
|
}
|
||||||
else if (match_string(line, "draw", &line))
|
else if (match_string(line, "draw", &line))
|
||||||
@ -990,6 +998,14 @@ static void parse_test_directive(struct shader_runner *runner, const char *line)
|
|||||||
if (line == rest)
|
if (line == rest)
|
||||||
instance_count = 1;
|
instance_count = 1;
|
||||||
|
|
||||||
|
runner->sample_count = 1;
|
||||||
|
for (unsigned int i = 0; i < runner->resource_count; ++i)
|
||||||
|
{
|
||||||
|
if (runner->resources[i]->desc.type == RESOURCE_TYPE_RENDER_TARGET
|
||||||
|
|| runner->resources[i]->desc.type == RESOURCE_TYPE_DEPTH_STENCIL)
|
||||||
|
runner->sample_count = max(runner->sample_count, runner->resources[i]->desc.sample_count);
|
||||||
|
}
|
||||||
|
|
||||||
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, "probe", &line))
|
else if (match_string(line, "probe", &line))
|
||||||
@ -1635,6 +1651,8 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_c
|
|||||||
runner->minimum_shader_model = caps->minimum_shader_model;
|
runner->minimum_shader_model = caps->minimum_shader_model;
|
||||||
runner->maximum_shader_model = caps->maximum_shader_model;
|
runner->maximum_shader_model = caps->maximum_shader_model;
|
||||||
|
|
||||||
|
runner->sample_mask = ~0u;
|
||||||
|
|
||||||
if ((testname = strrchr(test_options.filename, '/')))
|
if ((testname = strrchr(test_options.filename, '/')))
|
||||||
++testname;
|
++testname;
|
||||||
else
|
else
|
||||||
|
@ -186,6 +186,8 @@ struct shader_runner
|
|||||||
uint32_t failed_resources[RESOURCE_TYPE_VERTEX_BUFFER + 1][VKD3D_BITMAP_SIZE(MAX_RESOURCES)];
|
uint32_t failed_resources[RESOURCE_TYPE_VERTEX_BUFFER + 1][VKD3D_BITMAP_SIZE(MAX_RESOURCES)];
|
||||||
unsigned int failed_resource_count;
|
unsigned int failed_resource_count;
|
||||||
|
|
||||||
|
uint32_t sample_count;
|
||||||
|
|
||||||
struct sampler samplers[MAX_SAMPLERS];
|
struct sampler samplers[MAX_SAMPLERS];
|
||||||
size_t sampler_count;
|
size_t sampler_count;
|
||||||
|
|
||||||
|
@ -211,8 +211,8 @@ static VkBufferView create_buffer_view(const struct vulkan_shader_runner *runner
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VkImage create_2d_image(const struct vulkan_shader_runner *runner, uint32_t width, uint32_t height,
|
static VkImage create_2d_image(const struct vulkan_shader_runner *runner,
|
||||||
uint32_t level_count, VkImageUsageFlags usage, VkFormat format, VkDeviceMemory *memory)
|
const struct resource_desc *desc, VkImageUsageFlags usage, VkFormat format, VkDeviceMemory *memory)
|
||||||
{
|
{
|
||||||
VkImageCreateInfo image_info = {.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
|
VkImageCreateInfo image_info = {.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
|
||||||
VkMemoryRequirements memory_reqs;
|
VkMemoryRequirements memory_reqs;
|
||||||
@ -220,12 +220,12 @@ static VkImage create_2d_image(const struct vulkan_shader_runner *runner, uint32
|
|||||||
|
|
||||||
image_info.imageType = VK_IMAGE_TYPE_2D;
|
image_info.imageType = VK_IMAGE_TYPE_2D;
|
||||||
image_info.format = format;
|
image_info.format = format;
|
||||||
image_info.extent.width = width;
|
image_info.extent.width = desc->width;
|
||||||
image_info.extent.height = height;
|
image_info.extent.height = desc->height;
|
||||||
image_info.extent.depth = 1;
|
image_info.extent.depth = 1;
|
||||||
image_info.mipLevels = level_count;
|
image_info.mipLevels = desc->level_count;
|
||||||
image_info.arrayLayers = 1;
|
image_info.arrayLayers = 1;
|
||||||
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
|
image_info.samples = max(desc->sample_count, 1);
|
||||||
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
image_info.usage = usage;
|
image_info.usage = usage;
|
||||||
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
@ -281,8 +281,7 @@ static void resource_init_2d(struct vulkan_shader_runner *runner, struct vulkan_
|
|||||||
usage |= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
usage |= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
resource->image = create_2d_image(runner, params->desc.width, params->desc.height, params->desc.level_count,
|
resource->image = create_2d_image(runner, ¶ms->desc, usage, format, &resource->memory);
|
||||||
usage, format, &resource->memory);
|
|
||||||
resource->image_view = create_2d_image_view(runner, resource->image, format, VK_IMAGE_ASPECT_COLOR_BIT);
|
resource->image_view = create_2d_image_view(runner, resource->image, format, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||||
|
|
||||||
if (!params->data)
|
if (!params->data)
|
||||||
@ -374,7 +373,7 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c
|
|||||||
case RESOURCE_TYPE_RENDER_TARGET:
|
case RESOURCE_TYPE_RENDER_TARGET:
|
||||||
format = vkd3d_get_vk_format(params->desc.format);
|
format = vkd3d_get_vk_format(params->desc.format);
|
||||||
|
|
||||||
resource->image = create_2d_image(runner, params->desc.width, params->desc.height, params->desc.level_count,
|
resource->image = create_2d_image(runner, ¶ms->desc,
|
||||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, format, &resource->memory);
|
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, format, &resource->memory);
|
||||||
resource->image_view = create_2d_image_view(runner, resource->image, format, VK_IMAGE_ASPECT_COLOR_BIT);
|
resource->image_view = create_2d_image_view(runner, resource->image, format, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||||
|
|
||||||
@ -387,7 +386,7 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c
|
|||||||
case RESOURCE_TYPE_DEPTH_STENCIL:
|
case RESOURCE_TYPE_DEPTH_STENCIL:
|
||||||
format = vkd3d_get_vk_format(params->desc.format);
|
format = vkd3d_get_vk_format(params->desc.format);
|
||||||
|
|
||||||
resource->image = create_2d_image(runner, params->desc.width, params->desc.height, params->desc.level_count,
|
resource->image = create_2d_image(runner, ¶ms->desc,
|
||||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, format,
|
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, format,
|
||||||
&resource->memory);
|
&resource->memory);
|
||||||
resource->image_view = create_2d_image_view(runner, resource->image, format, VK_IMAGE_ASPECT_DEPTH_BIT);
|
resource->image_view = create_2d_image_view(runner, resource->image, format, VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||||
@ -451,6 +450,7 @@ static bool compile_shader(struct vulkan_shader_runner *runner, const char *sour
|
|||||||
enum vkd3d_shader_spirv_extension spirv_extensions[2];
|
enum vkd3d_shader_spirv_extension spirv_extensions[2];
|
||||||
struct vkd3d_shader_resource_binding *binding;
|
struct vkd3d_shader_resource_binding *binding;
|
||||||
struct vkd3d_shader_compile_option options[3];
|
struct vkd3d_shader_compile_option options[3];
|
||||||
|
struct vkd3d_shader_parameter parameters[1];
|
||||||
struct vkd3d_shader_compile_option *option;
|
struct vkd3d_shader_compile_option *option;
|
||||||
unsigned int i, compile_options;
|
unsigned int i, compile_options;
|
||||||
char profile[7];
|
char profile[7];
|
||||||
@ -599,6 +599,14 @@ static bool compile_shader(struct vulkan_shader_runner *runner, const char *sour
|
|||||||
interface_info.push_constant_buffer_count = 1;
|
interface_info.push_constant_buffer_count = 1;
|
||||||
interface_info.push_constant_buffers = &push_constants;
|
interface_info.push_constant_buffers = &push_constants;
|
||||||
|
|
||||||
|
parameters[0].name = VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT;
|
||||||
|
parameters[0].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT;
|
||||||
|
parameters[0].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32;
|
||||||
|
parameters[0].u.immediate_constant.u.u32 = runner->r.sample_count;
|
||||||
|
|
||||||
|
spirv_info.parameter_count = ARRAY_SIZE(parameters);
|
||||||
|
spirv_info.parameters = parameters;
|
||||||
|
|
||||||
if (!strcmp(type, "vs"))
|
if (!strcmp(type, "vs"))
|
||||||
{
|
{
|
||||||
interface_info.next = &runner->vs_signatures;
|
interface_info.next = &runner->vs_signatures;
|
||||||
@ -850,8 +858,8 @@ static VkPipeline create_graphics_pipeline(struct vulkan_shader_runner *runner,
|
|||||||
rs_desc.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
rs_desc.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
||||||
rs_desc.lineWidth = 1.0f;
|
rs_desc.lineWidth = 1.0f;
|
||||||
|
|
||||||
/* TODO: sample count and mask. */
|
ms_desc.rasterizationSamples = runner->r.sample_count;
|
||||||
ms_desc.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
ms_desc.pSampleMask = &runner->r.sample_mask;
|
||||||
|
|
||||||
pipeline_desc.stageCount = stage_count;
|
pipeline_desc.stageCount = stage_count;
|
||||||
pipeline_desc.pStages = stage_desc;
|
pipeline_desc.pStages = stage_desc;
|
||||||
@ -1118,7 +1126,7 @@ static void create_render_pass_and_framebuffer(struct vulkan_shader_runner *runn
|
|||||||
layout = is_ds ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
layout = is_ds ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
|
||||||
attachment_desc->format = vkd3d_get_vk_format(resource->r.desc.format);
|
attachment_desc->format = vkd3d_get_vk_format(resource->r.desc.format);
|
||||||
attachment_desc->samples = VK_SAMPLE_COUNT_1_BIT;
|
attachment_desc->samples = max(resource->r.desc.sample_count, 1);
|
||||||
attachment_desc->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
attachment_desc->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||||
attachment_desc->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
attachment_desc->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
attachment_desc->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
attachment_desc->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
@ -1225,7 +1233,7 @@ static void vulkan_runner_clear(struct shader_runner *r, struct resource *res, c
|
|||||||
|
|
||||||
attachment_desc.flags = 0;
|
attachment_desc.flags = 0;
|
||||||
attachment_desc.format = vkd3d_get_vk_format(resource->r.desc.format);
|
attachment_desc.format = vkd3d_get_vk_format(resource->r.desc.format);
|
||||||
attachment_desc.samples = VK_SAMPLE_COUNT_1_BIT;
|
attachment_desc.samples = max(resource->r.desc.sample_count, 1);
|
||||||
attachment_desc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
attachment_desc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||||
attachment_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
attachment_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
/* TODO: formats with a stencil component would a clear op here. */
|
/* TODO: formats with a stencil component would a clear op here. */
|
||||||
@ -1394,6 +1402,10 @@ static struct resource_readback *vulkan_runner_get_resource_readback(struct shad
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
struct resource_desc resolved_desc = resource->r.desc;
|
||||||
|
VkDeviceMemory resolved_memory;
|
||||||
|
VkImage resolved_image;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
@ -1414,13 +1426,48 @@ static struct resource_readback *vulkan_runner_get_resource_readback(struct shad
|
|||||||
region.imageExtent.height = resource->r.desc.height;
|
region.imageExtent.height = resource->r.desc.height;
|
||||||
region.imageExtent.depth = 1;
|
region.imageExtent.depth = 1;
|
||||||
|
|
||||||
VK_CALL(vkCmdCopyImageToBuffer(runner->cmd_buffer, resource->image,
|
if (resource->r.desc.sample_count > 1)
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, rb->buffer, 1, ®ion));
|
{
|
||||||
|
VkImageResolve resolve_region = {{0}};
|
||||||
|
|
||||||
|
resolve_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
resolve_region.srcSubresource.layerCount = 1;
|
||||||
|
resolve_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
resolve_region.dstSubresource.layerCount = 1;
|
||||||
|
resolve_region.extent.width = resource->r.desc.width;
|
||||||
|
resolve_region.extent.height = resource->r.desc.height;
|
||||||
|
resolve_region.extent.depth = 1;
|
||||||
|
|
||||||
|
resolved_desc.sample_count = 1;
|
||||||
|
resolved_image = create_2d_image(runner, &resolved_desc,
|
||||||
|
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
||||||
|
vkd3d_get_vk_format(resource->r.desc.format), &resolved_memory);
|
||||||
|
transition_image_layout(runner, resolved_image, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
|
||||||
|
VK_CALL(vkCmdResolveImage(runner->cmd_buffer, resource->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
|
resolved_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &resolve_region));
|
||||||
|
transition_image_layout(runner, resolved_image, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||||
|
VK_CALL(vkCmdCopyImageToBuffer(runner->cmd_buffer, resolved_image,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, rb->buffer, 1, ®ion));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VK_CALL(vkCmdCopyImageToBuffer(runner->cmd_buffer, resource->image,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, rb->buffer, 1, ®ion));
|
||||||
|
}
|
||||||
|
|
||||||
transition_image_layout(runner, resource->image, aspect_mask, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, layout);
|
transition_image_layout(runner, resource->image, aspect_mask, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, layout);
|
||||||
|
|
||||||
end_command_buffer(runner);
|
end_command_buffer(runner);
|
||||||
|
|
||||||
|
if (resource->r.desc.sample_count > 1)
|
||||||
|
{
|
||||||
|
VK_CALL(vkFreeMemory(device, resolved_memory, NULL));
|
||||||
|
VK_CALL(vkDestroyImage(device, resolved_image, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
VK_CALL(vkMapMemory(device, rb->memory, 0, VK_WHOLE_SIZE, 0, &rb->rb.data));
|
VK_CALL(vkMapMemory(device, rb->memory, 0, VK_WHOLE_SIZE, 0, &rb->rb.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@ VK_DEVICE_PFN(vkCmdEndRenderPass)
|
|||||||
VK_DEVICE_PFN(vkCmdFillBuffer)
|
VK_DEVICE_PFN(vkCmdFillBuffer)
|
||||||
VK_DEVICE_PFN(vkCmdPipelineBarrier)
|
VK_DEVICE_PFN(vkCmdPipelineBarrier)
|
||||||
VK_DEVICE_PFN(vkCmdPushConstants)
|
VK_DEVICE_PFN(vkCmdPushConstants)
|
||||||
|
VK_DEVICE_PFN(vkCmdResolveImage)
|
||||||
VK_DEVICE_PFN(vkCreateBuffer)
|
VK_DEVICE_PFN(vkCreateBuffer)
|
||||||
VK_DEVICE_PFN(vkCreateBufferView)
|
VK_DEVICE_PFN(vkCreateBufferView)
|
||||||
VK_DEVICE_PFN(vkCreateCommandPool)
|
VK_DEVICE_PFN(vkCreateCommandPool)
|
||||||
|
Loading…
Reference in New Issue
Block a user