tests/shader-runner: Support SRV buffers.

This commit is contained in:
Francisco Casas 2024-01-23 20:26:11 -03:00 committed by Alexandre Julliard
parent 22a0f14a2f
commit 4d855611b7
Notes: Alexandre Julliard 2024-02-19 22:59:16 +01:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Zebediah Figura (@zfigura)
Approved-by: Henri Verbeet (@hverbeet)
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/569
8 changed files with 300 additions and 28 deletions

View File

@ -174,6 +174,7 @@ vkd3d_shader_tests = \
tests/hlsl/sm6-uav-rwtexture.shader_test \ tests/hlsl/sm6-uav-rwtexture.shader_test \
tests/hlsl/smoothstep.shader_test \ tests/hlsl/smoothstep.shader_test \
tests/hlsl/sqrt.shader_test \ tests/hlsl/sqrt.shader_test \
tests/hlsl/srv-buffers.shader_test \
tests/hlsl/state-block-syntax.shader_test \ tests/hlsl/state-block-syntax.shader_test \
tests/hlsl/static-initializer.shader_test \ tests/hlsl/static-initializer.shader_test \
tests/hlsl/step.shader_test \ tests/hlsl/step.shader_test \

View File

@ -0,0 +1,189 @@
[require]
shader model >= 4.0
[buffer srv 0]
size (1, 4)
0.0 1.0 2.0 3.0
4.0 5.0 6.0 7.0
8.0 9.0 10.0 11.0
12.0 13.0 14.0 15.0
[pixel shader todo]
float4 a;
Buffer<float4> buffer;
float4 b;
float4 main() : sv_target
{
return float4(a.y, b.z, buffer[1].xw);
}
[test]
uniform 0 float4 100 200 300 400
uniform 4 float4 1000 2000 3000 4000
todo(sm<6) draw quad
probe all rgba (200, 3000, 4, 7)
[pixel shader todo]
float4 a;
Buffer<float3> buffer;
float4 b;
float4 main() : sv_target
{
return float4(b.w, buffer[2]);
}
[test]
uniform 0 float4 100 200 300 400
uniform 4 float4 1000 2000 3000 4000
todo(sm<6) draw quad
probe all rgba (4000.0, 8.0, 9.0, 10.0)
[texture 0]
size (1, 1)
-1.0 -1.0 -1.0 -1.0
[sampler 0]
filter linear linear linear
address clamp clamp clamp
[buffer srv 1]
size (1, 1)
1.0 2.0 3.0 4.0
[pixel shader todo]
Texture2D tex;
sampler sam;
Buffer<float4> buffer;
float4 main() : sv_target
{
return float4(buffer[0].zw, tex.Sample(sam, float2(0, 0)).zw);
}
[test]
todo(sm<6) draw quad
probe all rgba (3.0, 4.0, -1.0, -1.0)
[buffer srv 0]
size (1, 4)
0.0 1.0 2.0 3.0
4.0 5.0 6.0 7.0
8.0 9.0 10.0 11.0
12.0 13.0 14.0 15.0
[pixel shader todo]
Buffer buffer;
float4 main() : sv_target
{
return buffer.Load(1);
}
[test]
todo(sm<6) draw quad
probe all rgba (4.0, 5.0, 6.0, 7.0)
[pixel shader todo]
Buffer buffer;
float4 main() : sv_target
{
return buffer.Load(float2(2, 9999));
}
[test]
todo(sm<6) draw quad
probe all rgba (8.0, 9.0, 10.0, 11.0)
[pixel shader fail]
Buffer buffer;
sampler sam;
float4 main() : sv_target
{
return buffer.Sample(sam, 0);
}
[pixel shader fail]
Buffer buffer;
float4 main() : sv_target
{
uint u1, u2;
buffer.GetDimensions(u1, u2);
return 0;
}
[pixel shader todo]
Buffer buf;
uniform int u;
float4 main() : sv_target
{
return buf[u];
}
[test]
uniform 0 int 2
todo(sm<6) draw quad
probe all rgba (8.0, 9.0, 10.0, 11.0)
uniform 0 int 0
todo(sm<6) draw quad
probe all rgba (0.0, 1.0, 2.0, 3.0)
% Buffer doesn't have offset_dim or sample_index arguments allowed.
[pixel shader fail]
Buffer buffer;
float4 main() : sv_target
{
// This test fails because the output status must be an l-value.
buffer.Load(0, 0);
return 0;
}
[pixel shader fail]
Buffer buffer;
float4 main() : sv_target
{
uint u;
// This test fails because there is no overload for an argument in-between the load index and
// the output status.
buffer.Load(0, 0, u);
return 0;
}
[require]
shader model >= 5.0
[pixel shader todo]
Buffer buffer;
float4 main() : sv_target
{
uint width;
buffer.GetDimensions(width);
return width;
}
[test]
todo draw quad
probe all rgba (4.0, 4.0, 4.0, 4.0)

View File

@ -1583,6 +1583,20 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_o
current_resource.texel_size = 16; current_resource.texel_size = 16;
current_resource.level_count = 1; current_resource.level_count = 1;
} }
else if (sscanf(line, "[buffer srv %u]\n", &index))
{
state = STATE_RESOURCE;
memset(&current_resource, 0, sizeof(current_resource));
current_resource.slot = index;
current_resource.type = RESOURCE_TYPE_TEXTURE;
current_resource.dimension = RESOURCE_DIMENSION_BUFFER;
current_resource.format = DXGI_FORMAT_R32G32B32A32_FLOAT;
current_resource.data_type = TEXTURE_DATA_FLOAT;
current_resource.texel_size = 16;
current_resource.level_count = 1;
}
else if (sscanf(line, "[buffer uav %u]\n", &index)) else if (sscanf(line, "[buffer uav %u]\n", &index))
{ {
state = STATE_RESOURCE; state = STATE_RESOURCE;

View File

@ -428,6 +428,24 @@ static void init_resource_2d(struct d3d11_shader_runner *runner, struct d3d11_re
ok(hr == S_OK, "Failed to create view, hr %#lx.\n", hr); ok(hr == S_OK, "Failed to create view, hr %#lx.\n", hr);
} }
static void init_resource_srv_buffer(struct d3d11_shader_runner *runner, struct d3d11_resource *resource,
const struct resource_params *params)
{
D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc;
ID3D11Device *device = runner->device;
HRESULT hr;
resource->buffer = create_buffer(device, D3D11_BIND_SHADER_RESOURCE, params->data_size, params->data);
resource->resource = (ID3D11Resource *)resource->buffer;
srv_desc.Format = params->format;
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
srv_desc.Buffer.FirstElement = 0;
srv_desc.Buffer.NumElements = params->data_size / params->texel_size;
hr = ID3D11Device_CreateShaderResourceView(device, resource->resource, &srv_desc, &resource->srv);
ok(hr == S_OK, "Failed to create view, hr %#lx.\n", hr);
}
static void init_resource_uav_buffer(struct d3d11_shader_runner *runner, struct d3d11_resource *resource, static void init_resource_uav_buffer(struct d3d11_shader_runner *runner, struct d3d11_resource *resource,
const struct resource_params *params) const struct resource_params *params)
{ {
@ -460,7 +478,10 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co
{ {
case RESOURCE_TYPE_RENDER_TARGET: case RESOURCE_TYPE_RENDER_TARGET:
case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_TEXTURE:
init_resource_2d(runner, resource, params); if (params->dimension == RESOURCE_DIMENSION_BUFFER)
init_resource_srv_buffer(runner, resource, params);
else
init_resource_2d(runner, resource, params);
break; break;
case RESOURCE_TYPE_UAV: case RESOURCE_TYPE_UAV:

View File

@ -130,7 +130,7 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co
struct d3d12_shader_runner *runner = d3d12_shader_runner(r); struct d3d12_shader_runner *runner = d3d12_shader_runner(r);
struct test_context *test_context = &runner->test_context; struct test_context *test_context = &runner->test_context;
ID3D12Device *device = test_context->device; ID3D12Device *device = test_context->device;
D3D12_SUBRESOURCE_DATA resource_data[2]; D3D12_SUBRESOURCE_DATA resource_data[2] = {0};
struct d3d12_resource *resource; struct d3d12_resource *resource;
unsigned int buffer_offset = 0; unsigned int buffer_offset = 0;
D3D12_RESOURCE_STATES state; D3D12_RESOURCE_STATES state;
@ -173,15 +173,38 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co
runner->heap = create_gpu_descriptor_heap(device, runner->heap = create_gpu_descriptor_heap(device,
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, MAX_RESOURCE_DESCRIPTORS); D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, MAX_RESOURCE_DESCRIPTORS);
resource->resource = create_default_texture2d(device, params->width, params->height, 1, params->level_count, if (params->dimension == RESOURCE_DIMENSION_BUFFER)
params->format, 0, D3D12_RESOURCE_STATE_COPY_DEST); {
upload_texture_data_with_states(resource->resource, resource_data, D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = { 0 };
params->level_count, test_context->queue, test_context->list,
RESOURCE_STATE_DO_NOT_CHANGE, resource->resource = create_default_buffer(device, params->data_size,
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); 0, D3D12_RESOURCE_STATE_COPY_DEST);
reset_command_list(test_context->list, test_context->allocator); upload_buffer_data_with_states(resource->resource, 0, params->data_size, resource_data[0].pData,
ID3D12Device_CreateShaderResourceView(device, resource->resource, test_context->queue, test_context->list,
NULL, get_cpu_descriptor_handle(test_context, runner->heap, resource->r.slot)); RESOURCE_STATE_DO_NOT_CHANGE,
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
reset_command_list(test_context->list, test_context->allocator);
srv_desc.Format = params->format;
srv_desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srv_desc.Buffer.NumElements = params->width * params->height;
ID3D12Device_CreateShaderResourceView(device, resource->resource,
&srv_desc, get_cpu_descriptor_handle(test_context, runner->heap, resource->r.slot));
}
else
{
resource->resource = create_default_texture2d(device, params->width, params->height, 1, params->level_count,
params->format, 0, D3D12_RESOURCE_STATE_COPY_DEST);
upload_texture_data_with_states(resource->resource, resource_data,
params->level_count, test_context->queue, test_context->list,
RESOURCE_STATE_DO_NOT_CHANGE,
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
reset_command_list(test_context->list, test_context->allocator);
ID3D12Device_CreateShaderResourceView(device, resource->resource,
NULL, get_cpu_descriptor_handle(test_context, runner->heap, resource->r.slot));
}
break; break;
case RESOURCE_TYPE_UAV: case RESOURCE_TYPE_UAV:

View File

@ -240,6 +240,12 @@ static struct resource *d3d9_runner_create_resource(struct shader_runner *r, con
case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_TEXTURE:
{ {
if (params->dimension == RESOURCE_DIMENSION_BUFFER)
{
fatal_error("Buffer resources are not supported.\n");
break;
}
unsigned int src_buffer_offset = 0; unsigned int src_buffer_offset = 0;
hr = IDirect3DDevice9_CreateTexture(device, params->width, params->height, hr = IDirect3DDevice9_CreateTexture(device, params->width, params->height,
@ -387,6 +393,8 @@ static bool d3d9_runner_draw(struct shader_runner *r,
break; break;
case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_TEXTURE:
assert(resource->r.dimension != RESOURCE_DIMENSION_BUFFER);
hr = IDirect3DDevice9_SetTexture(device, resource->r.slot, (IDirect3DBaseTexture9 *)resource->texture); hr = IDirect3DDevice9_SetTexture(device, resource->r.slot, (IDirect3DBaseTexture9 *)resource->texture);
ok(hr == D3D_OK, "Failed to set texture, hr %#lx.\n", hr); ok(hr == D3D_OK, "Failed to set texture, hr %#lx.\n", hr);
break; break;

View File

@ -376,9 +376,6 @@ static struct resource *gl_runner_create_resource(struct shader_runner *r, const
{ {
case RESOURCE_TYPE_RENDER_TARGET: case RESOURCE_TYPE_RENDER_TARGET:
case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_TEXTURE:
init_resource_2d(resource, params);
break;
case RESOURCE_TYPE_UAV: case RESOURCE_TYPE_UAV:
if (params->dimension == RESOURCE_DIMENSION_BUFFER) if (params->dimension == RESOURCE_DIMENSION_BUFFER)
init_resource_buffer(resource, params); init_resource_buffer(resource, params);
@ -404,9 +401,6 @@ static void gl_runner_destroy_resource(struct shader_runner *r, struct resource
{ {
case RESOURCE_TYPE_RENDER_TARGET: case RESOURCE_TYPE_RENDER_TARGET:
case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_TEXTURE:
glDeleteTextures(1, &resource->id);
break;
case RESOURCE_TYPE_UAV: case RESOURCE_TYPE_UAV:
if (res->dimension == RESOURCE_DIMENSION_BUFFER) if (res->dimension == RESOURCE_DIMENSION_BUFFER)
{ {
@ -505,7 +499,10 @@ static bool compile_shader(struct gl_runner *runner, ID3DBlob *blob, struct vkd3
sampler->sampler_space = s->sampler_space; sampler->sampler_space = s->sampler_space;
sampler->sampler_index = s->sampler_index; sampler->sampler_index = s->sampler_index;
sampler->shader_visibility = VKD3D_SHADER_VISIBILITY_ALL; sampler->shader_visibility = VKD3D_SHADER_VISIBILITY_ALL;
sampler->flags = VKD3D_SHADER_BINDING_FLAG_IMAGE; /* We don't know if this combined sampler was created from a SRV buffer or a SRV image, so
* we pass both flags, otherwise the combined sampler won't be recognized when emitting the
* SPIR-V, which will result in a failing assertion. */
sampler->flags = VKD3D_SHADER_BINDING_FLAG_IMAGE | VKD3D_SHADER_BINDING_FLAG_BUFFER;
sampler->binding.set = 0; sampler->binding.set = 0;
sampler->binding.binding = runner->combined_sampler_count++; sampler->binding.binding = runner->combined_sampler_count++;
sampler->binding.count = 1; sampler->binding.count = 1;
@ -872,8 +869,17 @@ static bool gl_runner_draw(struct shader_runner *r,
if (!(resource = shader_runner_get_resource(r, RESOURCE_TYPE_TEXTURE, s->resource_index))) if (!(resource = shader_runner_get_resource(r, RESOURCE_TYPE_TEXTURE, s->resource_index)))
fatal_error("Resource not found.\n"); fatal_error("Resource not found.\n");
glActiveTexture(GL_TEXTURE0 + s->binding.binding); if (resource->dimension == RESOURCE_DIMENSION_BUFFER)
glBindTexture(GL_TEXTURE_2D, gl_resource(resource)->id); {
glActiveTexture(GL_TEXTURE0 + s->binding.binding);
glBindTexture(GL_TEXTURE_BUFFER, gl_resource(resource)->tbo_id);
}
else
{
glActiveTexture(GL_TEXTURE0 + s->binding.binding);
glBindTexture(GL_TEXTURE_2D, gl_resource(resource)->id);
}
if (s->sampler_index == VKD3D_SHADER_DUMMY_SAMPLER_INDEX) if (s->sampler_index == VKD3D_SHADER_DUMMY_SAMPLER_INDEX)
continue; continue;

View File

@ -338,9 +338,15 @@ static void resource_init_buffer(struct vulkan_shader_runner *runner, struct vul
{ {
VkFormat format = vkd3d_get_vk_format(params->format); VkFormat format = vkd3d_get_vk_format(params->format);
VkDevice device = runner->device; VkDevice device = runner->device;
VkBufferUsageFlagBits usage;
void *data; void *data;
resource->buffer = create_buffer(runner, params->data_size, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, if (params->type == RESOURCE_TYPE_UAV)
usage = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
else
usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
resource->buffer = create_buffer(runner, params->data_size, usage,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &resource->memory); VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &resource->memory);
resource->buffer_view = create_buffer_view(runner, resource->buffer, format); resource->buffer_view = create_buffer_view(runner, resource->buffer, format);
@ -376,9 +382,6 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c
break; break;
case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_TEXTURE:
resource_init_2d(runner, resource, params);
break;
case RESOURCE_TYPE_UAV: case RESOURCE_TYPE_UAV:
if (params->dimension == RESOURCE_DIMENSION_BUFFER) if (params->dimension == RESOURCE_DIMENSION_BUFFER)
resource_init_buffer(runner, resource, params); resource_init_buffer(runner, resource, params);
@ -859,7 +862,10 @@ static VkDescriptorSetLayout create_descriptor_set_layout(struct vulkan_shader_r
} }
else else
{ {
binding->descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; if (resource->r.dimension == RESOURCE_DIMENSION_BUFFER)
binding->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
else
binding->descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
} }
binding->descriptorCount = 1; binding->descriptorCount = 1;
binding->stageFlags = VK_SHADER_STAGE_ALL; binding->stageFlags = VK_SHADER_STAGE_ALL;
@ -926,14 +932,16 @@ static void bind_resources(struct vulkan_shader_runner *runner, VkPipelineBindPo
case RESOURCE_TYPE_UAV: case RESOURCE_TYPE_UAV:
if (resource->r.dimension == RESOURCE_DIMENSION_BUFFER) if (resource->r.dimension == RESOURCE_DIMENSION_BUFFER)
{ {
assert(resource->r.type == RESOURCE_TYPE_UAV);
write.dstSet = descriptor_set; write.dstSet = descriptor_set;
write.dstBinding = resource->binding; write.dstBinding = resource->binding;
write.dstArrayElement = 0; write.dstArrayElement = 0;
write.descriptorCount = 1; write.descriptorCount = 1;
write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
write.pTexelBufferView = &resource->buffer_view; write.pTexelBufferView = &resource->buffer_view;
if (resource->r.type == RESOURCE_TYPE_UAV)
write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
VK_CALL(vkUpdateDescriptorSets(runner->device, 1, &write, 0, NULL)); VK_CALL(vkUpdateDescriptorSets(runner->device, 1, &write, 0, NULL));
} }
else else
@ -1301,7 +1309,7 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner)
VkInstanceCreateInfo instance_desc = {.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO}; VkInstanceCreateInfo instance_desc = {.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};
VkDeviceCreateInfo device_desc = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO}; VkDeviceCreateInfo device_desc = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO};
VkPhysicalDeviceFeatures ret_features, features; VkPhysicalDeviceFeatures ret_features, features;
VkDescriptorPoolSize descriptor_pool_sizes[4]; VkDescriptorPoolSize descriptor_pool_sizes[5];
static const float queue_priority = 1.0f; static const float queue_priority = 1.0f;
VkFormatProperties format_props; VkFormatProperties format_props;
uint32_t count, graphics_index; uint32_t count, graphics_index;
@ -1428,6 +1436,8 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner)
descriptor_pool_sizes[2].descriptorCount = MAX_RESOURCES; descriptor_pool_sizes[2].descriptorCount = MAX_RESOURCES;
descriptor_pool_sizes[3].type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; descriptor_pool_sizes[3].type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
descriptor_pool_sizes[3].descriptorCount = MAX_RESOURCES; descriptor_pool_sizes[3].descriptorCount = MAX_RESOURCES;
descriptor_pool_sizes[4].type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
descriptor_pool_sizes[4].descriptorCount = MAX_RESOURCES;
descriptor_pool_desc.maxSets = 1; descriptor_pool_desc.maxSets = 1;
descriptor_pool_desc.poolSizeCount = ARRAY_SIZE(descriptor_pool_sizes); descriptor_pool_desc.poolSizeCount = ARRAY_SIZE(descriptor_pool_sizes);