summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--editor.cpp10
-rw-r--r--pipeline.cpp27
-rw-r--r--sc/sc.cpp87
-rw-r--r--video.cpp32
-rw-r--r--video.hpp24
5 files changed, 160 insertions, 20 deletions
diff --git a/editor.cpp b/editor.cpp
index 455b194..c4c18d0 100644
--- a/editor.cpp
+++ b/editor.cpp
@@ -189,7 +189,8 @@ static void init_pso_view(UI::Element* content, const Pipeline* pso) {
auto table = ui->create_element<UI::Table>(tree, rows);
disp_enum(table, "Type", (int)d.type,
"Texture",
- "Constant Buffer"
+ "Constant Buffer",
+ "Structured Buffer"
);
switch (d.type) {
case Descriptor::Type::texture: {
@@ -198,9 +199,10 @@ static void init_pso_view(UI::Element* content, const Pipeline* pso) {
disp_val(table, "Texture ID", "%d", (int)tex.texture.index);
disp_val(table, "Sampler ID", "%d", (int)tex.sampler.index);
} break;
- case Descriptor::Type::constant_buffer: {
- Constant_Buffer_Descriptor& cb =
- *(Constant_Buffer_Descriptor*)d.payload;
+ case Descriptor::Type::constant_buffer:
+ case Descriptor::Type::structured_buffer: {
+ Buffer_Descriptor& cb =
+ *(Buffer_Descriptor*)d.payload;
disp_val(table, "Offset", "%d", cb.offset);
disp_val(table, "Size", "%d", cb.size);
disp_val(table, "Buffer ID", "%d", (int)cb.buffer.index);
diff --git a/pipeline.cpp b/pipeline.cpp
index 30c110c..647ff49 100644
--- a/pipeline.cpp
+++ b/pipeline.cpp
@@ -232,10 +232,10 @@ void Pipeline_Builder::cbuffer(
int size
) {
Descriptor* d;
- Constant_Buffer_Descriptor* cd;
+ Buffer_Descriptor* cd;
assert(pip->descriptor_count < pipeline_max_descriptors);
d = &pip->descriptors[pip->descriptor_count++];
- cd = (Constant_Buffer_Descriptor*)d->payload;
+ cd = (Buffer_Descriptor*)d->payload;
d->slot = binding;
d->type = Descriptor::Type::constant_buffer;
cd->buffer = id;
@@ -243,6 +243,24 @@ void Pipeline_Builder::cbuffer(
cd->size = size;
}
+void Pipeline_Builder::sbuffer(
+ int binding,
+ Buffer_Id id,
+ int offset,
+ int size
+) {
+ Descriptor* d;
+ Buffer_Descriptor* cd;
+ assert(pip->descriptor_count < pipeline_max_descriptors);
+ d = &pip->descriptors[pip->descriptor_count++];
+ cd = (Buffer_Descriptor*)d->payload;
+ d->slot = binding;
+ d->type = Descriptor::Type::structured_buffer;
+ cd->buffer = id;
+ cd->offset = offset;
+ cd->size = size;
+}
+
void Pipeline_Builder::vertex_format(Vertex_Format_Id vf) {
pip->vertex_format = vf;
}
@@ -295,8 +313,9 @@ void Pipeline::hash() {
h(descriptor_resource_hash, td->sampler);
h(descriptor_resource_hash, td->texture);
} break;
- case Descriptor::Type::constant_buffer: {
- auto cd = (Constant_Buffer_Descriptor*)d->payload;
+ case Descriptor::Type::constant_buffer:
+ case Descriptor::Type::structured_buffer: {
+ auto cd = (Buffer_Descriptor*)d->payload;
h(descriptor_resource_hash, cd->buffer);
h(descriptor_resource_hash, cd->size);
h(descriptor_resource_hash, cd->offset);
diff --git a/sc/sc.cpp b/sc/sc.cpp
index 143c408..9b1789f 100644
--- a/sc/sc.cpp
+++ b/sc/sc.cpp
@@ -206,6 +206,10 @@ struct Desc {
std::string strct;
std::unordered_map<std::string, int> offsets;
};
+ struct SBuffer {
+ int stage;
+ std::string strct;
+ };
int type;
std::vector<Binding> bindings;
std::vector<Variable> trgts;
@@ -213,6 +217,7 @@ struct Desc {
std::unordered_map<std::string, Struct> structs;
std::unordered_map<std::string, Texture> textures;
std::unordered_map<std::string, CBuffer> cbuffers;
+ std::unordered_map<std::string, SBuffer> sbuffers;
std::vector<Descriptor> descriptors;
std::string entrypoints[shader_type_count];
void read_var(Variable& d, cfg_Object* desc) {
@@ -297,6 +302,7 @@ struct Desc {
}
desc = desc->next;
Struct& s = structs[n];
+ s.name = n;
while (desc && !strcmp(desc->name, "variable")) {
Variable v;
read_var(v, desc);
@@ -344,6 +350,36 @@ struct Desc {
buf.size = offset;
}
+ void read_sbuffer(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("SBuffer 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);
+ }
+ SBuffer& buf = sbuffers[n];
+ buf.strct = t;
+ buf.stage |= 1 << stage_from_string(sstage);
+ }
+
void build(cfg_Object* desc) {
int i;
Binding* cur_binding = 0;
@@ -392,6 +428,8 @@ struct Desc {
read_texture(desc);
} else if (!strcmp(desc->name, "cbuffer")) {
read_cbuffer(desc);
+ } else if (!strcmp(desc->name, "sbuffer")) {
+ read_sbuffer(desc);
} else if (!strcmp(desc->name, "struct")) {
desc = read_struct(desc);
continue;
@@ -417,7 +455,11 @@ struct Desc {
void build_descriptors() {
int slot = 0;
- descriptors.resize(textures.size() + cbuffers.size());
+ descriptors.resize(
+ textures.size() +
+ cbuffers.size() +
+ sbuffers.size()
+ );
for (auto& i : textures) {
Descriptor* d = find_desc(i.first.c_str());
d->name = i.first;
@@ -432,6 +474,13 @@ struct Desc {
d->stage = i.second.stage;
slot++;
}
+ for (auto& i : sbuffers) {
+ 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) {
@@ -468,6 +517,40 @@ struct Desc {
}
}
+ void add_sbuffer_structs(std::stringstream& ss, Shader_Type stage) {
+ std::unordered_map<std::string, bool> used;
+ for (const auto& i : sbuffers) {
+ const auto& sbuffer = i.second;
+ if (
+ sbuffer.stage & (1 << stage) &&
+ used.find(sbuffer.strct) == used.end()
+ ) {
+ const Struct& s = structs[sbuffer.strct];
+ ss << "struct " << s.name << "{\n";
+ for (auto& v : s.vars)
+ ss << "\t" << v.tname << " " << v.name << ";\n";
+ ss << "};\n";
+ used[sbuffer.strct] = true;
+ }
+ }
+ }
+
+ void add_sbuffers(std::stringstream& ss, Shader_Type stage) {
+ add_sbuffer_structs(ss, stage);
+ for (const auto& i : sbuffers) {
+ const auto& sbuffer = i.second;
+ if (sbuffer.stage & (1 << stage)) {
+ Descriptor* d = find_desc(i.first.c_str());
+ assert(d != 0);
+ ss << "layout (std140, binding = " << d->slot << ") ";
+ ss << "readonly buffer _SBuffer" << d->slot << " {\n";
+ ss << "\t" << sbuffer.strct << " ";
+ ss << i.first << "[];\n";
+ ss << "};\n";
+ }
+ }
+ }
+
std::string build_vs() {
std::stringstream ss;
size_t i, li = bindings.size();
@@ -490,6 +573,7 @@ struct Desc {
}
add_textures(ss, shader_type_vertex);
add_cbuffers(ss, shader_type_vertex);
+ add_sbuffers(ss, shader_type_vertex);
return ss.str();
}
@@ -510,6 +594,7 @@ struct Desc {
}
add_textures(ss, shader_type_fragment);
add_cbuffers(ss, shader_type_fragment);
+ add_sbuffers(ss, shader_type_fragment);
return ss.str();
}
};
diff --git a/video.cpp b/video.cpp
index f108319..f1fb512 100644
--- a/video.cpp
+++ b/video.cpp
@@ -2662,6 +2662,8 @@ void Context_Vk::submit_descriptors(
} break;
case Descriptor::Type::constant_buffer:
break; /* todo */
+ case Descriptor::Type::structured_buffer:
+ break; /* todo */
}
}
vkCmdBindDescriptorSets(
@@ -3062,6 +3064,9 @@ void Pipeline_Vk::init_descriptors(
case Descriptor::Type::constant_buffer:
dst.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
break;
+ case Descriptor::Type::structured_buffer:
+ dst.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+ break;
}
dst.binding = src.slot;
dst.descriptorCount = 1;
@@ -3180,7 +3185,7 @@ void Descriptor_Set_Vk::init(
const Pipeline& desc
) {
int count = desc.descriptor_count, i;
- int sampler_count = 0, cbuffer_count = 0;
+ int sampler_count = 0, cbuffer_count = 0, sbuffer_count = 0;
int size_count = 0;
VkDescriptorSetAllocateInfo da{};
VkDescriptorPoolSize sizes[4];
@@ -3194,6 +3199,9 @@ void Descriptor_Set_Vk::init(
case Descriptor::Type::constant_buffer:
cbuffer_count++;
break;
+ case Descriptor::Type::structured_buffer:
+ sbuffer_count++;
+ break;
}
}
if (sampler_count) {
@@ -3210,6 +3218,13 @@ void Descriptor_Set_Vk::init(
.descriptorCount = (uint32_t)cbuffer_count
};
}
+ if (sbuffer_count) {
+ int idx = size_count++;
+ sizes[idx] = {
+ .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+ .descriptorCount = (uint32_t)sbuffer_count
+ };
+ }
{
VkDescriptorPoolCreateInfo di{};
di.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
@@ -3260,8 +3275,8 @@ void Descriptor_Set_Vk::init(
wd.pImageInfo = &img;
} break;
case Descriptor::Type::constant_buffer: {
- Constant_Buffer_Descriptor* cd =
- (Constant_Buffer_Descriptor*)src.payload;
+ Buffer_Descriptor* cd =
+ (Buffer_Descriptor*)src.payload;
Buffer_Vk& b = *(Buffer_Vk*)&dev->get_buffer(cd->buffer);
assert(cd->buffer);
buf.buffer = b.buf;
@@ -3270,6 +3285,17 @@ void Descriptor_Set_Vk::init(
wd.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
wd.pBufferInfo = &buf;
} break;
+ case Descriptor::Type::structured_buffer: {
+ Buffer_Descriptor* cd =
+ (Buffer_Descriptor*)src.payload;
+ Buffer_Vk& b = *(Buffer_Vk*)&dev->get_buffer(cd->buffer);
+ assert(cd->buffer);
+ buf.buffer = b.buf;
+ buf.offset = cd->offset;
+ buf.range = cd->size? cd->size: b.size;
+ wd.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+ wd.pBufferInfo = &buf;
+ } break;
}
vkUpdateDescriptorSets(dev->dev, 1, &wd, 0, 0);
}
diff --git a/video.hpp b/video.hpp
index c93093e..ccc1f11 100644
--- a/video.hpp
+++ b/video.hpp
@@ -52,7 +52,8 @@ struct Sampler_Id : public Primitive_Id<uint32_t> {
struct Descriptor {
enum class Type {
texture,
- constant_buffer
+ constant_buffer,
+ structured_buffer
} type;
int slot;
uint8_t payload[descriptor_payload_size];
@@ -63,13 +64,13 @@ struct Texture_Descriptor {
Sampler_Id sampler;
};
-struct Constant_Buffer_Descriptor {
+struct Buffer_Descriptor {
int offset, size;
Buffer_Id buffer;
};
static_assert(sizeof(Texture_Descriptor) <= descriptor_payload_size);
-static_assert(sizeof(Constant_Buffer_Descriptor) <= descriptor_payload_size);
+static_assert(sizeof(Buffer_Descriptor) <= descriptor_payload_size);
#define pipeline_max_descriptors 16
@@ -195,11 +196,12 @@ struct Pipeline {
if (ta->texture != tb->texture) return false;
if (ta->sampler != tb->sampler) return false;
} break;
- case Descriptor::Type::constant_buffer: {
- Constant_Buffer_Descriptor* ca =
- (Constant_Buffer_Descriptor*)a.payload;
- Constant_Buffer_Descriptor* cb =
- (Constant_Buffer_Descriptor*)b.payload;
+ case Descriptor::Type::constant_buffer:
+ case Descriptor::Type::structured_buffer: {
+ Buffer_Descriptor* ca =
+ (Buffer_Descriptor*)a.payload;
+ Buffer_Descriptor* cb =
+ (Buffer_Descriptor*)b.payload;
if (ca->buffer != cb->buffer) return false;
if (ca->size != cb->size) return false;
if (ca->offset != cb->offset) return false;
@@ -328,6 +330,12 @@ struct Pipeline_Builder {
int offset = 0,
int size = 0
);
+ void sbuffer(
+ int binding,
+ Buffer_Id id,
+ int offset = 0,
+ int size = 0
+ );
Pipeline& build();
void validate();
};