diff --git a/Makefile.am b/Makefile.am index c02ec026..ec942086 100644 --- a/Makefile.am +++ b/Makefile.am @@ -174,6 +174,7 @@ vkd3d_shader_tests = \ tests/hlsl/sm6-uav-rwtexture.shader_test \ tests/hlsl/smoothstep.shader_test \ tests/hlsl/sqrt.shader_test \ + tests/hlsl/srv-buffers.shader_test \ tests/hlsl/state-block-syntax.shader_test \ tests/hlsl/static-initializer.shader_test \ tests/hlsl/step.shader_test \ diff --git a/tests/hlsl/srv-buffers.shader_test b/tests/hlsl/srv-buffers.shader_test new file mode 100644 index 00000000..2b466375 --- /dev/null +++ b/tests/hlsl/srv-buffers.shader_test @@ -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 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 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 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) diff --git a/tests/shader_runner.c b/tests/shader_runner.c index 486809bb..59ff7bb7 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -1583,6 +1583,20 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_o current_resource.texel_size = 16; current_resource.level_count = 1; } + else if (sscanf(line, "[buffer srv %u]\n", &index)) + { + state = STATE_RESOURCE; + + memset(¤t_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)) { state = STATE_RESOURCE; diff --git a/tests/shader_runner_d3d11.c b/tests/shader_runner_d3d11.c index 2e6b4ced..e7fb3800 100644 --- a/tests/shader_runner_d3d11.c +++ b/tests/shader_runner_d3d11.c @@ -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); } +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, 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_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; case RESOURCE_TYPE_UAV: diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index c7f9d4f7..88a34100 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -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 test_context *test_context = &runner->test_context; ID3D12Device *device = test_context->device; - D3D12_SUBRESOURCE_DATA resource_data[2]; + D3D12_SUBRESOURCE_DATA resource_data[2] = {0}; struct d3d12_resource *resource; unsigned int buffer_offset = 0; 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, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, MAX_RESOURCE_DESCRIPTORS); - 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)); + if (params->dimension == RESOURCE_DIMENSION_BUFFER) + { + D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = { 0 }; + + resource->resource = create_default_buffer(device, params->data_size, + 0, D3D12_RESOURCE_STATE_COPY_DEST); + upload_buffer_data_with_states(resource->resource, 0, params->data_size, resource_data[0].pData, + 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); + + 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; case RESOURCE_TYPE_UAV: diff --git a/tests/shader_runner_d3d9.c b/tests/shader_runner_d3d9.c index 773a27ff..c8ec532a 100644 --- a/tests/shader_runner_d3d9.c +++ b/tests/shader_runner_d3d9.c @@ -240,6 +240,12 @@ static struct resource *d3d9_runner_create_resource(struct shader_runner *r, con 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; hr = IDirect3DDevice9_CreateTexture(device, params->width, params->height, @@ -387,6 +393,8 @@ static bool d3d9_runner_draw(struct shader_runner *r, break; case RESOURCE_TYPE_TEXTURE: + assert(resource->r.dimension != RESOURCE_DIMENSION_BUFFER); + hr = IDirect3DDevice9_SetTexture(device, resource->r.slot, (IDirect3DBaseTexture9 *)resource->texture); ok(hr == D3D_OK, "Failed to set texture, hr %#lx.\n", hr); break; diff --git a/tests/shader_runner_gl.c b/tests/shader_runner_gl.c index 3ce319b9..a24beb7b 100644 --- a/tests/shader_runner_gl.c +++ b/tests/shader_runner_gl.c @@ -376,9 +376,6 @@ static struct resource *gl_runner_create_resource(struct shader_runner *r, const { case RESOURCE_TYPE_RENDER_TARGET: case RESOURCE_TYPE_TEXTURE: - init_resource_2d(resource, params); - break; - case RESOURCE_TYPE_UAV: if (params->dimension == RESOURCE_DIMENSION_BUFFER) 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_TEXTURE: - glDeleteTextures(1, &resource->id); - break; - case RESOURCE_TYPE_UAV: 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_index = s->sampler_index; 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.binding = runner->combined_sampler_count++; 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))) fatal_error("Resource not found.\n"); - glActiveTexture(GL_TEXTURE0 + s->binding.binding); - glBindTexture(GL_TEXTURE_2D, gl_resource(resource)->id); + if (resource->dimension == RESOURCE_DIMENSION_BUFFER) + { + 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) continue; diff --git a/tests/shader_runner_vulkan.c b/tests/shader_runner_vulkan.c index ca88dc99..f95fabc5 100644 --- a/tests/shader_runner_vulkan.c +++ b/tests/shader_runner_vulkan.c @@ -338,9 +338,15 @@ static void resource_init_buffer(struct vulkan_shader_runner *runner, struct vul { VkFormat format = vkd3d_get_vk_format(params->format); VkDevice device = runner->device; + VkBufferUsageFlagBits usage; 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); 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; case RESOURCE_TYPE_TEXTURE: - resource_init_2d(runner, resource, params); - break; - case RESOURCE_TYPE_UAV: if (params->dimension == RESOURCE_DIMENSION_BUFFER) resource_init_buffer(runner, resource, params); @@ -859,7 +862,10 @@ static VkDescriptorSetLayout create_descriptor_set_layout(struct vulkan_shader_r } 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->stageFlags = VK_SHADER_STAGE_ALL; @@ -926,14 +932,16 @@ static void bind_resources(struct vulkan_shader_runner *runner, VkPipelineBindPo case RESOURCE_TYPE_UAV: if (resource->r.dimension == RESOURCE_DIMENSION_BUFFER) { - assert(resource->r.type == RESOURCE_TYPE_UAV); write.dstSet = descriptor_set; write.dstBinding = resource->binding; write.dstArrayElement = 0; write.descriptorCount = 1; - write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; 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)); } 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}; VkDeviceCreateInfo device_desc = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO}; VkPhysicalDeviceFeatures ret_features, features; - VkDescriptorPoolSize descriptor_pool_sizes[4]; + VkDescriptorPoolSize descriptor_pool_sizes[5]; static const float queue_priority = 1.0f; VkFormatProperties format_props; 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[3].type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; 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.poolSizeCount = ARRAY_SIZE(descriptor_pool_sizes);