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