summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2024-12-26 22:06:57 +1100
committerquou <quou@disroot.org>2024-12-26 22:06:57 +1100
commit7fa078995b3ed62925788ce2460441bc3d373392 (patch)
tree3ea7cb6288319ed56b28b7443d628a4f40a4e5fd /sc
parentdac7103df9f748d3409ac87ac3d015e329f6c7f5 (diff)
constant buffers
Diffstat (limited to 'sc')
-rw-r--r--sc/sc.cpp127
1 files changed, 126 insertions, 1 deletions
diff --git a/sc/sc.cpp b/sc/sc.cpp
index f7acc1a..e806dd4 100644
--- a/sc/sc.cpp
+++ b/sc/sc.cpp
@@ -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();
}
};