X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Fspirvwriter.cpp;fp=source%2Fglsl%2Fspirvwriter.cpp;h=77ddbdb95c719442120873e809a73bb489ab4c49;hb=cc5483cc709fdf7b6966a3e69dabfcafebaaffa0;hp=0000000000000000000000000000000000000000;hpb=577a93f39f9b4d0f5101cd2f539fc774e7b06825;p=libs%2Fgl.git diff --git a/source/glsl/spirvwriter.cpp b/source/glsl/spirvwriter.cpp new file mode 100644 index 00000000..77ddbdb9 --- /dev/null +++ b/source/glsl/spirvwriter.cpp @@ -0,0 +1,213 @@ +#include "glsl_error.h" +#include "spirvwriter.h" + +using namespace std; + +namespace Msp { +namespace GL { +namespace SL { + +SpirVWriter::SpirVWriter(SpirVContent &c): + content(c), + op_target(0), + op_head_pos(0), + current_block_id(0) +{ } + +void SpirVWriter::append(vector &target, const vector &source) +{ + target.insert(target.end(), source.begin(), source.end()); +} + +void SpirVWriter::write(Word word) +{ + if(!op_target) + throw logic_error("write without begin_op"); + op_target->push_back(word); +} + +void SpirVWriter::write_float(float value) +{ + union + { + float fv; + Word word; + }; + fv = value; + write(word); +} + +void SpirVWriter::write_string(const string &str) +{ + for(unsigned i=0; i<=str.size(); i+=4) + { + Word word = 0; + for(unsigned j=0; (j<4 && i+j(str[i+j])<<(j*8); + write(word); + } +} + +void SpirVWriter::begin_op(vector &target, Opcode opcode, unsigned size) +{ + if(op_target) + throw logic_error("begin_op without end_op"); + if(&target==&content.function_body && !current_block_id) + throw logic_error("no open block in function"); + + op_head_pos = target.size(); + op_target = ⌖ + write(opcode | (size<<16)); + + if(opcode==OP_BRANCH || opcode==OP_BRANCH_CONDITIONAL || opcode==OP_KILL || + opcode==OP_RETURN || opcode==OP_RETURN_VALUE || opcode==OP_UNREACHABLE) + current_block_id = 0; +} + +void SpirVWriter::end_op(Opcode opcode) +{ + if(!op_target) + throw logic_error("end_op without begin_op"); + Word &op_head = (*op_target)[op_head_pos]; + if(opcode!=(op_head&0xFFFF)) + throw logic_error("opcode mismatch"); + + unsigned words = op_target->size()-op_head_pos; + unsigned op_size = op_head>>16; + if(op_size) + { + if(words!=op_size) + throw logic_error("incorred number of words written"); + } + else + op_head |= (words<<16); + + op_target = 0; + op_head_pos = 0; +} + +void SpirVWriter::write_op(vector &target, Opcode opcode) +{ + begin_op(target, opcode, 1); + end_op(opcode); +} + +void SpirVWriter::write_op(vector &target, Opcode opcode, Word arg0) +{ + begin_op(target, opcode, 2); + write(arg0); + end_op(opcode); +} + +void SpirVWriter::write_op(vector &target, Opcode opcode, Word arg0, Word arg1) +{ + begin_op(target, opcode, 3); + write(arg0); + write(arg1); + end_op(opcode); +} + +void SpirVWriter::write_op(vector &target, Opcode opcode, Word arg0, Word arg1, Word arg2) +{ + begin_op(target, opcode, 4); + write(arg0); + write(arg1); + write(arg2); + end_op(opcode); +} + +void SpirVWriter::write_op_name(Id id, const string &name) +{ + begin_op(content.names, OP_NAME); + write(id); + write_string(name); + end_op(OP_NAME); +} + +void SpirVWriter::write_op_member_name(Id id, unsigned index, const string &name) +{ + begin_op(content.names, OP_MEMBER_NAME); + write(id); + write(index); + write_string(name); + end_op(OP_MEMBER_NAME); +} + +void SpirVWriter::write_op_decorate(Id id, Decoration decoration) +{ + write_op(content.decorations, OP_DECORATE, id, decoration); +} + +void SpirVWriter::write_op_decorate(Id id, Decoration decoration, Word value) +{ + write_op(content.decorations, OP_DECORATE, id, decoration, value); +} + +void SpirVWriter::write_op_member_decorate(Id id, unsigned index, Decoration decoration) +{ + write_op(content.decorations, OP_MEMBER_DECORATE, id, index, decoration); +} + +void SpirVWriter::write_op_member_decorate(Id id, unsigned index, Decoration decoration, Word value) +{ + begin_op(content.decorations, OP_MEMBER_DECORATE, 5); + write(id); + write(index); + write(decoration); + write(value); + end_op(OP_MEMBER_DECORATE); +} + +void SpirVWriter::write_op_label(Id label_id) +{ + if(current_block_id) + write_op(content.function_body, OP_BRANCH, label_id); + current_block_id = label_id; + write_op(content.function_body, OP_LABEL, label_id); +} + +void SpirVWriter::begin_function_body(Id first_block_id) +{ + if(!content.function_body.empty() || current_block_id) + throw internal_error("begin_function without end_function"); + + current_block_id = first_block_id; + write_op(content.functions, OP_LABEL, first_block_id); +} + +void SpirVWriter::end_function_body() +{ + if(content.function_body.empty()) + throw internal_error("end_function without begin_function"); + if(current_block_id) + throw internal_error("end_function with open block"); + + append(content.functions, content.locals); + append(content.functions, content.function_body); + write_op(content.functions, OP_FUNCTION_END); + + content.locals.clear(); + content.function_body.clear(); +} + +void SpirVWriter::finalize(Id id_bound) +{ + content.code.push_back(SPIRV_MAGIC); + content.code.push_back(0x00010500); + content.code.push_back(0); // Generator + content.code.push_back(id_bound); + content.code.push_back(0); // Reserved + append(content.code, content.capabilities); + append(content.code, content.extensions); + write_op(content.code, OP_MEMORY_MODEL, 0, 1); // Logical, GLSL450 + append(content.code, content.entry_points); + append(content.code, content.exec_modes); + append(content.code, content.names); + append(content.code, content.decorations); + append(content.code, content.globals); + append(content.code, content.functions); +} + +} // namespace SL +} // namespace GL +} // namespace Msp