From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 112 +++++++++++++++++++++++ tests/hlsl/compute.shader_test | 2 +- tests/hlsl/sm6-uav-rwtexture.shader_test | 8 +- tests/hlsl/uav-load.shader_test | 2 +- tests/hlsl/uav-out-param.shader_test | 4 +- 5 files changed, 120 insertions(+), 8 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 32e14cb7d..801e12b3e 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -364,6 +364,7 @@ enum dx_intrinsic_opcode DX_CREATE_HANDLE = 57, DX_CBUFFER_LOAD_LEGACY = 59, DX_TEXTURE_LOAD = 66, + DX_TEXTURE_STORE = 67, DX_BUFFER_LOAD = 68, DX_DERIV_COARSEX = 83, DX_DERIV_COARSEY = 84, @@ -2192,6 +2193,13 @@ static void dst_param_init(struct vkd3d_shader_dst_param *param) param->shift = 0; }
+static void dst_param_init_with_mask(struct vkd3d_shader_dst_param *param, unsigned int mask) +{ + param->write_mask = mask; + param->modifiers = 0; + param->shift = 0; +} + static inline void dst_param_init_scalar(struct vkd3d_shader_dst_param *param, unsigned int component_idx) { param->write_mask = 1u << component_idx; @@ -3222,6 +3230,59 @@ struct function_emission_state unsigned int temp_idx; };
+static bool sm6_parser_emit_composite_construct(struct sm6_parser *sm6, const struct sm6_value **operands, + unsigned int component_count, struct function_emission_state *state, struct vkd3d_shader_register *reg) +{ + struct vkd3d_shader_instruction *ins = state->ins; + struct vkd3d_shader_src_param *src_params; + struct vkd3d_shader_dst_param *dst_param; + bool all_constant = true; + unsigned int i; + + if (component_count == 1) + { + *reg = operands[0]->u.reg; + return true; + } + + for (i = 0; i < component_count; ++i) + all_constant &= register_is_constant(&operands[i]->u.reg); + + if (all_constant) + { + vsir_register_init(reg, VKD3DSPR_IMMCONST, operands[0]->u.reg.data_type, 0); + reg->dimension = VSIR_DIMENSION_VEC4; + for (i = 0; i < component_count; ++i) + reg->u.immconst_u32[i] = operands[i]->u.reg.u.immconst_u32[0]; + return true; + } + + register_init_with_id(reg, VKD3DSPR_TEMP, operands[0]->u.reg.data_type, state->temp_idx++); + reg->dimension = VSIR_DIMENSION_VEC4; + + for (i = 0; i < component_count; ++i, ++ins) + { + vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); + + if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) + return false; + + src_param_init(&src_params[0]); + src_params[0].reg = operands[i]->u.reg; + + if (!(dst_param = instruction_dst_params_alloc(ins, 1, sm6))) + return false; + + dst_param_init_scalar(dst_param, i); + dst_param->reg = *reg; + } + + state->ins += component_count; + state->code_block->instruction_count += component_count; + + return true; +} + static void sm6_parser_emit_alloca(struct sm6_parser *sm6, const struct dxil_record *record, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) { @@ -4078,6 +4139,56 @@ static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intr instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); }
+static void sm6_parser_emit_dx_texture_store(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + struct vkd3d_shader_register coord, texel; + 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; + const struct sm6_value *resource; + + resource = operands[0]; + if (!sm6_value_validate_is_texture_handle(resource, op, sm6)) + return; + + if (!sm6_parser_emit_coordinate_construct(sm6, &operands[1], NULL, state, &coord)) + return; + + write_mask = sm6_value_get_constant_uint(operands[8]); + 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 texture 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 texture store operation is unhandled.", write_mask); + } + component_count = vsir_write_mask_component_count(write_mask); + + if (!sm6_parser_emit_composite_construct(sm6, &operands[4], 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_vector_from_reg(&src_params[0], &coord); + 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; +} + struct sm6_dx_opcode_info { const char *ret_type; @@ -4142,6 +4253,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output}, [DX_TAN ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_TEXTURE_LOAD ] = {"o", "HiiiiCCC", sm6_parser_emit_dx_texture_load}, + [DX_TEXTURE_STORE ] = {"v", "Hiiiooooc", sm6_parser_emit_dx_texture_store}, [DX_UBFE ] = {"m", "iiR", sm6_parser_emit_dx_tertiary}, [DX_UMAX ] = {"m", "RR", sm6_parser_emit_dx_binary}, [DX_UMIN ] = {"m", "RR", sm6_parser_emit_dx_binary}, diff --git a/tests/hlsl/compute.shader_test b/tests/hlsl/compute.shader_test index 2f2af9fc8..6d2f698c7 100644 --- a/tests/hlsl/compute.shader_test +++ b/tests/hlsl/compute.shader_test @@ -17,5 +17,5 @@ void main() }
[test] -todo(sm>=6) dispatch 1 1 1 +dispatch 1 1 1 probe uav 0 (0, 0) r (-123.0) diff --git a/tests/hlsl/sm6-uav-rwtexture.shader_test b/tests/hlsl/sm6-uav-rwtexture.shader_test index e2f4361f6..0597bf504 100644 --- a/tests/hlsl/sm6-uav-rwtexture.shader_test +++ b/tests/hlsl/sm6-uav-rwtexture.shader_test @@ -49,7 +49,7 @@ float4 main() : sv_target }
[test] -todo draw quad +draw quad probe uav 0 (0, 0) r (0.5) probe uav 0 (0, 1) r (0.6) probe uav 0 (1, 0) r (0.2) @@ -72,7 +72,7 @@ float4 main() : sv_target1 }
[test] -todo draw quad +draw quad probe uav 2 (0, 0) rgba (0.9, 0.8, 0.7, 0.6)
% Uppercase register set name @@ -86,7 +86,7 @@ float4 main() : sv_target1 }
[test] -todo draw quad +draw quad probe uav 2 (0, 0) rgba (0.9, 0.8, 0.7, 0.6)
% Test that we can declare and use an array of UAVs. @@ -112,7 +112,7 @@ float4 main() : sv_target1 }
[test] -todo draw quad +draw quad probe uav 1 (0, 0) rgba (1.1, 1.2, 1.3, 1.4) probe uav 2 (0, 0) rgba (2.1, 2.2, 2.3, 2.4)
diff --git a/tests/hlsl/uav-load.shader_test b/tests/hlsl/uav-load.shader_test index 9088ffa0d..fe6350e0c 100644 --- a/tests/hlsl/uav-load.shader_test +++ b/tests/hlsl/uav-load.shader_test @@ -23,7 +23,7 @@ void main() }
[test] -todo(sm>=6) dispatch 1 1 1 +dispatch 1 1 1 probe uav 0 (0, 0) r (0.6) probe uav 0 (1, 0) r (0.6) probe uav 0 (2, 0) r (0.6) diff --git a/tests/hlsl/uav-out-param.shader_test b/tests/hlsl/uav-out-param.shader_test index 796c4bf1f..f31344748 100644 --- a/tests/hlsl/uav-out-param.shader_test +++ b/tests/hlsl/uav-out-param.shader_test @@ -26,7 +26,7 @@ void main() }
[test] -todo(sm>=6) dispatch 1 1 1 +dispatch 1 1 1 probe uav 0 (0, 0) rgba (0.4, 0.1, 0.2, 0.3)
[uav 0] @@ -51,5 +51,5 @@ void main() }
[test] -todo(sm>=6) dispatch 1 1 1 +dispatch 1 1 1 probe uav 0 (0, 0) r (0.2)