diff options
-rw-r--r-- | editor.cpp | 10 | ||||
-rw-r--r-- | pipeline.cpp | 27 | ||||
-rw-r--r-- | sc/sc.cpp | 87 | ||||
-rw-r--r-- | video.cpp | 32 | ||||
-rw-r--r-- | video.hpp | 24 |
5 files changed, 160 insertions, 20 deletions
@@ -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); @@ -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(); } }; @@ -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); } @@ -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(); }; |