-- v7: 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 | 15 ++++++++------- tests/shader_runner_d3d12.c | 1 + tests/shader_runner_gl.c | 1 + tests/shader_runner_vulkan.c | 4 ++++ 7 files changed, 34 insertions(+), 7 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 299c48459..54c3be675 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..cc81d8f92 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; @@ -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 | 32 ++++++++++++++++++++--------- tests/shader_runner_gl.c | 1 + tests/utils.h | 1 + 4 files changed, 44 insertions(+), 10 deletions(-)
diff --git a/tests/hlsl/uav-rwbuffer.shader_test b/tests/hlsl/uav-rwbuffer.shader_test index ec8937b33..4c64dbb98 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) rgbasi (11, -12, 13, -14) +probe uav 1 (1) rgbasi (-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 54c3be675..7d4d37586 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}, @@ -586,7 +587,7 @@ static void set_uniforms(struct shader_runner *runner, size_t offset, size_t cou memcpy(runner->uniforms + offset, uniforms, count * sizeof(*runner->uniforms)); }
-static void read_int(const char **line, int *i) +static void read_int(const char **line, int *i, bool is_uniform) { char *rest; long val; @@ -594,14 +595,14 @@ static void read_int(const char **line, int *i) errno = 0; val = strtol(*line, &rest, 0);
- if (errno != 0 || (*rest != '\0' && !isspace((unsigned char)*rest))) + if (errno != 0 || (is_uniform && *rest != '\0' && !isspace((unsigned char)*rest))) fatal_error("Malformed int constant '%s'.\n", *line);
*i = val; if (*i != val) fatal_error("Out of range int constant '%.*s'.\n", (int)(rest - *line), *line);
- *line = rest; + *line = rest + (!is_uniform && *rest == ','); }
static void read_uint(const char **line, unsigned int *u, bool is_uniform) @@ -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); - read_int(line, &v->y); - read_int(line, &v->z); - read_int(line, &v->w); + 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) @@ -906,6 +907,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, "rgbasi", &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; @@ -989,7 +1001,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)) @@ -1003,7 +1015,7 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) { int i;
- read_int(&line, &i); + read_int(&line, &i, true); set_uniforms(runner, offset, 1, &i); } else if (match_string(line, "uint", &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..7cb1afff9 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) rgbasi (11, -12, 13, -14) +probe uav 2 (1) rgbasi (-15, 16, -17, 18)
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 65 ++++++++++++++++++- tests/hlsl/uav-rwbuffer.shader_test | 4 +- tests/hlsl/uav-rwstructuredbuffer.shader_test | 12 ++-- 3 files changed, 72 insertions(+), 9 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 33d30aef0..0a7315eb4 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -381,6 +381,7 @@ enum dx_intrinsic_opcode DX_TEXTURE_LOAD = 66, DX_TEXTURE_STORE = 67, DX_BUFFER_LOAD = 68, + DX_BUFFER_STORE = 69, DX_DERIV_COARSEX = 83, DX_DERIV_COARSEY = 84, DX_DERIV_FINEX = 85, @@ -2275,7 +2276,7 @@ static void src_param_init_from_value(struct vkd3d_shader_src_param *param, cons static void src_param_init_vector_from_reg(struct vkd3d_shader_src_param *param, const struct vkd3d_shader_register *reg) { - param->swizzle = VKD3D_SHADER_NO_SWIZZLE; + param->swizzle = (reg->dimension == VSIR_DIMENSION_VEC4) ? VKD3D_SHADER_NO_SWIZZLE : VKD3D_SHADER_SWIZZLE(X, X, X, X); param->modifiers = VKD3DSPSM_NONE; param->reg = *reg; } @@ -4062,6 +4063,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); @@ -4359,6 +4421,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_ATAN ] = {"g", "R", sm6_parser_emit_dx_unary}, [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 4c64dbb98..72c61601b 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) rgbasi (11, -12, 13, -14) probe uav 1 (1) rgbasi (-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 7cb1afff9..d4f80575c 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) rgbasi (11, -12, 13, -14) -probe uav 2 (1) rgbasi (-15, 16, -17, 18) +todo(sm<6) draw quad +todo probe uav 2 (0) rgbasi (11, -12, 13, -14) +todo probe uav 2 (1) rgbasi (-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 0a7315eb4..315188bfa 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -4021,6 +4021,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) { @@ -4077,6 +4128,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 d4f80575c..9ccc2a3fd 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) rgbasi (11, -12, 13, -14) -todo probe uav 2 (1) rgbasi (-15, 16, -17, 18) +probe uav 2 (0) rgbasi (11, -12, 13, -14) +probe uav 2 (1) rgbasi (-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 315188bfa..e8258af68 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -390,6 +390,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 @@ -4024,7 +4025,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; @@ -4054,6 +4055,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;
@@ -4070,6 +4089,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, @@ -4508,6 +4528,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},
On Mon Feb 19 14:11:56 2024 +0000, Conor McCarthy wrote:
`DX_RAW_BUFFER_STORE` is only emitted if SM 6.2 is specified. We'll need a way to test that at some point. It occurs in game shaders which don't use any other 6.2 features, so it's useful to have, but could be delayed too. We already have `DX_RAW_BUFFER_LOAD` though. UAV loads seem to be broken in SM < 6, or there's an issue with writing the initial data, or both. The Vulkan and vkd3d runners have different failures, so testing loads will have to wait.
I wasn't asking about testing `DX_RAW_BUFFER_STORE` specifically, rather testing storing to a raw buffer view even if that happens through `DX_BUFFER_STORE`. After a quick look it seems that it would require some work in the shader runner to declare raw buffer views, but that shouldn't be particularly hard.