summaryrefslogtreecommitdiff
path: root/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_parse.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_parse.cpp')
-rw-r--r--src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_parse.cpp424
1 files changed, 424 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_parse.cpp b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_parse.cpp
new file mode 100644
index 00000000000..a4f6cc6b661
--- /dev/null
+++ b/src/gallium/state_trackers/d3d1x/d3d1xshader/src/tpf_parse.cpp
@@ -0,0 +1,424 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Luca Barbieri
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "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_COMPS_0:
+ op.comps = 0;
+ break;
+ case TPF_OPERAND_COMPS_1:
+ op.comps = 1;
+ break;
+ case TPF_OPERAND_COMPS_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_COMPS_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_D3D11_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;
+}