2022-04-11 10:18:31 -07:00
|
|
|
/*
|
|
|
|
* Shader runner which uses libvkd3d-shader to compile HLSL -> D3D bytecode -> SPIR-V
|
|
|
|
*
|
|
|
|
* Copyright 2020-2022 Zebediah Figura for CodeWeavers
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
2023-01-18 04:53:51 -08:00
|
|
|
#ifndef _WIN32
|
|
|
|
|
2022-04-18 18:28:45 -07:00
|
|
|
#define VK_NO_PROTOTYPES
|
2022-05-17 06:45:40 -07:00
|
|
|
#define VKD3D_TEST_NO_DEFS
|
2022-04-11 10:18:31 -07:00
|
|
|
#include "config.h"
|
|
|
|
#include "vkd3d.h"
|
2023-07-12 22:41:14 -07:00
|
|
|
#include "vkd3d_d3dcompiler.h"
|
2022-04-11 10:18:31 -07:00
|
|
|
#include "shader_runner.h"
|
2024-07-07 20:52:54 -07:00
|
|
|
#include "vulkan_utils.h"
|
2022-04-11 10:18:31 -07:00
|
|
|
#include "vkd3d_test.h"
|
|
|
|
|
|
|
|
struct vulkan_resource
|
|
|
|
{
|
|
|
|
struct resource r;
|
|
|
|
|
|
|
|
VkBuffer buffer;
|
2023-05-09 10:56:55 -07:00
|
|
|
VkBufferView buffer_view;
|
2022-04-11 10:18:31 -07:00
|
|
|
VkImage image;
|
2023-05-09 10:56:55 -07:00
|
|
|
VkImageView image_view;
|
2022-04-11 10:18:31 -07:00
|
|
|
VkDeviceMemory memory;
|
|
|
|
|
|
|
|
uint32_t binding;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct vulkan_resource *vulkan_resource(struct resource *r)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(r, struct vulkan_resource, r);
|
|
|
|
}
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
struct vulkan_shader_runner
|
|
|
|
{
|
|
|
|
struct shader_runner r;
|
|
|
|
struct shader_runner_caps caps;
|
|
|
|
bool demote_to_helper_invocation;
|
2024-10-19 02:13:07 -07:00
|
|
|
bool driver_properties;
|
2024-07-07 20:42:49 -07:00
|
|
|
|
|
|
|
struct vulkan_test_context context;
|
|
|
|
|
2023-02-24 11:50:11 -08:00
|
|
|
struct vkd3d_shader_scan_signature_info vs_signatures;
|
|
|
|
|
2022-04-11 10:18:31 -07:00
|
|
|
struct vulkan_sampler
|
|
|
|
{
|
|
|
|
VkSampler vk_sampler;
|
|
|
|
uint32_t binding;
|
|
|
|
} samplers[MAX_SAMPLERS];
|
|
|
|
};
|
|
|
|
|
2023-10-11 14:09:23 -07:00
|
|
|
struct physical_device_info
|
|
|
|
{
|
|
|
|
VkPhysicalDeviceFeatures2 features2;
|
|
|
|
VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT interlock_features;
|
2024-04-17 07:16:34 -07:00
|
|
|
VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT demote_to_helper_invocation_features;
|
2024-10-19 02:13:07 -07:00
|
|
|
VkPhysicalDeviceProperties2 properties2;
|
|
|
|
VkPhysicalDeviceDriverPropertiesKHR driver_properties;
|
2023-10-11 14:09:23 -07:00
|
|
|
};
|
|
|
|
|
2022-04-11 10:18:31 -07:00
|
|
|
static struct vulkan_shader_runner *vulkan_shader_runner(struct shader_runner *r)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(r, struct vulkan_shader_runner, r);
|
|
|
|
}
|
|
|
|
|
2024-01-22 15:20:18 -08:00
|
|
|
static void resource_init_2d(struct vulkan_shader_runner *runner, struct vulkan_resource *resource,
|
|
|
|
const struct resource_params *params)
|
|
|
|
{
|
|
|
|
VkImageUsageFlagBits usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
|
|
|
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
2024-06-17 14:01:04 -07:00
|
|
|
VkFormat format = vkd3d_get_vk_format(params->desc.format);
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct resource_desc *desc = ¶ms->desc;
|
|
|
|
VkDevice device = context->device;
|
2024-01-22 15:20:18 -08:00
|
|
|
unsigned int buffer_offset = 0;
|
|
|
|
VkDeviceMemory staging_memory;
|
|
|
|
VkBuffer staging_buffer;
|
|
|
|
void *data;
|
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
if (params->desc.type == RESOURCE_TYPE_UAV)
|
2024-01-22 15:20:18 -08:00
|
|
|
{
|
|
|
|
layout = VK_IMAGE_LAYOUT_GENERAL;
|
|
|
|
usage |= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
|
|
|
}
|
|
|
|
|
2024-07-07 21:04:53 -07:00
|
|
|
resource->image = create_vulkan_2d_image(context, desc->width, desc->height, desc->level_count, desc->sample_count,
|
2024-07-07 20:42:49 -07:00
|
|
|
usage, format, &resource->memory);
|
2024-07-07 21:04:53 -07:00
|
|
|
resource->image_view = create_vulkan_2d_image_view(context, resource->image, format, VK_IMAGE_ASPECT_COLOR_BIT);
|
2024-01-22 15:20:18 -08:00
|
|
|
|
|
|
|
if (!params->data)
|
|
|
|
{
|
2024-07-07 20:42:49 -07:00
|
|
|
begin_command_buffer(context);
|
|
|
|
transition_image_layout(context, resource->image, VK_IMAGE_ASPECT_COLOR_BIT,
|
2024-01-22 15:20:18 -08:00
|
|
|
VK_IMAGE_LAYOUT_UNDEFINED, layout);
|
2024-07-07 20:42:49 -07:00
|
|
|
end_command_buffer(context);
|
2024-01-22 15:20:18 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-07-07 21:04:53 -07:00
|
|
|
staging_buffer = create_vulkan_buffer(context, params->data_size,
|
2024-01-22 15:20:18 -08:00
|
|
|
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &staging_memory);
|
|
|
|
VK_CALL(vkMapMemory(device, staging_memory, 0, VK_WHOLE_SIZE, 0, &data));
|
|
|
|
memcpy(data, params->data, params->data_size);
|
|
|
|
VK_CALL(vkUnmapMemory(device, staging_memory));
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
begin_command_buffer(context);
|
2024-01-22 15:20:18 -08:00
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
transition_image_layout(context, resource->image, VK_IMAGE_ASPECT_COLOR_BIT,
|
2024-01-22 15:20:18 -08:00
|
|
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
for (unsigned int level = 0; level < params->desc.level_count; ++level)
|
2024-01-22 15:20:18 -08:00
|
|
|
{
|
2024-06-17 14:01:04 -07:00
|
|
|
unsigned int level_width = get_level_dimension(params->desc.width, level);
|
|
|
|
unsigned int level_height = get_level_dimension(params->desc.height, level);
|
2024-01-22 15:20:18 -08:00
|
|
|
VkBufferImageCopy region = {0};
|
|
|
|
|
|
|
|
region.bufferOffset = buffer_offset;
|
|
|
|
region.imageSubresource.mipLevel = level;
|
|
|
|
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
region.imageSubresource.layerCount = 1;
|
|
|
|
region.imageExtent.width = level_width;
|
|
|
|
region.imageExtent.height = level_height;
|
|
|
|
region.imageExtent.depth = 1;
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkCmdCopyBufferToImage(context->cmd_buffer, staging_buffer, resource->image,
|
2024-01-22 15:20:18 -08:00
|
|
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion));
|
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
buffer_offset += level_width * level_height * params->desc.texel_size;
|
2024-01-22 15:20:18 -08:00
|
|
|
}
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
transition_image_layout(context, resource->image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, layout);
|
2024-01-22 15:20:18 -08:00
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
end_command_buffer(context);
|
2024-01-22 15:20:18 -08:00
|
|
|
|
|
|
|
VK_CALL(vkFreeMemory(device, staging_memory, NULL));
|
|
|
|
VK_CALL(vkDestroyBuffer(device, staging_buffer, NULL));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void resource_init_buffer(struct vulkan_shader_runner *runner, struct vulkan_resource *resource,
|
|
|
|
const struct resource_params *params)
|
|
|
|
{
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
2024-06-17 14:01:04 -07:00
|
|
|
VkFormat format = vkd3d_get_vk_format(params->desc.format);
|
2024-07-07 20:42:49 -07:00
|
|
|
VkDevice device = context->device;
|
2024-01-23 15:26:11 -08:00
|
|
|
VkBufferUsageFlagBits usage;
|
2024-01-22 15:20:18 -08:00
|
|
|
void *data;
|
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
if (params->desc.type == RESOURCE_TYPE_UAV)
|
2024-01-23 15:26:11 -08:00
|
|
|
usage = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
|
|
|
|
else
|
|
|
|
usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
|
|
|
|
|
2024-01-31 22:01:45 -08:00
|
|
|
/* d3d12 requires DXGI_FORMAT_UNKNOWN for structured buffers, but Vulkan requires a defined format. */
|
|
|
|
if (format == VK_FORMAT_UNDEFINED && params->stride)
|
|
|
|
format = VK_FORMAT_R32_UINT;
|
|
|
|
|
2024-07-07 21:04:53 -07:00
|
|
|
resource->buffer = create_vulkan_buffer(context, params->data_size, usage,
|
2024-01-22 15:20:18 -08:00
|
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &resource->memory);
|
2024-07-07 21:04:53 -07:00
|
|
|
resource->buffer_view = create_vulkan_buffer_view(context, resource->buffer, format, 0);
|
2024-01-22 15:20:18 -08:00
|
|
|
|
|
|
|
VK_CALL(vkMapMemory(device, resource->memory, 0, VK_WHOLE_SIZE, 0, &data));
|
|
|
|
memcpy(data, params->data, params->data_size);
|
|
|
|
VK_CALL(vkUnmapMemory(device, resource->memory));
|
|
|
|
}
|
|
|
|
|
2022-04-11 10:18:31 -07:00
|
|
|
static struct resource *vulkan_runner_create_resource(struct shader_runner *r, const struct resource_params *params)
|
|
|
|
{
|
|
|
|
struct vulkan_shader_runner *runner = vulkan_shader_runner(r);
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
|
|
|
const struct resource_desc *desc = ¶ms->desc;
|
|
|
|
VkDevice device = context->device;
|
2022-04-11 10:18:31 -07:00
|
|
|
struct vulkan_resource *resource;
|
|
|
|
VkFormat format;
|
|
|
|
void *data;
|
|
|
|
|
|
|
|
resource = calloc(1, sizeof(*resource));
|
2022-06-08 16:18:35 -07:00
|
|
|
init_resource(&resource->r, params);
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
switch (params->desc.type)
|
2022-04-11 10:18:31 -07:00
|
|
|
{
|
2022-06-08 16:18:37 -07:00
|
|
|
case RESOURCE_TYPE_RENDER_TARGET:
|
2024-06-17 14:01:04 -07:00
|
|
|
format = vkd3d_get_vk_format(params->desc.format);
|
2022-06-08 16:18:37 -07:00
|
|
|
|
2024-07-07 21:04:53 -07:00
|
|
|
resource->image = create_vulkan_2d_image(context, desc->width, desc->height, desc->level_count,
|
|
|
|
desc->sample_count, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
|
|
|
format, &resource->memory);
|
|
|
|
resource->image_view = create_vulkan_2d_image_view(context,
|
|
|
|
resource->image, format, VK_IMAGE_ASPECT_COLOR_BIT);
|
2022-06-08 16:18:37 -07:00
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
begin_command_buffer(context);
|
|
|
|
transition_image_layout(context, resource->image, VK_IMAGE_ASPECT_COLOR_BIT,
|
2022-06-08 16:18:37 -07:00
|
|
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
2024-07-07 20:42:49 -07:00
|
|
|
end_command_buffer(context);
|
2022-06-08 16:18:37 -07:00
|
|
|
break;
|
|
|
|
|
2024-04-14 17:33:15 -07:00
|
|
|
case RESOURCE_TYPE_DEPTH_STENCIL:
|
2024-06-17 14:01:04 -07:00
|
|
|
format = vkd3d_get_vk_format(params->desc.format);
|
2024-04-14 17:33:15 -07:00
|
|
|
|
2024-07-07 21:04:53 -07:00
|
|
|
resource->image = create_vulkan_2d_image(context, desc->width, desc->height, desc->level_count,
|
|
|
|
desc->sample_count, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
|
|
|
format, &resource->memory);
|
|
|
|
resource->image_view = create_vulkan_2d_image_view(context,
|
|
|
|
resource->image, format, VK_IMAGE_ASPECT_DEPTH_BIT);
|
2024-04-14 17:33:15 -07:00
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
begin_command_buffer(context);
|
|
|
|
transition_image_layout(context, resource->image, VK_IMAGE_ASPECT_DEPTH_BIT,
|
2024-04-14 17:33:15 -07:00
|
|
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
2024-07-07 20:42:49 -07:00
|
|
|
end_command_buffer(context);
|
2024-04-14 17:33:15 -07:00
|
|
|
break;
|
|
|
|
|
2022-04-11 10:18:31 -07:00
|
|
|
case RESOURCE_TYPE_TEXTURE:
|
2024-01-22 15:20:18 -08:00
|
|
|
case RESOURCE_TYPE_UAV:
|
2024-06-17 14:01:04 -07:00
|
|
|
if (params->desc.dimension == RESOURCE_DIMENSION_BUFFER)
|
2024-01-22 15:20:18 -08:00
|
|
|
resource_init_buffer(runner, resource, params);
|
|
|
|
else
|
|
|
|
resource_init_2d(runner, resource, params);
|
2023-05-09 10:56:55 -07:00
|
|
|
break;
|
|
|
|
|
2022-04-11 10:18:31 -07:00
|
|
|
case RESOURCE_TYPE_VERTEX_BUFFER:
|
2024-07-07 21:04:53 -07:00
|
|
|
resource->buffer = create_vulkan_buffer(context, params->data_size,
|
|
|
|
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &resource->memory);
|
2022-04-11 10:18:31 -07:00
|
|
|
|
|
|
|
VK_CALL(vkMapMemory(device, resource->memory, 0, VK_WHOLE_SIZE, 0, &data));
|
|
|
|
memcpy(data, params->data, params->data_size);
|
|
|
|
VK_CALL(vkUnmapMemory(device, resource->memory));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return &resource->r;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void vulkan_runner_destroy_resource(struct shader_runner *r, struct resource *res)
|
|
|
|
{
|
|
|
|
struct vulkan_shader_runner *runner = vulkan_shader_runner(r);
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
2022-04-11 10:18:31 -07:00
|
|
|
struct vulkan_resource *resource = vulkan_resource(res);
|
2024-07-07 20:42:49 -07:00
|
|
|
VkDevice device = context->device;
|
2022-04-11 10:18:31 -07:00
|
|
|
|
|
|
|
if (resource->memory)
|
|
|
|
VK_CALL(vkFreeMemory(device, resource->memory, NULL));
|
|
|
|
if (resource->image)
|
|
|
|
VK_CALL(vkDestroyImage(device, resource->image, NULL));
|
2023-05-09 10:56:55 -07:00
|
|
|
if (resource->image_view)
|
|
|
|
VK_CALL(vkDestroyImageView(device, resource->image_view, NULL));
|
2022-04-11 10:18:31 -07:00
|
|
|
if (resource->buffer)
|
|
|
|
VK_CALL(vkDestroyBuffer(device, resource->buffer, NULL));
|
2023-05-09 10:56:55 -07:00
|
|
|
if (resource->buffer_view)
|
|
|
|
VK_CALL(vkDestroyBufferView(device, resource->buffer_view, NULL));
|
2022-04-11 10:18:31 -07:00
|
|
|
|
|
|
|
free(resource);
|
|
|
|
}
|
|
|
|
|
2023-10-27 09:11:57 -07:00
|
|
|
static bool compile_shader(struct vulkan_shader_runner *runner,
|
|
|
|
const char *source, const char *type, struct vkd3d_shader_code *spirv)
|
2022-04-11 10:18:31 -07:00
|
|
|
{
|
|
|
|
struct vkd3d_shader_spirv_target_info spirv_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_SPIRV_TARGET_INFO};
|
|
|
|
struct vkd3d_shader_interface_info interface_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO};
|
2024-05-17 17:53:12 -07:00
|
|
|
struct vkd3d_shader_parameter_info parameter_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_PARAMETER_INFO};
|
2022-04-11 10:18:31 -07:00
|
|
|
struct vkd3d_shader_hlsl_source_info hlsl_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_HLSL_SOURCE_INFO};
|
|
|
|
struct vkd3d_shader_compile_info info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO};
|
|
|
|
struct vkd3d_shader_resource_binding bindings[MAX_RESOURCES + MAX_SAMPLERS];
|
|
|
|
struct vkd3d_shader_push_constant_buffer push_constants;
|
2024-04-17 07:16:34 -07:00
|
|
|
enum vkd3d_shader_spirv_extension spirv_extensions[2];
|
2022-04-11 10:18:31 -07:00
|
|
|
struct vkd3d_shader_resource_binding *binding;
|
2024-03-04 06:29:05 -08:00
|
|
|
struct vkd3d_shader_compile_option options[3];
|
2024-10-15 17:04:25 -07:00
|
|
|
struct vkd3d_shader_parameter1 parameters[17];
|
2024-03-04 06:26:44 -08:00
|
|
|
struct vkd3d_shader_compile_option *option;
|
2023-07-12 22:41:14 -07:00
|
|
|
unsigned int i, compile_options;
|
2023-10-27 09:11:57 -07:00
|
|
|
struct vkd3d_shader_code dxbc;
|
2022-04-11 10:18:31 -07:00
|
|
|
char profile[7];
|
|
|
|
char *messages;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
static const char *const shader_models[] =
|
|
|
|
{
|
2023-11-15 12:41:33 -08:00
|
|
|
[SHADER_MODEL_2_0] = "2_0",
|
|
|
|
[SHADER_MODEL_3_0] = "3_0",
|
2022-04-11 10:18:31 -07:00
|
|
|
[SHADER_MODEL_4_0] = "4_0",
|
|
|
|
[SHADER_MODEL_4_1] = "4_1",
|
|
|
|
[SHADER_MODEL_5_0] = "5_0",
|
|
|
|
[SHADER_MODEL_5_1] = "5_1",
|
|
|
|
};
|
|
|
|
|
|
|
|
info.next = &hlsl_info;
|
|
|
|
info.source.code = source;
|
|
|
|
info.source.size = strlen(source);
|
|
|
|
info.source_type = VKD3D_SHADER_SOURCE_HLSL;
|
2023-11-15 12:41:33 -08:00
|
|
|
if (runner->r.minimum_shader_model < SHADER_MODEL_4_0)
|
|
|
|
info.target_type = VKD3D_SHADER_TARGET_D3D_BYTECODE;
|
|
|
|
else
|
|
|
|
info.target_type = VKD3D_SHADER_TARGET_DXBC_TPF;
|
|
|
|
|
2022-04-11 10:18:31 -07:00
|
|
|
info.log_level = VKD3D_SHADER_LOG_WARNING;
|
|
|
|
|
2023-07-12 22:41:14 -07:00
|
|
|
info.options = options;
|
|
|
|
info.option_count = 0;
|
2024-03-04 06:26:44 -08:00
|
|
|
|
|
|
|
option = &options[info.option_count++];
|
|
|
|
option->name = VKD3D_SHADER_COMPILE_OPTION_API_VERSION;
|
2024-08-29 03:00:00 -07:00
|
|
|
option->value = VKD3D_SHADER_API_VERSION_1_13;
|
2024-03-04 06:26:44 -08:00
|
|
|
|
2023-07-12 22:41:14 -07:00
|
|
|
compile_options = runner->r.compile_options;
|
|
|
|
if (compile_options)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (compile_options & (D3DCOMPILE_PACK_MATRIX_ROW_MAJOR | D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR))
|
|
|
|
{
|
|
|
|
option = &options[info.option_count++];
|
|
|
|
option->name = VKD3D_SHADER_COMPILE_OPTION_PACK_MATRIX_ORDER;
|
|
|
|
option->value = 0;
|
|
|
|
if (compile_options & D3DCOMPILE_PACK_MATRIX_ROW_MAJOR)
|
|
|
|
option->value |= VKD3D_SHADER_COMPILE_OPTION_PACK_MATRIX_ROW_MAJOR;
|
|
|
|
if (compile_options & D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR)
|
|
|
|
option->value |= VKD3D_SHADER_COMPILE_OPTION_PACK_MATRIX_COLUMN_MAJOR;
|
|
|
|
|
|
|
|
compile_options &= ~(D3DCOMPILE_PACK_MATRIX_ROW_MAJOR | D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR);
|
|
|
|
}
|
|
|
|
|
2023-08-25 06:05:51 -07:00
|
|
|
/* FIXME: ignore compatibility flag for now */
|
|
|
|
if (compile_options & D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY)
|
|
|
|
compile_options &= ~D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY;
|
|
|
|
|
2023-07-12 22:41:14 -07:00
|
|
|
if (compile_options)
|
|
|
|
fatal_error("Unsupported compiler options %#x.\n", compile_options);
|
|
|
|
}
|
|
|
|
|
2022-04-11 10:18:31 -07:00
|
|
|
hlsl_info.entry_point = "main";
|
|
|
|
sprintf(profile, "%s_%s", type, shader_models[runner->r.minimum_shader_model]);
|
|
|
|
hlsl_info.profile = profile;
|
|
|
|
|
2023-10-27 09:11:57 -07:00
|
|
|
ret = vkd3d_shader_compile(&info, &dxbc, &messages);
|
2022-04-11 10:18:31 -07:00
|
|
|
if (messages && vkd3d_test_state.debug_level)
|
|
|
|
trace("%s\n", messages);
|
|
|
|
vkd3d_shader_free_messages(messages);
|
|
|
|
if (ret)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
info.next = &spirv_info;
|
2023-10-27 09:11:57 -07:00
|
|
|
info.source = dxbc;
|
2023-11-15 12:41:33 -08:00
|
|
|
if (runner->r.minimum_shader_model < SHADER_MODEL_4_0)
|
|
|
|
info.source_type = VKD3D_SHADER_SOURCE_D3D_BYTECODE;
|
|
|
|
else
|
|
|
|
info.source_type = VKD3D_SHADER_SOURCE_DXBC_TPF;
|
2022-04-11 10:18:31 -07:00
|
|
|
info.target_type = VKD3D_SHADER_TARGET_SPIRV_BINARY;
|
|
|
|
|
2024-03-04 06:29:05 -08:00
|
|
|
option = &options[info.option_count++];
|
|
|
|
option->name = VKD3D_SHADER_COMPILE_OPTION_FEATURE;
|
|
|
|
option->value = shader_runner_caps_get_feature_flags(&runner->caps);
|
|
|
|
|
2022-04-11 10:18:31 -07:00
|
|
|
spirv_info.next = &interface_info;
|
|
|
|
spirv_info.environment = VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0;
|
2024-04-17 07:16:34 -07:00
|
|
|
spirv_info.extensions = spirv_extensions;
|
|
|
|
spirv_info.extension_count = 0;
|
2023-10-11 14:09:23 -07:00
|
|
|
|
2024-10-05 05:46:00 -07:00
|
|
|
if (runner->caps.shader_caps[SHADER_CAP_ROV])
|
2024-04-17 07:16:34 -07:00
|
|
|
spirv_extensions[spirv_info.extension_count++] = VKD3D_SHADER_SPIRV_EXTENSION_EXT_FRAGMENT_SHADER_INTERLOCK;
|
|
|
|
if (runner->demote_to_helper_invocation)
|
|
|
|
spirv_extensions[spirv_info.extension_count++] = VKD3D_SHADER_SPIRV_EXTENSION_EXT_DEMOTE_TO_HELPER_INVOCATION;
|
2022-04-11 10:18:31 -07:00
|
|
|
|
|
|
|
push_constants.register_space = 0;
|
|
|
|
push_constants.register_index = 0;
|
|
|
|
push_constants.shader_visibility = VKD3D_SHADER_VISIBILITY_ALL;
|
|
|
|
push_constants.offset = 0;
|
|
|
|
push_constants.size = runner->r.uniform_count * sizeof(*runner->r.uniforms);
|
|
|
|
|
|
|
|
for (i = 0; i < runner->r.resource_count; ++i)
|
|
|
|
{
|
|
|
|
const struct vulkan_resource *resource = vulkan_resource(runner->r.resources[i]);
|
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
switch (resource->r.desc.type)
|
2022-04-11 10:18:31 -07:00
|
|
|
{
|
2022-06-08 16:18:37 -07:00
|
|
|
case RESOURCE_TYPE_RENDER_TARGET:
|
2024-04-14 17:33:15 -07:00
|
|
|
case RESOURCE_TYPE_DEPTH_STENCIL:
|
2022-04-11 10:18:31 -07:00
|
|
|
case RESOURCE_TYPE_VERTEX_BUFFER:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RESOURCE_TYPE_TEXTURE:
|
2022-06-08 16:18:35 -07:00
|
|
|
case RESOURCE_TYPE_UAV:
|
2022-04-11 10:18:31 -07:00
|
|
|
binding = &bindings[interface_info.binding_count++];
|
2024-06-17 14:01:04 -07:00
|
|
|
if (resource->r.desc.type == RESOURCE_TYPE_UAV)
|
2022-06-08 16:18:35 -07:00
|
|
|
binding->type = VKD3D_SHADER_DESCRIPTOR_TYPE_UAV;
|
|
|
|
else
|
|
|
|
binding->type = VKD3D_SHADER_DESCRIPTOR_TYPE_SRV;
|
2022-04-11 10:18:31 -07:00
|
|
|
binding->register_space = 0;
|
2024-06-17 14:01:04 -07:00
|
|
|
binding->register_index = resource->r.desc.slot;
|
2022-04-11 10:18:31 -07:00
|
|
|
binding->shader_visibility = VKD3D_SHADER_VISIBILITY_ALL;
|
2024-06-17 14:01:04 -07:00
|
|
|
if (resource->r.desc.dimension == RESOURCE_DIMENSION_BUFFER)
|
2023-05-09 10:56:55 -07:00
|
|
|
binding->flags = VKD3D_SHADER_BINDING_FLAG_BUFFER;
|
|
|
|
else
|
|
|
|
binding->flags = VKD3D_SHADER_BINDING_FLAG_IMAGE;
|
2022-04-11 10:18:31 -07:00
|
|
|
binding->binding.set = 0;
|
|
|
|
binding->binding.binding = resource->binding;
|
|
|
|
binding->binding.count = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < runner->r.sampler_count; ++i)
|
|
|
|
{
|
|
|
|
binding = &bindings[interface_info.binding_count++];
|
|
|
|
binding->type = VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER;
|
|
|
|
binding->register_space = 0;
|
|
|
|
binding->register_index = runner->r.samplers[i].slot;
|
|
|
|
binding->shader_visibility = VKD3D_SHADER_VISIBILITY_ALL;
|
|
|
|
binding->flags = VKD3D_SHADER_BINDING_FLAG_IMAGE;
|
|
|
|
binding->binding.set = 0;
|
|
|
|
binding->binding.binding = runner->samplers[i].binding;
|
|
|
|
binding->binding.count = 1;
|
|
|
|
}
|
|
|
|
|
2024-05-17 17:53:12 -07:00
|
|
|
interface_info.next = ¶meter_info;
|
2022-04-11 10:18:31 -07:00
|
|
|
interface_info.bindings = bindings;
|
|
|
|
|
|
|
|
interface_info.push_constant_buffer_count = 1;
|
|
|
|
interface_info.push_constant_buffers = &push_constants;
|
|
|
|
|
2024-06-18 21:53:49 -07:00
|
|
|
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;
|
|
|
|
|
2024-05-17 17:53:12 -07:00
|
|
|
parameters[1].name = VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_FUNC;
|
|
|
|
parameters[1].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT;
|
|
|
|
parameters[1].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32;
|
|
|
|
parameters[1].u.immediate_constant.u.u32 = runner->r.alpha_test_func;
|
|
|
|
|
|
|
|
parameters[2].name = VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_REF;
|
|
|
|
parameters[2].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT;
|
|
|
|
parameters[2].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32;
|
|
|
|
parameters[2].u.immediate_constant.u.f32 = runner->r.alpha_test_ref;
|
|
|
|
|
2024-07-11 15:31:02 -07:00
|
|
|
parameters[3].name = VKD3D_SHADER_PARAMETER_NAME_FLAT_INTERPOLATION;
|
|
|
|
parameters[3].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT;
|
|
|
|
parameters[3].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32;
|
|
|
|
parameters[3].u.immediate_constant.u.u32 = runner->r.flat_shading;
|
|
|
|
|
2024-07-16 17:49:30 -07:00
|
|
|
parameters[4].name = VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_MASK;
|
|
|
|
parameters[4].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT;
|
|
|
|
parameters[4].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32;
|
|
|
|
parameters[4].u.immediate_constant.u.u32 = runner->r.clip_plane_mask;
|
|
|
|
|
|
|
|
for (i = 0; i < 8; ++i)
|
|
|
|
{
|
|
|
|
parameters[5 + i].name = VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0 + i;
|
|
|
|
parameters[5 + i].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT;
|
|
|
|
parameters[5 + i].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4;
|
|
|
|
memcpy(parameters[5 + i].u.immediate_constant.u.f32_vec4, &runner->r.clip_planes[i], 4 * sizeof(float));
|
|
|
|
}
|
|
|
|
|
2024-10-03 14:23:04 -07:00
|
|
|
parameters[13].name = VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE;
|
|
|
|
parameters[13].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT;
|
|
|
|
parameters[13].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32;
|
|
|
|
parameters[13].u.immediate_constant.u.f32 = runner->r.point_size;
|
|
|
|
|
2024-10-03 15:55:33 -07:00
|
|
|
parameters[14].name = VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MIN;
|
|
|
|
parameters[14].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT;
|
|
|
|
parameters[14].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32;
|
|
|
|
parameters[14].u.immediate_constant.u.f32 = runner->r.point_size_min;
|
|
|
|
|
|
|
|
parameters[15].name = VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MAX;
|
|
|
|
parameters[15].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT;
|
|
|
|
parameters[15].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32;
|
|
|
|
parameters[15].u.immediate_constant.u.f32 = runner->r.point_size_max;
|
|
|
|
|
2024-10-15 17:04:25 -07:00
|
|
|
parameters[16].name = VKD3D_SHADER_PARAMETER_NAME_POINT_SPRITE;
|
|
|
|
parameters[16].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT;
|
|
|
|
parameters[16].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32;
|
|
|
|
parameters[16].u.immediate_constant.u.u32 = runner->r.point_sprite;
|
|
|
|
|
2024-05-17 17:53:12 -07:00
|
|
|
parameter_info.parameter_count = ARRAY_SIZE(parameters);
|
|
|
|
parameter_info.parameters = parameters;
|
2024-06-18 21:53:49 -07:00
|
|
|
|
2023-02-24 11:50:11 -08:00
|
|
|
if (!strcmp(type, "vs"))
|
|
|
|
{
|
2024-05-17 17:53:12 -07:00
|
|
|
parameter_info.next = &runner->vs_signatures;
|
2023-02-24 11:50:11 -08:00
|
|
|
|
|
|
|
runner->vs_signatures.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_SIGNATURE_INFO;
|
|
|
|
runner->vs_signatures.next = NULL;
|
|
|
|
}
|
|
|
|
|
2022-04-11 10:18:31 -07:00
|
|
|
ret = vkd3d_shader_compile(&info, spirv, &messages);
|
|
|
|
if (messages && vkd3d_test_state.debug_level)
|
|
|
|
trace("%s\n", messages);
|
|
|
|
vkd3d_shader_free_messages(messages);
|
2023-10-27 09:11:57 -07:00
|
|
|
vkd3d_shader_free_shader_code(&dxbc);
|
2022-04-11 10:18:31 -07:00
|
|
|
if (ret)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-10-27 09:11:57 -07:00
|
|
|
static bool create_shader_stage(struct vulkan_shader_runner *runner, VkPipelineShaderStageCreateInfo *stage_info,
|
|
|
|
const char *type, enum VkShaderStageFlagBits stage, const char *source)
|
2022-04-11 10:18:31 -07:00
|
|
|
{
|
|
|
|
VkShaderModuleCreateInfo module_info = {.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO};
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
2023-10-27 09:11:57 -07:00
|
|
|
struct vkd3d_shader_code spirv;
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2023-10-27 09:11:57 -07:00
|
|
|
if (!compile_shader(runner, source, type, &spirv))
|
2022-04-11 10:18:31 -07:00
|
|
|
return false;
|
|
|
|
|
|
|
|
memset(stage_info, 0, sizeof(*stage_info));
|
|
|
|
stage_info->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
|
|
|
stage_info->stage = stage;
|
|
|
|
stage_info->pName = "main";
|
|
|
|
|
|
|
|
module_info.codeSize = spirv.size;
|
|
|
|
module_info.pCode = spirv.code;
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkCreateShaderModule(context->device, &module_info, NULL, &stage_info->module));
|
2022-04-11 10:18:31 -07:00
|
|
|
vkd3d_shader_free_shader_code(&spirv);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VkPrimitiveTopology vulkan_primitive_topology_from_d3d(D3D_PRIMITIVE_TOPOLOGY topology)
|
|
|
|
{
|
|
|
|
switch (topology)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
fatal_error("Unhandled primitive topology %#x.\n", topology);
|
|
|
|
/* fall through */
|
2024-10-03 10:35:11 -07:00
|
|
|
case D3D_PRIMITIVE_TOPOLOGY_POINTLIST:
|
|
|
|
return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
|
2022-04-11 10:18:31 -07:00
|
|
|
case D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST:
|
|
|
|
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
|
|
|
case D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP:
|
|
|
|
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static VkPipelineLayout create_pipeline_layout(const struct vulkan_shader_runner *runner,
|
|
|
|
VkDescriptorSetLayout set_layout)
|
|
|
|
{
|
|
|
|
VkPipelineLayoutCreateInfo layout_desc = {.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO};
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
2022-04-11 10:18:31 -07:00
|
|
|
VkPushConstantRange push_constant_range;
|
|
|
|
VkPipelineLayout pipeline_layout;
|
|
|
|
|
|
|
|
layout_desc.setLayoutCount = 1;
|
|
|
|
layout_desc.pSetLayouts = &set_layout;
|
|
|
|
|
|
|
|
if (runner->r.uniform_count)
|
|
|
|
{
|
|
|
|
layout_desc.pushConstantRangeCount = 1;
|
|
|
|
layout_desc.pPushConstantRanges = &push_constant_range;
|
|
|
|
|
|
|
|
push_constant_range.stageFlags = VK_SHADER_STAGE_ALL;
|
|
|
|
push_constant_range.offset = 0;
|
|
|
|
push_constant_range.size = runner->r.uniform_count * sizeof(*runner->r.uniforms);
|
|
|
|
}
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkCreatePipelineLayout(context->device, &layout_desc, NULL, &pipeline_layout));
|
2022-04-11 10:18:31 -07:00
|
|
|
|
|
|
|
return pipeline_layout;
|
|
|
|
}
|
|
|
|
|
2024-04-14 17:33:15 -07:00
|
|
|
static enum VkCompareOp vk_compare_op_from_d3d12(D3D12_COMPARISON_FUNC op)
|
|
|
|
{
|
|
|
|
switch (op)
|
|
|
|
{
|
|
|
|
case D3D12_COMPARISON_FUNC_NEVER:
|
|
|
|
return VK_COMPARE_OP_NEVER;
|
|
|
|
case D3D12_COMPARISON_FUNC_LESS:
|
|
|
|
return VK_COMPARE_OP_LESS;
|
|
|
|
case D3D12_COMPARISON_FUNC_EQUAL:
|
|
|
|
return VK_COMPARE_OP_EQUAL;
|
|
|
|
case D3D12_COMPARISON_FUNC_LESS_EQUAL:
|
|
|
|
return VK_COMPARE_OP_LESS_OR_EQUAL;
|
|
|
|
case D3D12_COMPARISON_FUNC_GREATER:
|
|
|
|
return VK_COMPARE_OP_GREATER;
|
|
|
|
case D3D12_COMPARISON_FUNC_NOT_EQUAL:
|
|
|
|
return VK_COMPARE_OP_NOT_EQUAL;
|
|
|
|
case D3D12_COMPARISON_FUNC_GREATER_EQUAL:
|
|
|
|
return VK_COMPARE_OP_GREATER_OR_EQUAL;
|
|
|
|
case D3D12_COMPARISON_FUNC_ALWAYS:
|
|
|
|
return VK_COMPARE_OP_ALWAYS;
|
|
|
|
default:
|
|
|
|
fatal_error("Unhandled compare op %#x.\n", op);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-24 11:50:11 -08:00
|
|
|
static VkPipeline create_graphics_pipeline(struct vulkan_shader_runner *runner, VkRenderPass render_pass,
|
2022-04-11 10:18:31 -07:00
|
|
|
VkPipelineLayout pipeline_layout, D3D_PRIMITIVE_TOPOLOGY primitive_topology)
|
|
|
|
{
|
|
|
|
VkPipelineInputAssemblyStateCreateInfo ia_desc = {.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO};
|
|
|
|
VkPipelineRasterizationStateCreateInfo rs_desc = {.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO};
|
|
|
|
VkPipelineVertexInputStateCreateInfo input_desc = {.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO};
|
|
|
|
VkPipelineColorBlendStateCreateInfo blend_desc = {.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO};
|
|
|
|
VkPipelineMultisampleStateCreateInfo ms_desc = {.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO};
|
2024-05-17 17:50:33 -07:00
|
|
|
VkViewport viewport = {.y = RENDER_TARGET_HEIGHT,
|
2023-10-06 05:16:59 -07:00
|
|
|
.width = RENDER_TARGET_WIDTH, .height = -RENDER_TARGET_HEIGHT, .maxDepth = 1};
|
2022-04-11 10:18:31 -07:00
|
|
|
VkPipelineViewportStateCreateInfo vp_desc = {.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO};
|
|
|
|
static const VkRect2D rt_rect = {.extent.width = RENDER_TARGET_WIDTH, .extent.height = RENDER_TARGET_HEIGHT};
|
|
|
|
VkGraphicsPipelineCreateInfo pipeline_desc = {.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO};
|
2022-06-08 16:18:37 -07:00
|
|
|
VkPipelineColorBlendAttachmentState attachment_desc[MAX_RESOURCES] = {0};
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
2024-04-07 21:37:32 -07:00
|
|
|
VkPipelineTessellationStateCreateInfo tessellation_info;
|
2022-04-11 10:18:31 -07:00
|
|
|
VkVertexInputAttributeDescription input_attributes[32];
|
2024-04-14 17:33:15 -07:00
|
|
|
VkPipelineDepthStencilStateCreateInfo ds_desc = {0};
|
2022-04-11 10:18:31 -07:00
|
|
|
VkVertexInputBindingDescription input_bindings[32];
|
2024-04-18 19:33:56 -07:00
|
|
|
VkPipelineShaderStageCreateInfo stage_desc[5];
|
2024-07-07 20:42:49 -07:00
|
|
|
VkDevice device = context->device;
|
2024-04-21 08:29:29 -07:00
|
|
|
unsigned int stage_count = 0;
|
2022-04-11 10:18:31 -07:00
|
|
|
VkPipeline pipeline;
|
|
|
|
unsigned int i, j;
|
2023-07-01 16:30:06 -07:00
|
|
|
VkResult vr;
|
2022-04-11 10:18:31 -07:00
|
|
|
int ret;
|
|
|
|
|
2022-04-14 03:52:33 -07:00
|
|
|
memset(stage_desc, 0, sizeof(stage_desc));
|
2023-10-27 09:11:57 -07:00
|
|
|
ret = create_shader_stage(runner, &stage_desc[stage_count++],
|
|
|
|
"vs", VK_SHADER_STAGE_VERTEX_BIT, runner->r.vs_source);
|
|
|
|
ret &= create_shader_stage(runner, &stage_desc[stage_count++],
|
|
|
|
"ps", VK_SHADER_STAGE_FRAGMENT_BIT, runner->r.ps_source);
|
2024-04-07 21:37:32 -07:00
|
|
|
|
|
|
|
if (runner->r.hs_source)
|
|
|
|
{
|
2024-04-21 08:29:29 -07:00
|
|
|
ret &= create_shader_stage(runner, &stage_desc[stage_count++], "hs",
|
2023-10-27 09:11:57 -07:00
|
|
|
VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, runner->r.hs_source);
|
2024-04-21 08:29:29 -07:00
|
|
|
ret &= create_shader_stage(runner, &stage_desc[stage_count++], "ds",
|
2023-10-27 09:11:57 -07:00
|
|
|
VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, runner->r.ds_source);
|
2024-04-07 21:37:32 -07:00
|
|
|
}
|
2024-04-18 19:33:56 -07:00
|
|
|
|
|
|
|
if (runner->r.gs_source)
|
2023-10-27 09:11:57 -07:00
|
|
|
ret &= create_shader_stage(runner, &stage_desc[stage_count++],
|
|
|
|
"gs", VK_SHADER_STAGE_GEOMETRY_BIT, runner->r.gs_source);
|
2024-04-18 19:33:56 -07:00
|
|
|
|
2022-04-14 03:52:33 -07:00
|
|
|
if (!ret)
|
2022-04-11 10:18:31 -07:00
|
|
|
{
|
2024-10-19 02:13:07 -07:00
|
|
|
/* We ok() only when failing here, so that we don't result in a "todo
|
|
|
|
* succeeded" when the todo applies to pipeline linking. */
|
|
|
|
todo_if (runner->r.is_todo) ok(false, "Failed to compile shaders.\n");
|
2024-04-07 21:37:32 -07:00
|
|
|
for (i = 0; i < ARRAY_SIZE(stage_desc); ++i)
|
|
|
|
VK_CALL(vkDestroyShaderModule(device, stage_desc[i].module, NULL));
|
2022-04-11 10:18:31 -07:00
|
|
|
return VK_NULL_HANDLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (runner->r.input_element_count > ARRAY_SIZE(input_attributes))
|
|
|
|
fatal_error("Input element count %zu is too high.\n", runner->r.input_element_count);
|
|
|
|
|
|
|
|
for (i = 0; i < runner->r.input_element_count; ++i)
|
|
|
|
{
|
|
|
|
VkVertexInputAttributeDescription *attribute = &input_attributes[i];
|
|
|
|
const struct input_element *element = &runner->r.input_elements[i];
|
|
|
|
const struct vkd3d_shader_signature_element *signature_element;
|
|
|
|
|
2023-02-24 11:50:11 -08:00
|
|
|
signature_element = vkd3d_shader_find_signature_element(&runner->vs_signatures.input, element->name, element->index, 0);
|
|
|
|
ok(signature_element, "Cannot find signature element %s%u.\n", element->name, element->index);
|
2022-04-11 10:18:31 -07:00
|
|
|
|
|
|
|
attribute->location = signature_element->register_index;
|
|
|
|
attribute->binding = element->slot;
|
|
|
|
attribute->format = vkd3d_get_vk_format(element->format);
|
|
|
|
/* The offset will be filled below. */
|
|
|
|
}
|
|
|
|
|
|
|
|
input_desc.vertexAttributeDescriptionCount = runner->r.input_element_count;
|
|
|
|
input_desc.pVertexAttributeDescriptions = input_attributes;
|
|
|
|
input_desc.pVertexBindingDescriptions = input_bindings;
|
|
|
|
|
2022-06-08 16:18:37 -07:00
|
|
|
blend_desc.attachmentCount = 0;
|
|
|
|
blend_desc.pAttachments = attachment_desc;
|
|
|
|
|
2022-04-11 10:18:31 -07:00
|
|
|
for (i = 0; i < runner->r.resource_count; ++i)
|
|
|
|
{
|
|
|
|
const struct vulkan_resource *resource = vulkan_resource(runner->r.resources[i]);
|
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
switch (resource->r.desc.type)
|
2022-04-11 10:18:31 -07:00
|
|
|
{
|
|
|
|
case RESOURCE_TYPE_TEXTURE:
|
2022-06-08 16:18:35 -07:00
|
|
|
case RESOURCE_TYPE_UAV:
|
2022-04-11 10:18:31 -07:00
|
|
|
break;
|
|
|
|
|
2022-06-08 16:18:37 -07:00
|
|
|
case RESOURCE_TYPE_RENDER_TARGET:
|
|
|
|
attachment_desc[blend_desc.attachmentCount++].colorWriteMask =
|
|
|
|
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
|
|
|
|
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
|
|
|
break;
|
|
|
|
|
2024-04-14 17:33:15 -07:00
|
|
|
case RESOURCE_TYPE_DEPTH_STENCIL:
|
|
|
|
ds_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
|
|
|
ds_desc.pNext = NULL;
|
|
|
|
ds_desc.flags = 0;
|
|
|
|
ds_desc.depthTestEnable = VK_TRUE;
|
|
|
|
ds_desc.depthWriteEnable = VK_TRUE;
|
|
|
|
ds_desc.depthCompareOp = vk_compare_op_from_d3d12(runner->r.depth_func);
|
2024-08-31 09:54:44 -07:00
|
|
|
ds_desc.depthBoundsTestEnable = runner->r.depth_bounds;
|
2024-04-14 17:33:15 -07:00
|
|
|
ds_desc.stencilTestEnable = VK_FALSE;
|
2024-08-31 09:54:44 -07:00
|
|
|
ds_desc.minDepthBounds = runner->r.depth_min;
|
|
|
|
ds_desc.maxDepthBounds = runner->r.depth_max;
|
2024-04-14 17:33:15 -07:00
|
|
|
pipeline_desc.pDepthStencilState = &ds_desc;
|
|
|
|
break;
|
|
|
|
|
2022-04-11 10:18:31 -07:00
|
|
|
case RESOURCE_TYPE_VERTEX_BUFFER:
|
|
|
|
{
|
|
|
|
VkVertexInputBindingDescription *binding = &input_bindings[input_desc.vertexBindingDescriptionCount++];
|
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
binding->binding = resource->r.desc.slot;
|
2022-04-11 10:18:31 -07:00
|
|
|
binding->stride = 0;
|
|
|
|
binding->inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
|
|
|
|
|
|
|
for (j = 0; j < runner->r.input_element_count; ++j)
|
|
|
|
{
|
2024-06-17 14:01:04 -07:00
|
|
|
if (runner->r.input_elements[j].slot == resource->r.desc.slot)
|
2022-04-11 10:18:31 -07:00
|
|
|
{
|
|
|
|
input_attributes[j].offset = binding->stride;
|
|
|
|
binding->stride += runner->r.input_elements[j].texel_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ia_desc.topology = vulkan_primitive_topology_from_d3d(primitive_topology);
|
|
|
|
|
2024-05-17 17:50:33 -07:00
|
|
|
if (runner->r.minimum_shader_model < SHADER_MODEL_4_0)
|
|
|
|
{
|
|
|
|
viewport.x += 0.5f;
|
|
|
|
viewport.y += 0.5f;
|
|
|
|
}
|
|
|
|
|
2022-04-11 10:18:31 -07:00
|
|
|
vp_desc.viewportCount = 1;
|
|
|
|
vp_desc.pViewports = &viewport;
|
|
|
|
vp_desc.scissorCount = 1;
|
|
|
|
vp_desc.pScissors = &rt_rect;
|
|
|
|
|
2023-04-10 11:45:15 -07:00
|
|
|
rs_desc.cullMode = VK_CULL_MODE_NONE;
|
2023-10-06 05:16:59 -07:00
|
|
|
rs_desc.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
2022-04-11 10:18:31 -07:00
|
|
|
rs_desc.lineWidth = 1.0f;
|
|
|
|
|
2024-06-18 21:53:49 -07:00
|
|
|
ms_desc.rasterizationSamples = runner->r.sample_count;
|
|
|
|
ms_desc.pSampleMask = &runner->r.sample_mask;
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-04-21 08:29:29 -07:00
|
|
|
pipeline_desc.stageCount = stage_count;
|
2022-04-11 10:18:31 -07:00
|
|
|
pipeline_desc.pStages = stage_desc;
|
|
|
|
pipeline_desc.pVertexInputState = &input_desc;
|
|
|
|
pipeline_desc.pInputAssemblyState = &ia_desc;
|
|
|
|
pipeline_desc.pViewportState = &vp_desc;
|
|
|
|
pipeline_desc.pRasterizationState = &rs_desc;
|
|
|
|
pipeline_desc.pMultisampleState = &ms_desc;
|
|
|
|
pipeline_desc.pColorBlendState = &blend_desc;
|
|
|
|
pipeline_desc.layout = pipeline_layout;
|
2022-06-08 16:18:36 -07:00
|
|
|
pipeline_desc.renderPass = render_pass;
|
2022-04-11 10:18:31 -07:00
|
|
|
pipeline_desc.subpass = 0;
|
|
|
|
|
2024-04-07 21:37:32 -07:00
|
|
|
if (runner->r.hs_source)
|
|
|
|
{
|
|
|
|
tessellation_info.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
|
|
|
|
tessellation_info.pNext = NULL;
|
|
|
|
tessellation_info.flags = 0;
|
|
|
|
tessellation_info.patchControlPoints
|
|
|
|
= max(primitive_topology - D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + 1, 1);
|
|
|
|
pipeline_desc.pTessellationState = &tessellation_info;
|
|
|
|
}
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
vr = VK_CALL(vkCreateGraphicsPipelines(context->device, VK_NULL_HANDLE, 1, &pipeline_desc, NULL, &pipeline));
|
2024-10-19 02:13:07 -07:00
|
|
|
todo_if (runner->r.is_todo) ok(vr == VK_SUCCESS, "Failed to create graphics pipeline, vr %d.\n", vr);
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-04-07 21:37:32 -07:00
|
|
|
for (i = 0; i < ARRAY_SIZE(stage_desc); ++i)
|
|
|
|
VK_CALL(vkDestroyShaderModule(device, stage_desc[i].module, NULL));
|
2023-02-24 11:50:11 -08:00
|
|
|
vkd3d_shader_free_scan_signature_info(&runner->vs_signatures);
|
2022-04-11 10:18:31 -07:00
|
|
|
|
|
|
|
return pipeline;
|
|
|
|
}
|
|
|
|
|
2023-02-24 11:50:11 -08:00
|
|
|
static VkPipeline create_compute_pipeline(struct vulkan_shader_runner *runner, VkPipelineLayout pipeline_layout)
|
2021-08-13 14:37:31 -07:00
|
|
|
{
|
|
|
|
VkComputePipelineCreateInfo pipeline_desc = {.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO};
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
2021-08-13 14:37:31 -07:00
|
|
|
VkPipeline pipeline;
|
|
|
|
bool ret;
|
|
|
|
|
2023-10-27 09:11:57 -07:00
|
|
|
ret = create_shader_stage(runner, &pipeline_desc.stage, "cs", VK_SHADER_STAGE_COMPUTE_BIT, runner->r.cs_source);
|
2021-08-13 14:37:31 -07:00
|
|
|
todo_if (runner->r.is_todo) ok(ret, "Failed to compile shader.\n");
|
|
|
|
if (!ret)
|
|
|
|
return VK_NULL_HANDLE;
|
|
|
|
|
|
|
|
pipeline_desc.layout = pipeline_layout;
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkCreateComputePipelines(context->device, VK_NULL_HANDLE, 1, &pipeline_desc, NULL, &pipeline));
|
2021-08-13 14:37:31 -07:00
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkDestroyShaderModule(context->device, pipeline_desc.stage.module, NULL));
|
2021-08-13 14:37:31 -07:00
|
|
|
|
|
|
|
return pipeline;
|
|
|
|
}
|
|
|
|
|
2022-04-11 10:18:31 -07:00
|
|
|
static VkSamplerAddressMode vk_address_mode_from_d3d12(D3D12_TEXTURE_ADDRESS_MODE mode)
|
|
|
|
{
|
|
|
|
switch (mode)
|
|
|
|
{
|
|
|
|
case D3D12_TEXTURE_ADDRESS_MODE_WRAP:
|
|
|
|
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
|
|
case D3D12_TEXTURE_ADDRESS_MODE_MIRROR:
|
|
|
|
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
|
|
|
|
case D3D12_TEXTURE_ADDRESS_MODE_CLAMP:
|
|
|
|
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
|
|
|
case D3D12_TEXTURE_ADDRESS_MODE_BORDER:
|
|
|
|
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
|
|
|
default:
|
|
|
|
fatal_error("Unhandled sampler address mode %#x.\n", mode);
|
|
|
|
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static VkDescriptorSetLayout create_descriptor_set_layout(struct vulkan_shader_runner *runner)
|
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutCreateInfo set_desc = {.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO};
|
|
|
|
VkDescriptorSetLayoutBinding bindings[MAX_RESOURCES + MAX_SAMPLERS];
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
2022-04-11 10:18:31 -07:00
|
|
|
VkDescriptorSetLayoutBinding *binding;
|
|
|
|
VkDescriptorSetLayout set_layout;
|
|
|
|
uint32_t binding_index = 0;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (runner->r.resource_count > ARRAY_SIZE(bindings))
|
|
|
|
fatal_error("Resource count %zu is too high.\n", runner->r.resource_count);
|
|
|
|
|
|
|
|
set_desc.pBindings = bindings;
|
|
|
|
|
|
|
|
for (i = 0; i < runner->r.resource_count; ++i)
|
|
|
|
{
|
|
|
|
struct vulkan_resource *resource = vulkan_resource(runner->r.resources[i]);
|
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
switch (resource->r.desc.type)
|
2022-04-11 10:18:31 -07:00
|
|
|
{
|
2022-06-08 16:18:37 -07:00
|
|
|
case RESOURCE_TYPE_RENDER_TARGET:
|
2024-04-14 17:33:15 -07:00
|
|
|
case RESOURCE_TYPE_DEPTH_STENCIL:
|
2022-04-11 10:18:31 -07:00
|
|
|
case RESOURCE_TYPE_VERTEX_BUFFER:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RESOURCE_TYPE_TEXTURE:
|
2022-06-08 16:18:35 -07:00
|
|
|
case RESOURCE_TYPE_UAV:
|
2022-04-11 10:18:31 -07:00
|
|
|
binding = &bindings[set_desc.bindingCount++];
|
|
|
|
|
|
|
|
resource->binding = binding_index++;
|
|
|
|
|
|
|
|
binding->binding = resource->binding;
|
2024-06-17 14:01:04 -07:00
|
|
|
if (resource->r.desc.type == RESOURCE_TYPE_UAV)
|
2024-01-22 15:20:18 -08:00
|
|
|
{
|
2024-06-17 14:01:04 -07:00
|
|
|
if (resource->r.desc.dimension == RESOURCE_DIMENSION_BUFFER)
|
2024-01-22 15:20:18 -08:00
|
|
|
binding->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
|
|
|
|
else
|
|
|
|
binding->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
|
|
}
|
2022-06-08 16:18:35 -07:00
|
|
|
else
|
2024-01-22 15:20:18 -08:00
|
|
|
{
|
2024-06-17 14:01:04 -07:00
|
|
|
if (resource->r.desc.dimension == RESOURCE_DIMENSION_BUFFER)
|
2024-01-23 15:26:11 -08:00
|
|
|
binding->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
|
|
|
|
else
|
|
|
|
binding->descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
2024-01-22 15:20:18 -08:00
|
|
|
}
|
2022-04-11 10:18:31 -07:00
|
|
|
binding->descriptorCount = 1;
|
|
|
|
binding->stageFlags = VK_SHADER_STAGE_ALL;
|
|
|
|
binding->pImmutableSamplers = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < runner->r.sampler_count; ++i)
|
|
|
|
{
|
|
|
|
VkSamplerCreateInfo sampler_desc = {.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO};
|
|
|
|
struct vulkan_sampler *vulkan_sampler = &runner->samplers[i];
|
|
|
|
const struct sampler *sampler = &runner->r.samplers[i];
|
|
|
|
|
|
|
|
sampler_desc.magFilter = (sampler->filter & 0x4) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
|
|
|
|
sampler_desc.minFilter = (sampler->filter & 0x1) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
|
|
|
|
sampler_desc.mipmapMode = (sampler->filter & 0x10) ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
|
|
|
sampler_desc.addressModeU = vk_address_mode_from_d3d12(sampler->u_address);
|
|
|
|
sampler_desc.addressModeV = vk_address_mode_from_d3d12(sampler->v_address);
|
|
|
|
sampler_desc.addressModeW = vk_address_mode_from_d3d12(sampler->w_address);
|
2024-02-22 18:30:16 -08:00
|
|
|
sampler_desc.compareEnable = !!sampler->func;
|
|
|
|
sampler_desc.compareOp = sampler->func ? vk_compare_op_from_d3d12(sampler->func) : 0;
|
2023-04-30 17:23:00 -07:00
|
|
|
sampler_desc.maxLod = FLT_MAX;
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkCreateSampler(context->device, &sampler_desc, NULL, &vulkan_sampler->vk_sampler));
|
2022-04-11 10:18:31 -07:00
|
|
|
vulkan_sampler->binding = binding_index++;
|
|
|
|
|
|
|
|
binding = &bindings[set_desc.bindingCount++];
|
|
|
|
|
|
|
|
binding->binding = vulkan_sampler->binding;
|
|
|
|
binding->descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
|
|
|
|
binding->descriptorCount = 1;
|
|
|
|
binding->stageFlags = VK_SHADER_STAGE_ALL;
|
|
|
|
binding->pImmutableSamplers = &vulkan_sampler->vk_sampler;
|
|
|
|
}
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkCreateDescriptorSetLayout(context->device, &set_desc, NULL, &set_layout));
|
2022-04-11 10:18:31 -07:00
|
|
|
|
|
|
|
return set_layout;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void bind_resources(struct vulkan_shader_runner *runner, VkPipelineBindPoint bind_point,
|
|
|
|
VkDescriptorSetLayout set_layout, VkPipelineLayout pipeline_layout)
|
|
|
|
{
|
|
|
|
VkDescriptorSetAllocateInfo set_desc = {.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO};
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
|
|
|
VkCommandBuffer cmd_buffer = context->cmd_buffer;
|
2022-04-11 10:18:31 -07:00
|
|
|
VkDescriptorSet descriptor_set;
|
|
|
|
unsigned int i;
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
set_desc.descriptorPool = context->descriptor_pool;
|
2022-04-11 10:18:31 -07:00
|
|
|
set_desc.descriptorSetCount = 1;
|
|
|
|
set_desc.pSetLayouts = &set_layout;
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkAllocateDescriptorSets(context->device, &set_desc, &descriptor_set));
|
2022-04-11 10:18:31 -07:00
|
|
|
|
|
|
|
for (i = 0; i < runner->r.resource_count; ++i)
|
|
|
|
{
|
|
|
|
const struct vulkan_resource *resource = vulkan_resource(runner->r.resources[i]);
|
|
|
|
VkWriteDescriptorSet write = {.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET};
|
|
|
|
static const VkDeviceSize zero_offset;
|
|
|
|
VkDescriptorImageInfo image_info;
|
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
switch (resource->r.desc.type)
|
2022-04-11 10:18:31 -07:00
|
|
|
{
|
|
|
|
case RESOURCE_TYPE_TEXTURE:
|
2022-06-08 16:18:35 -07:00
|
|
|
case RESOURCE_TYPE_UAV:
|
2024-06-17 14:01:04 -07:00
|
|
|
if (resource->r.desc.dimension == RESOURCE_DIMENSION_BUFFER)
|
2022-06-08 16:18:35 -07:00
|
|
|
{
|
2024-01-22 15:20:18 -08:00
|
|
|
write.dstSet = descriptor_set;
|
|
|
|
write.dstBinding = resource->binding;
|
|
|
|
write.dstArrayElement = 0;
|
|
|
|
write.descriptorCount = 1;
|
2024-01-23 15:26:11 -08:00
|
|
|
write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
|
2024-01-22 15:20:18 -08:00
|
|
|
write.pTexelBufferView = &resource->buffer_view;
|
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
if (resource->r.desc.type == RESOURCE_TYPE_UAV)
|
2024-01-23 15:26:11 -08:00
|
|
|
write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkUpdateDescriptorSets(context->device, 1, &write, 0, NULL));
|
2022-06-08 16:18:35 -07:00
|
|
|
}
|
2024-01-22 15:20:18 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
image_info.imageView = resource->image_view;
|
|
|
|
image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
2022-06-08 16:18:35 -07:00
|
|
|
|
2024-01-22 15:20:18 -08:00
|
|
|
write.dstSet = descriptor_set;
|
|
|
|
write.dstBinding = resource->binding;
|
|
|
|
write.dstArrayElement = 0;
|
|
|
|
write.descriptorCount = 1;
|
|
|
|
write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
|
|
|
write.pImageInfo = &image_info;
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
if (resource->r.desc.type == RESOURCE_TYPE_UAV)
|
2024-01-22 15:20:18 -08:00
|
|
|
{
|
|
|
|
image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
|
|
|
write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
|
|
}
|
2023-05-09 10:56:55 -07:00
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkUpdateDescriptorSets(context->device, 1, &write, 0, NULL));
|
2024-01-22 15:20:18 -08:00
|
|
|
}
|
2023-05-09 10:56:55 -07:00
|
|
|
break;
|
|
|
|
|
2022-04-11 10:18:31 -07:00
|
|
|
case RESOURCE_TYPE_VERTEX_BUFFER:
|
|
|
|
if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS)
|
2024-06-17 14:01:04 -07:00
|
|
|
VK_CALL(vkCmdBindVertexBuffers(cmd_buffer, resource->r.desc.slot, 1, &resource->buffer, &zero_offset));
|
2022-04-11 10:18:31 -07:00
|
|
|
break;
|
2022-06-08 16:18:37 -07:00
|
|
|
|
|
|
|
case RESOURCE_TYPE_RENDER_TARGET:
|
2024-04-14 17:33:15 -07:00
|
|
|
case RESOURCE_TYPE_DEPTH_STENCIL:
|
2022-06-08 16:18:37 -07:00
|
|
|
break;
|
2022-04-11 10:18:31 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VK_CALL(vkCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_layout, 0, 1, &descriptor_set, 0, NULL));
|
|
|
|
|
|
|
|
if (runner->r.uniform_count)
|
|
|
|
VK_CALL(vkCmdPushConstants(cmd_buffer, pipeline_layout, VK_SHADER_STAGE_ALL, 0,
|
|
|
|
runner->r.uniform_count * sizeof(*runner->r.uniforms), runner->r.uniforms));
|
|
|
|
|
|
|
|
/* The descriptor set will be freed by resetting the descriptor pool. */
|
|
|
|
}
|
|
|
|
|
2022-06-08 16:18:36 -07:00
|
|
|
static void create_render_pass_and_framebuffer(struct vulkan_shader_runner *runner,
|
|
|
|
VkRenderPass *render_pass, VkFramebuffer *fb)
|
|
|
|
{
|
|
|
|
VkRenderPassCreateInfo render_pass_desc = {.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
|
|
|
|
VkFramebufferCreateInfo fb_desc = {.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
|
2024-04-14 17:33:15 -07:00
|
|
|
VkAttachmentReference ds_ref = {0}, color_refs[MAX_RESOURCES] = {0};
|
2022-06-08 16:18:37 -07:00
|
|
|
VkAttachmentDescription attachment_descs[MAX_RESOURCES] = {0};
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
2024-04-14 17:33:15 -07:00
|
|
|
unsigned int i, color_ref_count = 0, view_count = 0;
|
2022-06-08 16:18:36 -07:00
|
|
|
VkSubpassDescription subpass_desc = {0};
|
2024-04-14 17:33:15 -07:00
|
|
|
VkImageView views[MAX_RESOURCES];
|
|
|
|
VkImageLayout layout;
|
|
|
|
bool is_ds;
|
2022-06-08 16:18:36 -07:00
|
|
|
|
2022-06-08 16:18:37 -07:00
|
|
|
for (i = 0; i < runner->r.resource_count; ++i)
|
|
|
|
{
|
|
|
|
const struct vulkan_resource *resource = vulkan_resource(runner->r.resources[i]);
|
2024-04-14 17:33:15 -07:00
|
|
|
VkAttachmentDescription *attachment_desc = &attachment_descs[view_count];
|
|
|
|
VkAttachmentReference *color_ref = &color_refs[color_ref_count];
|
2022-06-08 16:18:37 -07:00
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
if (resource->r.desc.type != RESOURCE_TYPE_RENDER_TARGET && resource->r.desc.type != RESOURCE_TYPE_DEPTH_STENCIL)
|
2022-06-08 16:18:37 -07:00
|
|
|
continue;
|
2022-06-08 16:18:36 -07:00
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
is_ds = resource->r.desc.type == RESOURCE_TYPE_DEPTH_STENCIL;
|
2024-04-14 17:33:15 -07:00
|
|
|
layout = is_ds ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
attachment_desc->format = vkd3d_get_vk_format(resource->r.desc.format);
|
2024-06-18 21:53:49 -07:00
|
|
|
attachment_desc->samples = max(resource->r.desc.sample_count, 1);
|
2022-06-08 16:18:37 -07:00
|
|
|
attachment_desc->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
|
|
|
attachment_desc->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
|
|
|
attachment_desc->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
|
|
attachment_desc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
2024-04-14 17:33:15 -07:00
|
|
|
attachment_desc->initialLayout = layout;
|
|
|
|
attachment_desc->finalLayout = layout;
|
2022-06-08 16:18:37 -07:00
|
|
|
|
2024-04-14 17:33:15 -07:00
|
|
|
if (is_ds)
|
|
|
|
{
|
|
|
|
ds_ref.attachment = view_count;
|
|
|
|
ds_ref.layout = layout;
|
|
|
|
subpass_desc.pDepthStencilAttachment = &ds_ref;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
color_ref->attachment = view_count;
|
|
|
|
color_ref->layout = layout;
|
|
|
|
++color_ref_count;
|
|
|
|
}
|
2022-06-08 16:18:37 -07:00
|
|
|
|
2024-04-14 17:33:15 -07:00
|
|
|
views[view_count++] = resource->image_view;
|
2022-06-08 16:18:37 -07:00
|
|
|
}
|
2022-06-08 16:18:36 -07:00
|
|
|
|
|
|
|
subpass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
2024-04-14 17:33:15 -07:00
|
|
|
subpass_desc.colorAttachmentCount = color_ref_count;
|
2022-06-08 16:18:37 -07:00
|
|
|
subpass_desc.pColorAttachments = color_refs;
|
2022-06-08 16:18:36 -07:00
|
|
|
|
2024-04-14 17:33:15 -07:00
|
|
|
render_pass_desc.attachmentCount = view_count;
|
2022-06-08 16:18:37 -07:00
|
|
|
render_pass_desc.pAttachments = attachment_descs;
|
2022-06-08 16:18:36 -07:00
|
|
|
render_pass_desc.subpassCount = 1;
|
|
|
|
render_pass_desc.pSubpasses = &subpass_desc;
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkCreateRenderPass(context->device, &render_pass_desc, NULL, render_pass));
|
2022-06-08 16:18:36 -07:00
|
|
|
|
|
|
|
fb_desc.renderPass = *render_pass;
|
2024-04-14 17:33:15 -07:00
|
|
|
fb_desc.attachmentCount = view_count;
|
|
|
|
fb_desc.pAttachments = views;
|
2022-06-08 16:18:36 -07:00
|
|
|
fb_desc.width = RENDER_TARGET_WIDTH;
|
|
|
|
fb_desc.height = RENDER_TARGET_HEIGHT;
|
|
|
|
fb_desc.layers = 1;
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkCreateFramebuffer(context->device, &fb_desc, NULL, fb));
|
2022-06-08 16:18:36 -07:00
|
|
|
}
|
|
|
|
|
2021-08-13 14:37:31 -07:00
|
|
|
static bool vulkan_runner_dispatch(struct shader_runner *r, unsigned int x, unsigned int y, unsigned int z)
|
|
|
|
{
|
|
|
|
struct vulkan_shader_runner *runner = vulkan_shader_runner(r);
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
|
|
|
VkCommandBuffer cmd_buffer = context->cmd_buffer;
|
|
|
|
VkDevice device = context->device;
|
2021-08-13 14:37:31 -07:00
|
|
|
VkDescriptorSetLayout set_layout;
|
|
|
|
VkPipelineLayout pipeline_layout;
|
|
|
|
VkPipeline pipeline;
|
|
|
|
bool ret = false;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
/* Create this before compiling shaders, it will assign resource bindings. */
|
|
|
|
set_layout = create_descriptor_set_layout(runner);
|
|
|
|
|
|
|
|
pipeline_layout = create_pipeline_layout(runner, set_layout);
|
|
|
|
if (!(pipeline = create_compute_pipeline(runner, pipeline_layout)))
|
|
|
|
goto out;
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
begin_command_buffer(context);
|
2021-08-13 14:37:31 -07:00
|
|
|
|
|
|
|
VK_CALL(vkCmdBindPipeline(cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline));
|
|
|
|
|
|
|
|
bind_resources(runner, VK_PIPELINE_BIND_POINT_COMPUTE, set_layout, pipeline_layout);
|
|
|
|
|
|
|
|
VK_CALL(vkCmdDispatch(cmd_buffer, x, y, z));
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
end_command_buffer(context);
|
2021-08-13 14:37:31 -07:00
|
|
|
|
|
|
|
VK_CALL(vkDestroyPipeline(device, pipeline, NULL));
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkResetDescriptorPool(device, context->descriptor_pool, 0));
|
2021-08-13 14:37:31 -07:00
|
|
|
|
|
|
|
ret = true;
|
|
|
|
out:
|
|
|
|
for (i = 0; i < runner->r.sampler_count; ++i)
|
|
|
|
VK_CALL(vkDestroySampler(device, runner->samplers[i].vk_sampler, NULL));
|
|
|
|
|
|
|
|
VK_CALL(vkDestroyPipelineLayout(device, pipeline_layout, NULL));
|
|
|
|
VK_CALL(vkDestroyDescriptorSetLayout(device, set_layout, NULL));
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2024-04-14 17:33:15 -07:00
|
|
|
static void vulkan_runner_clear(struct shader_runner *r, struct resource *res, const struct vec4 *clear_value)
|
|
|
|
{
|
|
|
|
struct vulkan_shader_runner *runner = vulkan_shader_runner(r);
|
|
|
|
struct vulkan_resource *resource = vulkan_resource(res);
|
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
size_t width = resource->r.desc.width, height = resource->r.desc.height;
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
2024-04-14 17:33:15 -07:00
|
|
|
VkSubpassDescription sub_pass_desc = {0};
|
|
|
|
VkAttachmentDescription attachment_desc;
|
|
|
|
VkRenderPassCreateInfo pass_desc = {0};
|
|
|
|
VkAttachmentReference attachment_ref;
|
2024-07-07 20:42:49 -07:00
|
|
|
VkDevice device = context->device;
|
2024-04-14 17:33:15 -07:00
|
|
|
VkRenderPassBeginInfo begin_desc;
|
|
|
|
VkFramebufferCreateInfo fb_desc;
|
|
|
|
VkClearValue vk_clear_value;
|
|
|
|
VkRenderPass render_pass;
|
|
|
|
VkFramebuffer fb;
|
|
|
|
|
|
|
|
attachment_desc.flags = 0;
|
2024-06-17 14:01:04 -07:00
|
|
|
attachment_desc.format = vkd3d_get_vk_format(resource->r.desc.format);
|
2024-06-18 21:53:49 -07:00
|
|
|
attachment_desc.samples = max(resource->r.desc.sample_count, 1);
|
2024-04-14 17:33:15 -07:00
|
|
|
attachment_desc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
|
|
|
attachment_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
|
|
|
/* TODO: formats with a stencil component would a clear op here. */
|
|
|
|
attachment_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
|
|
attachment_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
|
|
|
|
|
|
sub_pass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
switch (resource->r.desc.type)
|
2024-04-14 17:33:15 -07:00
|
|
|
{
|
2024-04-14 17:37:37 -07:00
|
|
|
case RESOURCE_TYPE_RENDER_TARGET:
|
|
|
|
attachment_desc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
sub_pass_desc.colorAttachmentCount = 1;
|
|
|
|
sub_pass_desc.pColorAttachments = &attachment_ref;
|
|
|
|
memcpy(vk_clear_value.color.float32, clear_value, sizeof(vk_clear_value.color.float32));
|
|
|
|
break;
|
|
|
|
|
2024-04-14 17:33:15 -07:00
|
|
|
case RESOURCE_TYPE_DEPTH_STENCIL:
|
|
|
|
attachment_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|
|
|
sub_pass_desc.pDepthStencilAttachment = &attachment_ref;
|
|
|
|
vk_clear_value.depthStencil.depth = clear_value->x;
|
|
|
|
vk_clear_value.depthStencil.stencil = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2024-06-17 14:01:04 -07:00
|
|
|
fatal_error("Clears are not implemented for resource type %u.\n", resource->r.desc.type);
|
2024-04-14 17:33:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
attachment_desc.finalLayout = attachment_desc.initialLayout;
|
|
|
|
|
|
|
|
attachment_ref.attachment = 0;
|
|
|
|
attachment_ref.layout = attachment_desc.initialLayout;
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
begin_command_buffer(context);
|
2024-04-14 17:33:15 -07:00
|
|
|
|
|
|
|
pass_desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
|
|
|
pass_desc.attachmentCount = 1;
|
|
|
|
pass_desc.pAttachments = &attachment_desc;
|
|
|
|
pass_desc.subpassCount = 1;
|
|
|
|
pass_desc.pSubpasses = &sub_pass_desc;
|
|
|
|
VK_CALL(vkCreateRenderPass(device, &pass_desc, NULL, &render_pass));
|
|
|
|
|
|
|
|
fb_desc.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
|
|
|
fb_desc.pNext = NULL;
|
|
|
|
fb_desc.flags = 0;
|
|
|
|
fb_desc.renderPass = render_pass;
|
|
|
|
fb_desc.attachmentCount = 1;
|
|
|
|
fb_desc.pAttachments = &resource->image_view;
|
|
|
|
fb_desc.width = width;
|
|
|
|
fb_desc.height = height;
|
|
|
|
fb_desc.layers = 1;
|
|
|
|
VK_CALL(vkCreateFramebuffer(device, &fb_desc, NULL, &fb));
|
|
|
|
|
|
|
|
begin_desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
|
|
|
begin_desc.pNext = NULL;
|
|
|
|
begin_desc.renderPass = render_pass;
|
|
|
|
begin_desc.framebuffer = fb;
|
|
|
|
begin_desc.clearValueCount = 1;
|
|
|
|
begin_desc.pClearValues = &vk_clear_value;
|
|
|
|
begin_desc.renderArea.offset.x = 0;
|
|
|
|
begin_desc.renderArea.offset.y = 0;
|
|
|
|
begin_desc.renderArea.extent.width = width;
|
|
|
|
begin_desc.renderArea.extent.height = height;
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkCmdBeginRenderPass(context->cmd_buffer, &begin_desc, VK_SUBPASS_CONTENTS_INLINE));
|
|
|
|
VK_CALL(vkCmdEndRenderPass(context->cmd_buffer));
|
2024-04-14 17:33:15 -07:00
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
end_command_buffer(context);
|
2024-04-14 17:33:15 -07:00
|
|
|
|
|
|
|
VK_CALL(vkDestroyRenderPass(device, render_pass, NULL));
|
|
|
|
VK_CALL(vkDestroyFramebuffer(device, fb, NULL));
|
|
|
|
}
|
|
|
|
|
2022-04-14 03:52:32 -07:00
|
|
|
static bool vulkan_runner_draw(struct shader_runner *r,
|
2024-04-21 19:55:44 -07:00
|
|
|
D3D_PRIMITIVE_TOPOLOGY primitive_topology, unsigned int vertex_count, unsigned int instance_count)
|
2022-04-11 10:18:31 -07:00
|
|
|
{
|
|
|
|
VkRenderPassBeginInfo pass_begin_desc = {.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO};
|
2024-07-07 20:42:49 -07:00
|
|
|
struct vulkan_shader_runner *runner = vulkan_shader_runner(r);
|
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
|
|
|
VkCommandBuffer cmd_buffer = context->cmd_buffer;
|
|
|
|
VkDevice device = context->device;
|
2022-04-11 10:18:31 -07:00
|
|
|
VkDescriptorSetLayout set_layout;
|
|
|
|
VkPipelineLayout pipeline_layout;
|
2022-06-08 16:18:36 -07:00
|
|
|
VkRenderPass render_pass;
|
2022-04-11 10:18:31 -07:00
|
|
|
VkPipeline pipeline;
|
2022-06-08 16:18:36 -07:00
|
|
|
VkFramebuffer fb;
|
2021-08-13 14:37:31 -07:00
|
|
|
bool ret = false;
|
2022-04-11 10:18:31 -07:00
|
|
|
unsigned int i;
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
static const VkRect2D rt_rect = {.extent.width = RENDER_TARGET_WIDTH, .extent.height = RENDER_TARGET_HEIGHT};
|
|
|
|
|
2022-06-08 16:18:36 -07:00
|
|
|
create_render_pass_and_framebuffer(runner, &render_pass, &fb);
|
|
|
|
|
2022-04-11 10:18:31 -07:00
|
|
|
/* Create this before compiling shaders, it will assign resource bindings. */
|
|
|
|
set_layout = create_descriptor_set_layout(runner);
|
|
|
|
|
|
|
|
pipeline_layout = create_pipeline_layout(runner, set_layout);
|
2021-08-13 14:37:31 -07:00
|
|
|
if (!(pipeline = create_graphics_pipeline(runner, render_pass, pipeline_layout, primitive_topology)))
|
2022-04-11 10:18:31 -07:00
|
|
|
goto out;
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
begin_command_buffer(context);
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2022-06-08 16:18:36 -07:00
|
|
|
pass_begin_desc.renderPass = render_pass;
|
|
|
|
pass_begin_desc.framebuffer = fb;
|
2022-04-11 10:18:31 -07:00
|
|
|
pass_begin_desc.renderArea = rt_rect;
|
|
|
|
|
|
|
|
VK_CALL(vkCmdBeginRenderPass(cmd_buffer, &pass_begin_desc, VK_SUBPASS_CONTENTS_INLINE));
|
|
|
|
|
|
|
|
VK_CALL(vkCmdBindPipeline(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline));
|
|
|
|
|
|
|
|
bind_resources(runner, VK_PIPELINE_BIND_POINT_GRAPHICS, set_layout, pipeline_layout);
|
|
|
|
|
2024-04-21 19:55:44 -07:00
|
|
|
VK_CALL(vkCmdDraw(cmd_buffer, vertex_count, instance_count, 0, 0));
|
2022-04-11 10:18:31 -07:00
|
|
|
|
|
|
|
VK_CALL(vkCmdEndRenderPass(cmd_buffer));
|
2024-07-07 20:42:49 -07:00
|
|
|
end_command_buffer(context);
|
2022-04-11 10:18:31 -07:00
|
|
|
|
|
|
|
VK_CALL(vkDestroyPipeline(device, pipeline, NULL));
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkResetDescriptorPool(device, context->descriptor_pool, 0));
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2021-08-13 14:37:31 -07:00
|
|
|
ret = true;
|
2022-04-11 10:18:31 -07:00
|
|
|
out:
|
|
|
|
for (i = 0; i < runner->r.sampler_count; ++i)
|
|
|
|
VK_CALL(vkDestroySampler(device, runner->samplers[i].vk_sampler, NULL));
|
|
|
|
|
|
|
|
VK_CALL(vkDestroyPipelineLayout(device, pipeline_layout, NULL));
|
|
|
|
VK_CALL(vkDestroyDescriptorSetLayout(device, set_layout, NULL));
|
2022-06-08 16:18:36 -07:00
|
|
|
VK_CALL(vkDestroyRenderPass(device, render_pass, NULL));
|
|
|
|
VK_CALL(vkDestroyFramebuffer(device, fb, NULL));
|
2022-04-14 03:52:32 -07:00
|
|
|
|
|
|
|
return ret;
|
2022-04-11 10:18:31 -07:00
|
|
|
}
|
|
|
|
|
2022-05-17 06:45:39 -07:00
|
|
|
struct vulkan_resource_readback
|
2022-04-11 10:18:31 -07:00
|
|
|
{
|
2022-05-17 06:45:39 -07:00
|
|
|
struct resource_readback rb;
|
|
|
|
VkDeviceMemory memory;
|
|
|
|
VkBuffer buffer;
|
|
|
|
};
|
|
|
|
|
2022-06-08 16:18:37 -07:00
|
|
|
static struct resource_readback *vulkan_runner_get_resource_readback(struct shader_runner *r, struct resource *res)
|
2022-04-11 10:18:31 -07:00
|
|
|
{
|
|
|
|
struct vulkan_shader_runner *runner = vulkan_shader_runner(r);
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
2022-05-17 06:45:41 -07:00
|
|
|
struct vulkan_resource_readback *rb = malloc(sizeof(*rb));
|
2022-06-08 16:18:37 -07:00
|
|
|
struct vulkan_resource *resource = vulkan_resource(res);
|
2024-07-07 20:42:49 -07:00
|
|
|
VkDevice device = context->device;
|
2024-04-14 17:33:15 -07:00
|
|
|
VkImageAspectFlags aspect_mask;
|
2022-04-11 10:18:31 -07:00
|
|
|
VkBufferImageCopy region = {0};
|
2022-06-08 16:18:38 -07:00
|
|
|
VkImageLayout layout;
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
rb->rb.width = resource->r.desc.width;
|
|
|
|
rb->rb.height = resource->r.desc.height;
|
2022-05-17 06:45:41 -07:00
|
|
|
rb->rb.depth = 1;
|
2022-05-17 06:45:39 -07:00
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
rb->rb.row_pitch = rb->rb.width * resource->r.desc.texel_size;
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-07-07 21:04:53 -07:00
|
|
|
rb->buffer = create_vulkan_buffer(context, rb->rb.row_pitch * rb->rb.height,
|
2022-05-17 06:45:41 -07:00
|
|
|
VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &rb->memory);
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
if (resource->r.desc.type == RESOURCE_TYPE_UAV && resource->r.desc.dimension == RESOURCE_DIMENSION_BUFFER)
|
2023-05-09 10:56:55 -07:00
|
|
|
{
|
|
|
|
void *data;
|
|
|
|
|
|
|
|
VK_CALL(vkMapMemory(device, resource->memory, 0, VK_WHOLE_SIZE, 0, &data));
|
|
|
|
VK_CALL(vkMapMemory(device, rb->memory, 0, VK_WHOLE_SIZE, 0, &rb->rb.data));
|
|
|
|
memcpy(rb->rb.data, data, rb->rb.row_pitch * rb->rb.height);
|
|
|
|
VK_CALL(vkUnmapMemory(device, resource->memory));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-06-18 21:53:49 -07:00
|
|
|
struct resource_desc resolved_desc = resource->r.desc;
|
|
|
|
VkDeviceMemory resolved_memory;
|
|
|
|
VkImage resolved_image;
|
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
aspect_mask = (resource->r.desc.type == RESOURCE_TYPE_DEPTH_STENCIL)
|
2024-04-14 17:33:15 -07:00
|
|
|
? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
|
2024-06-17 14:01:04 -07:00
|
|
|
if (resource->r.desc.type == RESOURCE_TYPE_RENDER_TARGET)
|
2023-05-09 10:56:55 -07:00
|
|
|
layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
2024-06-17 14:01:04 -07:00
|
|
|
else if (resource->r.desc.type == RESOURCE_TYPE_DEPTH_STENCIL)
|
2024-04-14 17:33:15 -07:00
|
|
|
layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
2023-05-09 10:56:55 -07:00
|
|
|
else
|
|
|
|
layout = VK_IMAGE_LAYOUT_GENERAL;
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
begin_command_buffer(context);
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
transition_image_layout(context, resource->image, aspect_mask, layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-04-14 17:33:15 -07:00
|
|
|
region.imageSubresource.aspectMask = aspect_mask;
|
2023-05-09 10:56:55 -07:00
|
|
|
region.imageSubresource.layerCount = 1;
|
2024-06-17 14:01:04 -07:00
|
|
|
region.imageExtent.width = resource->r.desc.width;
|
|
|
|
region.imageExtent.height = resource->r.desc.height;
|
2023-05-09 10:56:55 -07:00
|
|
|
region.imageExtent.depth = 1;
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-06-18 21:53:49 -07:00
|
|
|
if (resource->r.desc.sample_count > 1)
|
|
|
|
{
|
|
|
|
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;
|
2024-07-07 21:04:53 -07:00
|
|
|
resolved_image = create_vulkan_2d_image(context, resolved_desc.width, resolved_desc.height,
|
2024-07-07 20:42:49 -07:00
|
|
|
resolved_desc.level_count, resolved_desc.sample_count,
|
2024-06-18 21:53:49 -07:00
|
|
|
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
|
|
|
vkd3d_get_vk_format(resource->r.desc.format), &resolved_memory);
|
2024-07-07 20:42:49 -07:00
|
|
|
transition_image_layout(context, resolved_image, VK_IMAGE_ASPECT_COLOR_BIT,
|
2024-06-18 21:53:49 -07:00
|
|
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkCmdResolveImage(context->cmd_buffer, resource->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
2024-06-18 21:53:49 -07:00
|
|
|
resolved_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &resolve_region));
|
2024-07-07 20:42:49 -07:00
|
|
|
transition_image_layout(context, resolved_image, VK_IMAGE_ASPECT_COLOR_BIT,
|
2024-06-18 21:53:49 -07:00
|
|
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkCmdCopyImageToBuffer(context->cmd_buffer, resolved_image,
|
2024-06-18 21:53:49 -07:00
|
|
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, rb->buffer, 1, ®ion));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkCmdCopyImageToBuffer(context->cmd_buffer, resource->image,
|
2024-06-18 21:53:49 -07:00
|
|
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, rb->buffer, 1, ®ion));
|
|
|
|
}
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
transition_image_layout(context, resource->image, aspect_mask, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, layout);
|
2023-05-09 10:56:55 -07:00
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
end_command_buffer(context);
|
2023-05-09 10:56:55 -07:00
|
|
|
|
2024-06-18 21:53:49 -07:00
|
|
|
if (resource->r.desc.sample_count > 1)
|
|
|
|
{
|
|
|
|
VK_CALL(vkFreeMemory(device, resolved_memory, NULL));
|
|
|
|
VK_CALL(vkDestroyImage(device, resolved_image, NULL));
|
|
|
|
}
|
|
|
|
|
2023-05-09 10:56:55 -07:00
|
|
|
VK_CALL(vkMapMemory(device, rb->memory, 0, VK_WHOLE_SIZE, 0, &rb->rb.data));
|
|
|
|
}
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2022-05-17 06:45:41 -07:00
|
|
|
return &rb->rb;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void vulkan_runner_release_readback(struct shader_runner *r, struct resource_readback *rb)
|
|
|
|
{
|
|
|
|
struct vulkan_resource_readback *vulkan_rb = CONTAINING_RECORD(rb, struct vulkan_resource_readback, rb);
|
|
|
|
struct vulkan_shader_runner *runner = vulkan_shader_runner(r);
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
|
|
|
VkDevice device = context->device;
|
2022-05-17 06:45:41 -07:00
|
|
|
|
|
|
|
VK_CALL(vkUnmapMemory(device, vulkan_rb->memory));
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2022-05-17 06:45:41 -07:00
|
|
|
VK_CALL(vkFreeMemory(device, vulkan_rb->memory, NULL));
|
|
|
|
VK_CALL(vkDestroyBuffer(device, vulkan_rb->buffer, NULL));
|
|
|
|
free(vulkan_rb);
|
2022-04-11 10:18:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct shader_runner_ops vulkan_runner_ops =
|
|
|
|
{
|
|
|
|
.create_resource = vulkan_runner_create_resource,
|
|
|
|
.destroy_resource = vulkan_runner_destroy_resource,
|
2021-08-13 14:37:31 -07:00
|
|
|
.dispatch = vulkan_runner_dispatch,
|
2024-04-14 17:33:15 -07:00
|
|
|
.clear = vulkan_runner_clear,
|
2022-04-11 10:18:31 -07:00
|
|
|
.draw = vulkan_runner_draw,
|
2022-06-08 16:18:37 -07:00
|
|
|
.get_resource_readback = vulkan_runner_get_resource_readback,
|
2022-05-17 06:45:41 -07:00
|
|
|
.release_readback = vulkan_runner_release_readback,
|
2022-04-11 10:18:31 -07:00
|
|
|
};
|
|
|
|
|
2024-07-07 20:52:54 -07:00
|
|
|
static bool check_device_extensions(struct vulkan_shader_runner *runner,
|
|
|
|
struct vulkan_extension_list *enabled_extensions)
|
2022-04-11 10:18:31 -07:00
|
|
|
{
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
|
|
|
VkPhysicalDevice phys_device = context->phys_device;
|
2022-04-11 10:18:31 -07:00
|
|
|
VkExtensionProperties *extensions;
|
|
|
|
uint32_t i, count;
|
|
|
|
|
2023-10-11 14:09:23 -07:00
|
|
|
static const struct
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
bool required;
|
|
|
|
}
|
|
|
|
device_extensions[] =
|
|
|
|
{
|
|
|
|
{VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME},
|
2024-04-17 07:16:34 -07:00
|
|
|
{VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME},
|
2023-10-11 14:09:23 -07:00
|
|
|
{VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, true},
|
|
|
|
{VK_KHR_MAINTENANCE1_EXTENSION_NAME, true},
|
2024-10-19 02:13:07 -07:00
|
|
|
{VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME},
|
2023-10-11 14:09:23 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
enabled_extensions->names = calloc(ARRAY_SIZE(device_extensions), sizeof(*enabled_extensions->names));
|
|
|
|
enabled_extensions->count = 0;
|
|
|
|
|
2022-04-11 10:18:31 -07:00
|
|
|
VK_CALL(vkEnumerateDeviceExtensionProperties(phys_device, NULL, &count, NULL));
|
|
|
|
extensions = calloc(count, sizeof(*extensions));
|
|
|
|
VK_CALL(vkEnumerateDeviceExtensionProperties(phys_device, NULL, &count, extensions));
|
|
|
|
|
2023-10-11 14:09:23 -07:00
|
|
|
for (i = 0; i < ARRAY_SIZE(device_extensions); ++i)
|
2022-04-11 10:18:31 -07:00
|
|
|
{
|
2023-10-11 14:09:23 -07:00
|
|
|
const char *name = device_extensions[i].name;
|
|
|
|
|
2024-07-07 20:52:54 -07:00
|
|
|
if (vk_extension_properties_contain(extensions, count, name))
|
2022-04-11 10:18:31 -07:00
|
|
|
{
|
2023-10-11 14:09:23 -07:00
|
|
|
enabled_extensions->names[enabled_extensions->count++] = name;
|
|
|
|
if (!strcmp(name, VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME))
|
2024-10-05 05:46:00 -07:00
|
|
|
runner->caps.shader_caps[SHADER_CAP_ROV] = true;
|
2024-04-17 07:16:34 -07:00
|
|
|
if (!strcmp(name, VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME))
|
|
|
|
runner->demote_to_helper_invocation = true;
|
2024-10-19 02:13:07 -07:00
|
|
|
if (!strcmp(name, VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME))
|
|
|
|
runner->driver_properties = true;
|
2023-10-11 14:09:23 -07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (device_extensions[i].required)
|
|
|
|
{
|
|
|
|
skip("The selected Vulkan device does not support %s.\n", name);
|
|
|
|
free(enabled_extensions->names);
|
2024-01-24 14:01:36 -08:00
|
|
|
free(extensions);
|
2022-04-11 10:18:31 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-24 14:01:36 -08:00
|
|
|
free(extensions);
|
2022-04-11 10:18:31 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-10-11 14:09:23 -07:00
|
|
|
static void get_physical_device_info(struct vulkan_shader_runner *runner, struct physical_device_info *info)
|
|
|
|
{
|
2024-07-07 20:42:49 -07:00
|
|
|
const struct vulkan_test_context *context = &runner->context;
|
2023-10-11 14:09:23 -07:00
|
|
|
memset(info, 0, sizeof(*info));
|
|
|
|
|
|
|
|
info->features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
2024-10-05 05:46:00 -07:00
|
|
|
if (runner->caps.shader_caps[SHADER_CAP_ROV])
|
2023-10-11 14:09:23 -07:00
|
|
|
{
|
|
|
|
info->features2.pNext = &info->interlock_features;
|
|
|
|
info->interlock_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT;
|
|
|
|
}
|
|
|
|
|
2024-04-17 07:16:34 -07:00
|
|
|
if (runner->demote_to_helper_invocation)
|
|
|
|
{
|
|
|
|
void *list = info->features2.pNext;
|
|
|
|
|
|
|
|
info->features2.pNext = &info->demote_to_helper_invocation_features;
|
|
|
|
info->demote_to_helper_invocation_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT;
|
|
|
|
info->demote_to_helper_invocation_features.pNext = list;
|
|
|
|
}
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
if (context->vkGetPhysicalDeviceFeatures2KHR)
|
|
|
|
VK_CALL(vkGetPhysicalDeviceFeatures2KHR(context->phys_device, &info->features2));
|
2023-10-11 14:09:23 -07:00
|
|
|
else
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkGetPhysicalDeviceFeatures(context->phys_device, &info->features2.features));
|
2024-10-19 02:13:07 -07:00
|
|
|
|
|
|
|
if (runner->driver_properties)
|
|
|
|
{
|
|
|
|
void *list = info->properties2.pNext;
|
|
|
|
|
|
|
|
info->properties2.pNext = &info->driver_properties;
|
|
|
|
info->driver_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR;
|
|
|
|
info->driver_properties.pNext = list;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (context->vkGetPhysicalDeviceFeatures2KHR)
|
|
|
|
VK_CALL(vkGetPhysicalDeviceProperties2KHR(context->phys_device, &info->properties2));
|
|
|
|
else
|
|
|
|
VK_CALL(vkGetPhysicalDeviceProperties(context->phys_device, &info->properties2.properties));
|
2023-10-11 14:09:23 -07:00
|
|
|
}
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
static uint32_t get_format_support(const struct vulkan_test_context *context, enum DXGI_FORMAT format)
|
2024-08-01 16:13:31 -07:00
|
|
|
{
|
|
|
|
VkFormatProperties properties;
|
|
|
|
uint32_t ret = 0;
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkGetPhysicalDeviceFormatProperties(context->phys_device, vkd3d_get_vk_format(format), &properties));
|
2024-08-01 16:13:31 -07:00
|
|
|
if ((properties.linearTilingFeatures | properties.optimalTilingFeatures) & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)
|
|
|
|
ret |= FORMAT_CAP_UAV_LOAD;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
static bool init_vulkan_runner(struct vulkan_shader_runner *runner)
|
|
|
|
{
|
|
|
|
VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT demote_to_helper_invocation_features;
|
|
|
|
VkDeviceQueueCreateInfo queue_desc = {.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO};
|
|
|
|
VkDeviceCreateInfo device_desc = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO};
|
|
|
|
VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT interlock_features;
|
|
|
|
struct vulkan_test_context *context = &runner->context;
|
2024-07-07 20:52:54 -07:00
|
|
|
struct vulkan_extension_list enabled_extensions;
|
2024-07-07 20:42:49 -07:00
|
|
|
const VkPhysicalDeviceFeatures *ret_features;
|
|
|
|
static const float queue_priority = 1.0f;
|
|
|
|
struct physical_device_info device_info;
|
|
|
|
VkPhysicalDeviceFeatures features;
|
|
|
|
VkFormatProperties format_props;
|
|
|
|
uint32_t graphics_index;
|
|
|
|
bool b;
|
|
|
|
|
|
|
|
static const char *instance_extensions[] =
|
|
|
|
{
|
|
|
|
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
|
|
|
|
};
|
|
|
|
static const enum DXGI_FORMAT formats[] =
|
|
|
|
{
|
|
|
|
DXGI_FORMAT_R32_FLOAT,
|
|
|
|
DXGI_FORMAT_R32_UINT,
|
|
|
|
DXGI_FORMAT_R32_SINT,
|
|
|
|
DXGI_FORMAT_R32G32B32A32_FLOAT,
|
|
|
|
DXGI_FORMAT_R32G32B32A32_UINT,
|
|
|
|
DXGI_FORMAT_R32G32B32A32_SINT,
|
|
|
|
DXGI_FORMAT_R16G16B16A16_FLOAT,
|
|
|
|
DXGI_FORMAT_R16G16B16A16_UINT,
|
|
|
|
DXGI_FORMAT_R16G16B16A16_SINT,
|
|
|
|
DXGI_FORMAT_R8G8B8A8_UNORM,
|
|
|
|
DXGI_FORMAT_R8G8B8A8_UINT,
|
|
|
|
DXGI_FORMAT_R8G8B8A8_SINT,
|
|
|
|
DXGI_FORMAT_R16_FLOAT,
|
|
|
|
DXGI_FORMAT_R16_UINT,
|
|
|
|
DXGI_FORMAT_R16_SINT,
|
|
|
|
DXGI_FORMAT_R8_UNORM,
|
|
|
|
DXGI_FORMAT_R8_UINT,
|
|
|
|
DXGI_FORMAT_R8_SINT,
|
|
|
|
};
|
2024-10-19 02:13:07 -07:00
|
|
|
static const char *const tags[] =
|
|
|
|
{
|
|
|
|
"vulkan",
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *const mvk_tags[] =
|
|
|
|
{
|
|
|
|
"vulkan",
|
|
|
|
"mvk",
|
|
|
|
};
|
2024-07-07 20:42:49 -07:00
|
|
|
|
|
|
|
if (!vulkan_test_context_init_instance(context, instance_extensions, ARRAY_SIZE(instance_extensions)))
|
|
|
|
return false;
|
|
|
|
|
2024-07-07 20:52:54 -07:00
|
|
|
if (!get_vulkan_queue_index(context, VK_QUEUE_GRAPHICS_BIT, &graphics_index))
|
2022-04-11 10:18:31 -07:00
|
|
|
{
|
|
|
|
skip("The selected Vulkan device does not support graphics operations.\n");
|
2024-07-07 20:42:49 -07:00
|
|
|
goto out_destroy_context;
|
2022-04-11 10:18:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
device_desc.pQueueCreateInfos = &queue_desc;
|
|
|
|
device_desc.queueCreateInfoCount = 1;
|
|
|
|
|
|
|
|
queue_desc.queueFamilyIndex = graphics_index;
|
|
|
|
queue_desc.queueCount = 1;
|
|
|
|
queue_desc.pQueuePriorities = &queue_priority;
|
|
|
|
|
2023-10-11 14:09:23 -07:00
|
|
|
if (!check_device_extensions(runner, &enabled_extensions))
|
2024-07-07 20:42:49 -07:00
|
|
|
goto out_destroy_context;
|
2023-10-11 14:09:23 -07:00
|
|
|
device_desc.ppEnabledExtensionNames = enabled_extensions.names;
|
|
|
|
device_desc.enabledExtensionCount = enabled_extensions.count;
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
VK_CALL(vkGetPhysicalDeviceFormatProperties(context->phys_device, VK_FORMAT_R32G32B32A32_SFLOAT, &format_props));
|
2022-04-11 10:18:31 -07:00
|
|
|
if (!(format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
|
|
|
|
{
|
|
|
|
skip("The selected Vulkan device does not support R32G32B32A32_SFLOAT render targets.\n");
|
2024-07-07 20:42:49 -07:00
|
|
|
goto out_destroy_context;
|
2022-04-11 10:18:31 -07:00
|
|
|
}
|
|
|
|
|
2024-02-19 08:01:00 -08:00
|
|
|
runner->caps.runner = "Vulkan";
|
2023-10-11 14:09:23 -07:00
|
|
|
get_physical_device_info(runner, &device_info);
|
|
|
|
ret_features = &device_info.features2.features;
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-10-19 02:13:07 -07:00
|
|
|
if (device_info.driver_properties.driverID == VK_DRIVER_ID_MOLTENVK)
|
|
|
|
{
|
|
|
|
runner->caps.tags = mvk_tags;
|
|
|
|
runner->caps.tag_count = ARRAY_SIZE(mvk_tags);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
runner->caps.tags = tags;
|
|
|
|
runner->caps.tag_count = ARRAY_SIZE(tags);
|
|
|
|
}
|
|
|
|
|
2024-10-05 05:46:00 -07:00
|
|
|
runner->caps.shader_caps[SHADER_CAP_CLIP_PLANES] = true;
|
|
|
|
runner->caps.shader_caps[SHADER_CAP_POINT_SIZE] = true;
|
2024-07-16 17:49:30 -07:00
|
|
|
|
2022-04-11 10:18:31 -07:00
|
|
|
device_desc.pEnabledFeatures = &features;
|
|
|
|
memset(&features, 0, sizeof(features));
|
|
|
|
|
|
|
|
/* FIXME: Probably make these optional. */
|
|
|
|
|
|
|
|
#define ENABLE_FEATURE(x) \
|
2023-10-11 14:09:23 -07:00
|
|
|
if (!ret_features->x) \
|
2022-04-11 10:18:31 -07:00
|
|
|
{ \
|
|
|
|
skip("The selected Vulkan device does not support " #x ".\n"); \
|
2024-07-07 20:42:49 -07:00
|
|
|
goto out_destroy_context; \
|
2022-04-11 10:18:31 -07:00
|
|
|
} \
|
|
|
|
features.x = VK_TRUE
|
|
|
|
|
2022-06-08 16:18:35 -07:00
|
|
|
ENABLE_FEATURE(fragmentStoresAndAtomics);
|
2024-07-16 17:49:30 -07:00
|
|
|
ENABLE_FEATURE(shaderClipDistance);
|
2022-04-11 10:18:31 -07:00
|
|
|
ENABLE_FEATURE(shaderImageGatherExtended);
|
2022-06-08 16:18:35 -07:00
|
|
|
ENABLE_FEATURE(shaderStorageImageWriteWithoutFormat);
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-10-14 12:48:41 -07:00
|
|
|
if (ret_features->geometryShader)
|
|
|
|
{
|
|
|
|
features.geometryShader = VK_TRUE;
|
2024-10-05 05:46:00 -07:00
|
|
|
runner->caps.shader_caps[SHADER_CAP_GEOMETRY_SHADER] = true;
|
2024-10-14 12:48:41 -07:00
|
|
|
}
|
|
|
|
|
2023-10-11 14:09:23 -07:00
|
|
|
if (ret_features->shaderFloat64)
|
2023-12-14 00:57:33 -08:00
|
|
|
{
|
|
|
|
features.shaderFloat64 = VK_TRUE;
|
2024-10-05 05:46:00 -07:00
|
|
|
runner->caps.shader_caps[SHADER_CAP_FLOAT64] = true;
|
2023-12-14 00:57:33 -08:00
|
|
|
}
|
2023-10-11 14:09:23 -07:00
|
|
|
|
|
|
|
if (ret_features->shaderInt64)
|
2023-12-14 00:59:46 -08:00
|
|
|
{
|
|
|
|
features.shaderInt64 = VK_TRUE;
|
2024-10-05 05:46:00 -07:00
|
|
|
runner->caps.shader_caps[SHADER_CAP_INT64] = true;
|
2023-12-14 00:59:46 -08:00
|
|
|
}
|
2023-12-14 00:57:33 -08:00
|
|
|
|
2024-08-31 09:54:44 -07:00
|
|
|
if (ret_features->depthBounds)
|
|
|
|
{
|
|
|
|
features.depthBounds = VK_TRUE;
|
2024-10-05 05:46:00 -07:00
|
|
|
runner->caps.shader_caps[SHADER_CAP_DEPTH_BOUNDS] = true;
|
2024-08-31 09:54:44 -07:00
|
|
|
}
|
|
|
|
|
2023-10-11 14:09:23 -07:00
|
|
|
if (device_info.interlock_features.fragmentShaderSampleInterlock
|
|
|
|
&& device_info.interlock_features.fragmentShaderPixelInterlock)
|
|
|
|
{
|
|
|
|
memset(&interlock_features, 0, sizeof(interlock_features));
|
|
|
|
interlock_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT;
|
|
|
|
interlock_features.pNext = (void *)device_desc.pNext;
|
|
|
|
interlock_features.fragmentShaderSampleInterlock = VK_TRUE;
|
|
|
|
interlock_features.fragmentShaderPixelInterlock = VK_TRUE;
|
|
|
|
device_desc.pNext = &interlock_features;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-10-05 05:46:00 -07:00
|
|
|
runner->caps.shader_caps[SHADER_CAP_ROV] = false;
|
2023-10-11 14:09:23 -07:00
|
|
|
}
|
|
|
|
|
2024-04-17 07:16:34 -07:00
|
|
|
if (device_info.demote_to_helper_invocation_features.shaderDemoteToHelperInvocation)
|
|
|
|
{
|
|
|
|
memset(&demote_to_helper_invocation_features, 0, sizeof(demote_to_helper_invocation_features));
|
|
|
|
demote_to_helper_invocation_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT;
|
|
|
|
demote_to_helper_invocation_features.pNext = (void *)device_desc.pNext;
|
|
|
|
demote_to_helper_invocation_features.shaderDemoteToHelperInvocation = VK_TRUE;
|
|
|
|
device_desc.pNext = &demote_to_helper_invocation_features;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
runner->demote_to_helper_invocation = false;
|
|
|
|
}
|
|
|
|
|
2024-08-01 16:13:31 -07:00
|
|
|
if (device_info.features2.features.shaderStorageImageReadWithoutFormat)
|
|
|
|
runner->caps.format_caps[DXGI_FORMAT_UNKNOWN] |= FORMAT_CAP_UAV_LOAD;
|
|
|
|
for (unsigned int i = 0; i < ARRAY_SIZE(formats); ++i)
|
|
|
|
{
|
2024-07-07 20:42:49 -07:00
|
|
|
runner->caps.format_caps[formats[i]] = get_format_support(context, formats[i]);
|
2024-08-01 16:13:31 -07:00
|
|
|
}
|
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
b = vulkan_test_context_init_device(context, &device_desc, graphics_index, MAX_RESOURCES, MAX_SAMPLERS);
|
2023-10-11 14:09:23 -07:00
|
|
|
free(enabled_extensions.names);
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
if (b)
|
|
|
|
return true;
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
out_destroy_context:
|
|
|
|
vulkan_test_context_destroy(context);
|
2022-04-11 10:18:31 -07:00
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2023-02-21 15:46:36 -08:00
|
|
|
void run_shader_tests_vulkan(void)
|
2022-04-11 10:18:31 -07:00
|
|
|
{
|
|
|
|
struct vulkan_shader_runner runner = {0};
|
|
|
|
|
|
|
|
if (!init_vulkan_runner(&runner))
|
|
|
|
return;
|
|
|
|
|
2024-02-19 07:47:11 -08:00
|
|
|
runner.caps.minimum_shader_model = SHADER_MODEL_2_0;
|
|
|
|
runner.caps.maximum_shader_model = SHADER_MODEL_3_0;
|
|
|
|
run_shader_tests(&runner.r, &runner.caps, &vulkan_runner_ops, NULL);
|
2023-11-15 12:41:33 -08:00
|
|
|
|
2024-02-19 07:47:11 -08:00
|
|
|
runner.caps.minimum_shader_model = SHADER_MODEL_4_0;
|
|
|
|
runner.caps.maximum_shader_model = SHADER_MODEL_5_1;
|
|
|
|
run_shader_tests(&runner.r, &runner.caps, &vulkan_runner_ops, NULL);
|
2022-04-11 10:18:31 -07:00
|
|
|
|
2024-07-07 20:42:49 -07:00
|
|
|
vulkan_test_context_destroy(&runner.context);
|
2022-04-11 10:18:31 -07:00
|
|
|
}
|
2023-01-18 04:53:51 -08:00
|
|
|
|
|
|
|
#endif
|