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 $^ > $@
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
#!/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\"",
--- /dev/null
+/**************************************************************************
+ *
+ * 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 <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <memory>
+#include <vector>
+#include <map>
+#include <iostream>
+#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<sm4_op> 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<sm4_op> 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<sm4_op> 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<sm4_dcl*> dcls;
+ std::vector<sm4_insn*> 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<int> 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<int> slot_to_resource;
+ std::vector<int> slot_to_sampler;
+ std::map<std::pair<int, int>, int> resource_sampler_to_slot;
+ std::map<int, int> resource_to_slot;
+
+ bool labels_found;
+ std::vector<int> label_to_insn_num;
+
+ sm4_program()
+ {
+ memset(&version, 0, sizeof(version));
+ labels_found = false;
+ resource_sampler_slots_assigned = false;
+ }
+
+ ~sm4_program()
+ {
+ for(std::vector<sm4_dcl*>::iterator i = dcls.begin(), e = dcls.end(); i != e; ++i)
+ delete *i;
+ for(std::vector<sm4_insn*>::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_ */
+
+++ /dev/null
-/**************************************************************************
- *
- * 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 <stdint.h>
-#include <string.h>
-#include <stdlib.h>
-#include <memory>
-#include <vector>
-#include <map>
-#include <iostream>
-#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<tpf_op> 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<tpf_op> 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<tpf_op> 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<tpf_dcl*> dcls;
- std::vector<tpf_insn*> 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<int> 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<int> slot_to_resource;
- std::vector<int> slot_to_sampler;
- std::map<std::pair<int, int>, int> resource_sampler_to_slot;
- std::map<int, int> resource_to_slot;
-
- bool labels_found;
- std::vector<int> label_to_insn_num;
-
- tpf_program()
- {
- memset(&version, 0, sizeof(version));
- labels_found = false;
- resource_sampler_slots_assigned = false;
- }
-
- ~tpf_program()
- {
- for(std::vector<tpf_dcl*>::iterator i = dcls.begin(), e = dcls.end(); i != e; ++i)
- delete *i;
- for(std::vector<tpf_insn*>::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_ */
-
--- /dev/null
+/**************************************************************************
+ *
+ * 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 <vector>
+#include <set>
+#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<int> cf_insn_linked;
+ cf_insn_linked.resize(program.insns.size());
+ memset(&cf_insn_linked[0], 0xff, cf_insn_linked.size() * sizeof(int));
+ std::vector<unsigned> 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<int> 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<std::pair<int, int> > pairs;
+ std::set<int> 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<std::pair<int, int> >::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<int>::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;
+}
--- /dev/null
+/**************************************************************************
+ *
+ * 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;
+}
--- /dev/null
+/**************************************************************************
+ *
+ * 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<typename T>
+ 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;
+}
+++ /dev/null
-/**************************************************************************
- *
- * 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 <vector>
-#include <set>
-#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<int> cf_insn_linked;
- cf_insn_linked.resize(program.insns.size());
- memset(&cf_insn_linked[0], 0xff, cf_insn_linked.size() * sizeof(int));
- std::vector<unsigned> 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<int> 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<std::pair<int, int> > pairs;
- std::set<int> 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<std::pair<int, int> >::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<int>::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;
-}
+++ /dev/null
-/**************************************************************************
- *
- * 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;
-}
+++ /dev/null
-/**************************************************************************
- *
- * 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<typename T>
- 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;
-}
**************************************************************************/
#include "dxbc.h"
-#include "tpf.h"
+#include "sm4.h"
#include <iostream>
#include <fstream>
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;
#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_program> tpf(tpf_parse(tpf_chunk + 1, bswap_le32(tpf_chunk->size)));
- if(!tpf.get())
+ std::auto_ptr<sm4_program> 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;
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);
#include <float.h>
#include "dxbc.h"
-#include "tpf.h"
-#include "tpf_to_tgsi.h"
+#include "sm4.h"
+#include "sm4_to_tgsi.h"
#include "d3d1xstutil.h"
--- /dev/null
+/**************************************************************************
+ *
+ * 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 <vector>
+
+#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<struct ureg_dst> temps;
+ std::vector<struct ureg_dst> outputs;
+ std::vector<struct ureg_src> inputs;
+ std::vector<struct ureg_src> samplers;
+ std::vector<std::pair<unsigned, unsigned> > targets; // first is normal, second shadow/comparison
+ std::vector<unsigned> sampler_modes; // 0 = normal, 1 = shadow/comparison
+ std::vector<std::pair<unsigned, unsigned> > loops;
+ sm4_insn* insn;
+ struct sm4_program& program;
+ std::vector<unsigned> sm4_to_tgsi_insn_num;
+ std::vector<std::pair<unsigned, unsigned> > 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<std::pair<int, int>, 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<struct ureg_dst> 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<int, int>::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();
+}
--- /dev/null
+/**************************************************************************
+ *
+ * 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_ */
**************************************************************************/
#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 <iostream>
#include <fstream>
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);
}
+++ /dev/null
-/**************************************************************************
- *
- * 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 <vector>
-
-#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<struct ureg_dst> temps;
- std::vector<struct ureg_dst> outputs;
- std::vector<struct ureg_src> inputs;
- std::vector<struct ureg_src> samplers;
- std::vector<std::pair<unsigned, unsigned> > targets; // first is normal, second shadow/comparison
- std::vector<unsigned> sampler_modes; // 0 = normal, 1 = shadow/comparison
- std::vector<std::pair<unsigned, unsigned> > loops;
- tpf_insn* insn;
- struct tpf_program& program;
- std::vector<unsigned> tpf_to_tgsi_insn_num;
- std::vector<std::pair<unsigned, unsigned> > 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<std::pair<int, int>, 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<struct ureg_dst> 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<int, int>::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();
-}
+++ /dev/null
-/**************************************************************************
- *
- * 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_ */