Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
-- v4: tests: Add a test for writing to RWBuffer. tests: Add support for specifing UAV buffers. vkd3d-shader/hlsl: Improve UAV format type checking for buffer types. vkd3d-shader/hlsl: Add support for writing RWStructuredBuffer declarations. vkd3d-shader/hlsl: Add support for RWBuffer object. vkd3d-shader: Fix dcl_uav_typed_* formatting.
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/d3d_asm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d-shader/d3d_asm.c index 9438bfac..3357b450 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -661,8 +661,9 @@ static void shader_dump_decl_usage(struct vkd3d_d3d_asm_compiler *compiler, else if (semantic->resource.reg.reg.type == VKD3DSPR_RESOURCE || semantic->resource.reg.reg.type == VKD3DSPR_UAV) { if (semantic->resource.reg.reg.type == VKD3DSPR_RESOURCE) - shader_addline(buffer, "_resource_"); + shader_addline(buffer, "_resource");
+ shader_addline(buffer, "_"); shader_dump_resource_type(compiler, semantic->resource_type); if (semantic->resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMS || semantic->resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY)
From: Nikolay Sivov nsivov@codeweavers.com
--- libs/vkd3d-shader/hlsl.h | 4 +++- libs/vkd3d-shader/hlsl.l | 1 + libs/vkd3d-shader/hlsl.y | 7 ++++++- libs/vkd3d-shader/tpf.c | 4 ++++ 4 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index a3453538..3c0aa03c 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -115,7 +115,8 @@ enum hlsl_sampler_dim HLSL_SAMPLER_DIM_2DMS, HLSL_SAMPLER_DIM_2DMSARRAY, HLSL_SAMPLER_DIM_CUBEARRAY, - HLSL_SAMPLER_DIM_MAX = HLSL_SAMPLER_DIM_CUBEARRAY, + HLSL_SAMPLER_DIM_BUFFER, + HLSL_SAMPLER_DIM_MAX = HLSL_SAMPLER_DIM_BUFFER, };
enum hlsl_regset @@ -1023,6 +1024,7 @@ static inline unsigned int hlsl_sampler_dim_count(enum hlsl_sampler_dim dim) switch (dim) { case HLSL_SAMPLER_DIM_1D: + case HLSL_SAMPLER_DIM_BUFFER: return 1; case HLSL_SAMPLER_DIM_1DARRAY: case HLSL_SAMPLER_DIM_2D: diff --git a/libs/vkd3d-shader/hlsl.l b/libs/vkd3d-shader/hlsl.l index 10751bbe..9c76cc4e 100644 --- a/libs/vkd3d-shader/hlsl.l +++ b/libs/vkd3d-shader/hlsl.l @@ -103,6 +103,7 @@ RasterizerState {return KW_RASTERIZERSTATE; } RenderTargetView {return KW_RENDERTARGETVIEW; } return {return KW_RETURN; } register {return KW_REGISTER; } +RWBuffer {return KW_RWBUFFER; } RWTexture1D {return KW_RWTEXTURE1D; } RWTexture2D {return KW_RWTEXTURE2D; } RWTexture3D {return KW_RWTEXTURE3D; } diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index a3ddae51..c1c32ca6 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -4153,6 +4153,7 @@ static void validate_texture_format_type(struct hlsl_ctx *ctx, struct hlsl_type %token KW_RETURN %token KW_REGISTER %token KW_ROW_MAJOR +%token KW_RWBUFFER %token KW_RWTEXTURE1D %token KW_RWTEXTURE2D %token KW_RWTEXTURE3D @@ -4962,7 +4963,11 @@ texture_ms_type: }
uav_type: - KW_RWTEXTURE1D + KW_RWBUFFER + { + $$ = HLSL_SAMPLER_DIM_BUFFER; + } + | KW_RWTEXTURE1D { $$ = HLSL_SAMPLER_DIM_1D; } diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 3c23cc3c..cc5f83a3 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -2663,6 +2663,8 @@ static D3D_SRV_DIMENSION sm4_rdef_resource_dimension(const struct hlsl_type *typ return D3D_SRV_DIMENSION_TEXTURE2DMSARRAY; case HLSL_SAMPLER_DIM_CUBEARRAY: return D3D_SRV_DIMENSION_TEXTURECUBEARRAY; + case HLSL_SAMPLER_DIM_BUFFER: + return D3D_SRV_DIMENSION_BUFFER; default: vkd3d_unreachable(); } @@ -2962,6 +2964,8 @@ static enum vkd3d_sm4_resource_type sm4_resource_dimension(const struct hlsl_typ return VKD3D_SM4_RESOURCE_TEXTURE_2DMSARRAY; case HLSL_SAMPLER_DIM_CUBEARRAY: return VKD3D_SM4_RESOURCE_TEXTURE_CUBEARRAY; + case HLSL_SAMPLER_DIM_BUFFER: + return VKD3D_SM4_RESOURCE_BUFFER; default: vkd3d_unreachable(); }
From: Nikolay Sivov nsivov@codeweavers.com
--- libs/vkd3d-shader/hlsl.h | 28 +++++++++++++++------------- libs/vkd3d-shader/hlsl.l | 1 + libs/vkd3d-shader/hlsl.y | 5 +++++ libs/vkd3d-shader/tpf.c | 29 ++++++++++++++++++++++++++--- 4 files changed, 47 insertions(+), 16 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 3c0aa03c..7d8efb97 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -104,19 +104,20 @@ enum hlsl_base_type
enum hlsl_sampler_dim { - HLSL_SAMPLER_DIM_GENERIC, - HLSL_SAMPLER_DIM_1D, - HLSL_SAMPLER_DIM_2D, - HLSL_SAMPLER_DIM_3D, - HLSL_SAMPLER_DIM_CUBE, - HLSL_SAMPLER_DIM_LAST_SAMPLER = HLSL_SAMPLER_DIM_CUBE, - HLSL_SAMPLER_DIM_1DARRAY, - HLSL_SAMPLER_DIM_2DARRAY, - HLSL_SAMPLER_DIM_2DMS, - HLSL_SAMPLER_DIM_2DMSARRAY, - HLSL_SAMPLER_DIM_CUBEARRAY, - HLSL_SAMPLER_DIM_BUFFER, - HLSL_SAMPLER_DIM_MAX = HLSL_SAMPLER_DIM_BUFFER, + HLSL_SAMPLER_DIM_GENERIC, + HLSL_SAMPLER_DIM_1D, + HLSL_SAMPLER_DIM_2D, + HLSL_SAMPLER_DIM_3D, + HLSL_SAMPLER_DIM_CUBE, + HLSL_SAMPLER_DIM_LAST_SAMPLER = HLSL_SAMPLER_DIM_CUBE, + HLSL_SAMPLER_DIM_1DARRAY, + HLSL_SAMPLER_DIM_2DARRAY, + HLSL_SAMPLER_DIM_2DMS, + HLSL_SAMPLER_DIM_2DMSARRAY, + HLSL_SAMPLER_DIM_CUBEARRAY, + HLSL_SAMPLER_DIM_BUFFER, + HLSL_SAMPLER_DIM_STRUCTURED_BUFFER, + HLSL_SAMPLER_DIM_MAX = HLSL_SAMPLER_DIM_STRUCTURED_BUFFER, };
enum hlsl_regset @@ -1025,6 +1026,7 @@ static inline unsigned int hlsl_sampler_dim_count(enum hlsl_sampler_dim dim) { case HLSL_SAMPLER_DIM_1D: case HLSL_SAMPLER_DIM_BUFFER: + case HLSL_SAMPLER_DIM_STRUCTURED_BUFFER: return 1; case HLSL_SAMPLER_DIM_1DARRAY: case HLSL_SAMPLER_DIM_2D: diff --git a/libs/vkd3d-shader/hlsl.l b/libs/vkd3d-shader/hlsl.l index 9c76cc4e..19e0f2fa 100644 --- a/libs/vkd3d-shader/hlsl.l +++ b/libs/vkd3d-shader/hlsl.l @@ -104,6 +104,7 @@ RenderTargetView {return KW_RENDERTARGETVIEW; } return {return KW_RETURN; } register {return KW_REGISTER; } RWBuffer {return KW_RWBUFFER; } +RWStructuredBuffer {return KW_RWSTRUCTUREDBUFFER; } RWTexture1D {return KW_RWTEXTURE1D; } RWTexture2D {return KW_RWTEXTURE2D; } RWTexture3D {return KW_RWTEXTURE3D; } diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index c1c32ca6..9b5d8258 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -4154,6 +4154,7 @@ static void validate_texture_format_type(struct hlsl_ctx *ctx, struct hlsl_type %token KW_REGISTER %token KW_ROW_MAJOR %token KW_RWBUFFER +%token KW_RWSTRUCTUREDBUFFER %token KW_RWTEXTURE1D %token KW_RWTEXTURE2D %token KW_RWTEXTURE3D @@ -4967,6 +4968,10 @@ uav_type: { $$ = HLSL_SAMPLER_DIM_BUFFER; } + | KW_RWSTRUCTUREDBUFFER + { + $$ = HLSL_SAMPLER_DIM_STRUCTURED_BUFFER; + } | KW_RWTEXTURE1D { $$ = HLSL_SAMPLER_DIM_1D; diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index cc5f83a3..a0ee6567 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -2664,6 +2664,7 @@ static D3D_SRV_DIMENSION sm4_rdef_resource_dimension(const struct hlsl_type *typ case HLSL_SAMPLER_DIM_CUBEARRAY: return D3D_SRV_DIMENSION_TEXTURECUBEARRAY; case HLSL_SAMPLER_DIM_BUFFER: + case HLSL_SAMPLER_DIM_STRUCTURED_BUFFER: return D3D_SRV_DIMENSION_BUFFER; default: vkd3d_unreachable(); @@ -2965,6 +2966,7 @@ static enum vkd3d_sm4_resource_type sm4_resource_dimension(const struct hlsl_typ case HLSL_SAMPLER_DIM_CUBEARRAY: return VKD3D_SM4_RESOURCE_TEXTURE_CUBEARRAY; case HLSL_SAMPLER_DIM_BUFFER: + case HLSL_SAMPLER_DIM_STRUCTURED_BUFFER: return VKD3D_SM4_RESOURCE_BUFFER; default: vkd3d_unreachable(); @@ -3040,6 +3042,8 @@ struct sm4_instruction } srcs[4]; unsigned int src_count;
+ unsigned int byte_stride; + uint32_t idx[3]; unsigned int idx_count; }; @@ -3274,6 +3278,8 @@ static void write_sm4_instruction(struct vkd3d_bytecode_buffer *buffer, const st for (i = 0; i < instr->src_count; ++i) size += sm4_register_order(&instr->srcs[i].reg); size += instr->idx_count; + if (instr->byte_stride) + ++size;
token |= (size << VKD3D_SM4_INSTRUCTION_LENGTH_SHIFT);
@@ -3328,6 +3334,9 @@ static void write_sm4_instruction(struct vkd3d_bytecode_buffer *buffer, const st } }
+ if (instr->byte_stride) + put_u32(buffer, instr->byte_stride); + for (j = 0; j < instr->idx_count; ++j) put_u32(buffer, instr->idx[j]); } @@ -3413,9 +3422,6 @@ static void write_sm4_dcl_textures(struct hlsl_ctx *ctx, struct vkd3d_bytecode_b
instr = (struct sm4_instruction) { - .opcode = (uav ? VKD3D_SM5_OP_DCL_UAV_TYPED : VKD3D_SM4_OP_DCL_RESOURCE) - | (sm4_resource_dimension(component_type) << VKD3D_SM4_RESOURCE_TYPE_SHIFT), - .dsts[0].reg.type = uav ? VKD3D_SM5_RT_UAV : VKD3D_SM4_RT_RESOURCE, .dsts[0].reg.idx = {var->regs[regset].id + i}, .dsts[0].reg.idx_count = 1, @@ -3425,6 +3431,23 @@ static void write_sm4_dcl_textures(struct hlsl_ctx *ctx, struct vkd3d_bytecode_b .idx_count = 1, };
+ if (uav) + { + switch (var->data_type->sampler_dim) + { + case HLSL_SAMPLER_DIM_STRUCTURED_BUFFER: + instr.opcode = VKD3D_SM5_OP_DCL_UAV_STRUCTURED; + instr.byte_stride = var->data_type->e.resource_format->reg_size[HLSL_REGSET_NUMERIC] * 4; + break; + default: + instr.opcode = VKD3D_SM5_OP_DCL_UAV_TYPED; + break; + } + } + else + instr.opcode = VKD3D_SM4_OP_DCL_RESOURCE; + instr.opcode |= (sm4_resource_dimension(component_type) << VKD3D_SM4_RESOURCE_TYPE_SHIFT); + if (component_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS || component_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY) {
From: Nikolay Sivov nsivov@codeweavers.com
--- libs/vkd3d-shader/hlsl.y | 48 +++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 8 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 9b5d8258..e6c2cb96 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -5104,16 +5104,48 @@ type_no_void: } | uav_type '<' type '>' { - if ($3->class > HLSL_CLASS_VECTOR) - { - struct vkd3d_string_buffer *string; + struct vkd3d_string_buffer *string = hlsl_type_to_string(ctx, $3);
- string = hlsl_type_to_string(ctx, $3); - if (string) - hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "UAV data type %s is not scalar or vector.", string->buffer); - hlsl_release_string_buffer(ctx, string); + switch ($1) + { + case HLSL_SAMPLER_DIM_BUFFER: + if ($3->class > HLSL_CLASS_MATRIX) + { + if (string) + hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "UAV data type %s is not scalar, vector, or matrix.", string->buffer); + } + else if ($3->reg_size[HLSL_REGSET_NUMERIC] > 4) + { + if (string) + hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "UAV data type %s size exceeds 4-component register size.", string->buffer); + } + break; + case HLSL_SAMPLER_DIM_STRUCTURED_BUFFER: + if ($3->class > HLSL_CLASS_STRUCT) + { + if (string) + hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "UAV data type %s can't be used with structured buffers.", string->buffer); + } + break; + case HLSL_SAMPLER_DIM_1D: + case HLSL_SAMPLER_DIM_2D: + case HLSL_SAMPLER_DIM_3D: + if ($3->class > HLSL_CLASS_VECTOR) + { + if (string) + hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "UAV data type %s is not scalar or vector.", string->buffer); + } + break; + default: + vkd3d_unreachable(); } + + hlsl_release_string_buffer(ctx, string); + $$ = hlsl_new_uav_type(ctx, $1, $3); } | TYPE_IDENTIFIER
From: Nikolay Sivov nsivov@codeweavers.com
--- tests/shader_runner.c | 22 +++++++ tests/shader_runner.h | 1 + tests/shader_runner_d3d11.c | 7 ++- tests/shader_runner_d3d12.c | 4 ++ tests/shader_runner_d3d9.c | 2 + tests/shader_runner_vulkan.c | 118 +++++++++++++++++++++++++++-------- tests/vulkan_procs.h | 2 + 7 files changed, 127 insertions(+), 29 deletions(-)
diff --git a/tests/shader_runner.c b/tests/shader_runner.c index b51145c7..64013f98 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -567,6 +567,16 @@ static void parse_test_directive(struct shader_runner *runner, const char *line)
resource = get_resource(runner, RESOURCE_TYPE_UAV, slot); } + else if (match_string(line, "buffer uav", &line)) + { + slot = strtoul(line, &rest, 10); + + if (rest == line) + fatal_error("Malformed buffer UAV index '%s'.\n", line); + line = rest; + + resource = get_resource(runner, RESOURCE_TYPE_BUFFER_UAV, slot); + } else if (match_string(line, "render target", &line)) { slot = strtoul(line, &rest, 10); @@ -1035,6 +1045,18 @@ 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 uav %u]\n", &index)) + { + state = STATE_RESOURCE; + + memset(¤t_resource, 0, sizeof(current_resource)); + + current_resource.slot = index; + current_resource.type = RESOURCE_TYPE_BUFFER_UAV; + current_resource.format = DXGI_FORMAT_R32G32B32A32_FLOAT; + current_resource.data_type = TEXTURE_DATA_FLOAT; + current_resource.texel_size = 16; + } else if (sscanf(line, "[vertex buffer %u]\n", &index)) { state = STATE_RESOURCE; diff --git a/tests/shader_runner.h b/tests/shader_runner.h index 8962a8fc..7a2498f4 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -58,6 +58,7 @@ enum resource_type RESOURCE_TYPE_RENDER_TARGET, RESOURCE_TYPE_TEXTURE, RESOURCE_TYPE_UAV, + RESOURCE_TYPE_BUFFER_UAV, RESOURCE_TYPE_VERTEX_BUFFER, };
diff --git a/tests/shader_runner_d3d11.c b/tests/shader_runner_d3d11.c index a6b9c693..e9179b58 100644 --- a/tests/shader_runner_d3d11.c +++ b/tests/shader_runner_d3d11.c @@ -350,6 +350,7 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co case RESOURCE_TYPE_RENDER_TARGET: case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_UAV: + case RESOURCE_TYPE_BUFFER_UAV: { D3D11_SUBRESOURCE_DATA resource_data[2]; D3D11_TEXTURE2D_DESC desc = {0}; @@ -364,7 +365,7 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co desc.Format = params->format; desc.SampleDesc.Count = 1; desc.Usage = D3D11_USAGE_DEFAULT; - if (params->type == RESOURCE_TYPE_UAV) + if (params->type == RESOURCE_TYPE_UAV || params->type == RESOURCE_TYPE_BUFFER_UAV) desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; else if (params->type == RESOURCE_TYPE_RENDER_TARGET) desc.BindFlags = D3D11_BIND_RENDER_TARGET; @@ -394,7 +395,7 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr);
resource->resource = (ID3D11Resource *)resource->texture; - if (params->type == RESOURCE_TYPE_UAV) + if (params->type == RESOURCE_TYPE_UAV || params->type == RESOURCE_TYPE_BUFFER_UAV) hr = ID3D11Device_CreateUnorderedAccessView(device, resource->resource, NULL, &resource->uav); else if (params->type == RESOURCE_TYPE_RENDER_TARGET) hr = ID3D11Device_CreateRenderTargetView(device, resource->resource, NULL, &resource->rtv); @@ -485,6 +486,7 @@ static bool d3d11_runner_dispatch(struct shader_runner *r, unsigned int x, unsig break;
case RESOURCE_TYPE_UAV: + case RESOURCE_TYPE_BUFFER_UAV: ID3D11DeviceContext_CSSetUnorderedAccessViews(context, resource->r.slot, 1, &resource->uav, NULL); break;
@@ -571,6 +573,7 @@ static bool d3d11_runner_draw(struct shader_runner *r, break;
case RESOURCE_TYPE_UAV: + case RESOURCE_TYPE_BUFFER_UAV: uavs[resource->r.slot] = resource->uav; min_uav_slot = min(min_uav_slot, resource->r.slot); break; diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index c73dbf64..7d9d1cd2 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -145,6 +145,7 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co break;
case RESOURCE_TYPE_UAV: + case RESOURCE_TYPE_BUFFER_UAV: if (!runner->heap) runner->heap = create_gpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, MAX_RESOURCE_DESCRIPTORS); @@ -213,6 +214,7 @@ static ID3D12RootSignature *d3d12_runner_create_root_signature(struct d3d12_shad { case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_UAV: + case RESOURCE_TYPE_BUFFER_UAV: range = &resource->descriptor_range;
resource->root_index = root_signature_desc.NumParameters++; @@ -314,6 +316,7 @@ static bool d3d12_runner_dispatch(struct shader_runner *r, unsigned int x, unsig break;
case RESOURCE_TYPE_UAV: + case RESOURCE_TYPE_BUFFER_UAV: ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(command_list, resource->root_index, get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot + MAX_RESOURCES)); break; @@ -447,6 +450,7 @@ static bool d3d12_runner_draw(struct shader_runner *r, break;
case RESOURCE_TYPE_UAV: + case RESOURCE_TYPE_BUFFER_UAV: ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, resource->root_index, get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot + MAX_RESOURCES)); break; diff --git a/tests/shader_runner_d3d9.c b/tests/shader_runner_d3d9.c index 973b2342..15a5ab3e 100644 --- a/tests/shader_runner_d3d9.c +++ b/tests/shader_runner_d3d9.c @@ -258,6 +258,7 @@ static struct resource *d3d9_runner_create_resource(struct shader_runner *r, con }
case RESOURCE_TYPE_UAV: + case RESOURCE_TYPE_BUFFER_UAV: fatal_error("UAVs are not supported.\n"); break;
@@ -383,6 +384,7 @@ static bool d3d9_runner_draw(struct shader_runner *r, break;
case RESOURCE_TYPE_UAV: + case RESOURCE_TYPE_BUFFER_UAV: vkd3d_unreachable();
case RESOURCE_TYPE_VERTEX_BUFFER: diff --git a/tests/shader_runner_vulkan.c b/tests/shader_runner_vulkan.c index 670a454d..ce9ac7e8 100644 --- a/tests/shader_runner_vulkan.c +++ b/tests/shader_runner_vulkan.c @@ -34,8 +34,9 @@ struct vulkan_resource struct resource r;
VkBuffer buffer; + VkBufferView buffer_view; VkImage image; - VkImageView view; + VkImageView image_view; VkDeviceMemory memory;
uint32_t binding; @@ -177,6 +178,21 @@ static VkBuffer create_buffer(const struct vulkan_shader_runner *runner, VkDevic return buffer; }
+static VkBufferView create_buffer_view(const struct vulkan_shader_runner *runner, VkBuffer buffer, + VkFormat format) +{ + VkBufferViewCreateInfo view_info = {.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}; + VkBufferView view; + + view_info.buffer = buffer; + view_info.format = format; + view_info.range = VK_WHOLE_SIZE; + + VK_CALL(vkCreateBufferView(runner->device, &view_info, NULL, &view)); + + return view; +} + static VkImage create_2d_image(const struct vulkan_shader_runner *runner, uint32_t width, uint32_t height, uint32_t level_count, VkImageUsageFlags usage, VkFormat format, VkDeviceMemory *memory) { @@ -249,7 +265,7 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c
resource->image = create_2d_image(runner, params->width, params->height, params->level_count, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, format, &resource->memory); - resource->view = create_2d_image_view(runner, resource->image, format); + resource->image_view = create_2d_image_view(runner, resource->image, format);
begin_command_buffer(runner); transition_image_layout(runner, resource->image, @@ -274,7 +290,7 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c
resource->image = create_2d_image(runner, params->width, params->height, params->level_count, usage, format, &resource->memory); - resource->view = create_2d_image_view(runner, resource->image, format); + resource->image_view = create_2d_image_view(runner, resource->image, format);
staging_buffer = create_buffer(runner, params->data_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &staging_memory); @@ -315,6 +331,18 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c break; }
+ case RESOURCE_TYPE_BUFFER_UAV: + format = vkd3d_get_vk_format(params->format); + + resource->buffer = create_buffer(runner, params->data_size, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &resource->memory); + resource->buffer_view = create_buffer_view(runner, resource->buffer, format); + + 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; + case RESOURCE_TYPE_VERTEX_BUFFER: resource->buffer = create_buffer(runner, params->data_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &resource->memory); @@ -338,10 +366,12 @@ static void vulkan_runner_destroy_resource(struct shader_runner *r, struct resou VK_CALL(vkFreeMemory(device, resource->memory, NULL)); if (resource->image) VK_CALL(vkDestroyImage(device, resource->image, NULL)); - if (resource->view) - VK_CALL(vkDestroyImageView(device, resource->view, NULL)); + if (resource->image_view) + VK_CALL(vkDestroyImageView(device, resource->image_view, NULL)); if (resource->buffer) VK_CALL(vkDestroyBuffer(device, resource->buffer, NULL)); + if (resource->buffer_view) + VK_CALL(vkDestroyBufferView(device, resource->buffer_view, NULL));
free(resource); } @@ -415,15 +445,19 @@ static bool compile_shader(const struct vulkan_shader_runner *runner, const char
case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_UAV: + case RESOURCE_TYPE_BUFFER_UAV: binding = &bindings[interface_info.binding_count++]; - if (resource->r.type == RESOURCE_TYPE_UAV) + if (resource->r.type == RESOURCE_TYPE_UAV || resource->r.type == RESOURCE_TYPE_BUFFER_UAV) binding->type = VKD3D_SHADER_DESCRIPTOR_TYPE_UAV; else binding->type = VKD3D_SHADER_DESCRIPTOR_TYPE_SRV; binding->register_space = 0; binding->register_index = resource->r.slot; binding->shader_visibility = VKD3D_SHADER_VISIBILITY_ALL; - binding->flags = VKD3D_SHADER_BINDING_FLAG_IMAGE; + if (resource->r.type == RESOURCE_TYPE_BUFFER_UAV) + binding->flags = VKD3D_SHADER_BINDING_FLAG_BUFFER; + else + binding->flags = VKD3D_SHADER_BINDING_FLAG_IMAGE; binding->binding.set = 0; binding->binding.binding = resource->binding; binding->binding.count = 1; @@ -596,6 +630,7 @@ static VkPipeline create_graphics_pipeline(const struct vulkan_shader_runner *ru { case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_UAV: + case RESOURCE_TYPE_BUFFER_UAV: break;
case RESOURCE_TYPE_RENDER_TARGET: @@ -724,6 +759,7 @@ static VkDescriptorSetLayout create_descriptor_set_layout(struct vulkan_shader_r
case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_UAV: + case RESOURCE_TYPE_BUFFER_UAV: binding = &bindings[set_desc.bindingCount++];
resource->binding = binding_index++; @@ -731,6 +767,8 @@ static VkDescriptorSetLayout create_descriptor_set_layout(struct vulkan_shader_r binding->binding = resource->binding; if (resource->r.type == RESOURCE_TYPE_UAV) binding->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + else if (resource->r.type == RESOURCE_TYPE_BUFFER_UAV) + binding->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; else binding->descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; binding->descriptorCount = 1; @@ -796,7 +834,7 @@ static void bind_resources(struct vulkan_shader_runner *runner, VkPipelineBindPo { case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_UAV: - image_info.imageView = resource->view; + image_info.imageView = resource->image_view; image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
write.dstSet = descriptor_set; @@ -815,6 +853,17 @@ static void bind_resources(struct vulkan_shader_runner *runner, VkPipelineBindPo VK_CALL(vkUpdateDescriptorSets(runner->device, 1, &write, 0, NULL)); break;
+ case RESOURCE_TYPE_BUFFER_UAV: + write.dstSet = descriptor_set; + write.dstBinding = resource->binding; + write.dstArrayElement = 0; + write.descriptorCount = 1; + write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + write.pTexelBufferView = &resource->buffer_view; + + VK_CALL(vkUpdateDescriptorSets(runner->device, 1, &write, 0, NULL)); + break; + case RESOURCE_TYPE_VERTEX_BUFFER: if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) VK_CALL(vkCmdBindVertexBuffers(cmd_buffer, resource->r.slot, 1, &resource->buffer, &zero_offset)); @@ -867,7 +916,7 @@ static void create_render_pass_and_framebuffer(struct vulkan_shader_runner *runn color_ref->attachment = rt_count; color_ref->layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- rtvs[rt_count] = resource->view; + rtvs[rt_count] = resource->image_view;
++rt_count; } @@ -1011,11 +1060,6 @@ static struct resource_readback *vulkan_runner_get_resource_readback(struct shad VkBufferImageCopy region = {0}; VkImageLayout layout;
- if (resource->r.type == RESOURCE_TYPE_RENDER_TARGET) - layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - else - layout = VK_IMAGE_LAYOUT_GENERAL; - rb->rb.width = resource->r.width; rb->rb.height = resource->r.height; rb->rb.depth = 1; @@ -1025,24 +1069,42 @@ static struct resource_readback *vulkan_runner_get_resource_readback(struct shad rb->buffer = create_buffer(runner, rb->rb.row_pitch * rb->rb.height, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &rb->memory);
- begin_command_buffer(runner); + if (resource->r.type == RESOURCE_TYPE_BUFFER_UAV) + { + 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 + { + if (resource->r.type == RESOURCE_TYPE_RENDER_TARGET) + layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + else + layout = VK_IMAGE_LAYOUT_GENERAL;
- transition_image_layout(runner, resource->image, layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + begin_command_buffer(runner);
- region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.layerCount = 1; - region.imageExtent.width = resource->r.width; - region.imageExtent.height = resource->r.height; - region.imageExtent.depth = 1; + transition_image_layout(runner, resource->image, layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
- VK_CALL(vkCmdCopyImageToBuffer(runner->cmd_buffer, resource->image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, rb->buffer, 1, ®ion)); + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.width = resource->r.width; + region.imageExtent.height = resource->r.height; + region.imageExtent.depth = 1;
- transition_image_layout(runner, resource->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, layout); + VK_CALL(vkCmdCopyImageToBuffer(runner->cmd_buffer, resource->image, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, rb->buffer, 1, ®ion));
- end_command_buffer(runner); + transition_image_layout(runner, resource->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, layout); + + end_command_buffer(runner); + + VK_CALL(vkMapMemory(device, rb->memory, 0, VK_WHOLE_SIZE, 0, &rb->rb.data)); + }
- VK_CALL(vkMapMemory(device, rb->memory, 0, VK_WHOLE_SIZE, 0, &rb->rb.data)); return &rb->rb; }
@@ -1141,7 +1203,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[3]; + VkDescriptorPoolSize descriptor_pool_sizes[4]; static const float queue_priority = 1.0f; VkFormatProperties format_props; uint32_t count, graphics_index; @@ -1253,6 +1315,8 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner) descriptor_pool_sizes[1].descriptorCount = MAX_SAMPLERS; descriptor_pool_sizes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; 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_desc.maxSets = 1; descriptor_pool_desc.poolSizeCount = ARRAY_SIZE(descriptor_pool_sizes); diff --git a/tests/vulkan_procs.h b/tests/vulkan_procs.h index 9d70b499..1829133b 100644 --- a/tests/vulkan_procs.h +++ b/tests/vulkan_procs.h @@ -65,6 +65,7 @@ VK_DEVICE_PFN(vkCmdFillBuffer) VK_DEVICE_PFN(vkCmdPipelineBarrier) VK_DEVICE_PFN(vkCmdPushConstants) VK_DEVICE_PFN(vkCreateBuffer) +VK_DEVICE_PFN(vkCreateBufferView) VK_DEVICE_PFN(vkCreateCommandPool) VK_DEVICE_PFN(vkCreateComputePipelines) VK_DEVICE_PFN(vkCreateDescriptorPool) @@ -78,6 +79,7 @@ VK_DEVICE_PFN(vkCreateRenderPass) VK_DEVICE_PFN(vkCreateSampler) VK_DEVICE_PFN(vkCreateShaderModule) VK_DEVICE_PFN(vkDestroyBuffer) +VK_DEVICE_PFN(vkDestroyBufferView) VK_DEVICE_PFN(vkDestroyCommandPool) VK_DEVICE_PFN(vkDestroyDescriptorPool) VK_DEVICE_PFN(vkDestroyDescriptorSetLayout)
From: Nikolay Sivov nsivov@codeweavers.com
--- tests/uav.shader_test | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/tests/uav.shader_test b/tests/uav.shader_test index 9740575c..bd46bd45 100644 --- a/tests/uav.shader_test +++ b/tests/uav.shader_test @@ -161,3 +161,21 @@ float4 main() : sv_target1 draw quad probe uav 2 (0, 0) rgba (1.1, 1.2, 1.3, 1.4) probe uav 3 (0, 0) rgba (2.1, 2.2, 2.3, 2.4) + +[buffer uav 2] +size (1, 1) + +0.1 0.2 0.3 0.4 + +[pixel shader] +RWBuffer<float4> u : register(u2); + +float4 main() : sv_target1 +{ + u[0] = float4(11.1, 12.2, 13.3, 14.4); + return 0; +} + +[test] +draw quad +probe buffer uav 2 (0, 0) rgba (11.1, 12.2, 13.3, 14.4)
On Thu May 4 16:28:53 2023 +0000, Zebediah Figura wrote:
The shader runner only declares image UAVs; it'll need separate handling for buffer UAVs. Probably best is to add a new resource type RESOURCE_TYPE_BUFFER_UAV. It shouldn't be too difficult, but I can also look into this if you'd prefer.
I pushed support for that that works for me with Vulkan runner. d3d12 runner on Linux crashes, while crosstest works fine on Windows. I'll look into it.
Please take a look if this seems fine in general.
Zebediah Figura (@zfigura) commented about libs/vkd3d-shader/hlsl.y:
hlsl_release_string_buffer(ctx, string);
switch ($1)
{
case HLSL_SAMPLER_DIM_BUFFER:
if ($3->class > HLSL_CLASS_MATRIX)
{
if (string)
hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
"UAV data type %s is not scalar, vector, or matrix.", string->buffer);
}
else if ($3->reg_size[HLSL_REGSET_NUMERIC] > 4)
{
if (string)
hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
"UAV data type %s size exceeds 4-component register size.", string->buffer);
}
This really should have tests.
Zebediah Figura (@zfigura) commented about libs/vkd3d-shader/hlsl.y:
"UAV data type %s is not scalar, vector, or matrix.", string->buffer);
}
else if ($3->reg_size[HLSL_REGSET_NUMERIC] > 4)
{
if (string)
hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
"UAV data type %s size exceeds 4-component register size.", string->buffer);
}
break;
case HLSL_SAMPLER_DIM_STRUCTURED_BUFFER:
if ($3->class > HLSL_CLASS_STRUCT)
{
if (string)
hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
"UAV data type %s can't be used with structured buffers.", string->buffer);
}
This also should have tests, and the greater-than comparison to HLSL_CLASS_STRUCT seems unclear (what's greater than STRUCT?) and also fragile.
I pushed support for that that works for me with Vulkan runner. d3d12 runner on Linux crashes, while crosstest works fine on Windows. I'll look into it.
Please take a look if this seems fine in general.
The patches look mostly good now, thanks.
d3d12 tests are probably failing because you're still creating a texture rather than a buffer. Incidentally, the same is true of d3d11.