-- v10: vkd3d-shader/dxil: Implement DX intrinsic RawBufferStore. vkd3d-shader/dxil: Handle raw and structured buffers in sm6_parser_emit_dx_buffer_store(). vkd3d-shader/dxil: Implement DX intrinsic BufferStore. tests/shader-runner: Add a test for a signed int structured buffer UAV. tests/shader-runner: Add a test for a signed int typed buffer UAV. tests/shader-runner: Support structured buffer UAVs.
From: Conor McCarthy cmccarthy@codeweavers.com
--- tests/hlsl/uav-rwstructuredbuffer.shader_test | 12 ++++++++++++ tests/shader_runner.c | 7 +++++++ tests/shader_runner.h | 1 + tests/shader_runner_d3d11.c | 17 +++++++++-------- tests/shader_runner_d3d12.c | 1 + tests/shader_runner_gl.c | 1 + tests/shader_runner_vulkan.c | 4 ++++ 7 files changed, 35 insertions(+), 8 deletions(-)
diff --git a/tests/hlsl/uav-rwstructuredbuffer.shader_test b/tests/hlsl/uav-rwstructuredbuffer.shader_test index f962e18e0..bbe0ac950 100644 --- a/tests/hlsl/uav-rwstructuredbuffer.shader_test +++ b/tests/hlsl/uav-rwstructuredbuffer.shader_test @@ -1,6 +1,12 @@ [require] shader model >= 5.0
+[uav 2] +stride 16 +size (buffer, 2) + +0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 + [pixel shader todo] struct s { @@ -22,9 +28,15 @@ RWStructuredBuffer<struct s2> u5; float4 main() : sv_target1 { u[0] = float4(11.1, 12.2, 13.3, 14.4); + u[1] = float4(15.5, 16.6, 17.7, 18.8); return 0; }
+[test] +todo draw quad +probe uav 2 (0) rgba (11.1, 12.2, 13.3, 14.4) +probe uav 2 (1) rgba (15.5, 16.6, 17.7, 18.8) + [pixel shader todo] struct s { diff --git a/tests/shader_runner.c b/tests/shader_runner.c index 85c88d7b7..c20932cc8 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -427,6 +427,13 @@ static void parse_resource_directive(struct resource_params *resource, const cha { resource->format = parse_format(line, &resource->data_type, &resource->texel_size, &line); } + else if (match_string(line, "stride", &line)) + { + if (sscanf(line, "%u", &resource->stride) < 1) + fatal_error("Malformed texture stride '%s'.\n", line); + resource->texel_size = resource->stride; + resource->format = DXGI_FORMAT_UNKNOWN; + } else if (match_string(line, "size", &line)) { if (sscanf(line, "( buffer , %u ) ", &resource->width) == 1) diff --git a/tests/shader_runner.h b/tests/shader_runner.h index 5ad6a278a..62358d78c 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -87,6 +87,7 @@ struct resource_params DXGI_FORMAT format; enum texture_data_type data_type; unsigned int texel_size; + unsigned int stride; unsigned int width, height; unsigned int level_count; uint8_t *data; diff --git a/tests/shader_runner_d3d11.c b/tests/shader_runner_d3d11.c index 0d13fc003..528c04e9d 100644 --- a/tests/shader_runner_d3d11.c +++ b/tests/shader_runner_d3d11.c @@ -330,7 +330,8 @@ static void destroy_test_context(struct d3d11_shader_runner *runner) ok(!ref, "Device has %lu references left.\n", ref); }
-static ID3D11Buffer *create_buffer(ID3D11Device *device, unsigned int bind_flags, unsigned int size, const void *data) +static ID3D11Buffer *create_buffer(ID3D11Device *device, unsigned int bind_flags, unsigned int size, + unsigned int stride, const void *data) { D3D11_SUBRESOURCE_DATA resource_data; D3D11_BUFFER_DESC buffer_desc; @@ -341,8 +342,8 @@ static ID3D11Buffer *create_buffer(ID3D11Device *device, unsigned int bind_flags buffer_desc.Usage = D3D11_USAGE_DEFAULT; buffer_desc.BindFlags = bind_flags; buffer_desc.CPUAccessFlags = 0; - buffer_desc.MiscFlags = 0; - buffer_desc.StructureByteStride = 0; + buffer_desc.MiscFlags = stride ? D3D11_RESOURCE_MISC_BUFFER_STRUCTURED : 0; + buffer_desc.StructureByteStride = stride;
resource_data.pSysMem = data; resource_data.SysMemPitch = 0; @@ -417,7 +418,7 @@ static void init_resource_srv_buffer(struct d3d11_shader_runner *runner, struct ID3D11Device *device = runner->device; HRESULT hr;
- resource->buffer = create_buffer(device, D3D11_BIND_SHADER_RESOURCE, params->data_size, params->data); + resource->buffer = create_buffer(device, D3D11_BIND_SHADER_RESOURCE, params->data_size, params->stride, params->data); resource->resource = (ID3D11Resource *)resource->buffer;
srv_desc.Format = params->format; @@ -435,7 +436,7 @@ static void init_resource_uav_buffer(struct d3d11_shader_runner *runner, struct ID3D11Device *device = runner->device; HRESULT hr;
- resource->buffer = create_buffer(device, D3D11_BIND_UNORDERED_ACCESS, params->data_size, params->data); + resource->buffer = create_buffer(device, D3D11_BIND_UNORDERED_ACCESS, params->data_size, params->stride, params->data); resource->resource = (ID3D11Resource *)resource->buffer;
uav_desc.Format = params->format; @@ -474,7 +475,7 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co break;
case RESOURCE_TYPE_VERTEX_BUFFER: - resource->buffer = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, params->data_size, params->data); + resource->buffer = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, params->data_size, params->stride, params->data); resource->resource = (ID3D11Resource *)resource->buffer; break; } @@ -538,7 +539,7 @@ static bool d3d11_runner_dispatch(struct shader_runner *r, unsigned int x, unsig ID3D11Buffer *cb;
cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, - runner->r.uniform_count * sizeof(*runner->r.uniforms), runner->r.uniforms); + runner->r.uniform_count * sizeof(*runner->r.uniforms), 0, runner->r.uniforms); ID3D11DeviceContext_CSSetConstantBuffers(context, 0, 1, &cb); ID3D11Buffer_Release(cb); } @@ -618,7 +619,7 @@ static bool d3d11_runner_draw(struct shader_runner *r, if (runner->r.uniform_count) { cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, - runner->r.uniform_count * sizeof(*runner->r.uniforms), runner->r.uniforms); + runner->r.uniform_count * sizeof(*runner->r.uniforms), 0, runner->r.uniforms); ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); }
diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index b7a294316..ca1375124 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -200,6 +200,7 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co uav_desc.Format = params->format; uav_desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; uav_desc.Buffer.NumElements = params->width * params->height; + uav_desc.Buffer.StructureByteStride = params->stride;
ID3D12Device_CreateUnorderedAccessView(device, resource->resource, NULL, &uav_desc, get_cpu_descriptor_handle(test_context, runner->heap, resource->r.slot + MAX_RESOURCES)); diff --git a/tests/shader_runner_gl.c b/tests/shader_runner_gl.c index f4e4fa75d..263d1ba75 100644 --- a/tests/shader_runner_gl.c +++ b/tests/shader_runner_gl.c @@ -290,6 +290,7 @@ static const struct format_info *get_format_info(enum DXGI_FORMAT format)
static const struct format_info format_info[] = { + {DXGI_FORMAT_UNKNOWN, 1, true, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT}, {DXGI_FORMAT_R32G32B32A32_FLOAT, 4, false, GL_RGBA32F, GL_RGBA, GL_FLOAT}, {DXGI_FORMAT_R32G32B32A32_UINT, 4, true, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT}, {DXGI_FORMAT_R32G32_FLOAT, 2, false, GL_RG32F, GL_RG, GL_FLOAT}, diff --git a/tests/shader_runner_vulkan.c b/tests/shader_runner_vulkan.c index f9ab204f6..35db729b5 100644 --- a/tests/shader_runner_vulkan.c +++ b/tests/shader_runner_vulkan.c @@ -330,6 +330,10 @@ static void resource_init_buffer(struct vulkan_shader_runner *runner, struct vul else usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
+ /* 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; + 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);
From: Conor McCarthy cmccarthy@codeweavers.com
Check for backend type mismatches resulting from the absence of signedness in SM 6. --- tests/hlsl/uav-rwbuffer.shader_test | 20 ++++++++++++++++++++ tests/shader_runner.c | 24 ++++++++++++++++++------ tests/shader_runner_gl.c | 1 + tests/utils.h | 1 + 4 files changed, 40 insertions(+), 6 deletions(-)
diff --git a/tests/hlsl/uav-rwbuffer.shader_test b/tests/hlsl/uav-rwbuffer.shader_test index ec8937b33..c813d0d18 100644 --- a/tests/hlsl/uav-rwbuffer.shader_test +++ b/tests/hlsl/uav-rwbuffer.shader_test @@ -164,6 +164,26 @@ float4 main() : sv_target1 return 0; }
+[uav 1] +format r32g32b32a32 sint +size (buffer, 2) +1 2 3 4 5 6 7 8 + +[pixel shader] +RWBuffer<int4> u : register(u1); + +float4 main() : sv_target +{ + u[0] = int4(11, -12, 13, -14); + u[1] = int4(-15, 16, -17, 18); + return 0; +} + +[test] +todo(sm>=6) draw quad +probe uav 1 (0) rgbai (11, -12, 13, -14) +probe uav 1 (1) rgbai (-15, 16, -17, 18) + [uav 2] size (buffer, 1) 0.1 0.2 0.3 0.4 diff --git a/tests/shader_runner.c b/tests/shader_runner.c index c20932cc8..d0d806508 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -336,6 +336,7 @@ static DXGI_FORMAT parse_format(const char *line, enum texture_data_type *data_t formats[] = { {"r32g32b32a32 float", TEXTURE_DATA_FLOAT, 16, DXGI_FORMAT_R32G32B32A32_FLOAT}, + {"r32g32b32a32 sint", TEXTURE_DATA_SINT, 16, DXGI_FORMAT_R32G32B32A32_SINT}, {"r32g32b32a32 uint", TEXTURE_DATA_UINT, 16, DXGI_FORMAT_R32G32B32A32_UINT}, {"r32g32 float", TEXTURE_DATA_FLOAT, 8, DXGI_FORMAT_R32G32_FLOAT}, {"r32g32 int", TEXTURE_DATA_SINT, 8, DXGI_FORMAT_R32G32_SINT}, @@ -622,12 +623,12 @@ static void read_uint(const char **line, unsigned int *u, bool is_uniform) *line = rest + (!is_uniform && *rest == ','); }
-static void read_int4(const char **line, struct ivec4 *v) +static void read_int4(const char **line, struct ivec4 *v, bool is_uniform) { - read_int(line, &v->x, true); - read_int(line, &v->y, true); - read_int(line, &v->z, true); - read_int(line, &v->w, true); + read_int(line, &v->x, is_uniform); + read_int(line, &v->y, is_uniform); + read_int(line, &v->z, is_uniform); + read_int(line, &v->w, is_uniform); }
static void read_uint4(const char **line, struct uvec4 *v, bool is_uniform) @@ -907,6 +908,17 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) line = close_parentheses(line); todo_if(runner->is_todo) check_readback_data_uvec4(rb, &rect, &v); } + else if (match_string(line, "rgbai", &line)) + { + struct ivec4 v; + + if (*line != '(') + fatal_error("Malformed probe arguments '%s'.\n", line); + ++line; + read_int4(&line, &v, false); + line = close_parentheses(line); + todo_if(runner->is_todo) check_readback_data_ivec4(rb, &rect, &v); + } else if (match_string(line, "rgba", &line)) { struct vec4 v; @@ -993,7 +1005,7 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) { struct ivec4 v;
- read_int4(&line, &v); + read_int4(&line, &v, true); set_uniforms(runner, offset, 4, &v); } else if (match_string(line, "uint4", &line)) diff --git a/tests/shader_runner_gl.c b/tests/shader_runner_gl.c index 263d1ba75..6cec33a43 100644 --- a/tests/shader_runner_gl.c +++ b/tests/shader_runner_gl.c @@ -293,6 +293,7 @@ static const struct format_info *get_format_info(enum DXGI_FORMAT format) {DXGI_FORMAT_UNKNOWN, 1, true, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT}, {DXGI_FORMAT_R32G32B32A32_FLOAT, 4, false, GL_RGBA32F, GL_RGBA, GL_FLOAT}, {DXGI_FORMAT_R32G32B32A32_UINT, 4, true, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT}, + {DXGI_FORMAT_R32G32B32A32_SINT, 4, true, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT}, {DXGI_FORMAT_R32G32_FLOAT, 2, false, GL_RG32F, GL_RG, GL_FLOAT}, {DXGI_FORMAT_R32G32_UINT, 2, true, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT}, {DXGI_FORMAT_R32G32_SINT, 2, true, GL_RG32I, GL_RG_INTEGER, GL_INT}, diff --git a/tests/utils.h b/tests/utils.h index 98dceba84..cd5215fe5 100644 --- a/tests/utils.h +++ b/tests/utils.h @@ -275,6 +275,7 @@ static inline void check_readback_data_vec4_(unsigned int line, const struct res got.x, got.y, got.z, got.w, expected->x, expected->y, expected->z, expected->w, x, y); }
+#define check_readback_data_ivec4(a, b, c) check_readback_data_uvec4_(__LINE__, a, b, (const struct uvec4 *)(c)) #define check_readback_data_uvec4(a, b, c) check_readback_data_uvec4_(__LINE__, a, b, c) static inline void check_readback_data_uvec4_(unsigned int line, const struct resource_readback *rb, const RECT *rect, const struct uvec4 *expected)
From: Conor McCarthy cmccarthy@codeweavers.com
Check for backend type mismatches resulting from the absence of signedness in SM 6. --- tests/hlsl/uav-rwstructuredbuffer.shader_test | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+)
diff --git a/tests/hlsl/uav-rwstructuredbuffer.shader_test b/tests/hlsl/uav-rwstructuredbuffer.shader_test index bbe0ac950..93864f0f4 100644 --- a/tests/hlsl/uav-rwstructuredbuffer.shader_test +++ b/tests/hlsl/uav-rwstructuredbuffer.shader_test @@ -135,3 +135,24 @@ float4 main() : sv_target u[0].x = float3(30.0, 40.0, 50.0); return 0; } + +[uav 2] +stride 16 +size (buffer, 2) + +1 2 3 4 5 6 7 8 + +[pixel shader todo] +RWStructuredBuffer<int4> u : register(u2); + +float4 main() : sv_target1 +{ + u[0] = int4(11, -12, 13, -14); + u[1] = int4(-15, 16, -17, 18); + return 0; +} + +[test] +todo draw quad +probe uav 2 (0) rgbai (11, -12, 13, -14) +probe uav 2 (1) rgbai (-15, 16, -17, 18)
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 63 +++++++++++++++++++ tests/hlsl/uav-rwbuffer.shader_test | 4 +- tests/hlsl/uav-rwstructuredbuffer.shader_test | 12 ++-- 3 files changed, 71 insertions(+), 8 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 2ca3aa955..d461fad25 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -383,6 +383,7 @@ enum dx_intrinsic_opcode DX_TEXTURE_LOAD = 66, DX_TEXTURE_STORE = 67, DX_BUFFER_LOAD = 68, + DX_BUFFER_STORE = 69, DX_ATOMIC_BINOP = 78, DX_ATOMIC_CMP_XCHG = 79, DX_DERIV_COARSEX = 83, @@ -4179,6 +4180,67 @@ static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intri instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); }
+static void sm6_parser_emit_dx_buffer_store(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + struct vkd3d_shader_src_param *src_params; + struct vkd3d_shader_dst_param *dst_param; + unsigned int write_mask, component_count; + struct vkd3d_shader_instruction *ins; + struct vkd3d_shader_register texel; + const struct sm6_value *resource; + + resource = operands[0]; + if (!sm6_value_validate_is_handle(resource, sm6)) + return; + + if (resource->u.handle.d->kind != RESOURCE_KIND_TYPEDBUFFER) + { + WARN("Resource is not a typed buffer.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION, + "Resource for a typed buffer store is not a typed buffer."); + } + + write_mask = sm6_value_get_constant_uint(operands[7]); + if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) + { + WARN("Invalid write mask %#x.\n", write_mask); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Write mask %#x for a typed buffer store operation is invalid.", write_mask); + return; + } + else if (write_mask & (write_mask + 1)) + { + /* In this case, it is unclear which source operands will be defined unless we encounter it in a shader. */ + FIXME("Unhandled write mask %#x.\n", write_mask); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Write mask %#x for a typed buffer store operation is unhandled.", write_mask); + } + component_count = vsir_write_mask_component_count(write_mask); + + if (!sm6_parser_emit_composite_construct(sm6, &operands[3], component_count, state, &texel)) + return; + + ins = state->ins; + vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_STORE_UAV_TYPED); + + if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) + return; + src_param_init_from_value(&src_params[0], operands[1]); + if (!sm6_value_is_undef(operands[2])) + { + /* Constant zero would have no effect, but is not worth checking for unless it shows up. */ + WARN("Ignoring structure offset.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, + "Ignoring structure offset for a typed buffer store."); + } + src_param_init_vector_from_reg(&src_params[1], &texel); + + dst_param = instruction_dst_params_alloc(ins, 1, sm6); + dst_param_init_with_mask(dst_param, write_mask); + dst_param->reg = resource->u.handle.reg; +} + static unsigned int sm6_value_get_texel_offset(const struct sm6_value *value) { return sm6_value_is_undef(value) ? 0 : sm6_value_get_constant_uint(value); @@ -4478,6 +4540,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_ATOMIC_CMP_XCHG ] = {"o", "HiiiRR", sm6_parser_emit_dx_atomic_binop}, [DX_BFREV ] = {"m", "R", sm6_parser_emit_dx_unary}, [DX_BUFFER_LOAD ] = {"o", "Hii", sm6_parser_emit_dx_buffer_load}, + [DX_BUFFER_STORE ] = {"v", "Hiiooooc", sm6_parser_emit_dx_buffer_store}, [DX_CBUFFER_LOAD_LEGACY ] = {"o", "Hi", sm6_parser_emit_dx_cbuffer_load}, [DX_COS ] = {"g", "R", sm6_parser_emit_dx_sincos}, [DX_COUNT_BITS ] = {"i", "m", sm6_parser_emit_dx_unary}, diff --git a/tests/hlsl/uav-rwbuffer.shader_test b/tests/hlsl/uav-rwbuffer.shader_test index c813d0d18..bcd5c695a 100644 --- a/tests/hlsl/uav-rwbuffer.shader_test +++ b/tests/hlsl/uav-rwbuffer.shader_test @@ -180,7 +180,7 @@ float4 main() : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe uav 1 (0) rgbai (11, -12, 13, -14) probe uav 1 (1) rgbai (-15, 16, -17, 18)
@@ -198,5 +198,5 @@ float4 main() : sv_target1 }
[test] -todo(sm>=6) draw quad +draw quad probe uav 2 (0) rgba (11.1, 12.2, 13.3, 14.4) diff --git a/tests/hlsl/uav-rwstructuredbuffer.shader_test b/tests/hlsl/uav-rwstructuredbuffer.shader_test index 93864f0f4..d2fe7a3ff 100644 --- a/tests/hlsl/uav-rwstructuredbuffer.shader_test +++ b/tests/hlsl/uav-rwstructuredbuffer.shader_test @@ -33,9 +33,9 @@ float4 main() : sv_target1 }
[test] -todo draw quad -probe uav 2 (0) rgba (11.1, 12.2, 13.3, 14.4) -probe uav 2 (1) rgba (15.5, 16.6, 17.7, 18.8) +todo(sm<6) draw quad +todo probe uav 2 (0) rgba (11.1, 12.2, 13.3, 14.4) +todo probe uav 2 (1) rgba (15.5, 16.6, 17.7, 18.8)
[pixel shader todo] struct s @@ -153,6 +153,6 @@ float4 main() : sv_target1 }
[test] -todo draw quad -probe uav 2 (0) rgbai (11, -12, 13, -14) -probe uav 2 (1) rgbai (-15, 16, -17, 18) +todo(sm<6) draw quad +todo probe uav 2 (0) rgbai (11, -12, 13, -14) +todo probe uav 2 (1) rgbai (-15, 16, -17, 18)
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 57 +++++++++++++++++++ tests/hlsl/uav-rwstructuredbuffer.shader_test | 8 +-- 2 files changed, 61 insertions(+), 4 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index d461fad25..5d98a38c8 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -4138,6 +4138,57 @@ static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_i instruction_dst_param_init_ssa_vector(ins, component_count, sm6); }
+static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + unsigned int write_mask, component_count, operand_count; + struct vkd3d_shader_src_param *src_params; + struct vkd3d_shader_dst_param *dst_param; + struct vkd3d_shader_instruction *ins; + struct vkd3d_shader_register data; + const struct sm6_value *resource; + bool raw; + + resource = operands[0]; + if (!sm6_value_validate_is_handle(resource, sm6)) + return; + raw = resource->u.handle.d->kind == RESOURCE_KIND_RAWBUFFER; + + write_mask = sm6_value_get_constant_uint(operands[7]); + if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) + { + WARN("Invalid write mask %#x.\n", write_mask); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Write mask %#x for a raw/structured buffer store operation is invalid.", write_mask); + return; + } + else if (write_mask & (write_mask + 1)) + { + /* In this case, it is unclear which source operands will be defined unless we encounter it in a shader. */ + FIXME("Unhandled write mask %#x.\n", write_mask); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Write mask %#x for a raw/structured buffer store operation is unhandled.", write_mask); + } + component_count = vsir_write_mask_component_count(write_mask); + + if (!sm6_parser_emit_composite_construct(sm6, &operands[3], component_count, state, &data)) + return; + + ins = state->ins; + vsir_instruction_init(ins, &sm6->p.location, raw ? VKD3DSIH_STORE_RAW : VKD3DSIH_STORE_STRUCTURED); + operand_count = 2 + !raw; + + if (!(src_params = instruction_src_params_alloc(ins, operand_count, sm6))) + return; + src_params_init_from_operands(src_params, &operands[1], operand_count - 1); + data.data_type = VKD3D_DATA_UINT; + src_param_init_vector_from_reg(&src_params[operand_count - 1], &data); + + dst_param = instruction_dst_params_alloc(ins, 1, sm6); + dst_param_init_with_mask(dst_param, write_mask); + dst_param->reg = resource->u.handle.reg; +} + static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { @@ -4194,6 +4245,12 @@ static void sm6_parser_emit_dx_buffer_store(struct sm6_parser *sm6, enum dx_intr if (!sm6_value_validate_is_handle(resource, sm6)) return;
+ if (resource->u.handle.d->kind == RESOURCE_KIND_RAWBUFFER + || resource->u.handle.d->kind == RESOURCE_KIND_STRUCTUREDBUFFER) + { + return sm6_parser_emit_dx_raw_buffer_store(sm6, op, operands, state); + } + if (resource->u.handle.d->kind != RESOURCE_KIND_TYPEDBUFFER) { WARN("Resource is not a typed buffer.\n"); diff --git a/tests/hlsl/uav-rwstructuredbuffer.shader_test b/tests/hlsl/uav-rwstructuredbuffer.shader_test index d2fe7a3ff..15026d06c 100644 --- a/tests/hlsl/uav-rwstructuredbuffer.shader_test +++ b/tests/hlsl/uav-rwstructuredbuffer.shader_test @@ -34,8 +34,8 @@ float4 main() : sv_target1
[test] todo(sm<6) draw quad -todo probe uav 2 (0) rgba (11.1, 12.2, 13.3, 14.4) -todo probe uav 2 (1) rgba (15.5, 16.6, 17.7, 18.8) +probe uav 2 (0) rgba (11.1, 12.2, 13.3, 14.4) +probe uav 2 (1) rgba (15.5, 16.6, 17.7, 18.8)
[pixel shader todo] struct s @@ -154,5 +154,5 @@ float4 main() : sv_target1
[test] todo(sm<6) draw quad -todo probe uav 2 (0) rgbai (11, -12, 13, -14) -todo probe uav 2 (1) rgbai (-15, 16, -17, 18) +probe uav 2 (0) rgbai (11, -12, 13, -14) +probe uav 2 (1) rgbai (-15, 16, -17, 18)
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 5d98a38c8..93ed3e06a 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -394,6 +394,7 @@ enum dx_intrinsic_opcode DX_LEGACY_F32TOF16 = 130, DX_LEGACY_F16TOF32 = 131, DX_RAW_BUFFER_LOAD = 139, + DX_RAW_BUFFER_STORE = 140, };
enum dxil_cast_code @@ -4141,7 +4142,7 @@ static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_i static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { - unsigned int write_mask, component_count, operand_count; + unsigned int write_mask, component_count, alignment = 0, operand_count; struct vkd3d_shader_src_param *src_params; struct vkd3d_shader_dst_param *dst_param; struct vkd3d_shader_instruction *ins; @@ -4171,6 +4172,24 @@ static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_ } component_count = vsir_write_mask_component_count(write_mask);
+ if (op == DX_RAW_BUFFER_STORE) + { + if (!raw && resource->u.handle.d->kind != RESOURCE_KIND_STRUCTUREDBUFFER) + { + WARN("Resource is not a raw or structured buffer.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION, + "Resource for a raw buffer store is not a raw or structured buffer."); + } + + alignment = sm6_value_get_constant_uint(operands[8]); + if (alignment & (alignment - 1)) + { + FIXME("Invalid alignment %#x.\n", alignment); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Alignment %#x for a raw/structured buffer store operation is invalid.", alignment); + } + } + if (!sm6_parser_emit_composite_construct(sm6, &operands[3], component_count, state, &data)) return;
@@ -4187,6 +4206,7 @@ static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_ dst_param = instruction_dst_params_alloc(ins, 1, sm6); dst_param_init_with_mask(dst_param, write_mask); dst_param->reg = resource->u.handle.reg; + dst_param->reg.alignment = alignment; }
static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, @@ -4627,6 +4647,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_LOAD_INPUT ] = {"o", "ii8i", sm6_parser_emit_dx_load_input}, [DX_LOG ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_RAW_BUFFER_LOAD ] = {"o", "Hii8i", sm6_parser_emit_dx_raw_buffer_load}, + [DX_RAW_BUFFER_STORE ] = {"v", "Hiioooocc", sm6_parser_emit_dx_raw_buffer_store}, [DX_ROUND_NE ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_ROUND_NI ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_ROUND_PI ] = {"g", "R", sm6_parser_emit_dx_unary},
This merge request was approved by Giovanni Mascellani.
This merge request was approved by Henri Verbeet.