From e5ae4588d150a179974a812887f3b6445d8e2f34 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Thu, 23 Sep 2010 13:31:30 +0200 Subject: d3d1x: s/tpf/sm4/g --- .../state_trackers/d3d1x/d3d1xshader/Makefile | 4 +- .../state_trackers/d3d1x/d3d1xshader/gen-header.sh | 6 +- .../state_trackers/d3d1x/d3d1xshader/gen-text.sh | 2 +- .../state_trackers/d3d1x/d3d1xshader/include/sm4.h | 410 ++++++++++ .../state_trackers/d3d1x/d3d1xshader/include/tpf.h | 408 ---------- .../d3d1x/d3d1xshader/src/sm4_analyze.cpp | 186 +++++ .../d3d1x/d3d1xshader/src/sm4_dump.cpp | 222 ++++++ .../d3d1x/d3d1xshader/src/sm4_parse.cpp | 424 +++++++++++ .../d3d1x/d3d1xshader/src/tpf_analyze.cpp | 186 ----- .../d3d1x/d3d1xshader/src/tpf_dump.cpp | 222 ------ .../d3d1x/d3d1xshader/src/tpf_parse.cpp | 424 ----------- .../d3d1x/d3d1xshader/tools/fxdis.cpp | 14 +- .../state_trackers/d3d1x/gd3d11/d3d11_screen.h | 14 +- .../state_trackers/d3d1x/gd3d1x/d3d1x_private.h | 4 +- .../state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.cpp | 832 +++++++++++++++++++++ .../state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.h | 34 + .../d3d1x/gd3d1x/tools/dxbc2tgsi.cpp | 16 +- .../state_trackers/d3d1x/gd3d1x/tpf_to_tgsi.cpp | 832 --------------------- .../state_trackers/d3d1x/gd3d1x/tpf_to_tgsi.h | 34 - 19 files changed, 2138 insertions(+), 2136 deletions(-) create mode 100644 src/gallium/state_trackers/d3d1x/d3d1xshader/include/sm4.h delete mode 100644 src/gallium/state_trackers/d3d1x/d3d1xshader/include/tpf.h create mode 100644 src/gallium/state_trackers/d3d1x/d3d1xshader/src/sm4_analyze.cpp create mode 100644 src/gallium/state_trackers/d3d1x/d3d1xshader/src/sm4_dump.cpp create mode 100644 src/gallium/state_trackers/d3d1x/d3d1xshader/src/sm4_parse.cpp delete mode 100644 src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_analyze.cpp delete mode 100644 src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_dump.cpp delete mode 100644 src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_parse.cpp create mode 100644 src/gallium/state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.cpp create mode 100644 src/gallium/state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.h delete mode 100644 src/gallium/state_trackers/d3d1x/gd3d1x/tpf_to_tgsi.cpp delete mode 100644 src/gallium/state_trackers/d3d1x/gd3d1x/tpf_to_tgsi.h (limited to 'src/gallium/state_trackers/d3d1x') diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/Makefile b/src/gallium/state_trackers/d3d1x/d3d1xshader/Makefile index 866762e1bb..4f67145b6f 100644 --- a/src/gallium/state_trackers/d3d1x/d3d1xshader/Makefile +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/Makefile @@ -6,8 +6,8 @@ LIBS=libd3d1xshader.a include ../Makefile.inc -include/tpf_defs.h: $(wildcard defs/*.txt) +include/sm4_defs.h: $(wildcard defs/*.txt) ./gen-header.sh $^ > $@ -src/tpf_text.cpp: $(wildcard defs/*.txt) +src/sm4_text.cpp: $(wildcard defs/*.txt) ./gen-text.sh $^ > $@ diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/gen-header.sh b/src/gallium/state_trackers/d3d1x/d3d1xshader/gen-header.sh index 558794f1d2..fcda13f907 100755 --- a/src/gallium/state_trackers/d3d1x/d3d1xshader/gen-header.sh +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/gen-header.sh @@ -2,12 +2,12 @@ for i in "$@"; do n=$(basename "$i" .txt|sed -e 's/s$//') if test "$n" == "shortfile"; then continue; fi - echo "enum tpf_$n" + echo "enum sm4_$n" echo "{" while read j; do - echo $'\t'"TPF_${n}_$j", + echo $'\t'"SM4_${n}_$j", done < "$i" |tr '[a-z]' '[A-Z]'|tr ' ' '_' - echo $'\t'"TPF_${n}_COUNT"|tr '[a-z]' '[A-Z]' + echo $'\t'"SM4_${n}_COUNT"|tr '[a-z]' '[A-Z]' echo "};" echo done diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/gen-text.sh b/src/gallium/state_trackers/d3d1x/d3d1xshader/gen-text.sh index b31e16e19c..4663f635d4 100755 --- a/src/gallium/state_trackers/d3d1x/d3d1xshader/gen-text.sh +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/gen-text.sh @@ -1,7 +1,7 @@ #!/bin/bash for i in "$@"; do n=$(basename "$i" .txt|sed -e 's/s$//') - echo "const char* tpf_${n}_names[] =" + echo "const char* sm4_${n}_names[] =" echo "{" while read j; do echo $'\t'"\"$j\"", diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/include/sm4.h b/src/gallium/state_trackers/d3d1x/d3d1xshader/include/sm4.h new file mode 100644 index 0000000000..07f84f0c73 --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/include/sm4.h @@ -0,0 +1,410 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Header for Shader Model 4.0, 4.1 and 5.0 */ + +#ifndef SM4_H_ +#define SM4_H_ + +#include +#include +#include +#include +#include +#include +#include +#include "le32.h" + +#include "sm4_defs.h" + +extern const char* sm4_opcode_names[]; +extern const char* sm4_file_names[]; +extern const char* sm4_file_ms_names[]; +extern const char* sm4_target_names[]; +extern const char* sm4_interpolation_names[]; +extern const char* sm4_sv_names[]; + +struct sm4_token_version +{ + unsigned minor : 4; + unsigned major : 4; + unsigned format : 8; + unsigned type : 16; +}; + +struct sm4_token_instruction +{ + // we don't make it an union directly because unions can't be inherited from + union + { + // length and extended are always present, but they are only here to reduce duplication + struct + { + unsigned opcode : 11; + unsigned _11_23 : 13; + unsigned length : 7; + unsigned extended : 1; + }; + struct + { + unsigned opcode : 11; + unsigned resinfo_return_type : 2; + unsigned sat : 1; + unsigned _14_17 : 4; + unsigned test_nz : 1; // bit 18 + unsigned precise_mask : 4; + unsigned _23 : 1; + unsigned length : 7; + unsigned extended : 1; + } insn; + struct + { + unsigned opcode : 11; + unsigned threads_in_group : 1; + unsigned shared_memory : 1; + unsigned uav_group : 1; + unsigned uav_global : 1; + unsigned _15_17 : 3; + } sync; + struct + { + unsigned opcode : 11; + unsigned allow_refactoring : 1; + unsigned fp64 : 1; + unsigned early_depth_stencil : 1; + unsigned enable_raw_and_structured_in_non_cs : 1; + } dcl_global_flags; + struct + { + unsigned opcode : 11; + unsigned target : 5; + unsigned nr_samples : 7; + } dcl_resource; + struct + { + unsigned opcode : 11; + unsigned shadow : 1; + unsigned mono : 1; + } dcl_sampler; + struct + { + unsigned opcode : 11; + unsigned interpolation : 5; + } dcl_input_ps; + struct + { + unsigned opcode : 11; + unsigned dynamic : 1; + } dcl_constant_buffer; + struct + { + unsigned opcode : 11; + unsigned primitive : 6; + } dcl_gs_input_primitive; + struct + { + unsigned opcode : 11; + unsigned primitive_topology : 7; + } dcl_gs_output_primitive_topology; + struct + { + unsigned opcode : 11; + unsigned control_points : 6; + } dcl_input_control_point_count; + struct + { + unsigned opcode : 11; + unsigned control_points : 6; + } dcl_output_control_point_count; + struct + { + unsigned opcode : 11; + unsigned domain : 3; /* D3D_TESSELLATOR_DOMAIN */ + } dcl_tess_domain; + struct + { + unsigned opcode : 11; + unsigned partitioning : 3; /* D3D_TESSELLATOR_PARTITIONING */ + } dcl_tess_partitioning; + struct + { + unsigned opcode : 11; + unsigned primitive : 3; /* D3D_TESSELLATOR_OUTPUT_PRIMITIVE */ + } dcl_tess_output_primitive; + }; +}; + +union sm4_token_instruction_extended +{ + struct + { + unsigned type : 6; + unsigned _6_30 : 25; + unsigned extended :1; + }; + struct + { + unsigned type : 6; + unsigned _6_8 : 3; + int offset_u : 4; + int offset_v : 4; + int offset_w : 4; + } sample_controls; + struct + { + unsigned type : 6; + unsigned target : 5; + } resource_target; + struct + { + unsigned type : 6; + unsigned x : 4; + unsigned y : 4; + unsigned z : 4; + unsigned w : 4; + } resource_return_type; +}; + +struct sm4_token_resource_return_type +{ + unsigned x : 4; + unsigned y : 4; + unsigned z : 4; + unsigned w : 4; +}; + +struct sm4_token_operand +{ + unsigned comps_enum : 2; /* sm4_operands_comps */ + unsigned mode : 2; /* sm4_operand_mode */ + unsigned sel : 8; + unsigned file : 8; /* sm4_file */ + unsigned num_indices : 2; + unsigned index0_repr : 3; /* sm4_operand_index_repr */ + unsigned index1_repr : 3; /* sm4_operand_index_repr */ + unsigned index2_repr : 3; /* sm4_operand_index_repr */ + unsigned extended : 1; +}; + +#define SM4_OPERAND_SEL_MASK(sel) ((sel) & 0xf) +#define SM4_OPERAND_SEL_SWZ(sel, i) (((sel) >> ((i) * 2)) & 3) +#define SM4_OPERAND_SEL_SCALAR(sel) ((sel) & 3) + +struct sm4_token_operand_extended +{ + unsigned type : 6; + unsigned neg : 1; + unsigned abs : 1; +}; + +union sm4_any +{ + double f64; + float f32; + int64_t i64; + int32_t i32; + uint64_t u64; + int64_t u32; +}; + +struct sm4_op; +struct sm4_insn; +struct sm4_dcl; +struct sm4_program; +std::ostream& operator <<(std::ostream& out, const sm4_op& op); +std::ostream& operator <<(std::ostream& out, const sm4_insn& op); +std::ostream& operator <<(std::ostream& out, const sm4_dcl& op); +std::ostream& operator <<(std::ostream& out, const sm4_program& op); + +struct sm4_op +{ + uint8_t mode; + uint8_t comps; + uint8_t mask; + uint8_t num_indices; + uint8_t swizzle[4]; + sm4_file file; + sm4_any imm_values[4]; + bool neg; + bool abs; + struct + { + int64_t disp; + std::auto_ptr reg; + } indices[3]; + + bool is_index_simple(unsigned i) const + { + return !indices[i].reg.get() && indices[i].disp >= 0 && (int64_t)(int32_t)indices[i].disp == indices[i].disp; + } + + bool has_simple_index() const + { + return num_indices == 1 && is_index_simple(0); + } + + sm4_op() + { + memset(this, 0, sizeof(*this)); + } + + void dump(); + +private: + sm4_op(const sm4_op& op) + {} +}; + +/* for sample_d */ +#define SM4_MAX_OPS 6 + +struct sm4_insn : public sm4_token_instruction +{ + int8_t sample_offset[3]; + uint8_t resource_target; + uint8_t resource_return_type[4]; + + unsigned num; + unsigned num_ops; + std::auto_ptr ops[SM4_MAX_OPS]; + + sm4_insn() + { + memset(this, 0, sizeof(*this)); + } + + void dump(); + +private: + sm4_insn(const sm4_insn& op) + {} +}; + +struct sm4_dcl : public sm4_token_instruction +{ + std::auto_ptr op; + union + { + unsigned num; + float f32; + sm4_sv sv; + struct + { + unsigned id; + unsigned expected_function_table_length; + unsigned table_length; + unsigned array_length; + } intf; + unsigned thread_group_size[3]; + sm4_token_resource_return_type rrt; + struct + { + unsigned num; + unsigned comps; + } indexable_temp; + struct + { + unsigned stride; + unsigned count; + } structured; + }; + + void* data; + + sm4_dcl() + { + memset(this, 0, sizeof(*this)); + } + + ~sm4_dcl() + { + free(data); + } + + void dump(); + +private: + sm4_dcl(const sm4_dcl& op) + {} +}; + +struct sm4_program +{ + sm4_token_version version; + std::vector dcls; + std::vector insns; + + /* for ifs, the insn number of the else or endif if there is no else + * for elses, the insn number of the endif + * for endifs, the insn number of the if + * for loops, the insn number of the endloop + * for endloops, the insn number of the loop + * for all others, -1 + */ + std::vector cf_insn_linked; + + /* NOTE: sampler 0 is the unnormalized nearest sampler for LD/LD_MS, while + * sampler 1 is user-specified sampler 0 + */ + bool resource_sampler_slots_assigned; + std::vector slot_to_resource; + std::vector slot_to_sampler; + std::map, int> resource_sampler_to_slot; + std::map resource_to_slot; + + bool labels_found; + std::vector label_to_insn_num; + + sm4_program() + { + memset(&version, 0, sizeof(version)); + labels_found = false; + resource_sampler_slots_assigned = false; + } + + ~sm4_program() + { + for(std::vector::iterator i = dcls.begin(), e = dcls.end(); i != e; ++i) + delete *i; + for(std::vector::iterator i = insns.begin(), e = insns.end(); i != e; ++i) + delete *i; + } + + void dump(); + +private: + sm4_program(const sm4_dcl& op) + {} +}; + +sm4_program* sm4_parse(void* tokens, int size); + +bool sm4_link_cf_insns(sm4_program& program); +bool sm4_find_labels(sm4_program& program); +bool sm4_allocate_resource_sampler_pairs(sm4_program& program); + +#endif /* SM4_H_ */ + diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/include/tpf.h b/src/gallium/state_trackers/d3d1x/d3d1xshader/include/tpf.h deleted file mode 100644 index 6ab9b820e8..0000000000 --- a/src/gallium/state_trackers/d3d1x/d3d1xshader/include/tpf.h +++ /dev/null @@ -1,408 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Luca Barbieri - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef TPF_H_ -#define TPF_H_ - -#include -#include -#include -#include -#include -#include -#include -#include "le32.h" - -#include "tpf_defs.h" - -extern const char* tpf_opcode_names[]; -extern const char* tpf_file_names[]; -extern const char* tpf_file_ms_names[]; -extern const char* tpf_target_names[]; -extern const char* tpf_interpolation_names[]; -extern const char* tpf_sv_names[]; - -struct tpf_token_version -{ - unsigned minor : 4; - unsigned major : 4; - unsigned format : 8; - unsigned type : 16; -}; - -struct tpf_token_instruction -{ - // we don't make it an union directly because unions can't be inherited from - union - { - // length and extended are always present, but they are only here to reduce duplication - struct - { - unsigned opcode : 11; - unsigned _11_23 : 13; - unsigned length : 7; - unsigned extended : 1; - }; - struct - { - unsigned opcode : 11; - unsigned resinfo_return_type : 2; - unsigned sat : 1; - unsigned _14_17 : 4; - unsigned test_nz : 1; // bit 18 - unsigned precise_mask : 4; - unsigned _23 : 1; - unsigned length : 7; - unsigned extended : 1; - } insn; - struct - { - unsigned opcode : 11; - unsigned threads_in_group : 1; - unsigned shared_memory : 1; - unsigned uav_group : 1; - unsigned uav_global : 1; - unsigned _15_17 : 3; - } sync; - struct - { - unsigned opcode : 11; - unsigned allow_refactoring : 1; - unsigned fp64 : 1; - unsigned early_depth_stencil : 1; - unsigned enable_raw_and_structured_in_non_cs : 1; - } dcl_global_flags; - struct - { - unsigned opcode : 11; - unsigned target : 5; - unsigned nr_samples : 7; - } dcl_resource; - struct - { - unsigned opcode : 11; - unsigned shadow : 1; - unsigned mono : 1; - } dcl_sampler; - struct - { - unsigned opcode : 11; - unsigned interpolation : 5; - } dcl_input_ps; - struct - { - unsigned opcode : 11; - unsigned dynamic : 1; - } dcl_constant_buffer; - struct - { - unsigned opcode : 11; - unsigned primitive : 6; - } dcl_gs_input_primitive; - struct - { - unsigned opcode : 11; - unsigned primitive_topology : 7; - } dcl_gs_output_primitive_topology; - struct - { - unsigned opcode : 11; - unsigned control_points : 6; - } dcl_input_control_point_count; - struct - { - unsigned opcode : 11; - unsigned control_points : 6; - } dcl_output_control_point_count; - struct - { - unsigned opcode : 11; - unsigned domain : 3; /* D3D_TESSELLATOR_DOMAIN */ - } dcl_tess_domain; - struct - { - unsigned opcode : 11; - unsigned partitioning : 3; /* D3D_TESSELLATOR_PARTITIONING */ - } dcl_tess_partitioning; - struct - { - unsigned opcode : 11; - unsigned primitive : 3; /* D3D_TESSELLATOR_OUTPUT_PRIMITIVE */ - } dcl_tess_output_primitive; - }; -}; - -union tpf_token_instruction_extended -{ - struct - { - unsigned type : 6; - unsigned _6_30 : 25; - unsigned extended :1; - }; - struct - { - unsigned type : 6; - unsigned _6_8 : 3; - int offset_u : 4; - int offset_v : 4; - int offset_w : 4; - } sample_controls; - struct - { - unsigned type : 6; - unsigned target : 5; - } resource_target; - struct - { - unsigned type : 6; - unsigned x : 4; - unsigned y : 4; - unsigned z : 4; - unsigned w : 4; - } resource_return_type; -}; - -struct tpf_token_resource_return_type -{ - unsigned x : 4; - unsigned y : 4; - unsigned z : 4; - unsigned w : 4; -}; - -struct tpf_token_operand -{ - unsigned comps_enum : 2; /* tpf_operands_comps */ - unsigned mode : 2; /* tpf_operand_mode */ - unsigned sel : 8; - unsigned file : 8; /* tpf_file */ - unsigned num_indices : 2; - unsigned index0_repr : 3; /* tpf_operand_index_repr */ - unsigned index1_repr : 3; /* tpf_operand_index_repr */ - unsigned index2_repr : 3; /* tpf_operand_index_repr */ - unsigned extended : 1; -}; - -#define TPF_OPERAND_SEL_MASK(sel) ((sel) & 0xf) -#define TPF_OPERAND_SEL_SWZ(sel, i) (((sel) >> ((i) * 2)) & 3) -#define TPF_OPERAND_SEL_SCALAR(sel) ((sel) & 3) - -struct tpf_token_operand_extended -{ - unsigned type : 6; - unsigned neg : 1; - unsigned abs : 1; -}; - -union tpf_any -{ - double f64; - float f32; - int64_t i64; - int32_t i32; - uint64_t u64; - int64_t u32; -}; - -struct tpf_op; -struct tpf_insn; -struct tpf_dcl; -struct tpf_program; -std::ostream& operator <<(std::ostream& out, const tpf_op& op); -std::ostream& operator <<(std::ostream& out, const tpf_insn& op); -std::ostream& operator <<(std::ostream& out, const tpf_dcl& op); -std::ostream& operator <<(std::ostream& out, const tpf_program& op); - -struct tpf_op -{ - uint8_t mode; - uint8_t comps; - uint8_t mask; - uint8_t num_indices; - uint8_t swizzle[4]; - tpf_file file; - tpf_any imm_values[4]; - bool neg; - bool abs; - struct - { - int64_t disp; - std::auto_ptr reg; - } indices[3]; - - bool is_index_simple(unsigned i) const - { - return !indices[i].reg.get() && indices[i].disp >= 0 && (int64_t)(int32_t)indices[i].disp == indices[i].disp; - } - - bool has_simple_index() const - { - return num_indices == 1 && is_index_simple(0); - } - - tpf_op() - { - memset(this, 0, sizeof(*this)); - } - - void dump(); - -private: - tpf_op(const tpf_op& op) - {} -}; - -/* for sample_d */ -#define TPF_MAX_OPS 6 - -struct tpf_insn : public tpf_token_instruction -{ - int8_t sample_offset[3]; - uint8_t resource_target; - uint8_t resource_return_type[4]; - - unsigned num; - unsigned num_ops; - std::auto_ptr ops[TPF_MAX_OPS]; - - tpf_insn() - { - memset(this, 0, sizeof(*this)); - } - - void dump(); - -private: - tpf_insn(const tpf_insn& op) - {} -}; - -struct tpf_dcl : public tpf_token_instruction -{ - std::auto_ptr op; - union - { - unsigned num; - float f32; - tpf_sv sv; - struct - { - unsigned id; - unsigned expected_function_table_length; - unsigned table_length; - unsigned array_length; - } intf; - unsigned thread_group_size[3]; - tpf_token_resource_return_type rrt; - struct - { - unsigned num; - unsigned comps; - } indexable_temp; - struct - { - unsigned stride; - unsigned count; - } structured; - }; - - void* data; - - tpf_dcl() - { - memset(this, 0, sizeof(*this)); - } - - ~tpf_dcl() - { - free(data); - } - - void dump(); - -private: - tpf_dcl(const tpf_dcl& op) - {} -}; - -struct tpf_program -{ - tpf_token_version version; - std::vector dcls; - std::vector insns; - - /* for ifs, the insn number of the else or endif if there is no else - * for elses, the insn number of the endif - * for endifs, the insn number of the if - * for loops, the insn number of the endloop - * for endloops, the insn number of the loop - * for all others, -1 - */ - std::vector cf_insn_linked; - - /* NOTE: sampler 0 is the unnormalized nearest sampler for LD/LD_MS, while - * sampler 1 is user-specified sampler 0 - */ - bool resource_sampler_slots_assigned; - std::vector slot_to_resource; - std::vector slot_to_sampler; - std::map, int> resource_sampler_to_slot; - std::map resource_to_slot; - - bool labels_found; - std::vector label_to_insn_num; - - tpf_program() - { - memset(&version, 0, sizeof(version)); - labels_found = false; - resource_sampler_slots_assigned = false; - } - - ~tpf_program() - { - for(std::vector::iterator i = dcls.begin(), e = dcls.end(); i != e; ++i) - delete *i; - for(std::vector::iterator i = insns.begin(), e = insns.end(); i != e; ++i) - delete *i; - } - - void dump(); - -private: - tpf_program(const tpf_dcl& op) - {} -}; - -tpf_program* tpf_parse(void* tokens, int size); - -bool tpf_link_cf_insns(tpf_program& program); -bool tpf_find_labels(tpf_program& program); -bool tpf_allocate_resource_sampler_pairs(tpf_program& program); - -#endif /* TPF_H_ */ - diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/src/sm4_analyze.cpp b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/sm4_analyze.cpp new file mode 100644 index 0000000000..848db1bdbb --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/sm4_analyze.cpp @@ -0,0 +1,186 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include +#include "sm4.h" + +#define check(x) do {if(!(x)) return false;} while(0) + +bool sm4_link_cf_insns(sm4_program& program) +{ + if(program.cf_insn_linked.size()) + return true; + + std::vector cf_insn_linked; + cf_insn_linked.resize(program.insns.size()); + memset(&cf_insn_linked[0], 0xff, cf_insn_linked.size() * sizeof(int)); + std::vector cf_stack; + for(unsigned insn_num = 0; insn_num < program.insns.size(); ++insn_num) + { + unsigned v; + switch(program.insns[insn_num]->opcode) + { + case SM4_OPCODE_LOOP: + cf_stack.push_back(insn_num); + break; + case SM4_OPCODE_ENDLOOP: + check(!cf_stack.empty()); + v = cf_stack.back(); + check(program.insns[v]->opcode == SM4_OPCODE_LOOP); + cf_insn_linked[v] = insn_num; + cf_insn_linked[insn_num] = v; + cf_stack.pop_back(); + break; + case SM4_OPCODE_IF: + case SM4_OPCODE_SWITCH: + cf_insn_linked[insn_num] = insn_num; // later changed + cf_stack.push_back(insn_num); + break; + case SM4_OPCODE_ELSE: + case SM4_OPCODE_CASE: + check(!cf_stack.empty()); + v = cf_stack.back(); + if(program.insns[insn_num]->opcode == SM4_OPCODE_ELSE) + check(program.insns[v]->opcode == SM4_OPCODE_IF); + else + check(program.insns[v]->opcode == SM4_OPCODE_SWITCH || program.insns[v]->opcode == SM4_OPCODE_CASE); + cf_insn_linked[insn_num] = cf_insn_linked[v]; // later changed + cf_insn_linked[v] = insn_num; + cf_stack.back() = insn_num; + break; + case SM4_OPCODE_ENDSWITCH: + case SM4_OPCODE_ENDIF: + check(!cf_stack.empty()); + v = cf_stack.back(); + if(program.insns[insn_num]->opcode == SM4_OPCODE_ENDIF) + check(program.insns[v]->opcode == SM4_OPCODE_IF || program.insns[v]->opcode == SM4_OPCODE_ELSE); + else + check(program.insns[v]->opcode == SM4_OPCODE_SWITCH || program.insns[v]->opcode == SM4_OPCODE_CASE); + cf_insn_linked[insn_num] = cf_insn_linked[v]; + cf_insn_linked[v] = insn_num; + cf_stack.pop_back(); + break; + } + } + check(cf_stack.empty()); + program.cf_insn_linked.swap(cf_insn_linked); + return true; +} + +bool sm4_find_labels(sm4_program& program) +{ + if(program.labels_found) + return true; + + std::vector labels; + for(unsigned insn_num = 0; insn_num < program.insns.size(); ++insn_num) + { + switch(program.insns[insn_num]->opcode) + { + case SM4_OPCODE_LABEL: + if(program.insns[insn_num]->num_ops > 0) + { + sm4_op& op = *program.insns[insn_num]->ops[0]; + if(op.file == SM4_FILE_LABEL && op.has_simple_index()) + { + unsigned idx = (unsigned)op.indices[0].disp; + if(idx >= labels.size()) + labels.resize(idx + 1); + labels[idx] = insn_num; + } + } + break; + } + } + program.label_to_insn_num.swap(labels); + program.labels_found = true; + return true; +} + +bool sm4_allocate_resource_sampler_pairs(sm4_program& program) +{ + if(program.resource_sampler_slots_assigned) + return true; + + std::set > pairs; + std::set resinfos; + + for(unsigned insn_num = 0; insn_num < program.insns.size(); ++insn_num) + { + int resource = -1; + int sampler = -2; + for(unsigned i = 0; i < program.insns[insn_num]->num_ops; ++i) + { + sm4_op* op = program.insns[insn_num]->ops[i].get(); + if(op) + { + if(op->file == SM4_FILE_RESOURCE) + { + if(!op->has_simple_index() || resource >= 0) + return false; + resource = (int)op->indices[0].disp; + } + if(op->file == SM4_FILE_SAMPLER) + { + if(!op->has_simple_index() || sampler >= 0) + return false; + sampler = (int)op->indices[0].disp; + } + } + } + + unsigned opcode = program.insns[insn_num]->opcode; + if(opcode == SM4_OPCODE_LD || opcode == SM4_OPCODE_LD_MS) + sampler = -1; + if(sampler >= -1 && resource >= 0) + pairs.insert(std::make_pair(resource, sampler)); + if(opcode == SM4_OPCODE_RESINFO) + resinfos.insert(resource); + } + + for(std::set >::iterator i = pairs.begin(); i != pairs.end(); ++i) + { + program.resource_sampler_to_slot[*i] = program.slot_to_resource.size(); + if(!program.resource_to_slot.count(i->first)) + { + program.resource_to_slot[i->first] = program.slot_to_resource.size(); + resinfos.erase(i->first); + } + program.slot_to_resource.push_back(i->first); + program.slot_to_sampler.push_back(i->second); + } + + for(std::set::iterator i = resinfos.begin(); i != resinfos.end(); ++i) + { + program.resource_sampler_to_slot[std::make_pair(*i, -1)] = program.slot_to_resource.size(); + program.resource_to_slot[*i] = program.slot_to_resource.size(); + program.slot_to_resource.push_back(*i); + program.slot_to_sampler.push_back(-1); + } + program.resource_sampler_slots_assigned = true; + return true; +} diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/src/sm4_dump.cpp b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/sm4_dump.cpp new file mode 100644 index 0000000000..746d7c8927 --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/sm4_dump.cpp @@ -0,0 +1,222 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "sm4.h" + +// TODO: we should fix this to output the same syntax as fxc, if sm4_dump_short_syntax is set + +bool sm4_dump_short_syntax = true; + +std::ostream& operator <<(std::ostream& out, const sm4_op& op) +{ + if(op.neg) + out << '-'; + if(op.abs) + out << '|'; + if(op.file == SM4_FILE_IMMEDIATE32) + { + out << "l("; + for(unsigned i = 0; i < op.comps; ++i) + { + if(i) + out << ", "; + out << op.imm_values[i].f32; + } + out << ")"; + } + else if(op.file == SM4_FILE_IMMEDIATE64) + { + out << "d("; + for(unsigned i = 0; i < op.comps; ++i) + { + if(i) + out << ", "; + out << op.imm_values[i].f64; + } + out << ")"; + return out; + } + else + { + bool naked = false; + if(sm4_dump_short_syntax) + { + switch(op.file) + { + case SM4_FILE_TEMP: + case SM4_FILE_INPUT: + case SM4_FILE_OUTPUT: + case SM4_FILE_CONSTANT_BUFFER: + case SM4_FILE_INDEXABLE_TEMP: + case SM4_FILE_UNORDERED_ACCESS_VIEW: + case SM4_FILE_THREAD_GROUP_SHARED_MEMORY: + naked = true; + break; + default: + naked = false; + break; + } + } + + out << (sm4_dump_short_syntax ? sm4_shortfile_names : sm4_file_names)[op.file]; + + if(op.indices[0].reg.get()) + naked = false; + + for(unsigned i = 0; i < op.num_indices; ++i) + { + if(!naked || i) + out << '['; + if(op.indices[i].reg.get()) + { + out << *op.indices[i].reg; + if(op.indices[i].disp) + out << '+' << op.indices[i].disp; + } + else + out << op.indices[i].disp; + if(!naked || i) + out << ']'; + } + if(op.comps) + { + switch(op.mode) + { + case SM4_OPERAND_MODE_MASK: + out << (sm4_dump_short_syntax ? '.' : '!'); + for(unsigned i = 0; i < op.comps; ++i) + { + if(op.mask & (1 << i)) + out << "xyzw"[i]; + } + break; + case SM4_OPERAND_MODE_SWIZZLE: + out << '.'; + for(unsigned i = 0; i < op.comps; ++i) + out << "xyzw"[op.swizzle[i]]; + break; + case SM4_OPERAND_MODE_SCALAR: + out << (sm4_dump_short_syntax ? '.' : ':'); + out << "xyzw"[op.swizzle[0]]; + break; + } + } + } + if(op.abs) + out << '|'; + return out; +} + +std::ostream& operator <<(std::ostream& out, const sm4_dcl& dcl) +{ + out << sm4_opcode_names[dcl.opcode]; + switch(dcl.opcode) + { + case SM4_OPCODE_DCL_GLOBAL_FLAGS: + if(dcl.dcl_global_flags.allow_refactoring) + out << " refactoringAllowed"; + if(dcl.dcl_global_flags.early_depth_stencil) + out << " forceEarlyDepthStencil"; + if(dcl.dcl_global_flags.fp64) + out << " enableDoublePrecisionFloatOps"; + if(dcl.dcl_global_flags.enable_raw_and_structured_in_non_cs) + out << " enableRawAndStructuredBuffers"; + break; + case SM4_OPCODE_DCL_INPUT_PS: + case SM4_OPCODE_DCL_INPUT_PS_SIV: + case SM4_OPCODE_DCL_INPUT_PS_SGV: + out << ' ' << sm4_interpolation_names[dcl.dcl_input_ps.interpolation]; + break; + case SM4_OPCODE_DCL_TEMPS: + out << ' ' << dcl.num; + break; + default: + break; + } + if(dcl.op.get()) + out << ' ' << *dcl.op; + switch(dcl.opcode) + { + case SM4_OPCODE_DCL_CONSTANT_BUFFER: + out << ", " << (dcl.dcl_constant_buffer.dynamic ? "dynamicIndexed" : "immediateIndexed"); + break; + case SM4_OPCODE_DCL_INPUT_SIV: + case SM4_OPCODE_DCL_INPUT_SGV: + case SM4_OPCODE_DCL_OUTPUT_SIV: + case SM4_OPCODE_DCL_OUTPUT_SGV: + case SM4_OPCODE_DCL_INPUT_PS_SIV: + case SM4_OPCODE_DCL_INPUT_PS_SGV: + out << ", " << sm4_sv_names[dcl.num]; + break; + } + + return out; +} + +std::ostream& operator <<(std::ostream& out, const sm4_insn& insn) +{ + out << sm4_opcode_names[insn.opcode]; + if(insn.insn.sat) + out << "_sat"; + for(unsigned i = 0; i < insn.num_ops; ++i) + { + if(i) + out << ','; + out << ' ' << *insn.ops[i]; + } + return out; +} + +std::ostream& operator <<(std::ostream& out, const sm4_program& program) +{ + out << "pvghdc"[program.version.type] << "s_" << program.version.major << "_" << program.version.minor << "\n"; + for(unsigned i = 0; i < program.dcls.size(); ++i) + out << *program.dcls[i] << "\n"; + + for(unsigned i = 0; i < program.insns.size(); ++i) + out << *program.insns[i] << "\n"; + return out; +} + +void sm4_op::dump() +{ + std::cout << *this; +} + +void sm4_insn::dump() +{ + std::cout << *this; +} + +void sm4_dcl::dump() +{ + std::cout << *this; +} + +void sm4_program::dump() +{ + std::cout << *this; +} diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/src/sm4_parse.cpp b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/sm4_parse.cpp new file mode 100644 index 0000000000..2c0f8269af --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/sm4_parse.cpp @@ -0,0 +1,424 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "sm4.h" +#include "utils.h" + +#if 1 +#define check(x) assert(x) +#define fail(x) assert(0 && (x)) +#else +#define check(x) do {if(!(x)) throw(#x);} while(0) +#define fail(x) throw(x) +#endif + +struct sm4_parser +{ + unsigned* tokens; + unsigned* tokens_end; + sm4_program& program; + + sm4_parser(sm4_program& program, void* p_tokens, unsigned size) + : program(program) + { + tokens = (unsigned*)p_tokens; + tokens_end = (unsigned*)((char*)p_tokens + size); + } + + /* TODO: byteswap if machine is big endian */ + uint32_t read32() + { + check(tokens < tokens_end); + return bswap_le32(*tokens++); + } + + template + void read_token(T* tok) + { + *(unsigned*)tok = read32(); + } + + uint64_t read64() + { + unsigned a = read32(); + unsigned b = read32(); + return (uint64_t)a | ((uint64_t)b << 32); + } + + void skip(unsigned toskip) + { + tokens += toskip; + } + + void read_op(sm4_op* pop) + { + sm4_op& op = *pop; + sm4_token_operand optok; + read_token(&optok); + assert(optok.file < SM4_FILE_COUNT); + op.swizzle[0] = 0; + op.swizzle[1] = 1; + op.swizzle[2] = 2; + op.swizzle[3] = 3; + op.mask = 0xf; + switch(optok.comps_enum) + { + case SM4_OPERAND_COMPNUM_0: + op.comps = 0; + break; + case SM4_OPERAND_COMPNUM_1: + op.comps = 1; + break; + case SM4_OPERAND_COMPNUM_4: + op.comps = 4; + op.mode = optok.mode; + switch(optok.mode) + { + case SM4_OPERAND_MODE_MASK: + op.mask = SM4_OPERAND_SEL_MASK(optok.sel); + break; + case SM4_OPERAND_MODE_SWIZZLE: + op.swizzle[0] = SM4_OPERAND_SEL_SWZ(optok.sel, 0); + op.swizzle[1] = SM4_OPERAND_SEL_SWZ(optok.sel, 1); + op.swizzle[2] = SM4_OPERAND_SEL_SWZ(optok.sel, 2); + op.swizzle[3] = SM4_OPERAND_SEL_SWZ(optok.sel, 3); + break; + case SM4_OPERAND_MODE_SCALAR: + op.swizzle[0] = op.swizzle[1] = op.swizzle[2] = op.swizzle[3] = SM4_OPERAND_SEL_SCALAR(optok.sel); + break; + } + break; + case SM4_OPERAND_COMPNUM_N: + fail("Unhandled operand component type"); + } + op.file = (sm4_file)optok.file; + op.num_indices = optok.num_indices; + + if(optok.extended) + { + sm4_token_operand_extended optokext; + read_token(&optokext); + if(optokext.type == 0) + {} + else if(optokext.type == 1) + { + op.neg = optokext.neg; + op.abs= optokext.abs; + } + else + fail("Unhandled extended operand token type"); + } + + for(unsigned i = 0; i < op.num_indices; ++i) + { + unsigned repr; + if(i == 0) + repr = optok.index0_repr; + else if(i == 1) + repr = optok.index1_repr; + else if(i == 2) + repr = optok.index2_repr; + else + fail("Unhandled operand index representation"); + op.indices[0].disp = 0; + // TODO: is disp supposed to be signed here?? + switch(repr) + { + case SM4_OPERAND_INDEX_REPR_IMM32: + op.indices[i].disp = (int32_t)read32(); + break; + case SM4_OPERAND_INDEX_REPR_IMM64: + op.indices[i].disp = read64(); + break; + case SM4_OPERAND_INDEX_REPR_REG: +relative: + op.indices[i].reg.reset(new sm4_op()); + read_op(&*op.indices[0].reg); + break; + case SM4_OPERAND_INDEX_REPR_REG_IMM32: + op.indices[i].disp = (int32_t)read32(); + goto relative; + case SM4_OPERAND_INDEX_REPR_REG_IMM64: + op.indices[i].disp = read64(); + goto relative; + } + } + + if(op.file == SM4_FILE_IMMEDIATE32) + { + for(unsigned i = 0; i < op.comps; ++i) + op.imm_values[i].i32 = read32(); + } + else if(op.file == SM4_FILE_IMMEDIATE64) + { + for(unsigned i = 0; i < op.comps; ++i) + op.imm_values[i].i64 = read64(); + } + } + + void do_parse() + { + read_token(&program.version); + + unsigned lentok = read32(); + tokens_end = tokens - 2 + lentok; + + while(tokens != tokens_end) + { + sm4_token_instruction insntok; + read_token(&insntok); + unsigned* insn_end = tokens - 1 + insntok.length; + sm4_opcode opcode = (sm4_opcode)insntok.opcode; + check(opcode < SM4_OPCODE_COUNT); + + if(opcode == SM4_OPCODE_CUSTOMDATA) + { + unsigned customlen = read32() - 2; + skip(customlen); + continue; + } + + if((opcode >= SM4_OPCODE_DCL_RESOURCE && opcode <= SM4_OPCODE_DCL_GLOBAL_FLAGS) + || (opcode >= SM4_OPCODE_DCL_STREAM && opcode <= SM4_OPCODE_DCL_RESOURCE_STRUCTURED)) + { + sm4_dcl& dcl = *new sm4_dcl; + program.dcls.push_back(&dcl); + (sm4_token_instruction&)dcl = insntok; + + sm4_token_instruction_extended exttok; + memcpy(&exttok, &insntok, sizeof(exttok)); + while(exttok.extended) + { + read_token(&exttok); + } + +#define READ_OP_ANY dcl.op.reset(new sm4_op()); read_op(&*dcl.op); +#define READ_OP(FILE) READ_OP_ANY + //check(dcl.op->file == SM4_FILE_##FILE); + + switch(opcode) + { + case SM4_OPCODE_DCL_GLOBAL_FLAGS: + break; + case SM4_OPCODE_DCL_RESOURCE: + READ_OP(RESOURCE); + read_token(&dcl.rrt); + break; + case SM4_OPCODE_DCL_SAMPLER: + READ_OP(SAMPLER); + break; + case SM4_OPCODE_DCL_INPUT: + case SM4_OPCODE_DCL_INPUT_PS: + READ_OP(INPUT); + break; + case SM4_OPCODE_DCL_INPUT_SIV: + case SM4_OPCODE_DCL_INPUT_SGV: + case SM4_OPCODE_DCL_INPUT_PS_SIV: + case SM4_OPCODE_DCL_INPUT_PS_SGV: + READ_OP(INPUT); + dcl.sv = (sm4_sv)(uint16_t)read32(); + break; + case SM4_OPCODE_DCL_OUTPUT: + READ_OP(OUTPUT); + break; + case SM4_OPCODE_DCL_OUTPUT_SIV: + case SM4_OPCODE_DCL_OUTPUT_SGV: + READ_OP(OUTPUT); + dcl.sv = (sm4_sv)(uint16_t)read32(); + break; + case SM4_OPCODE_DCL_INDEX_RANGE: + READ_OP_ANY; + check(dcl.op->file == SM4_FILE_INPUT || dcl.op->file == SM4_FILE_OUTPUT); + dcl.num = read32(); + break; + case SM4_OPCODE_DCL_TEMPS: + dcl.num = read32(); + break; + case SM4_OPCODE_DCL_INDEXABLE_TEMP: + READ_OP(INDEXABLE_TEMP); + dcl.indexable_temp.num = read32(); + dcl.indexable_temp.comps = read32(); + break; + case SM4_OPCODE_DCL_CONSTANT_BUFFER: + READ_OP(CONSTANT_BUFFER); + break; + case SM4_OPCODE_DCL_GS_INPUT_PRIMITIVE: + case SM4_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: + break; + case SM4_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: + dcl.num = read32(); + break; + case SM4_OPCODE_DCL_GS_INSTANCE_COUNT: + dcl.num = read32(); + break; + case SM4_OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: + case SM4_OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: + case SM4_OPCODE_DCL_TESS_DOMAIN: + case SM4_OPCODE_DCL_TESS_PARTITIONING: + case SM4_OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: + break; + case SM4_OPCODE_DCL_HS_MAX_TESSFACTOR: + dcl.f32 = read32(); + break; + case SM4_OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: + dcl.num = read32(); + break; + case SM4_OPCODE_DCL_FUNCTION_BODY: + dcl.num = read32(); + break; + case SM4_OPCODE_DCL_FUNCTION_TABLE: + dcl.num = read32(); + dcl.data = malloc(dcl.num * sizeof(uint32_t)); + for(unsigned i = 0; i < dcl.num; ++i) + ((uint32_t*)dcl.data)[i] = read32(); + break; + case SM4_OPCODE_DCL_INTERFACE: + dcl.intf.id = read32(); + dcl.intf.expected_function_table_length = read32(); + { + uint32_t v = read32(); + dcl.intf.table_length = v & 0xffff; + dcl.intf.array_length = v >> 16; + } + dcl.data = malloc(dcl.intf.table_length * sizeof(uint32_t)); + for(unsigned i = 0; i < dcl.intf.table_length; ++i) + ((uint32_t*)dcl.data)[i] = read32(); + break; + case SM4_OPCODE_DCL_THREAD_GROUP: + dcl.thread_group_size[0] = read32(); + dcl.thread_group_size[1] = read32(); + dcl.thread_group_size[2] = read32(); + break; + case SM4_OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: + READ_OP(UNORDERED_ACCESS_VIEW); + read_token(&dcl.rrt); + break; + case SM4_OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: + READ_OP(UNORDERED_ACCESS_VIEW); + break; + case SM4_OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: + READ_OP(UNORDERED_ACCESS_VIEW); + dcl.structured.stride = read32(); + break; + case SM4_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW: + READ_OP(THREAD_GROUP_SHARED_MEMORY); + dcl.num = read32(); + break; + case SM4_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: + READ_OP(THREAD_GROUP_SHARED_MEMORY); + dcl.structured.stride = read32(); + dcl.structured.count = read32(); + break; + case SM4_OPCODE_DCL_RESOURCE_RAW: + READ_OP(RESOURCE); + break; + case SM4_OPCODE_DCL_RESOURCE_STRUCTURED: + READ_OP(RESOURCE); + dcl.structured.stride = read32(); + break; + case SM4_OPCODE_DCL_STREAM: + /* TODO: dcl_stream is undocumented: what is it? */ + fail("Unhandled dcl_stream since it's undocumented"); + default: + fail("Unhandled declaration"); + } + + check(tokens == insn_end); + } + else + { + sm4_insn& insn = *new sm4_insn; + program.insns.push_back(&insn); + (sm4_token_instruction&)insn = insntok; + + sm4_token_instruction_extended exttok; + memcpy(&exttok, &insntok, sizeof(exttok)); + while(exttok.extended) + { + read_token(&exttok); + if(exttok.type == SM4_TOKEN_INSTRUCTION_EXTENDED_TYPE_SAMPLE_CONTROLS) + { + insn.sample_offset[0] = exttok.sample_controls.offset_u; + insn.sample_offset[1] = exttok.sample_controls.offset_v; + insn.sample_offset[2] = exttok.sample_controls.offset_w; + } + else if(exttok.type == SM4_TOKEN_INSTRUCTION_EXTENDED_TYPE_RESOURCE_DIM) + insn.resource_target = exttok.resource_target.target; + else if(exttok.type == SM4_TOKEN_INSTRUCTION_EXTENDED_TYPE_RESOURCE_RETURN_TYPE) + { + insn.resource_return_type[0] = exttok.resource_return_type.x; + insn.resource_return_type[1] = exttok.resource_return_type.y; + insn.resource_return_type[2] = exttok.resource_return_type.z; + insn.resource_return_type[3] = exttok.resource_return_type.w; + } + } + + switch(opcode) + { + case SM4_OPCODE_INTERFACE_CALL: + insn.num = read32(); + break; + default: + break; + } + + unsigned op_num = 0; + while(tokens != insn_end) + { + check(tokens < insn_end); + check(op_num < SM4_MAX_OPS); + insn.ops[op_num].reset(new sm4_op); + read_op(&*insn.ops[op_num]); + ++op_num; + } + insn.num_ops = op_num; + } + } + } + + const char* parse() + { + try + { + do_parse(); + return 0; + } + catch(const char* error) + { + return error; + } + } +}; + +sm4_program* sm4_parse(void* tokens, int size) +{ + sm4_program* program = new sm4_program; + sm4_parser parser(*program, tokens, size); + if(!parser.parse()) + return program; + delete program; + return 0; +} diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_analyze.cpp b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_analyze.cpp deleted file mode 100644 index a381564ada..0000000000 --- a/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_analyze.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Luca Barbieri - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include -#include -#include "tpf.h" - -#define check(x) do {if(!(x)) return false;} while(0) - -bool tpf_link_cf_insns(tpf_program& program) -{ - if(program.cf_insn_linked.size()) - return true; - - std::vector cf_insn_linked; - cf_insn_linked.resize(program.insns.size()); - memset(&cf_insn_linked[0], 0xff, cf_insn_linked.size() * sizeof(int)); - std::vector cf_stack; - for(unsigned insn_num = 0; insn_num < program.insns.size(); ++insn_num) - { - unsigned v; - switch(program.insns[insn_num]->opcode) - { - case TPF_OPCODE_LOOP: - cf_stack.push_back(insn_num); - break; - case TPF_OPCODE_ENDLOOP: - check(!cf_stack.empty()); - v = cf_stack.back(); - check(program.insns[v]->opcode == TPF_OPCODE_LOOP); - cf_insn_linked[v] = insn_num; - cf_insn_linked[insn_num] = v; - cf_stack.pop_back(); - break; - case TPF_OPCODE_IF: - case TPF_OPCODE_SWITCH: - cf_insn_linked[insn_num] = insn_num; // later changed - cf_stack.push_back(insn_num); - break; - case TPF_OPCODE_ELSE: - case TPF_OPCODE_CASE: - check(!cf_stack.empty()); - v = cf_stack.back(); - if(program.insns[insn_num]->opcode == TPF_OPCODE_ELSE) - check(program.insns[v]->opcode == TPF_OPCODE_IF); - else - check(program.insns[v]->opcode == TPF_OPCODE_SWITCH || program.insns[v]->opcode == TPF_OPCODE_CASE); - cf_insn_linked[insn_num] = cf_insn_linked[v]; // later changed - cf_insn_linked[v] = insn_num; - cf_stack.back() = insn_num; - break; - case TPF_OPCODE_ENDSWITCH: - case TPF_OPCODE_ENDIF: - check(!cf_stack.empty()); - v = cf_stack.back(); - if(program.insns[insn_num]->opcode == TPF_OPCODE_ENDIF) - check(program.insns[v]->opcode == TPF_OPCODE_IF || program.insns[v]->opcode == TPF_OPCODE_ELSE); - else - check(program.insns[v]->opcode == TPF_OPCODE_SWITCH || program.insns[v]->opcode == TPF_OPCODE_CASE); - cf_insn_linked[insn_num] = cf_insn_linked[v]; - cf_insn_linked[v] = insn_num; - cf_stack.pop_back(); - break; - } - } - check(cf_stack.empty()); - program.cf_insn_linked.swap(cf_insn_linked); - return true; -} - -bool tpf_find_labels(tpf_program& program) -{ - if(program.labels_found) - return true; - - std::vector labels; - for(unsigned insn_num = 0; insn_num < program.insns.size(); ++insn_num) - { - switch(program.insns[insn_num]->opcode) - { - case TPF_OPCODE_LABEL: - if(program.insns[insn_num]->num_ops > 0) - { - tpf_op& op = *program.insns[insn_num]->ops[0]; - if(op.file == TPF_FILE_LABEL && op.has_simple_index()) - { - unsigned idx = (unsigned)op.indices[0].disp; - if(idx >= labels.size()) - labels.resize(idx + 1); - labels[idx] = insn_num; - } - } - break; - } - } - program.label_to_insn_num.swap(labels); - program.labels_found = true; - return true; -} - -bool tpf_allocate_resource_sampler_pairs(tpf_program& program) -{ - if(program.resource_sampler_slots_assigned) - return true; - - std::set > pairs; - std::set resinfos; - - for(unsigned insn_num = 0; insn_num < program.insns.size(); ++insn_num) - { - int resource = -1; - int sampler = -2; - for(unsigned i = 0; i < program.insns[insn_num]->num_ops; ++i) - { - tpf_op* op = program.insns[insn_num]->ops[i].get(); - if(op) - { - if(op->file == TPF_FILE_RESOURCE) - { - if(!op->has_simple_index() || resource >= 0) - return false; - resource = (int)op->indices[0].disp; - } - if(op->file == TPF_FILE_SAMPLER) - { - if(!op->has_simple_index() || sampler >= 0) - return false; - sampler = (int)op->indices[0].disp; - } - } - } - - unsigned opcode = program.insns[insn_num]->opcode; - if(opcode == TPF_OPCODE_LD || opcode == TPF_OPCODE_LD_MS) - sampler = -1; - if(sampler >= -1 && resource >= 0) - pairs.insert(std::make_pair(resource, sampler)); - if(opcode == TPF_OPCODE_RESINFO) - resinfos.insert(resource); - } - - for(std::set >::iterator i = pairs.begin(); i != pairs.end(); ++i) - { - program.resource_sampler_to_slot[*i] = program.slot_to_resource.size(); - if(!program.resource_to_slot.count(i->first)) - { - program.resource_to_slot[i->first] = program.slot_to_resource.size(); - resinfos.erase(i->first); - } - program.slot_to_resource.push_back(i->first); - program.slot_to_sampler.push_back(i->second); - } - - for(std::set::iterator i = resinfos.begin(); i != resinfos.end(); ++i) - { - program.resource_sampler_to_slot[std::make_pair(*i, -1)] = program.slot_to_resource.size(); - program.resource_to_slot[*i] = program.slot_to_resource.size(); - program.slot_to_resource.push_back(*i); - program.slot_to_sampler.push_back(-1); - } - program.resource_sampler_slots_assigned = true; - return true; -} diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_dump.cpp b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_dump.cpp deleted file mode 100644 index 2e6e0949a8..0000000000 --- a/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_dump.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Luca Barbieri - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "tpf.h" - -// TODO: we should fix this to output the same syntax as fxc, if tpf_dump_ms_syntax is set - -bool tpf_dump_ms_syntax = true; - -std::ostream& operator <<(std::ostream& out, const tpf_op& op) -{ - if(op.neg) - out << '-'; - if(op.abs) - out << '|'; - if(op.file == TPF_FILE_IMMEDIATE32) - { - out << "l("; - for(unsigned i = 0; i < op.comps; ++i) - { - if(i) - out << ", "; - out << op.imm_values[i].f32; - } - out << ")"; - } - else if(op.file == TPF_FILE_IMMEDIATE64) - { - out << "d("; - for(unsigned i = 0; i < op.comps; ++i) - { - if(i) - out << ", "; - out << op.imm_values[i].f64; - } - out << ")"; - return out; - } - else - { - bool naked = false; - if(tpf_dump_ms_syntax) - { - switch(op.file) - { - case TPF_FILE_TEMP: - case TPF_FILE_INPUT: - case TPF_FILE_OUTPUT: - case TPF_FILE_CONSTANT_BUFFER: - case TPF_FILE_INDEXABLE_TEMP: - case TPF_FILE_UNORDERED_ACCESS_VIEW: - case TPF_FILE_THREAD_GROUP_SHARED_MEMORY: - naked = true; - break; - default: - naked = false; - break; - } - } - - out << (tpf_dump_ms_syntax ? tpf_file_ms_names : tpf_file_names)[op.file]; - - if(op.indices[0].reg.get()) - naked = false; - - for(unsigned i = 0; i < op.num_indices; ++i) - { - if(!naked || i) - out << '['; - if(op.indices[i].reg.get()) - { - out << *op.indices[i].reg; - if(op.indices[i].disp) - out << '+' << op.indices[i].disp; - } - else - out << op.indices[i].disp; - if(!naked || i) - out << ']'; - } - if(op.comps) - { - switch(op.mode) - { - case TPF_OPERAND_MODE_MASK: - out << (tpf_dump_ms_syntax ? '.' : '!'); - for(unsigned i = 0; i < op.comps; ++i) - { - if(op.mask & (1 << i)) - out << "xyzw"[i]; - } - break; - case TPF_OPERAND_MODE_SWIZZLE: - out << '.'; - for(unsigned i = 0; i < op.comps; ++i) - out << "xyzw"[op.swizzle[i]]; - break; - case TPF_OPERAND_MODE_SCALAR: - out << (tpf_dump_ms_syntax ? '.' : ':'); - out << "xyzw"[op.swizzle[0]]; - break; - } - } - } - if(op.abs) - out << '|'; - return out; -} - -std::ostream& operator <<(std::ostream& out, const tpf_dcl& dcl) -{ - out << tpf_opcode_names[dcl.opcode]; - switch(dcl.opcode) - { - case TPF_OPCODE_DCL_GLOBAL_FLAGS: - if(dcl.dcl_global_flags.allow_refactoring) - out << " refactoringAllowed"; - if(dcl.dcl_global_flags.early_depth_stencil) - out << " forceEarlyDepthStencil"; - if(dcl.dcl_global_flags.fp64) - out << " enableDoublePrecisionFloatOps"; - if(dcl.dcl_global_flags.enable_raw_and_structured_in_non_cs) - out << " enableRawAndStructuredBuffers"; - break; - case TPF_OPCODE_DCL_INPUT_PS: - case TPF_OPCODE_DCL_INPUT_PS_SIV: - case TPF_OPCODE_DCL_INPUT_PS_SGV: - out << ' ' << tpf_interpolation_names[dcl.dcl_input_ps.interpolation]; - break; - case TPF_OPCODE_DCL_TEMPS: - out << ' ' << dcl.num; - break; - default: - break; - } - if(dcl.op.get()) - out << ' ' << *dcl.op; - switch(dcl.opcode) - { - case TPF_OPCODE_DCL_CONSTANT_BUFFER: - out << ", " << (dcl.dcl_constant_buffer.dynamic ? "dynamicIndexed" : "immediateIndexed"); - break; - case TPF_OPCODE_DCL_INPUT_SIV: - case TPF_OPCODE_DCL_INPUT_SGV: - case TPF_OPCODE_DCL_OUTPUT_SIV: - case TPF_OPCODE_DCL_OUTPUT_SGV: - case TPF_OPCODE_DCL_INPUT_PS_SIV: - case TPF_OPCODE_DCL_INPUT_PS_SGV: - out << ", " << tpf_sv_names[dcl.num]; - break; - } - - return out; -} - -std::ostream& operator <<(std::ostream& out, const tpf_insn& insn) -{ - out << tpf_opcode_names[insn.opcode]; - if(insn.insn.sat) - out << "_sat"; - for(unsigned i = 0; i < insn.num_ops; ++i) - { - if(i) - out << ','; - out << ' ' << *insn.ops[i]; - } - return out; -} - -std::ostream& operator <<(std::ostream& out, const tpf_program& program) -{ - out << "pvghdc"[program.version.type] << "s_" << program.version.major << "_" << program.version.minor << "\n"; - for(unsigned i = 0; i < program.dcls.size(); ++i) - out << *program.dcls[i] << "\n"; - - for(unsigned i = 0; i < program.insns.size(); ++i) - out << *program.insns[i] << "\n"; - return out; -} - -void tpf_op::dump() -{ - std::cout << *this; -} - -void tpf_insn::dump() -{ - std::cout << *this; -} - -void tpf_dcl::dump() -{ - std::cout << *this; -} - -void tpf_program::dump() -{ - std::cout << *this; -} diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_parse.cpp b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_parse.cpp deleted file mode 100644 index 2dfb88e5be..0000000000 --- a/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_parse.cpp +++ /dev/null @@ -1,424 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Luca Barbieri - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "tpf.h" -#include "utils.h" - -#if 1 -#define check(x) assert(x) -#define fail(x) assert(0 && (x)) -#else -#define check(x) do {if(!(x)) throw(#x);} while(0) -#define fail(x) throw(x) -#endif - -struct tpf_parser -{ - unsigned* tokens; - unsigned* tokens_end; - tpf_program& program; - - tpf_parser(tpf_program& program, void* p_tokens, unsigned size) - : program(program) - { - tokens = (unsigned*)p_tokens; - tokens_end = (unsigned*)((char*)p_tokens + size); - } - - /* TODO: byteswap if machine is big endian */ - uint32_t read32() - { - check(tokens < tokens_end); - return bswap_le32(*tokens++); - } - - template - void read_token(T* tok) - { - *(unsigned*)tok = read32(); - } - - uint64_t read64() - { - unsigned a = read32(); - unsigned b = read32(); - return (uint64_t)a | ((uint64_t)b << 32); - } - - void skip(unsigned toskip) - { - tokens += toskip; - } - - void read_op(tpf_op* pop) - { - tpf_op& op = *pop; - tpf_token_operand optok; - read_token(&optok); - assert(optok.file < TPF_FILE_COUNT); - op.swizzle[0] = 0; - op.swizzle[1] = 1; - op.swizzle[2] = 2; - op.swizzle[3] = 3; - op.mask = 0xf; - switch(optok.comps_enum) - { - case TPF_OPERAND_COMPNUM_0: - op.comps = 0; - break; - case TPF_OPERAND_COMPNUM_1: - op.comps = 1; - break; - case TPF_OPERAND_COMPNUM_4: - op.comps = 4; - op.mode = optok.mode; - switch(optok.mode) - { - case TPF_OPERAND_MODE_MASK: - op.mask = TPF_OPERAND_SEL_MASK(optok.sel); - break; - case TPF_OPERAND_MODE_SWIZZLE: - op.swizzle[0] = TPF_OPERAND_SEL_SWZ(optok.sel, 0); - op.swizzle[1] = TPF_OPERAND_SEL_SWZ(optok.sel, 1); - op.swizzle[2] = TPF_OPERAND_SEL_SWZ(optok.sel, 2); - op.swizzle[3] = TPF_OPERAND_SEL_SWZ(optok.sel, 3); - break; - case TPF_OPERAND_MODE_SCALAR: - op.swizzle[0] = op.swizzle[1] = op.swizzle[2] = op.swizzle[3] = TPF_OPERAND_SEL_SCALAR(optok.sel); - break; - } - break; - case TPF_OPERAND_COMPNUM_N: - fail("Unhandled operand component type"); - } - op.file = (tpf_file)optok.file; - op.num_indices = optok.num_indices; - - if(optok.extended) - { - tpf_token_operand_extended optokext; - read_token(&optokext); - if(optokext.type == 0) - {} - else if(optokext.type == 1) - { - op.neg = optokext.neg; - op.abs= optokext.abs; - } - else - fail("Unhandled extended operand token type"); - } - - for(unsigned i = 0; i < op.num_indices; ++i) - { - unsigned repr; - if(i == 0) - repr = optok.index0_repr; - else if(i == 1) - repr = optok.index1_repr; - else if(i == 2) - repr = optok.index2_repr; - else - fail("Unhandled operand index representation"); - op.indices[0].disp = 0; - // TODO: is disp supposed to be signed here?? - switch(repr) - { - case TPF_OPERAND_INDEX_REPR_IMM32: - op.indices[i].disp = (int32_t)read32(); - break; - case TPF_OPERAND_INDEX_REPR_IMM64: - op.indices[i].disp = read64(); - break; - case TPF_OPERAND_INDEX_REPR_REG: -relative: - op.indices[i].reg.reset(new tpf_op()); - read_op(&*op.indices[0].reg); - break; - case TPF_OPERAND_INDEX_REPR_REG_IMM32: - op.indices[i].disp = (int32_t)read32(); - goto relative; - case TPF_OPERAND_INDEX_REPR_REG_IMM64: - op.indices[i].disp = read64(); - goto relative; - } - } - - if(op.file == TPF_FILE_IMMEDIATE32) - { - for(unsigned i = 0; i < op.comps; ++i) - op.imm_values[i].i32 = read32(); - } - else if(op.file == TPF_FILE_IMMEDIATE64) - { - for(unsigned i = 0; i < op.comps; ++i) - op.imm_values[i].i64 = read64(); - } - } - - void do_parse() - { - read_token(&program.version); - - unsigned lentok = read32(); - tokens_end = tokens - 2 + lentok; - - while(tokens != tokens_end) - { - tpf_token_instruction insntok; - read_token(&insntok); - unsigned* insn_end = tokens - 1 + insntok.length; - tpf_opcode opcode = (tpf_opcode)insntok.opcode; - check(opcode < TPF_OPCODE_COUNT); - - if(opcode == TPF_OPCODE_CUSTOMDATA) - { - unsigned customlen = read32() - 2; - skip(customlen); - continue; - } - - if((opcode >= TPF_OPCODE_DCL_RESOURCE && opcode <= TPF_OPCODE_DCL_GLOBAL_FLAGS) - || (opcode >= TPF_OPCODE_DCL_STREAM && opcode <= TPF_OPCODE_DCL_RESOURCE_STRUCTURED)) - { - tpf_dcl& dcl = *new tpf_dcl; - program.dcls.push_back(&dcl); - (tpf_token_instruction&)dcl = insntok; - - tpf_token_instruction_extended exttok; - memcpy(&exttok, &insntok, sizeof(exttok)); - while(exttok.extended) - { - read_token(&exttok); - } - -#define READ_OP_ANY dcl.op.reset(new tpf_op()); read_op(&*dcl.op); -#define READ_OP(FILE) READ_OP_ANY - //check(dcl.op->file == TPF_FILE_##FILE); - - switch(opcode) - { - case TPF_OPCODE_DCL_GLOBAL_FLAGS: - break; - case TPF_OPCODE_DCL_RESOURCE: - READ_OP(RESOURCE); - read_token(&dcl.rrt); - break; - case TPF_OPCODE_DCL_SAMPLER: - READ_OP(SAMPLER); - break; - case TPF_OPCODE_DCL_INPUT: - case TPF_OPCODE_DCL_INPUT_PS: - READ_OP(INPUT); - break; - case TPF_OPCODE_DCL_INPUT_SIV: - case TPF_OPCODE_DCL_INPUT_SGV: - case TPF_OPCODE_DCL_INPUT_PS_SIV: - case TPF_OPCODE_DCL_INPUT_PS_SGV: - READ_OP(INPUT); - dcl.sv = (tpf_sv)(uint16_t)read32(); - break; - case TPF_OPCODE_DCL_OUTPUT: - READ_OP(OUTPUT); - break; - case TPF_OPCODE_DCL_OUTPUT_SIV: - case TPF_OPCODE_DCL_OUTPUT_SGV: - READ_OP(OUTPUT); - dcl.sv = (tpf_sv)(uint16_t)read32(); - break; - case TPF_OPCODE_DCL_INDEX_RANGE: - READ_OP_ANY; - check(dcl.op->file == TPF_FILE_INPUT || dcl.op->file == TPF_FILE_OUTPUT); - dcl.num = read32(); - break; - case TPF_OPCODE_DCL_TEMPS: - dcl.num = read32(); - break; - case TPF_OPCODE_DCL_INDEXABLE_TEMP: - READ_OP(INDEXABLE_TEMP); - dcl.indexable_temp.num = read32(); - dcl.indexable_temp.comps = read32(); - break; - case TPF_OPCODE_DCL_CONSTANT_BUFFER: - READ_OP(CONSTANT_BUFFER); - break; - case TPF_OPCODE_DCL_GS_INPUT_PRIMITIVE: - case TPF_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: - break; - case TPF_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: - dcl.num = read32(); - break; - case TPF_OPCODE_DCL_GS_INSTANCE_COUNT: - dcl.num = read32(); - break; - case TPF_OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: - case TPF_OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: - case TPF_OPCODE_DCL_TESS_DOMAIN: - case TPF_OPCODE_DCL_TESS_PARTITIONING: - case TPF_OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: - break; - case TPF_OPCODE_DCL_HS_MAX_TESSFACTOR: - dcl.f32 = read32(); - break; - case TPF_OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: - dcl.num = read32(); - break; - case TPF_OPCODE_DCL_FUNCTION_BODY: - dcl.num = read32(); - break; - case TPF_OPCODE_DCL_FUNCTION_TABLE: - dcl.num = read32(); - dcl.data = malloc(dcl.num * sizeof(uint32_t)); - for(unsigned i = 0; i < dcl.num; ++i) - ((uint32_t*)dcl.data)[i] = read32(); - break; - case TPF_OPCODE_DCL_INTERFACE: - dcl.intf.id = read32(); - dcl.intf.expected_function_table_length = read32(); - { - uint32_t v = read32(); - dcl.intf.table_length = v & 0xffff; - dcl.intf.array_length = v >> 16; - } - dcl.data = malloc(dcl.intf.table_length * sizeof(uint32_t)); - for(unsigned i = 0; i < dcl.intf.table_length; ++i) - ((uint32_t*)dcl.data)[i] = read32(); - break; - case TPF_OPCODE_DCL_THREAD_GROUP: - dcl.thread_group_size[0] = read32(); - dcl.thread_group_size[1] = read32(); - dcl.thread_group_size[2] = read32(); - break; - case TPF_OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: - READ_OP(UNORDERED_ACCESS_VIEW); - read_token(&dcl.rrt); - break; - case TPF_OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: - READ_OP(UNORDERED_ACCESS_VIEW); - break; - case TPF_OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: - READ_OP(UNORDERED_ACCESS_VIEW); - dcl.structured.stride = read32(); - break; - case TPF_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW: - READ_OP(THREAD_GROUP_SHARED_MEMORY); - dcl.num = read32(); - break; - case TPF_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: - READ_OP(THREAD_GROUP_SHARED_MEMORY); - dcl.structured.stride = read32(); - dcl.structured.count = read32(); - break; - case TPF_OPCODE_DCL_RESOURCE_RAW: - READ_OP(RESOURCE); - break; - case TPF_OPCODE_DCL_RESOURCE_STRUCTURED: - READ_OP(RESOURCE); - dcl.structured.stride = read32(); - break; - case TPF_OPCODE_DCL_STREAM: - /* TODO: dcl_stream is undocumented: what is it? */ - fail("Unhandled dcl_stream since it's undocumented"); - default: - fail("Unhandled declaration"); - } - - check(tokens == insn_end); - } - else - { - tpf_insn& insn = *new tpf_insn; - program.insns.push_back(&insn); - (tpf_token_instruction&)insn = insntok; - - tpf_token_instruction_extended exttok; - memcpy(&exttok, &insntok, sizeof(exttok)); - while(exttok.extended) - { - read_token(&exttok); - if(exttok.type == TPF_TOKEN_INSTRUCTION_EXTENDED_TYPE_SAMPLE_CONTROLS) - { - insn.sample_offset[0] = exttok.sample_controls.offset_u; - insn.sample_offset[1] = exttok.sample_controls.offset_v; - insn.sample_offset[2] = exttok.sample_controls.offset_w; - } - else if(exttok.type == TPF_TOKEN_INSTRUCTION_EXTENDED_TYPE_RESOURCE_DIM) - insn.resource_target = exttok.resource_target.target; - else if(exttok.type == TPF_TOKEN_INSTRUCTION_EXTENDED_TYPE_RESOURCE_RETURN_TYPE) - { - insn.resource_return_type[0] = exttok.resource_return_type.x; - insn.resource_return_type[1] = exttok.resource_return_type.y; - insn.resource_return_type[2] = exttok.resource_return_type.z; - insn.resource_return_type[3] = exttok.resource_return_type.w; - } - } - - switch(opcode) - { - case TPF_OPCODE_INTERFACE_CALL: - insn.num = read32(); - break; - default: - break; - } - - unsigned op_num = 0; - while(tokens != insn_end) - { - check(tokens < insn_end); - check(op_num < TPF_MAX_OPS); - insn.ops[op_num].reset(new tpf_op); - read_op(&*insn.ops[op_num]); - ++op_num; - } - insn.num_ops = op_num; - } - } - } - - const char* parse() - { - try - { - do_parse(); - return 0; - } - catch(const char* error) - { - return error; - } - } -}; - -tpf_program* tpf_parse(void* tokens, int size) -{ - tpf_program* program = new tpf_program; - tpf_parser parser(*program, tokens, size); - if(!parser.parse()) - return program; - delete program; - return 0; -} diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/tools/fxdis.cpp b/src/gallium/state_trackers/d3d1x/d3d1xshader/tools/fxdis.cpp index 721f95fc8a..20a7cbd1c3 100644 --- a/src/gallium/state_trackers/d3d1x/d3d1xshader/tools/fxdis.cpp +++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/tools/fxdis.cpp @@ -25,7 +25,7 @@ **************************************************************************/ #include "dxbc.h" -#include "tpf.h" +#include "sm4.h" #include #include @@ -60,14 +60,14 @@ int main(int argc, char** argv) if(dxbc) { std::cout << *dxbc; - dxbc_chunk_header* tpf_chunk = dxbc_find_shader_bytecode(&data[0], data.size()); - if(tpf_chunk) + dxbc_chunk_header* sm4_chunk = dxbc_find_shader_bytecode(&data[0], data.size()); + if(sm4_chunk) { - tpf_program* tpf = tpf_parse(tpf_chunk + 1, bswap_le32(tpf_chunk->size)); - if(tpf) + sm4_program* sm4 = sm4_parse(sm4_chunk + 1, bswap_le32(sm4_chunk->size)); + if(sm4) { - std::cout << *tpf; - delete tpf; + std::cout << *sm4; + delete sm4; } } delete dxbc; diff --git a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_screen.h b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_screen.h index 50039e388d..0c8d3ed943 100644 --- a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_screen.h +++ b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_screen.h @@ -1172,17 +1172,17 @@ struct GalliumD3D11ScreenImpl : public GalliumD3D11Screen #endif ) { - dxbc_chunk_header* tpf_chunk = dxbc_find_shader_bytecode(pShaderBytecode, BytecodeLength); - if(!tpf_chunk) + dxbc_chunk_header* sm4_chunk = dxbc_find_shader_bytecode(pShaderBytecode, BytecodeLength); + if(!sm4_chunk) return 0; - std::auto_ptr tpf(tpf_parse(tpf_chunk + 1, bswap_le32(tpf_chunk->size))); - if(!tpf.get()) + std::auto_ptr sm4(sm4_parse(sm4_chunk + 1, bswap_le32(sm4_chunk->size))); + if(!sm4.get()) return 0; struct pipe_shader_state tgsi_shader; memset(&tgsi_shader, 0, sizeof(tgsi_shader)); - tgsi_shader.tokens = (const tgsi_token*)tpf_to_tgsi(*tpf); + tgsi_shader.tokens = (const tgsi_token*)sm4_to_tgsi(*sm4); if(!tgsi_shader.tokens) return 0; @@ -1211,8 +1211,8 @@ struct GalliumD3D11ScreenImpl : public GalliumD3D11Screen if(shader) { - shader->slot_to_resource = tpf->slot_to_resource; - shader->slot_to_sampler = tpf->slot_to_sampler; + shader->slot_to_resource = sm4->slot_to_resource; + shader->slot_to_sampler = sm4->slot_to_sampler; } free((void*)tgsi_shader.tokens); diff --git a/src/gallium/state_trackers/d3d1x/gd3d1x/d3d1x_private.h b/src/gallium/state_trackers/d3d1x/gd3d1x/d3d1x_private.h index 6756b2112d..0274a1baf6 100644 --- a/src/gallium/state_trackers/d3d1x/gd3d1x/d3d1x_private.h +++ b/src/gallium/state_trackers/d3d1x/gd3d1x/d3d1x_private.h @@ -33,8 +33,8 @@ #include #include "dxbc.h" -#include "tpf.h" -#include "tpf_to_tgsi.h" +#include "sm4.h" +#include "sm4_to_tgsi.h" #include "d3d1xstutil.h" diff --git a/src/gallium/state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.cpp b/src/gallium/state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.cpp new file mode 100644 index 0000000000..995059e15b --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.cpp @@ -0,0 +1,832 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "sm4.h" +#include "tgsi/tgsi_ureg.h" +#include + +#if 1 +#define check(x) assert(x) +#define fail(x) assert(0 && (x)) +#else +#define check(x) do {if(!(x)) throw(#x);} while(0) +#define fail(x) throw(x) +#endif + +static unsigned sm4_to_pipe_interpolation[] = +{ + TGSI_INTERPOLATE_PERSPECTIVE, /* UNDEFINED */ + TGSI_INTERPOLATE_CONSTANT, + TGSI_INTERPOLATE_PERSPECTIVE, /* LINEAR */ + TGSI_INTERPOLATE_PERSPECTIVE, /* LINEAR_CENTROID */ + TGSI_INTERPOLATE_LINEAR, /* LINEAR_NOPERSPECTIVE */ + TGSI_INTERPOLATE_LINEAR, /* LINEAR_NOPERSPECTIVE_CENTROID */ + + // Added in D3D10.1 + TGSI_INTERPOLATE_PERSPECTIVE, /* LINEAR_SAMPLE */ + TGSI_INTERPOLATE_LINEAR, /* LINEAR_NOPERSPECTIVE_SAMPLE */ +}; + +static int sm4_to_pipe_sv[] = +{ + -1, + TGSI_SEMANTIC_POSITION, + -1, /*TGSI_SEMANTIC_CLIP_DISTANCE */ + -1, /*TGSI_SEMANTIC_CULL_DISTANCE */ + -1, /*TGSI_SEMANTIC_RENDER_TARGET_ARRAY_INDEX */ + -1, /*TGSI_SEMANTIC_VIEWPORT_ARRAY_INDEX */ + -1, /*TGSI_SEMANTIC_VERTEXID,*/ + TGSI_SEMANTIC_PRIMID, + TGSI_SEMANTIC_INSTANCEID, + TGSI_SEMANTIC_FACE, + -1, /*TGSI_SEMANTIC_SAMPLE_INDEX*/ +}; + +struct sm4_to_tgsi_converter +{ + struct ureg_program* ureg; + std::vector temps; + std::vector outputs; + std::vector inputs; + std::vector samplers; + std::vector > targets; // first is normal, second shadow/comparison + std::vector sampler_modes; // 0 = normal, 1 = shadow/comparison + std::vector > loops; + sm4_insn* insn; + struct sm4_program& program; + std::vector sm4_to_tgsi_insn_num; + std::vector > label_to_sm4_insn_num; + bool in_sub; + bool avoid_txf; + bool avoid_int; + + sm4_to_tgsi_converter(struct sm4_program& program) + : program(program) + { + avoid_txf = true; + avoid_int = false; + } + + struct ureg_dst _reg(sm4_op& op) + { + switch(op.file) + { + case SM4_FILE_NULL: + { + struct ureg_dst d; + memset(&d, 0, sizeof(d)); + d.File = TGSI_FILE_NULL; + return d; + } + case SM4_FILE_TEMP: + check(op.has_simple_index()); + check(op.indices[0].disp < temps.size()); + return temps[op.indices[0].disp]; + case SM4_FILE_OUTPUT: + check(op.has_simple_index()); + check(op.indices[0].disp < outputs.size()); + return outputs[op.indices[0].disp]; + default: + check(0); + return ureg_dst_undef(); + } + } + + struct ureg_dst _dst(unsigned i = 0) + { + check(i < insn->num_ops); + sm4_op& op = *insn->ops[i]; + check(op.mode == SM4_OPERAND_MODE_MASK || op.mode == SM4_OPERAND_MODE_SCALAR); + struct ureg_dst d = ureg_writemask(_reg(op), op.mask); + if(insn->insn.sat) + d = ureg_saturate(d); + return d; + } + + struct ureg_src _src(unsigned i) + { + check(i < insn->num_ops); + sm4_op& op = *insn->ops[i]; + struct ureg_src s; + switch(op.file) + { + case SM4_FILE_IMMEDIATE32: + s = ureg_imm4f(ureg, op.imm_values[0].f32, op.imm_values[1].f32, op.imm_values[2].f32, op.imm_values[3].f32); + break; + case SM4_FILE_INPUT: + check(op.has_simple_index()); + check(op.indices[0].disp < inputs.size()); + s = inputs[op.indices[0].disp]; + break; + case SM4_FILE_CONSTANT_BUFFER: + // TODO: indirect addressing + check(op.num_indices == 2); + check(op.is_index_simple(0)); + check(op.is_index_simple(1)); + s = ureg_src_register(TGSI_FILE_CONSTANT, (unsigned)op.indices[1].disp); + s.Dimension = 1; + s.DimensionIndex = op.indices[0].disp; + break; + default: + s = ureg_src(_reg(op)); + break; + } + if(op.mode == SM4_OPERAND_MODE_SWIZZLE || op.mode == SM4_OPERAND_MODE_SCALAR) + s = ureg_swizzle(s, op.swizzle[0], op.swizzle[1], op.swizzle[2], op.swizzle[3]); + else + { + /* immediates are masked to show needed values */ + check(op.file == SM4_FILE_IMMEDIATE32 || op.file == SM4_FILE_IMMEDIATE64); + } + if(op.abs) + s = ureg_abs(s); + if(op.neg) + s = ureg_negate(s); + return s; + }; + + int _idx(sm4_file file, unsigned i = 0) + { + check(i < insn->num_ops); + sm4_op& op = *insn->ops[i]; + check(op.file == file); + check(op.has_simple_index()); + return (int)op.indices[0].disp; + } + + int _texslot(bool have_sampler = true) + { + std::map, int>::iterator i; + i = program.resource_sampler_to_slot.find(std::make_pair(_idx(SM4_FILE_RESOURCE, 2), have_sampler ? _idx(SM4_FILE_SAMPLER, 3) : -1)); + check(i != program.resource_sampler_to_slot.end()); + return i->second; + } + + unsigned tex_target(unsigned texslot) + { + unsigned mode = sampler_modes[program.slot_to_sampler[texslot]]; + unsigned target; + if(mode) + target = targets[program.slot_to_resource[texslot]].second; + else + target = targets[program.slot_to_resource[texslot]].first; + check(target); + return target; + } + + std::vector insn_tmps; + + struct ureg_dst _tmp() + { + struct ureg_dst t = ureg_DECL_temporary(ureg); + insn_tmps.push_back(t); + return t; + } + + struct ureg_dst _tmp(struct ureg_dst d) + { + if(d.File == TGSI_FILE_TEMPORARY) + return d; + else + return ureg_writemask(_tmp(), d.WriteMask); + } + +#define OP1_(d, g) case SM4_OPCODE_##d: ureg_##g(ureg, _dst(), _src(1)); break +#define OP2_(d, g) case SM4_OPCODE_##d: ureg_##g(ureg, _dst(), _src(1), _src(2)); break +#define OP3_(d, g) case SM4_OPCODE_##d: ureg_##g(ureg, _dst(), _src(1), _src(2), _src(3)); break +#define OP1(n) OP1_(n, n) +#define OP2(n) OP2_(n, n) +#define OP3(n) OP3_(n, n) +#define OP_CF(d, g) case SM4_OPCODE_##d: ureg_##g(ureg, &label); label_to_sm4_insn_num.push_back(std::make_pair(label, program.cf_insn_linked[insn_num])); break; + + void translate_insns(unsigned begin, unsigned end) + { + for(unsigned insn_num = begin; insn_num < end; ++insn_num) + { + sm4_to_tgsi_insn_num[insn_num] = ureg_get_instruction_number(ureg); + unsigned label; + insn = program.insns[insn_num]; + bool ok; + ok = true; + switch(insn->opcode) + { + // trivial instructions + case SM4_OPCODE_NOP: + break; + OP1(MOV); + + // float + OP2(ADD); + OP2(MUL); + OP3(MAD); + OP2(DIV); + OP1(FRC); + OP1(RCP); + OP2(MIN); + OP2(MAX); + OP2_(LT, SLT); + OP2_(GE, SGE); + OP2_(EQ, SEQ); + OP2_(NE, SNE); + + // bitwise + OP1(NOT); + OP2(AND); + OP2(OR); + OP2(XOR); + + // special mathematical + OP2(DP2); + OP2(DP3); + OP2(DP4); + OP1(RSQ); + OP1_(LOG, LG2); + OP1_(EXP, EX2); + + // rounding + OP1_(ROUND_NE, ROUND); + OP1_(ROUND_Z, TRUNC); + OP1_(ROUND_PI, CEIL); + OP1_(ROUND_NI, FLR); + + // cross-thread + OP1_(DERIV_RTX, DDX); + OP1_(DERIV_RTX_COARSE, DDX); + OP1_(DERIV_RTX_FINE, DDX); + OP1_(DERIV_RTY, DDY); + OP1_(DERIV_RTY_COARSE, DDY); + OP1_(DERIV_RTY_FINE, DDY); + case SM4_OPCODE_EMIT: + ureg_EMIT(ureg); + break; + case SM4_OPCODE_CUT: + ureg_ENDPRIM(ureg); + break; + case SM4_OPCODE_EMITTHENCUT: + ureg_EMIT(ureg); + ureg_ENDPRIM(ureg); + break; + + // non-trivial instructions + case SM4_OPCODE_MOVC: + /* CMP checks for < 0, but MOVC checks for != 0 + * but fortunately, x != 0 is equivalent to -abs(x) < 0 + * XXX: can test_nz apply to this?! + */ + ureg_CMP(ureg, _dst(), ureg_negate(ureg_abs(_src(1))), _src(2), _src(3)); + break; + case SM4_OPCODE_SQRT: + { + struct ureg_dst d = _dst(); + struct ureg_dst t = _tmp(d); + ureg_RSQ(ureg, t, _src(1)); + ureg_RCP(ureg, d, ureg_src(t)); + break; + } + case SM4_OPCODE_SINCOS: + { + struct ureg_dst s = _dst(0); + struct ureg_dst c = _dst(1); + struct ureg_src v = _src(2); + if(s.File != TGSI_FILE_NULL) + ureg_SIN(ureg, s, v); + if(c.File != TGSI_FILE_NULL) + ureg_COS(ureg, c, v); + break; + } + + // control flow + case SM4_OPCODE_DISCARD: + ureg_KIL(ureg, _src(0)); + break; + OP_CF(LOOP, BGNLOOP); + OP_CF(ENDLOOP, ENDLOOP); + case SM4_OPCODE_BREAK: + ureg_BRK(ureg); + break; + case SM4_OPCODE_BREAKC: + // XXX: can test_nz apply to this?! + ureg_BREAKC(ureg, _src(0)); + break; + case SM4_OPCODE_CONTINUE: + ureg_CONT(ureg); + break; + case SM4_OPCODE_CONTINUEC: + // XXX: can test_nz apply to this?! + ureg_IF(ureg, _src(0), &label); + ureg_CONT(ureg); + ureg_fixup_label(ureg, label, ureg_get_instruction_number(ureg)); + ureg_ENDIF(ureg); + break; + case SM4_OPCODE_SWITCH: + ureg_SWITCH(ureg, _src(0)); + break; + case SM4_OPCODE_CASE: + ureg_CASE(ureg, _src(0)); + break; + case SM4_OPCODE_DEFAULT: + ureg_DEFAULT(ureg); + break; + case SM4_OPCODE_ENDSWITCH: + ureg_ENDSWITCH(ureg); + break; + case SM4_OPCODE_CALL: + ureg_CAL(ureg, &label); + label_to_sm4_insn_num.push_back(std::make_pair(label, program.label_to_insn_num[_idx(SM4_FILE_LABEL)])); + break; + case SM4_OPCODE_LABEL: + if(in_sub) + ureg_ENDSUB(ureg); + else + ureg_END(ureg); + ureg_BGNSUB(ureg); + in_sub = true; + break; + case SM4_OPCODE_RET: + if(in_sub || insn_num != (program.insns.size() - 1)) + ureg_RET(ureg); + break; + case SM4_OPCODE_RETC: + ureg_IF(ureg, _src(0), &label); + if(insn->insn.test_nz) + ureg_RET(ureg); + ureg_fixup_label(ureg, label, ureg_get_instruction_number(ureg)); + if(!insn->insn.test_nz) + { + ureg_ELSE(ureg, &label); + ureg_RET(ureg); + ureg_fixup_label(ureg, label, ureg_get_instruction_number(ureg)); + } + ureg_ENDIF(ureg); + break; + OP_CF(ELSE, ELSE); + case SM4_OPCODE_ENDIF: + ureg_ENDIF(ureg); + break; + case SM4_OPCODE_IF: + if(insn->insn.test_nz) + { + ureg_IF(ureg, _src(0), &label); + label_to_sm4_insn_num.push_back(std::make_pair(label, program.cf_insn_linked[insn_num])); + } + else + { + unsigned linked = program.cf_insn_linked[insn_num]; + if(program.insns[linked]->opcode == SM4_OPCODE_ENDIF) + { + ureg_IF(ureg, _src(0), &label); + ureg_fixup_label(ureg, label, ureg_get_instruction_number(ureg)); + ureg_ELSE(ureg, &label); + label_to_sm4_insn_num.push_back(std::make_pair(label, linked)); + } + else + { + /* we have to swap the branches in this case (fun!) + * TODO: maybe just emit a SEQ 0? + * */ + unsigned endif = program.cf_insn_linked[linked]; + + ureg_IF(ureg, _src(0), &label); + label_to_sm4_insn_num.push_back(std::make_pair(label, linked)); + + translate_insns(linked + 1, endif); + + sm4_to_tgsi_insn_num[linked] = ureg_get_instruction_number(ureg); + ureg_ELSE(ureg, &label); + label_to_sm4_insn_num.push_back(std::make_pair(label, endif)); + + translate_insns(insn_num + 1, linked); + + insn_num = endif - 1; + goto next; + } + } + break; + case SM4_OPCODE_RESINFO: + { + std::map::iterator i; + i = program.resource_to_slot.find(_idx(SM4_FILE_RESOURCE, 2)); + check(i != program.resource_to_slot.end()); + unsigned texslot = i->second; + + // no driver actually provides this, unfortunately + ureg_TXQ(ureg, _dst(), tex_target(texslot), _src(1), samplers[texslot]); + break; + }; + // TODO: sample offset, sample index + case SM4_OPCODE_LD: // dst, coord_int, res; mipmap level in last coord_int arg (ouch) + case SM4_OPCODE_LD_MS: + { + unsigned texslot = _texslot(false); + unsigned dim = 0; + switch(targets[texslot].first) + { + case TGSI_TEXTURE_1D: + dim = 1; + break; + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_RECT: + dim = 2; + break; + case TGSI_TEXTURE_3D: + dim = 3; + break; + default: + check(0); + } + struct ureg_dst tmp = _tmp(); + if(avoid_txf) + { + struct ureg_src texcoord; + if(!avoid_int) + { + ureg_I2F(ureg, tmp, _src(1)); + texcoord = ureg_src(tmp); + } + else + texcoord = _src(1); + + ureg_TXL(ureg, _dst(), tex_target(texslot), ureg_swizzle(texcoord, 0, 1, 2, dim), samplers[texslot]); + } + else + ureg_TXF(ureg, _dst(), tex_target(texslot), ureg_swizzle(_src(1), 0, 1, 2, dim), samplers[texslot]); + break; + } + case SM4_OPCODE_SAMPLE: // dst, coord, res, samp + { + unsigned texslot = _texslot(); + ureg_TEX(ureg, _dst(), tex_target(texslot), _src(1), samplers[texslot]); + break; + } + case SM4_OPCODE_SAMPLE_B: // dst, coord, res, samp, bias.x + { + unsigned texslot = _texslot(); + struct ureg_dst tmp = _tmp(); + ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), _src(1)); + ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), ureg_swizzle(_src(4), 0, 0, 0, 0)); + ureg_TXB(ureg, _dst(), tex_target(texslot), ureg_src(tmp), samplers[texslot]); + break; + } + case SM4_OPCODE_SAMPLE_C: // dst, coord, res, samp, comp.x + { + unsigned texslot = _texslot(); + struct ureg_dst tmp = _tmp(); + ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), _src(1)); + ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Z), ureg_swizzle(_src(4), 0, 0, 0, 0)); + ureg_TEX(ureg, _dst(), tex_target(texslot), ureg_src(tmp), samplers[texslot]); + break; + } + case SM4_OPCODE_SAMPLE_C_LZ: // dst, coord, res, samp, comp.x + { + unsigned texslot = _texslot(); + struct ureg_dst tmp = _tmp(); + ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), _src(1)); + ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Z), ureg_swizzle(_src(4), 0, 0, 0, 0)); + ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 0.0)); + ureg_TXL(ureg, _dst(), tex_target(texslot), ureg_src(tmp), samplers[texslot]); + break; + } + case SM4_OPCODE_SAMPLE_D: // dst, coord, res, samp, ddx, ddy + { + unsigned texslot = _texslot(); + ureg_TXD(ureg, _dst(), tex_target(texslot), _src(1), samplers[texslot], _src(4), _src(5)); + break; + } + case SM4_OPCODE_SAMPLE_L: // dst, coord, res, samp, bias.x + { + unsigned texslot = _texslot(); + struct ureg_dst tmp = _tmp(); + ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), _src(1)); + ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), ureg_swizzle(_src(4), 0, 0, 0, 0)); + ureg_TXL(ureg, _dst(), tex_target(texslot), ureg_src(tmp), samplers[texslot]); + break; + } + default: + ok = false; + break; + } + + if(!ok && !avoid_int) + { + ok = true; + switch(insn->opcode) + { + // integer + OP1_(ITOF, I2F); + OP1_(FTOI, F2I); + OP2_(IADD, UADD); + OP1(INEG); + OP2_(IMUL, UMUL); + OP3_(IMAD, UMAD); + OP2_(ISHL, SHL); + OP2_(ISHR, ISHR); + OP2(IMIN); + OP2(IMAX); + OP2_(ILT, ISLT); + OP2_(IGE, ISGE); + OP2_(IEQ, USEQ); + OP2_(INE, USNE); + + // unsigned + OP1_(UTOF, U2F); + OP1_(FTOU, F2U); + OP2(UMUL); + OP3(UMAD); + OP2(UMIN); + OP2(UMAX); + OP2_(ULT, USLT); + OP2_(UGE, USGE); + OP2(USHR); + + case SM4_OPCODE_UDIV: + { + struct ureg_dst q = _dst(0); + struct ureg_dst r = _dst(1); + struct ureg_src a = _src(2); + struct ureg_src b = _src(3); + if(q.File != TGSI_FILE_NULL) + ureg_UDIV(ureg, q, a, b); + if(r.File != TGSI_FILE_NULL) + ureg_UMOD(ureg, r, a, b); + break; + } + default: + ok = false; + } + } + + if(!ok && avoid_int) + { + ok = true; + switch(insn->opcode) + { + case SM4_OPCODE_ITOF: + case SM4_OPCODE_UTOF: + break; + OP1_(FTOI, TRUNC); + OP1_(FTOU, FLR); + // integer + OP2_(IADD, ADD); + OP2_(IMUL, MUL); + OP3_(IMAD, MAD); + OP2_(MIN, MIN); + OP2_(MAX, MAX); + OP2_(ILT, SLT); + OP2_(IGE, SGE); + OP2_(IEQ, SEQ); + OP2_(INE, SNE); + + // unsigned + OP2_(UMUL, MUL); + OP3_(UMAD, MAD); + OP2_(UMIN, MIN); + OP2_(UMAX, MAX); + OP2_(ULT, SLT); + OP2_(UGE, SGE); + + case SM4_OPCODE_INEG: + ureg_MOV(ureg, _dst(), ureg_negate(_src(1))); + break; + case SM4_OPCODE_ISHL: + { + struct ureg_dst d = _dst(); + struct ureg_dst t = _tmp(d); + ureg_EX2(ureg, t, _src(2)); + ureg_MUL(ureg, d, ureg_src(t), _src(1)); + break; + } + case SM4_OPCODE_ISHR: + case SM4_OPCODE_USHR: + { + struct ureg_dst d = _dst(); + struct ureg_dst t = _tmp(d); + ureg_EX2(ureg, t, ureg_negate(_src(2))); + ureg_MUL(ureg, t, ureg_src(t), _src(1)); + ureg_FLR(ureg, d, ureg_src(t)); + break; + } + case SM4_OPCODE_UDIV: + { + struct ureg_dst q = _dst(0); + struct ureg_dst r = _dst(1); + struct ureg_src a = _src(2); + struct ureg_src b = _src(3); + struct ureg_dst f = _tmp(); + ureg_DIV(ureg, f, a, b); + if(q.File != TGSI_FILE_NULL) + ureg_FLR(ureg, q, ureg_src(f)); + if(r.File != TGSI_FILE_NULL) + { + ureg_FRC(ureg, f, ureg_src(f)); + ureg_MUL(ureg, r, ureg_src(f), b); + } + break; + } + default: + ok = false; + } + } + + check(ok); + + if(!insn_tmps.empty()) + { + for(unsigned i = 0; i < insn_tmps.size(); ++i) + ureg_release_temporary(ureg, insn_tmps[i]); + insn_tmps.clear(); + } +next:; + } + } + + void* do_translate() + { + unsigned processor; + switch(program.version.type) + { + case 0: + processor = TGSI_PROCESSOR_FRAGMENT; + break; + case 1: + processor = TGSI_PROCESSOR_VERTEX; + break; + case 2: + processor = TGSI_PROCESSOR_GEOMETRY; + break; + default: + fail("Tessellation and compute shaders not yet supported"); + return 0; + } + + if(!sm4_link_cf_insns(program)) + fail("Malformed control flow"); + if(!sm4_find_labels(program)) + fail("Failed to locate labels"); + if(!sm4_allocate_resource_sampler_pairs(program)) + fail("Unsupported (indirect?) accesses to resources and/or samplers"); + + ureg = ureg_create(processor); + + in_sub = false; + + for(unsigned i = 0; i < program.slot_to_resource.size(); ++i) + samplers.push_back(ureg_DECL_sampler(ureg, i)); + + sm4_to_tgsi_insn_num.resize(program.insns.size()); + for(unsigned insn_num = 0; insn_num < program.dcls.size(); ++insn_num) + { + sm4_dcl& dcl = *program.dcls[insn_num]; + int idx = -1; + if(dcl.op.get() && dcl.op->has_simple_index()) + idx = dcl.op->indices[0].disp; + switch(dcl.opcode) + { + case SM4_OPCODE_DCL_GLOBAL_FLAGS: + break; + case SM4_OPCODE_DCL_TEMPS: + for(unsigned i = 0; i < dcl.num; ++i) + temps.push_back(ureg_DECL_temporary(ureg)); + break; + case SM4_OPCODE_DCL_INPUT: + check(idx >= 0); + if(inputs.size() <= (unsigned)idx) + inputs.resize(idx + 1); + if(processor == TGSI_PROCESSOR_VERTEX) + inputs[idx] = ureg_DECL_vs_input(ureg, idx); + else + check(0); + break; + case SM4_OPCODE_DCL_INPUT_PS: + check(idx >= 0); + if(inputs.size() <= (unsigned)idx) + inputs.resize(idx + 1); + inputs[idx] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, idx, sm4_to_pipe_interpolation[dcl.dcl_input_ps.interpolation]); + break; + case SM4_OPCODE_DCL_OUTPUT: + check(idx >= 0); + if(outputs.size() <= (unsigned)idx) + outputs.resize(idx + 1); + if(processor == TGSI_PROCESSOR_FRAGMENT) + outputs[idx] = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, idx); + else + outputs[idx] = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, idx); + break; + case SM4_OPCODE_DCL_INPUT_SIV: + case SM4_OPCODE_DCL_INPUT_SGV: + case SM4_OPCODE_DCL_INPUT_PS_SIV: + case SM4_OPCODE_DCL_INPUT_PS_SGV: + check(idx >= 0); + if(inputs.size() <= (unsigned)idx) + inputs.resize(idx + 1); + // TODO: is this correct? + inputs[idx] = ureg_DECL_system_value(ureg, idx, sm4_to_pipe_sv[dcl.sv], 0); + break; + case SM4_OPCODE_DCL_OUTPUT_SIV: + case SM4_OPCODE_DCL_OUTPUT_SGV: + check(idx >= 0); + if(outputs.size() <= (unsigned)idx) + outputs.resize(idx + 1); + check(sm4_to_pipe_sv[dcl.sv] >= 0); + outputs[idx] = ureg_DECL_output(ureg, sm4_to_pipe_sv[dcl.sv], 0); + break; + case SM4_OPCODE_DCL_RESOURCE: + check(idx >= 0); + if(targets.size() <= (unsigned)idx) + targets.resize(idx + 1); + switch(dcl.dcl_resource.target) + { + case SM4_TARGET_TEXTURE1D: + targets[idx].first = TGSI_TEXTURE_1D; + targets[idx].second = TGSI_TEXTURE_SHADOW1D; + break; + case SM4_TARGET_TEXTURE2D: + targets[idx].first = TGSI_TEXTURE_2D; + targets[idx].second = TGSI_TEXTURE_SHADOW2D; + break; + case SM4_TARGET_TEXTURE3D: + targets[idx].first = TGSI_TEXTURE_3D; + targets[idx].second = 0; + break; + case SM4_TARGET_TEXTURECUBE: + targets[idx].first = TGSI_TEXTURE_CUBE; + targets[idx].second = 0; + break; + default: + check(0); + } + break; + case SM4_OPCODE_DCL_SAMPLER: + check(idx >= 0); + if(sampler_modes.size() <= (unsigned)idx) + sampler_modes.resize(idx + 1); + check(!dcl.dcl_sampler.mono); + sampler_modes[idx] = dcl.dcl_sampler.shadow; + break; + case SM4_OPCODE_DCL_CONSTANT_BUFFER: + check(dcl.op->num_indices == 2); + check(dcl.op->is_index_simple(0)); + check(dcl.op->is_index_simple(1)); + idx = dcl.op->indices[0].disp; + ureg_DECL_constant2D(ureg, 0, (unsigned)dcl.op->indices[1].disp - 1, idx); + break; + default: + check(0); + } + } + + translate_insns(0, program.insns.size()); + sm4_to_tgsi_insn_num.push_back(ureg_get_instruction_number(ureg)); + if(in_sub) + ureg_ENDSUB(ureg); + else + ureg_END(ureg); + + for(unsigned i = 0; i < label_to_sm4_insn_num.size(); ++i) + ureg_fixup_label(ureg, label_to_sm4_insn_num[i].first, sm4_to_tgsi_insn_num[label_to_sm4_insn_num[i].second]); + + const struct tgsi_token * tokens = ureg_get_tokens(ureg, 0); + ureg_destroy(ureg); + return (void*)tokens; + } + + void* translate() + { + try + { + return do_translate(); + } + catch(const char*) + { + return 0; + } + } +}; + +void* sm4_to_tgsi(struct sm4_program& program) +{ + sm4_to_tgsi_converter conv(program); + return conv.translate(); +} diff --git a/src/gallium/state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.h b/src/gallium/state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.h new file mode 100644 index 0000000000..5722b277fb --- /dev/null +++ b/src/gallium/state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.h @@ -0,0 +1,34 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef SM4_TO_TGSI_H_ +#define SM4_TO_TGSI_H_ + +#include "sm4.h" + +void* sm4_to_tgsi(struct sm4_program& program); + +#endif /* SM4_TO_TGSI_H_ */ diff --git a/src/gallium/state_trackers/d3d1x/gd3d1x/tools/dxbc2tgsi.cpp b/src/gallium/state_trackers/d3d1x/gd3d1x/tools/dxbc2tgsi.cpp index 2e5062f2ca..d210f8acad 100644 --- a/src/gallium/state_trackers/d3d1x/gd3d1x/tools/dxbc2tgsi.cpp +++ b/src/gallium/state_trackers/d3d1x/gd3d1x/tools/dxbc2tgsi.cpp @@ -25,8 +25,8 @@ **************************************************************************/ #include "dxbc.h" -#include "tpf.h" -#include "../tpf_to_tgsi.h" +#include "sm4.h" +#include "../sm4_to_tgsi.h" #include "tgsi/tgsi_dump.h" #include #include @@ -62,16 +62,16 @@ int main(int argc, char** argv) if(dxbc) { std::cout << *dxbc; - dxbc_chunk_header* tpf_chunk = dxbc_find_shader_bytecode(&data[0], data.size()); - if(tpf_chunk) + dxbc_chunk_header* sm4_chunk = dxbc_find_shader_bytecode(&data[0], data.size()); + if(sm4_chunk) { - tpf_program* tpf = tpf_parse(tpf_chunk + 1, bswap_le32(tpf_chunk->size)); - if(tpf) + sm4_program* sm4 = sm4_parse(sm4_chunk + 1, bswap_le32(sm4_chunk->size)); + if(sm4) { - const struct tgsi_token* tokens = (const struct tgsi_token*)tpf_to_tgsi(*tpf); + const struct tgsi_token* tokens = (const struct tgsi_token*)sm4_to_tgsi(*sm4); if(tokens) { - std::cout << *tpf; + std::cout << *sm4; std::cout << "\n# TGSI program: " << std::endl; tgsi_dump(tokens, 0); } diff --git a/src/gallium/state_trackers/d3d1x/gd3d1x/tpf_to_tgsi.cpp b/src/gallium/state_trackers/d3d1x/gd3d1x/tpf_to_tgsi.cpp deleted file mode 100644 index 4d7c296bb6..0000000000 --- a/src/gallium/state_trackers/d3d1x/gd3d1x/tpf_to_tgsi.cpp +++ /dev/null @@ -1,832 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Luca Barbieri - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "tpf.h" -#include "tgsi/tgsi_ureg.h" -#include - -#if 1 -#define check(x) assert(x) -#define fail(x) assert(0 && (x)) -#else -#define check(x) do {if(!(x)) throw(#x);} while(0) -#define fail(x) throw(x) -#endif - -static unsigned tpf_to_pipe_interpolation[] = -{ - TGSI_INTERPOLATE_PERSPECTIVE, /* UNDEFINED */ - TGSI_INTERPOLATE_CONSTANT, - TGSI_INTERPOLATE_PERSPECTIVE, /* LINEAR */ - TGSI_INTERPOLATE_PERSPECTIVE, /* LINEAR_CENTROID */ - TGSI_INTERPOLATE_LINEAR, /* LINEAR_NOPERSPECTIVE */ - TGSI_INTERPOLATE_LINEAR, /* LINEAR_NOPERSPECTIVE_CENTROID */ - - // Added in D3D10.1 - TGSI_INTERPOLATE_PERSPECTIVE, /* LINEAR_SAMPLE */ - TGSI_INTERPOLATE_LINEAR, /* LINEAR_NOPERSPECTIVE_SAMPLE */ -}; - -static int tpf_to_pipe_sv[] = -{ - -1, - TGSI_SEMANTIC_POSITION, - -1, /*TGSI_SEMANTIC_CLIP_DISTANCE */ - -1, /*TGSI_SEMANTIC_CULL_DISTANCE */ - -1, /*TGSI_SEMANTIC_RENDER_TARGET_ARRAY_INDEX */ - -1, /*TGSI_SEMANTIC_VIEWPORT_ARRAY_INDEX */ - -1, /*TGSI_SEMANTIC_VERTEXID,*/ - TGSI_SEMANTIC_PRIMID, - TGSI_SEMANTIC_INSTANCEID, - TGSI_SEMANTIC_FACE, - -1, /*TGSI_SEMANTIC_SAMPLE_INDEX*/ -}; - -struct tpf_to_tgsi_converter -{ - struct ureg_program* ureg; - std::vector temps; - std::vector outputs; - std::vector inputs; - std::vector samplers; - std::vector > targets; // first is normal, second shadow/comparison - std::vector sampler_modes; // 0 = normal, 1 = shadow/comparison - std::vector > loops; - tpf_insn* insn; - struct tpf_program& program; - std::vector tpf_to_tgsi_insn_num; - std::vector > label_to_tpf_insn_num; - bool in_sub; - bool avoid_txf; - bool avoid_int; - - tpf_to_tgsi_converter(struct tpf_program& program) - : program(program) - { - avoid_txf = true; - avoid_int = false; - } - - struct ureg_dst _reg(tpf_op& op) - { - switch(op.file) - { - case TPF_FILE_NULL: - { - struct ureg_dst d; - memset(&d, 0, sizeof(d)); - d.File = TGSI_FILE_NULL; - return d; - } - case TPF_FILE_TEMP: - check(op.has_simple_index()); - check(op.indices[0].disp < temps.size()); - return temps[op.indices[0].disp]; - case TPF_FILE_OUTPUT: - check(op.has_simple_index()); - check(op.indices[0].disp < outputs.size()); - return outputs[op.indices[0].disp]; - default: - check(0); - return ureg_dst_undef(); - } - } - - struct ureg_dst _dst(unsigned i = 0) - { - check(i < insn->num_ops); - tpf_op& op = *insn->ops[i]; - check(op.mode == TPF_OPERAND_MODE_MASK || op.mode == TPF_OPERAND_MODE_SCALAR); - struct ureg_dst d = ureg_writemask(_reg(op), op.mask); - if(insn->insn.sat) - d = ureg_saturate(d); - return d; - } - - struct ureg_src _src(unsigned i) - { - check(i < insn->num_ops); - tpf_op& op = *insn->ops[i]; - struct ureg_src s; - switch(op.file) - { - case TPF_FILE_IMMEDIATE32: - s = ureg_imm4f(ureg, op.imm_values[0].f32, op.imm_values[1].f32, op.imm_values[2].f32, op.imm_values[3].f32); - break; - case TPF_FILE_INPUT: - check(op.has_simple_index()); - check(op.indices[0].disp < inputs.size()); - s = inputs[op.indices[0].disp]; - break; - case TPF_FILE_CONSTANT_BUFFER: - // TODO: indirect addressing - check(op.num_indices == 2); - check(op.is_index_simple(0)); - check(op.is_index_simple(1)); - s = ureg_src_register(TGSI_FILE_CONSTANT, (unsigned)op.indices[1].disp); - s.Dimension = 1; - s.DimensionIndex = op.indices[0].disp; - break; - default: - s = ureg_src(_reg(op)); - break; - } - if(op.mode == TPF_OPERAND_MODE_SWIZZLE || op.mode == TPF_OPERAND_MODE_SCALAR) - s = ureg_swizzle(s, op.swizzle[0], op.swizzle[1], op.swizzle[2], op.swizzle[3]); - else - { - /* immediates are masked to show needed values */ - check(op.file == TPF_FILE_IMMEDIATE32 || op.file == TPF_FILE_IMMEDIATE64); - } - if(op.abs) - s = ureg_abs(s); - if(op.neg) - s = ureg_negate(s); - return s; - }; - - int _idx(tpf_file file, unsigned i = 0) - { - check(i < insn->num_ops); - tpf_op& op = *insn->ops[i]; - check(op.file == file); - check(op.has_simple_index()); - return (int)op.indices[0].disp; - } - - int _texslot(bool have_sampler = true) - { - std::map, int>::iterator i; - i = program.resource_sampler_to_slot.find(std::make_pair(_idx(TPF_FILE_RESOURCE, 2), have_sampler ? _idx(TPF_FILE_SAMPLER, 3) : -1)); - check(i != program.resource_sampler_to_slot.end()); - return i->second; - } - - unsigned tex_target(unsigned texslot) - { - unsigned mode = sampler_modes[program.slot_to_sampler[texslot]]; - unsigned target; - if(mode) - target = targets[program.slot_to_resource[texslot]].second; - else - target = targets[program.slot_to_resource[texslot]].first; - check(target); - return target; - } - - std::vector insn_tmps; - - struct ureg_dst _tmp() - { - struct ureg_dst t = ureg_DECL_temporary(ureg); - insn_tmps.push_back(t); - return t; - } - - struct ureg_dst _tmp(struct ureg_dst d) - { - if(d.File == TGSI_FILE_TEMPORARY) - return d; - else - return ureg_writemask(_tmp(), d.WriteMask); - } - -#define OP1_(d, g) case TPF_OPCODE_##d: ureg_##g(ureg, _dst(), _src(1)); break -#define OP2_(d, g) case TPF_OPCODE_##d: ureg_##g(ureg, _dst(), _src(1), _src(2)); break -#define OP3_(d, g) case TPF_OPCODE_##d: ureg_##g(ureg, _dst(), _src(1), _src(2), _src(3)); break -#define OP1(n) OP1_(n, n) -#define OP2(n) OP2_(n, n) -#define OP3(n) OP3_(n, n) -#define OP_CF(d, g) case TPF_OPCODE_##d: ureg_##g(ureg, &label); label_to_tpf_insn_num.push_back(std::make_pair(label, program.cf_insn_linked[insn_num])); break; - - void translate_insns(unsigned begin, unsigned end) - { - for(unsigned insn_num = begin; insn_num < end; ++insn_num) - { - tpf_to_tgsi_insn_num[insn_num] = ureg_get_instruction_number(ureg); - unsigned label; - insn = program.insns[insn_num]; - bool ok; - ok = true; - switch(insn->opcode) - { - // trivial instructions - case TPF_OPCODE_NOP: - break; - OP1(MOV); - - // float - OP2(ADD); - OP2(MUL); - OP3(MAD); - OP2(DIV); - OP1(FRC); - OP1(RCP); - OP2(MIN); - OP2(MAX); - OP2_(LT, SLT); - OP2_(GE, SGE); - OP2_(EQ, SEQ); - OP2_(NE, SNE); - - // bitwise - OP1(NOT); - OP2(AND); - OP2(OR); - OP2(XOR); - - // special mathematical - OP2(DP2); - OP2(DP3); - OP2(DP4); - OP1(RSQ); - OP1_(LOG, LG2); - OP1_(EXP, EX2); - - // rounding - OP1_(ROUND_NE, ROUND); - OP1_(ROUND_Z, TRUNC); - OP1_(ROUND_PI, CEIL); - OP1_(ROUND_NI, FLR); - - // cross-thread - OP1_(DERIV_RTX, DDX); - OP1_(DERIV_RTX_COARSE, DDX); - OP1_(DERIV_RTX_FINE, DDX); - OP1_(DERIV_RTY, DDY); - OP1_(DERIV_RTY_COARSE, DDY); - OP1_(DERIV_RTY_FINE, DDY); - case TPF_OPCODE_EMIT: - ureg_EMIT(ureg); - break; - case TPF_OPCODE_CUT: - ureg_ENDPRIM(ureg); - break; - case TPF_OPCODE_EMITTHENCUT: - ureg_EMIT(ureg); - ureg_ENDPRIM(ureg); - break; - - // non-trivial instructions - case TPF_OPCODE_MOVC: - /* CMP checks for < 0, but MOVC checks for != 0 - * but fortunately, x != 0 is equivalent to -abs(x) < 0 - * XXX: can test_nz apply to this?! - */ - ureg_CMP(ureg, _dst(), ureg_negate(ureg_abs(_src(1))), _src(2), _src(3)); - break; - case TPF_OPCODE_SQRT: - { - struct ureg_dst d = _dst(); - struct ureg_dst t = _tmp(d); - ureg_RSQ(ureg, t, _src(1)); - ureg_RCP(ureg, d, ureg_src(t)); - break; - } - case TPF_OPCODE_SINCOS: - { - struct ureg_dst s = _dst(0); - struct ureg_dst c = _dst(1); - struct ureg_src v = _src(2); - if(s.File != TGSI_FILE_NULL) - ureg_SIN(ureg, s, v); - if(c.File != TGSI_FILE_NULL) - ureg_COS(ureg, c, v); - break; - } - - // control flow - case TPF_OPCODE_DISCARD: - ureg_KIL(ureg, _src(0)); - break; - OP_CF(LOOP, BGNLOOP); - OP_CF(ENDLOOP, ENDLOOP); - case TPF_OPCODE_BREAK: - ureg_BRK(ureg); - break; - case TPF_OPCODE_BREAKC: - // XXX: can test_nz apply to this?! - ureg_BREAKC(ureg, _src(0)); - break; - case TPF_OPCODE_CONTINUE: - ureg_CONT(ureg); - break; - case TPF_OPCODE_CONTINUEC: - // XXX: can test_nz apply to this?! - ureg_IF(ureg, _src(0), &label); - ureg_CONT(ureg); - ureg_fixup_label(ureg, label, ureg_get_instruction_number(ureg)); - ureg_ENDIF(ureg); - break; - case TPF_OPCODE_SWITCH: - ureg_SWITCH(ureg, _src(0)); - break; - case TPF_OPCODE_CASE: - ureg_CASE(ureg, _src(0)); - break; - case TPF_OPCODE_DEFAULT: - ureg_DEFAULT(ureg); - break; - case TPF_OPCODE_ENDSWITCH: - ureg_ENDSWITCH(ureg); - break; - case TPF_OPCODE_CALL: - ureg_CAL(ureg, &label); - label_to_tpf_insn_num.push_back(std::make_pair(label, program.label_to_insn_num[_idx(TPF_FILE_LABEL)])); - break; - case TPF_OPCODE_LABEL: - if(in_sub) - ureg_ENDSUB(ureg); - else - ureg_END(ureg); - ureg_BGNSUB(ureg); - in_sub = true; - break; - case TPF_OPCODE_RET: - if(in_sub || insn_num != (program.insns.size() - 1)) - ureg_RET(ureg); - break; - case TPF_OPCODE_RETC: - ureg_IF(ureg, _src(0), &label); - if(insn->insn.test_nz) - ureg_RET(ureg); - ureg_fixup_label(ureg, label, ureg_get_instruction_number(ureg)); - if(!insn->insn.test_nz) - { - ureg_ELSE(ureg, &label); - ureg_RET(ureg); - ureg_fixup_label(ureg, label, ureg_get_instruction_number(ureg)); - } - ureg_ENDIF(ureg); - break; - OP_CF(ELSE, ELSE); - case TPF_OPCODE_ENDIF: - ureg_ENDIF(ureg); - break; - case TPF_OPCODE_IF: - if(insn->insn.test_nz) - { - ureg_IF(ureg, _src(0), &label); - label_to_tpf_insn_num.push_back(std::make_pair(label, program.cf_insn_linked[insn_num])); - } - else - { - unsigned linked = program.cf_insn_linked[insn_num]; - if(program.insns[linked]->opcode == TPF_OPCODE_ENDIF) - { - ureg_IF(ureg, _src(0), &label); - ureg_fixup_label(ureg, label, ureg_get_instruction_number(ureg)); - ureg_ELSE(ureg, &label); - label_to_tpf_insn_num.push_back(std::make_pair(label, linked)); - } - else - { - /* we have to swap the branches in this case (fun!) - * TODO: maybe just emit a SEQ 0? - * */ - unsigned endif = program.cf_insn_linked[linked]; - - ureg_IF(ureg, _src(0), &label); - label_to_tpf_insn_num.push_back(std::make_pair(label, linked)); - - translate_insns(linked + 1, endif); - - tpf_to_tgsi_insn_num[linked] = ureg_get_instruction_number(ureg); - ureg_ELSE(ureg, &label); - label_to_tpf_insn_num.push_back(std::make_pair(label, endif)); - - translate_insns(insn_num + 1, linked); - - insn_num = endif - 1; - goto next; - } - } - break; - case TPF_OPCODE_RESINFO: - { - std::map::iterator i; - i = program.resource_to_slot.find(_idx(TPF_FILE_RESOURCE, 2)); - check(i != program.resource_to_slot.end()); - unsigned texslot = i->second; - - // no driver actually provides this, unfortunately - ureg_TXQ(ureg, _dst(), tex_target(texslot), _src(1), samplers[texslot]); - break; - }; - // TODO: sample offset, sample index - case TPF_OPCODE_LD: // dst, coord_int, res; mipmap level in last coord_int arg (ouch) - case TPF_OPCODE_LD_MS: - { - unsigned texslot = _texslot(false); - unsigned dim = 0; - switch(targets[texslot].first) - { - case TGSI_TEXTURE_1D: - dim = 1; - break; - case TGSI_TEXTURE_2D: - case TGSI_TEXTURE_RECT: - dim = 2; - break; - case TGSI_TEXTURE_3D: - dim = 3; - break; - default: - check(0); - } - struct ureg_dst tmp = _tmp(); - if(avoid_txf) - { - struct ureg_src texcoord; - if(!avoid_int) - { - ureg_I2F(ureg, tmp, _src(1)); - texcoord = ureg_src(tmp); - } - else - texcoord = _src(1); - - ureg_TXL(ureg, _dst(), tex_target(texslot), ureg_swizzle(texcoord, 0, 1, 2, dim), samplers[texslot]); - } - else - ureg_TXF(ureg, _dst(), tex_target(texslot), ureg_swizzle(_src(1), 0, 1, 2, dim), samplers[texslot]); - break; - } - case TPF_OPCODE_SAMPLE: // dst, coord, res, samp - { - unsigned texslot = _texslot(); - ureg_TEX(ureg, _dst(), tex_target(texslot), _src(1), samplers[texslot]); - break; - } - case TPF_OPCODE_SAMPLE_B: // dst, coord, res, samp, bias.x - { - unsigned texslot = _texslot(); - struct ureg_dst tmp = _tmp(); - ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), _src(1)); - ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), ureg_swizzle(_src(4), 0, 0, 0, 0)); - ureg_TXB(ureg, _dst(), tex_target(texslot), ureg_src(tmp), samplers[texslot]); - break; - } - case TPF_OPCODE_SAMPLE_C: // dst, coord, res, samp, comp.x - { - unsigned texslot = _texslot(); - struct ureg_dst tmp = _tmp(); - ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), _src(1)); - ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Z), ureg_swizzle(_src(4), 0, 0, 0, 0)); - ureg_TEX(ureg, _dst(), tex_target(texslot), ureg_src(tmp), samplers[texslot]); - break; - } - case TPF_OPCODE_SAMPLE_C_LZ: // dst, coord, res, samp, comp.x - { - unsigned texslot = _texslot(); - struct ureg_dst tmp = _tmp(); - ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), _src(1)); - ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Z), ureg_swizzle(_src(4), 0, 0, 0, 0)); - ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 0.0)); - ureg_TXL(ureg, _dst(), tex_target(texslot), ureg_src(tmp), samplers[texslot]); - break; - } - case TPF_OPCODE_SAMPLE_D: // dst, coord, res, samp, ddx, ddy - { - unsigned texslot = _texslot(); - ureg_TXD(ureg, _dst(), tex_target(texslot), _src(1), samplers[texslot], _src(4), _src(5)); - break; - } - case TPF_OPCODE_SAMPLE_L: // dst, coord, res, samp, bias.x - { - unsigned texslot = _texslot(); - struct ureg_dst tmp = _tmp(); - ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), _src(1)); - ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), ureg_swizzle(_src(4), 0, 0, 0, 0)); - ureg_TXL(ureg, _dst(), tex_target(texslot), ureg_src(tmp), samplers[texslot]); - break; - } - default: - ok = false; - break; - } - - if(!ok && !avoid_int) - { - ok = true; - switch(insn->opcode) - { - // integer - OP1_(ITOF, I2F); - OP1_(FTOI, F2I); - OP2_(IADD, UADD); - OP1(INEG); - OP2_(IMUL, UMUL); - OP3_(IMAD, UMAD); - OP2_(ISHL, SHL); - OP2_(ISHR, ISHR); - OP2(IMIN); - OP2(IMAX); - OP2_(ILT, ISLT); - OP2_(IGE, ISGE); - OP2_(IEQ, USEQ); - OP2_(INE, USNE); - - // unsigned - OP1_(UTOF, U2F); - OP1_(FTOU, F2U); - OP2(UMUL); - OP3(UMAD); - OP2(UMIN); - OP2(UMAX); - OP2_(ULT, USLT); - OP2_(UGE, USGE); - OP2(USHR); - - case TPF_OPCODE_UDIV: - { - struct ureg_dst q = _dst(0); - struct ureg_dst r = _dst(1); - struct ureg_src a = _src(2); - struct ureg_src b = _src(3); - if(q.File != TGSI_FILE_NULL) - ureg_UDIV(ureg, q, a, b); - if(r.File != TGSI_FILE_NULL) - ureg_UMOD(ureg, r, a, b); - break; - } - default: - ok = false; - } - } - - if(!ok && avoid_int) - { - ok = true; - switch(insn->opcode) - { - case TPF_OPCODE_ITOF: - case TPF_OPCODE_UTOF: - break; - OP1_(FTOI, TRUNC); - OP1_(FTOU, FLR); - // integer - OP2_(IADD, ADD); - OP2_(IMUL, MUL); - OP3_(IMAD, MAD); - OP2_(MIN, MIN); - OP2_(MAX, MAX); - OP2_(ILT, SLT); - OP2_(IGE, SGE); - OP2_(IEQ, SEQ); - OP2_(INE, SNE); - - // unsigned - OP2_(UMUL, MUL); - OP3_(UMAD, MAD); - OP2_(UMIN, MIN); - OP2_(UMAX, MAX); - OP2_(ULT, SLT); - OP2_(UGE, SGE); - - case TPF_OPCODE_INEG: - ureg_MOV(ureg, _dst(), ureg_negate(_src(1))); - break; - case TPF_OPCODE_ISHL: - { - struct ureg_dst d = _dst(); - struct ureg_dst t = _tmp(d); - ureg_EX2(ureg, t, _src(2)); - ureg_MUL(ureg, d, ureg_src(t), _src(1)); - break; - } - case TPF_OPCODE_ISHR: - case TPF_OPCODE_USHR: - { - struct ureg_dst d = _dst(); - struct ureg_dst t = _tmp(d); - ureg_EX2(ureg, t, ureg_negate(_src(2))); - ureg_MUL(ureg, t, ureg_src(t), _src(1)); - ureg_FLR(ureg, d, ureg_src(t)); - break; - } - case TPF_OPCODE_UDIV: - { - struct ureg_dst q = _dst(0); - struct ureg_dst r = _dst(1); - struct ureg_src a = _src(2); - struct ureg_src b = _src(3); - struct ureg_dst f = _tmp(); - ureg_DIV(ureg, f, a, b); - if(q.File != TGSI_FILE_NULL) - ureg_FLR(ureg, q, ureg_src(f)); - if(r.File != TGSI_FILE_NULL) - { - ureg_FRC(ureg, f, ureg_src(f)); - ureg_MUL(ureg, r, ureg_src(f), b); - } - break; - } - default: - ok = false; - } - } - - check(ok); - - if(!insn_tmps.empty()) - { - for(unsigned i = 0; i < insn_tmps.size(); ++i) - ureg_release_temporary(ureg, insn_tmps[i]); - insn_tmps.clear(); - } -next:; - } - } - - void* do_translate() - { - unsigned processor; - switch(program.version.type) - { - case 0: - processor = TGSI_PROCESSOR_FRAGMENT; - break; - case 1: - processor = TGSI_PROCESSOR_VERTEX; - break; - case 2: - processor = TGSI_PROCESSOR_GEOMETRY; - break; - default: - fail("Tessellation and compute shaders not yet supported"); - return 0; - } - - if(!tpf_link_cf_insns(program)) - fail("Malformed control flow"); - if(!tpf_find_labels(program)) - fail("Failed to locate labels"); - if(!tpf_allocate_resource_sampler_pairs(program)) - fail("Unsupported (indirect?) accesses to resources and/or samplers"); - - ureg = ureg_create(processor); - - in_sub = false; - - for(unsigned i = 0; i < program.slot_to_resource.size(); ++i) - samplers.push_back(ureg_DECL_sampler(ureg, i)); - - tpf_to_tgsi_insn_num.resize(program.insns.size()); - for(unsigned insn_num = 0; insn_num < program.dcls.size(); ++insn_num) - { - tpf_dcl& dcl = *program.dcls[insn_num]; - int idx = -1; - if(dcl.op.get() && dcl.op->has_simple_index()) - idx = dcl.op->indices[0].disp; - switch(dcl.opcode) - { - case TPF_OPCODE_DCL_GLOBAL_FLAGS: - break; - case TPF_OPCODE_DCL_TEMPS: - for(unsigned i = 0; i < dcl.num; ++i) - temps.push_back(ureg_DECL_temporary(ureg)); - break; - case TPF_OPCODE_DCL_INPUT: - check(idx >= 0); - if(inputs.size() <= (unsigned)idx) - inputs.resize(idx + 1); - if(processor == TGSI_PROCESSOR_VERTEX) - inputs[idx] = ureg_DECL_vs_input(ureg, idx); - else - check(0); - break; - case TPF_OPCODE_DCL_INPUT_PS: - check(idx >= 0); - if(inputs.size() <= (unsigned)idx) - inputs.resize(idx + 1); - inputs[idx] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, idx, tpf_to_pipe_interpolation[dcl.dcl_input_ps.interpolation]); - break; - case TPF_OPCODE_DCL_OUTPUT: - check(idx >= 0); - if(outputs.size() <= (unsigned)idx) - outputs.resize(idx + 1); - if(processor == TGSI_PROCESSOR_FRAGMENT) - outputs[idx] = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, idx); - else - outputs[idx] = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, idx); - break; - case TPF_OPCODE_DCL_INPUT_SIV: - case TPF_OPCODE_DCL_INPUT_SGV: - case TPF_OPCODE_DCL_INPUT_PS_SIV: - case TPF_OPCODE_DCL_INPUT_PS_SGV: - check(idx >= 0); - if(inputs.size() <= (unsigned)idx) - inputs.resize(idx + 1); - // TODO: is this correct? - inputs[idx] = ureg_DECL_system_value(ureg, idx, tpf_to_pipe_sv[dcl.sv], 0); - break; - case TPF_OPCODE_DCL_OUTPUT_SIV: - case TPF_OPCODE_DCL_OUTPUT_SGV: - check(idx >= 0); - if(outputs.size() <= (unsigned)idx) - outputs.resize(idx + 1); - check(tpf_to_pipe_sv[dcl.sv] >= 0); - outputs[idx] = ureg_DECL_output(ureg, tpf_to_pipe_sv[dcl.sv], 0); - break; - case TPF_OPCODE_DCL_RESOURCE: - check(idx >= 0); - if(targets.size() <= (unsigned)idx) - targets.resize(idx + 1); - switch(dcl.dcl_resource.target) - { - case TPF_TARGET_TEXTURE1D: - targets[idx].first = TGSI_TEXTURE_1D; - targets[idx].second = TGSI_TEXTURE_SHADOW1D; - break; - case TPF_TARGET_TEXTURE2D: - targets[idx].first = TGSI_TEXTURE_2D; - targets[idx].second = TGSI_TEXTURE_SHADOW2D; - break; - case TPF_TARGET_TEXTURE3D: - targets[idx].first = TGSI_TEXTURE_3D; - targets[idx].second = 0; - break; - case TPF_TARGET_TEXTURECUBE: - targets[idx].first = TGSI_TEXTURE_CUBE; - targets[idx].second = 0; - break; - default: - check(0); - } - break; - case TPF_OPCODE_DCL_SAMPLER: - check(idx >= 0); - if(sampler_modes.size() <= (unsigned)idx) - sampler_modes.resize(idx + 1); - check(!dcl.dcl_sampler.mono); - sampler_modes[idx] = dcl.dcl_sampler.shadow; - break; - case TPF_OPCODE_DCL_CONSTANT_BUFFER: - check(dcl.op->num_indices == 2); - check(dcl.op->is_index_simple(0)); - check(dcl.op->is_index_simple(1)); - idx = dcl.op->indices[0].disp; - ureg_DECL_constant2D(ureg, 0, (unsigned)dcl.op->indices[1].disp - 1, idx); - break; - default: - check(0); - } - } - - translate_insns(0, program.insns.size()); - tpf_to_tgsi_insn_num.push_back(ureg_get_instruction_number(ureg)); - if(in_sub) - ureg_ENDSUB(ureg); - else - ureg_END(ureg); - - for(unsigned i = 0; i < label_to_tpf_insn_num.size(); ++i) - ureg_fixup_label(ureg, label_to_tpf_insn_num[i].first, tpf_to_tgsi_insn_num[label_to_tpf_insn_num[i].second]); - - const struct tgsi_token * tokens = ureg_get_tokens(ureg, 0); - ureg_destroy(ureg); - return (void*)tokens; - } - - void* translate() - { - try - { - return do_translate(); - } - catch(const char*) - { - return 0; - } - } -}; - -void* tpf_to_tgsi(struct tpf_program& program) -{ - tpf_to_tgsi_converter conv(program); - return conv.translate(); -} diff --git a/src/gallium/state_trackers/d3d1x/gd3d1x/tpf_to_tgsi.h b/src/gallium/state_trackers/d3d1x/gd3d1x/tpf_to_tgsi.h deleted file mode 100644 index 68a30d2d2e..0000000000 --- a/src/gallium/state_trackers/d3d1x/gd3d1x/tpf_to_tgsi.h +++ /dev/null @@ -1,34 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Luca Barbieri - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef TPF_TO_TGSI_H_ -#define TPF_TO_TGSI_H_ - -#include "tpf.h" - -void* tpf_to_tgsi(struct tpf_program& program); - -#endif /* TPF_TO_TGSI_H_ */ -- cgit v1.2.3