diff options
Diffstat (limited to 'sc')
-rw-r--r-- | sc/sc.cpp | 127 |
1 files changed, 126 insertions, 1 deletions
@@ -156,6 +156,27 @@ struct Desc { int type; std::string name; std::string tname; + + std::pair<int, int> size() const { + switch (type) { + case svariable_type_float: + return { 4, 4 }; + case svariable_type_vec2: + return { 8, 8 }; + case svariable_type_vec3: + return { 12, 16 }; + case svariable_type_vec4: + return { 16, 16 }; + } + assert(0); + return { 0, 0 }; + } + + int size(int coff) const { + auto [desired, align] = size(); + int pad = align_size(coff, align) - coff; + return desired + pad; + } }; struct Binding { SBinding_Rate rate; @@ -171,11 +192,24 @@ struct Desc { int slot; int stage; }; + struct Struct { + std::string name; + std::vector<Variable> vars; + }; + struct CBuffer { + int size; + int stage; + int var_count; + std::string strct; + std::unordered_map<std::string, int> offsets; + }; int type; std::vector<Binding> bindings; std::vector<Variable> trgts; std::vector<Variable> interp; + std::unordered_map<std::string, Struct> structs; std::unordered_map<std::string, Texture> textures; + std::unordered_map<std::string, CBuffer> cbuffers; std::vector<Descriptor> descriptors; std::string entrypoints[shader_type_count]; void read_var(Variable& d, cfg_Object* desc) { @@ -243,6 +277,66 @@ struct Desc { t.stage |= 1 << stage_from_string(sstage); t.dimension = find_int_default(desc, "dimension", 2); } + cfg_Object* read_struct(cfg_Object* desc) { + const char* sname = find_string_default(desc, "name", 0); + if (!sname) { + print_err("%s must have a name.\n", desc->name); + pbreak(901); + } + std::string n = std::string(sname); + if (structs.contains(n)) { + print_err("Already a struct with the name %s.\n", sname); + pbreak(903); + } + desc = desc->next; + Struct& s = structs[n]; + while (desc && !strcmp(desc->name, "variable")) { + Variable v; + read_var(v, desc); + s.vars.push_back(v); + desc = desc->next; + } + return desc; + } + + void read_cbuffer(cfg_Object* desc) { + const char* sname = find_string_default(desc, "name", 0); + if (!sname) { + print_err("%s must have a name.\n", desc->name); + pbreak(951); + } + const char* stype = find_string_default(desc, "type", 0); + if (!stype) { + print_err("%s must define a type.\n", desc->name); + } + std::string n = std::string(sname); + std::string t = std::string(stype); + if (n.size() > 23) { + print_err("CBuffer name too long (max 23 chars).\n"); + pbreak(952); + } + if (!structs.contains(t)) { + print_err("No such struct %s\n", stype); + pbreak(953); + } + const char* sstage = find_string_default(desc, "stage", 0); + if (!sstage) { + print_err("%s must define a stage.\n", sname); + pbreak(954); + } + Struct& strct = structs[t]; + CBuffer& buf = cbuffers[n]; + int offset = 0; + buf.strct = t; + buf.stage |= 1 << stage_from_string(sstage); + buf.var_count = strct.vars.size(); + for (const auto& v : strct.vars) { + buf.offsets[v.name] = offset; + offset += v.size(offset); + } + buf.size = offset; + } + void build(cfg_Object* desc) { int i; Binding* cur_binding = 0; @@ -289,6 +383,11 @@ struct Desc { interp.push_back(v); } else if (!strcmp(desc->name, "texture")) { read_texture(desc); + } else if (!strcmp(desc->name, "cbuffer")) { + read_cbuffer(desc); + } else if (!strcmp(desc->name, "struct")) { + desc = read_struct(desc); + continue; } desc = desc->next; } @@ -311,7 +410,7 @@ struct Desc { void build_descriptors() { int slot = 0; - descriptors.resize(textures.size()); + descriptors.resize(textures.size() + cbuffers.size()); for (auto& i : textures) { Descriptor* d = find_desc(i.first.c_str()); d->name = i.first; @@ -319,6 +418,13 @@ struct Desc { d->stage = i.second.stage; slot++; } + for (auto& i : cbuffers) { + Descriptor* d = find_desc(i.first.c_str()); + d->name = i.first; + d->slot = slot; + d->stage = i.second.stage; + slot++; + } } void add_textures(std::stringstream& ss, Shader_Type stage) { @@ -334,6 +440,23 @@ struct Desc { } } + void add_cbuffers(std::stringstream& ss, Shader_Type stage) { + for (const auto& it : cbuffers) { + const auto& cbuffer = it.second; + if (cbuffer.stage & (1 << stage)) { + const Struct& s = structs[cbuffer.strct]; + Descriptor* d = find_desc(it.first.c_str()); + assert(d != 0); + ss << "layout (std140, binding = " << d->slot << ") "; + ss << "uniform " << cbuffer.strct << "{\n"; + for (const auto& v : s.vars) { + ss << v.tname << " " << v.name << ";\n"; + } + ss << "} " << it.first << ";\n"; + } + } + } + std::string build_vs() { std::stringstream ss; size_t i, li = bindings.size(); @@ -353,6 +476,7 @@ struct Desc { ss << i.tname << " " << i.name << ";\n"; ss << "} interpolator;\n"; add_textures(ss, shader_type_vertex); + add_cbuffers(ss, shader_type_vertex); return ss.str(); } @@ -370,6 +494,7 @@ struct Desc { ss << i.tname << " " << i.name << ";\n"; ss << "} interpolator;\n"; add_textures(ss, shader_type_fragment); + add_cbuffers(ss, shader_type_fragment); return ss.str(); } }; |