diff options
| -rw-r--r-- | c2.cpp | 28 | ||||
| -rw-r--r-- | intermediate/triangle.glsl | 13 | ||||
| -rw-r--r-- | pipeline.cpp | 15 | ||||
| -rw-r--r-- | sc/sc.cpp | 127 | ||||
| -rw-r--r-- | video.cpp | 34 | ||||
| -rw-r--r-- | video.hpp | 34 | 
6 files changed, 226 insertions, 25 deletions
@@ -5,6 +5,7 @@ extern "C" {  #include "memory.h"  }  #include <string.h> +#include <math.h>  #define video_arena_size (1024 * 1024 * 16)  #define asset_arena_size (1024 * 1024 * 4) @@ -58,6 +59,10 @@ static Sampler_Id create_clamped_linear(Device* dev) {  	return dev->create_sampler(s);  } +struct Config_Buffer { +	float offset[2]; +}; +  int main() {  	Arena video_arena;  	Arena asset_arena; @@ -66,7 +71,7 @@ int main() {  	Shader* shader;  	Texture* texture;  	Texture* texture2; -	Buffer_Id vbo; +	Buffer_Id vbo, cbuf;  	Sampler_Id clamped_linear;  	C2* app = App::create<C2>("c2");  	void* per_frame; @@ -88,6 +93,11 @@ int main() {  	shader = (Shader*)assets.load("triangle.csh");  	texture = (Texture*)assets.load("22.tex");  	texture2 = (Texture*)assets.load("kita.tex"); +	cbuf = dev->create_buffer( +		sizeof verts, +		Buffer_Flags::constant_buffer | +		Buffer_Flags::cpu_readwrite +	);  	per_frame = heap_alloc(  		dev->heap,  		per_frame_memory_size @@ -103,6 +113,15 @@ int main() {  		app->begin();  		dev->begin_frame(); +		{ +			void* mem; +			mem = dev->map_buffer(cbuf, 0, sizeof(Config_Buffer)); +			Config_Buffer* c = (Config_Buffer*)mem; +			c->offset[0] = sinf((float)frame / 10.0f); +			c->offset[1] = cosf((float)frame / 30.0f); +			dev->unmap_buffer(cbuf); +		} +  		Pipeline_Builder pb(&frame_arena);  		pb.begin_rp();  		pb.rp_target(dev->get_backbuffer(), { r, 0x00, 0xff, 0xff }); @@ -112,10 +131,14 @@ int main() {  		pb.shader(shader->id);  		pb.vertex_format(shader->vf);  		pb.texture( -			shader->descriptor_index("colour_texture"), +			shader->descriptor_binding("colour_texture"),  			frame % 2? texture->id: texture2->id,  			clamped_linear  		); +		pb.cbuffer( +			shader->descriptor_binding("config_buffer"), +			cbuf +		);  		Pipeline& pip = pb.build();  		Vertex_Buffer_Binding binding[] = {{ @@ -139,6 +162,7 @@ int main() {  	assets.destroy();  	dev->destroy_sampler(clamped_linear);  	dev->destroy_buffer(vbo); +	dev->destroy_buffer(cbuf);  	dev->destroy();  	app->destroy();  } diff --git a/intermediate/triangle.glsl b/intermediate/triangle.glsl index 8f3b586..1e883f5 100644 --- a/intermediate/triangle.glsl +++ b/intermediate/triangle.glsl @@ -33,6 +33,17 @@ name: colour_texture  stage: fragment  dimension: 2 +[struct] +name: Config +[variable] +name: offset +type: vec2 + +[cbuffer] +name: config_buffer +type: Config +stage: vertex +  #endif  #ifdef VERTEX_SHADER @@ -40,7 +51,7 @@ dimension: 2  void main() {  	interpolator.colour = colour;  	interpolator.uv = uv; -	gl_Position = vec4(position, 0.0, 1.0); +	gl_Position = vec4(position + config_buffer.offset, 0.0, 1.0);  }  #endif diff --git a/pipeline.cpp b/pipeline.cpp index 527c1e7..89f606d 100644 --- a/pipeline.cpp +++ b/pipeline.cpp @@ -56,6 +56,17 @@ void Pipeline_Builder::texture(  	td->texture = t;  } +void Pipeline_Builder::cbuffer(int binding, Buffer_Id id) { +	Descriptor* d; +	Constant_Buffer_Descriptor* cd; +	assert(pip->descriptor_count < pipeline_max_descriptors); +	d = &pip->descriptors[pip->descriptor_count++]; +	cd = (Constant_Buffer_Descriptor*)d->payload; +	d->slot = binding; +	d->type = Descriptor::Type::constant_buffer; +	cd->buffer = id; +} +  void Pipeline_Builder::vertex_format(Vertex_Format_Id vf) {  	pip->vertex_format = vf;  } @@ -83,6 +94,10 @@ Pipeline& Pipeline_Builder::build() {  					h(pip->descriptor_resource_hash, td->sampler);  					h(pip->descriptor_resource_hash, td->texture);  				} break; +				case Descriptor::Type::constant_buffer: { +					auto cd = (Constant_Buffer_Descriptor*)d->payload; +					h(pip->descriptor_resource_hash, cd->buffer); +				} break;  			}  		}  	} @@ -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();  	}  }; @@ -479,7 +479,7 @@ struct Buffer_Vk : public Buffer, public Late_Terminated {  			r |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;  		if (flags & Buffer_Flags::vertex_buffer)  			r |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; -		if (flags & Buffer_Flags::uniform_buffer) +		if (flags & Buffer_Flags::constant_buffer)  			r |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;  		if (flags & Buffer_Flags::storage_buffer)  			r |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; @@ -2266,8 +2266,8 @@ void Pipeline_Vk::init_descriptors(  				case Descriptor::Type::texture:  					dst.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;  					break; -				default: -					assert(0); +				case Descriptor::Type::constant_buffer: +					dst.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;  					break;  			}  			dst.binding = src.slot; @@ -2382,8 +2382,8 @@ void Descriptor_Set_Vk::init(  			case Descriptor::Type::texture:  				sampler_count++;  				break; -			default: -				assert(0); +			case Descriptor::Type::constant_buffer: +				cbuffer_count++;  				break;  		}  	} @@ -2428,6 +2428,7 @@ void Descriptor_Set_Vk::init(  	}  	for (i = 0; i < count; i++) {  		VkDescriptorImageInfo img{}; +		VkDescriptorBufferInfo buf{};  		VkWriteDescriptorSet wd{};  		auto& src = desc.descriptors[i];  		wd.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; @@ -2439,16 +2440,27 @@ void Descriptor_Set_Vk::init(  		switch (src.type) {  			case Descriptor::Type::texture: {  				Texture_Descriptor* td = (Texture_Descriptor*)src.payload; -				assert(td->texture); -				assert(td->sampler);  				Texture_Vk& t = *(Texture_Vk*)&dev->get_texture(td->texture);  				Sampler_Vk& s = *(Sampler_Vk*)&dev->samplers[td->sampler]; +				assert(td->texture); +				assert(td->sampler);  				img.imageView = t.view;  				img.sampler = s.sampler;  				img.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;  				wd.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;  				wd.pImageInfo = &img;  			} break; +			case Descriptor::Type::constant_buffer: { +				Constant_Buffer_Descriptor* cd = +					(Constant_Buffer_Descriptor*)src.payload; +				Buffer_Vk& b = *(Buffer_Vk*)&dev->get_buffer(cd->buffer); +				assert(cd->buffer); +				buf.buffer = b.buf; +				buf.offset = 0; +				buf.range = b.size; +				wd.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; +				wd.pBufferInfo = &buf; +			} break;  		}  		vkUpdateDescriptorSets(dev->dev, 1, &wd, 0, 0);  	} @@ -2667,7 +2679,7 @@ int Shader::binding_index(const char* name) {  	Shader_Vk* sh = (Shader_Vk*)this;  	idx = sh->vfd.find_binding(name);  	if (idx < 0 || !sh->vfd.bindings[idx].name[0]) return -1; -	return idx; +	return sh->vfd.bindings[idx].index;  }  int Shader::attribute_index(const char* name) { @@ -2675,15 +2687,15 @@ int Shader::attribute_index(const char* name) {  	Shader_Vk* sh = (Shader_Vk*)this;  	idx = sh->vfd.find_attribute(name);  	if (idx < 0 || !sh->vfd.attributes[idx].name[0]) return -1; -	return idx; +	return sh->vfd.attributes[idx].index;  } -int Shader::descriptor_index(const char* name) { +int Shader::descriptor_binding(const char* name) {  	int idx;  	Shader_Vk* sh = (Shader_Vk*)this;  	idx = sh->find_descriptor(name);  	if (idx < 0 || !sh->descs[idx].name[0]) return -1; -	return idx; +	return sh->descs[idx].slot;  }  int Shader::descriptor_stage(int slot) { @@ -48,7 +48,8 @@ struct Sampler_Id : public Primitive_Id<uint32_t> {  struct Descriptor {  	enum class Type { -		texture +		texture, +		constant_buffer  	} type;  	int slot;  	uint8_t payload[descriptor_payload_size]; @@ -59,7 +60,12 @@ struct Texture_Descriptor {  	Sampler_Id sampler;  }; +struct Constant_Buffer_Descriptor { +	Buffer_Id buffer; +}; +  static_assert(sizeof(Texture_Descriptor) <= descriptor_payload_size); +static_assert(sizeof(Constant_Buffer_Descriptor) <= descriptor_payload_size);  #define pipeline_max_descriptors 16 @@ -103,6 +109,13 @@ 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; +					if (ca->buffer != cb->buffer) return false; +				} break;  			}  		}  		return true; @@ -157,6 +170,7 @@ struct Pipeline_Builder {  	void shader(Shader_Id s);  	void vertex_format(Vertex_Format_Id vf);  	void texture(int binding, Texture_Id t, Sampler_Id s); +	void cbuffer(int binding, Buffer_Id id);  	Pipeline& build();  	void validate();  }; @@ -176,14 +190,14 @@ struct Texture : public Asset {  namespace Buffer_Flags {  	enum { -		index_buffer   = 1 << 0, -		vertex_buffer  = 1 << 1, -		uniform_buffer = 1 << 2, -		storage_buffer = 1 << 3, -		cpu_read       = 1 << 4, -		cpu_readwrite  = 1 << 5, -		copy_src       = 1 << 6, -		copy_dst       = 1 << 7 +		index_buffer    = 1 << 0, +		vertex_buffer   = 1 << 1, +		constant_buffer = 1 << 2, +		storage_buffer  = 1 << 3, +		cpu_read        = 1 << 4, +		cpu_readwrite   = 1 << 5, +		copy_src        = 1 << 6, +		copy_dst        = 1 << 7  	};  }; @@ -301,7 +315,7 @@ struct Shader : public Asset {  	int binding_index(const char* name);  	int attribute_index(const char* name);  	int target_index(const char* name); -	int descriptor_index(const char* name); +	int descriptor_binding(const char* name);  	int descriptor_stage(int slot);  };  |