diff options
| -rw-r--r-- | c2.cpp | 52 | ||||
| -rw-r--r-- | model.cpp | 2 | ||||
| -rw-r--r-- | pipeline.cpp | 11 | ||||
| -rw-r--r-- | renderer.cpp | 6 | ||||
| -rw-r--r-- | renderer.hpp | 1 | ||||
| -rw-r--r-- | video.cpp | 115 | ||||
| -rw-r--r-- | video.hpp | 15 | 
7 files changed, 172 insertions, 30 deletions
@@ -24,6 +24,8 @@ extern "C" {  #define scene_arena_size (1024 * 4)  #define per_frame_memory_size (1024 * 1024) +#define MSAA_SAMPLES 4 +  static float verts[] = {  	 0.5f,  0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,  	-0.5f,  0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, @@ -653,7 +655,7 @@ struct C2 : public App {  	Tonemap tonemap;  	Buffer_Id vbo, cbuf;  	Sampler_Id clamped_linear; -	Texture_Id hdr_target; +	Texture_Id hdr_target, hdr_resolved, ms_depth;  	Texture_Id ui_texture;  	Buffer_Id ui_buffer;  	Line_Renderer lr; @@ -876,7 +878,7 @@ struct C2 : public App {  		pb.begin_rp();  		pb.rp_target(hdr_target, Clear_Mode::restore); -		pb.rp_depth_target(dev->get_depth_target(), Clear_Mode::restore); +		pb.rp_depth_target(ms_depth, Clear_Mode::restore);  		Render_Pass& sky_pass = pb.build_rp();  		pb.begin_rp(); @@ -903,6 +905,7 @@ struct C2 : public App {  			dev,  			&frame_arena,  			hdr_target, +			ms_depth,  			&lighting  		);  		ctx.debug_pop(); @@ -919,6 +922,8 @@ struct C2 : public App {  		);  		ctx.debug_pop(); +		ctx.resolve(hdr_resolved, hdr_target); +  		tonemap.update(dev, 0.2f);  		ctx.debug_push("TONEMAP"); @@ -927,7 +932,7 @@ struct C2 : public App {  			&frame_arena,  			quad,  			tonemap_pass, -			hdr_target, +			hdr_resolved,  			clamped_linear  		);  		ctx.debug_pop(); @@ -1014,6 +1019,8 @@ struct C2 : public App {  		assets.destroy();  		dev->destroy_texture(default_texture);  		dev->destroy_texture(hdr_target); +		dev->destroy_texture(hdr_resolved); +		dev->destroy_texture(ms_depth);  		dev->destroy_texture(ui_texture);  		dev->destroy_buffer(ui_buffer);  		dev->destroy_sampler(clamped_linear); @@ -1025,7 +1032,9 @@ struct C2 : public App {  	void on_resize() override {  		ui->layout(w, h);  		dev->on_resize(); +		dev->destroy_texture(ms_depth);  		dev->destroy_texture(hdr_target); +		dev->destroy_texture(hdr_resolved);  		dev->destroy_texture(ui_texture);  		dev->destroy_buffer(ui_buffer);  		make_hdr_target(); @@ -1033,16 +1042,43 @@ struct C2 : public App {  	}  	void make_hdr_target() { +		int sw = dev->swap_w(); +		int sh = dev->swap_h();  		hdr_target = dev->create_texture( -			"HDR target", +			"MS HDR target",  			texture_format_rgba16f, -			Texture_Flags::sampleable | Texture_Flags::colour_target, -			dev->swap_w(), -			dev->swap_h(), +			Texture_Flags::copy_src | Texture_Flags::colour_target, +			sw, +			sh,  			1,  			1,  			1, -			Buffer_Id(0) +			Buffer_Id(0), +			MSAA_SAMPLES +		); +		hdr_resolved = dev->create_texture( +			"Resolved HDR", +			texture_format_rgba16f, +			Texture_Flags::sampleable | Texture_Flags::copy_dst, +			sw, +			sh, +			1, +			1, +			1, +			Buffer_Id(0), +			1 +		); +		ms_depth = dev->create_texture( +			"MS depth", +			texture_format_d24s8, +			Texture_Flags::sampleable | Texture_Flags::depth_stencil_target, +			sw, +			sh, +			1, +			1, +			1, +			0, +			MSAA_SAMPLES  		);  	} @@ -384,7 +384,7 @@ void Model_Instance::render(  				res.vp  			);  		} else { -			pb.depth(true, false, Depth_Mode::equal); +			pb.depth(true, true, Depth_Mode::less);  			pb.shader(mesh.shader);  			pb.sbuffer(mesh.light_binding, lighting->lights.gpuonly);  			pb.sbuffer(mesh.casters_binding, lighting->casters.gpuonly); diff --git a/pipeline.cpp b/pipeline.cpp index 0636a1c..374dad8 100644 --- a/pipeline.cpp +++ b/pipeline.cpp @@ -23,6 +23,7 @@ Pipeline_Builder& Pipeline_Builder::rp_target(Texture_Id id, Colour clear) {  	Render_Pass::Target t{  		.id = id,  		.fmt = texture.fmt, +		.samples = texture.samples,  		.mode = Clear_Mode::clear,  		.clear = { .colour = clear }  	}; @@ -37,6 +38,7 @@ Pipeline_Builder& Pipeline_Builder::rp_target(Texture_Id id, Clear_Mode clear) {  	Render_Pass::Target t{  		.id = id,  		.fmt = texture.fmt, +		.samples = texture.samples,  		.mode = clear,  		.clear = { .depth = 0.0f }  	}; @@ -51,6 +53,7 @@ Pipeline_Builder& Pipeline_Builder::rp_depth_target(Texture_Id id, float clear)  	Render_Pass::Target t{  		.id = id,  		.fmt = texture.fmt, +		.samples = texture.samples,  		.mode = Clear_Mode::clear,  		.clear = { .depth = clear }  	}; @@ -63,6 +66,7 @@ Pipeline_Builder& Pipeline_Builder::rp_depth_target(Texture_Id id, Clear_Mode mo  	Render_Pass::Target t{  		.id = id,  		.fmt = texture.fmt, +		.samples = texture.samples,  		.mode = mode,  		.clear = { .depth = 0.0f }  	}; @@ -73,7 +77,7 @@ Pipeline_Builder& Pipeline_Builder::rp_depth_target(Texture_Id id, Clear_Mode mo  void Pipeline_Builder::validate_rp() {  	int i, c = pass->colour_count; -	int w, h; +	int w, h, s;  	assert(c || pass->depth.id);  	if (c) {  		Texture& tex = dev->get_texture(pass->colours[0].id); @@ -81,7 +85,8 @@ void Pipeline_Builder::validate_rp() {  		assert(pass->colours[0].fmt == tex.fmt);  		w = tex.w;  		h = tex.h; -		assert(w && h); +		s = tex.samples; +		assert(w && h && s);  	}  	for (i = 1; i < c; i++) {  		Texture& tex = dev->get_texture(pass->colours[i].id); @@ -89,6 +94,7 @@ void Pipeline_Builder::validate_rp() {  		assert(pass->colours[i].fmt == tex.fmt);  		assert(tex.w == w);  		assert(tex.h == h); +		assert(tex.samples == s);  	}  	if (pass->depth.id) {  		Texture& d = dev->get_texture(pass->depth.id); @@ -101,6 +107,7 @@ void Pipeline_Builder::validate_rp() {  		if (c) {  			assert(d.w == w);  			assert(d.h == h); +			assert(d.samples == s);  		}  	}  } diff --git a/renderer.cpp b/renderer.cpp index d8c4895..c7040ec 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -108,7 +108,9 @@ void Renderer::update_globals(  void Renderer::render(  	Device* dev, -	Arena* a, Texture_Id hdr_target, +	Arena* a, +	Texture_Id hdr_target, +	Texture_Id depth_target,  	const Lighting* l  ) {  	int i, j; @@ -124,7 +126,7 @@ void Renderer::render(  	Render_Pass& forward_pass = pb  		.begin_rp()  		.rp_target(hdr_target, Clear_Mode::restore) -		.rp_depth_target(dev->get_depth_target(), Clear_Mode::restore) +		.rp_depth_target(depth_target, 1.0f)  		.build_rp();  	Render_Pass* shadow_passes[Lighting::max_shadows];  	for (i = 0; i < Lighting::max_shadows; i++) { diff --git a/renderer.hpp b/renderer.hpp index c49c804..6bfe551 100644 --- a/renderer.hpp +++ b/renderer.hpp @@ -50,6 +50,7 @@ struct Renderer {  		Device* dev,  		Arena* a,  		Texture_Id hdr_target, +		Texture_Id depth_target,  		const Lighting* l  	); @@ -561,7 +561,8 @@ struct Texture_Vk : public Texture, public Late_Terminated {  		int array_size,  		int start_mip,  		int start_array, -		bool alias +		bool alias, +		int samples  	);  	void destroy(Device_Vk*) override;  	void set_name(Device_Vk* dev, const char* name); @@ -732,7 +733,8 @@ struct Pipeline_Vk {  		Arena& scope,  		Device_Vk* dev,  		VkGraphicsPipelineCreateInfo& info, -		const Pipeline& desc +		const Pipeline& desc, +		const Render_Pass& rpo  	);  	void init_depthstencil(  		Arena& scope, @@ -934,6 +936,7 @@ struct Device_Vk : public Device {  	VkPhysicalDevice phys_dev;  	VkSurfaceKHR surf;  	uint32_t backbuffer_index; +	VkSampleCountFlagBits max_samples;  	Texture_Id backbuffer_id;  	Swap_Cap swap_cap;  	VkPhysicalDeviceMemoryProperties mem_props; @@ -1021,6 +1024,9 @@ struct Device_Vk : public Device {  	void create_terminators();  	void create_depth(int w, int h); +	VkSampleCountFlagBits get_max_samples(); +	VkSampleCountFlagBits get_samples(int); +  	int find_memory_type(  		uint32_t filter,  		VkMemoryPropertyFlags flags @@ -1114,6 +1120,37 @@ void Device_Vk::init_validation() {  #endif +VkSampleCountFlagBits Device_Vk::get_max_samples() { +	VkPhysicalDeviceProperties p; +	VkSampleCountFlagBits +		i = VK_SAMPLE_COUNT_64_BIT, +		e = VK_SAMPLE_COUNT_1_BIT; +	VkSampleCountFlags c; +	vkGetPhysicalDeviceProperties(phys_dev, &p); +	c = +		p.limits.framebufferColorSampleCounts & +		p.limits.framebufferDepthSampleCounts; +	for (; i >= e; i = (VkSampleCountFlagBits)(i >> 1)) +		if (c & i) return i; +	return VK_SAMPLE_COUNT_1_BIT; +} + +VkSampleCountFlagBits Device_Vk::get_samples( +	int c +) { +	VkSampleCountFlagBits b = VK_SAMPLE_COUNT_1_BIT; +	switch (c) { +		case 1:  b = VK_SAMPLE_COUNT_1_BIT;  break; +		case 2:  b = VK_SAMPLE_COUNT_2_BIT;  break; +		case 4:  b = VK_SAMPLE_COUNT_4_BIT;  break; +		case 8:  b = VK_SAMPLE_COUNT_8_BIT;  break; +		case 16: b = VK_SAMPLE_COUNT_16_BIT; break; +		case 32: b = VK_SAMPLE_COUNT_32_BIT; break; +		case 64: b = VK_SAMPLE_COUNT_64_BIT; break; +		default: break; +	} +	return std::min(max_samples, b); +}  bool Device_Vk::has_validation() {  	unsigned count, i; @@ -1352,6 +1389,7 @@ void Device_Vk::init_internal() {  #endif  	surf = app_create_vk_surface(app, inst);  	create_dev(&swap_cap); +	max_samples = get_max_samples();  	vrama.init(this);  	gladLoaderLoadVulkan(inst, phys_dev, dev);  	vkGetDeviceQueue(dev, (uint32_t)queue_index, 0, &queue); @@ -1642,7 +1680,7 @@ void Renderpass_Vk::init(  		auto& colour = rp.colours[i];  		auto& ad = ads[index];  		ad.format = get_vk_format(colour.fmt); -		ad.samples = VK_SAMPLE_COUNT_1_BIT; +		ad.samples = dev->get_samples(colour.samples);  		ad.loadOp = load_op_from_mode(colour.mode);  		ad.storeOp = VK_ATTACHMENT_STORE_OP_STORE;  		ad.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; @@ -1659,9 +1697,10 @@ void Renderpass_Vk::init(  	if (has_depth) {  		int i = count++;  		auto& ad = ads[i]; -		ad.format = get_vk_format(dev->get_texture(rp.depth.id).fmt); -		ad.samples = VK_SAMPLE_COUNT_1_BIT; -		ad.loadOp = load_op_from_mode(rp.depth.mode); +		auto& depth = rp.depth; +		ad.format = get_vk_format(dev->get_texture(depth.id).fmt); +		ad.samples = dev->get_samples(depth.samples); +		ad.loadOp = load_op_from_mode(depth.mode);  		ad.storeOp = VK_ATTACHMENT_STORE_OP_STORE;  		ad.stencilLoadOp = ad.loadOp;  		ad.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; @@ -1887,7 +1926,8 @@ Texture_Id Swapchain::create_image(  		1,  		0,  		0, -		true +		true, +		1  	);  	return id;  } @@ -2286,6 +2326,37 @@ void Context::copy(  	);  } +void Context::resolve(Texture_Id dst, Texture_Id src) { +	Context_Vk* ctx = (Context_Vk*)this; +	Device_Vk* dev = ctx->dev; +	Texture_Vk& d = *(Texture_Vk*)&dev->get_texture(dst); +	Texture_Vk& s = *(Texture_Vk*)&dev->get_texture(src); +	VkImageResolve r{}; +	r.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; +	r.srcSubresource.layerCount = 1; +	r.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; +	r.dstSubresource.layerCount = 1; +	r.extent.width = d.w; +	r.extent.height = d.h; +	r.extent.depth = 1; +	assert(d.w == s.w); +	assert(d.h == s.h); +	assert(d.d == 1 && s.d == 1); +	assert(d.samples == 1 && s.samples > 1); +	ctx->check_end_rp(); +	transition(src, Resource_State::copy_src); +	transition(dst, Resource_State::copy_dst); +	vkCmdResolveImage( +		ctx->cb, +		s.image, +		state_to_image_layout(s.state), +		d.image, +		state_to_image_layout(d.state), +		1, +		&r +	); +} +  void Context::transition(Texture_Id id, Resource_State state) {  	Context_Vk* ctx = (Context_Vk*)this;  	Device_Vk* dev = ctx->dev; @@ -2434,6 +2505,14 @@ void Context::transition(Texture_Id id, Resource_State state) {  		b.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;  		src_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;  		dst_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; +	} else if ( +		src_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL && +		dst_layout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL +	) { +		b.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; +		b.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; +		src_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; +		dst_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;  	} else {  		print_err("Bad resource transition.\n");  		assert(0); @@ -2857,7 +2936,8 @@ void Pipeline_Vk::init_msaa(  	Arena& scope,  	Device_Vk* dev,  	VkGraphicsPipelineCreateInfo& info, -	const Pipeline& desc +	const Pipeline& desc, +	const Render_Pass& rpo  ) {  	VkPipelineMultisampleStateCreateInfo& mi =   		*(VkPipelineMultisampleStateCreateInfo*)arena_alloc( @@ -2869,7 +2949,7 @@ void Pipeline_Vk::init_msaa(  	zero(&mi, sizeof mi);  	mi.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;  	mi.sampleShadingEnable = VK_FALSE; -	mi.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; +	mi.rasterizationSamples = dev->get_samples(rpo.get_samples());  	info.pMultisampleState = &mi;  } @@ -3064,7 +3144,7 @@ void Pipeline_Vk::init(Device_Vk* dev, const Pso_Key& key) {  	init_input_assembly(scope, dev, info, desc);  	init_viewport(scope, info, desc);  	init_rasterisation(scope, dev, info, desc); -	init_msaa(scope, dev, info, desc); +	init_msaa(scope, dev, info, desc, key.rpo.rpo);  	init_depthstencil(scope, dev, info, desc);  	init_blending(scope, dev, info, key.rpo.rpo, desc);  	info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; @@ -3594,7 +3674,8 @@ Texture_Id Device::create_texture(  	int d,  	int mip_count,  	int array_size, -	Buffer_Id init +	Buffer_Id init, +	int samples  ) {  	VkImageCreateInfo ii{};  	VkResult r; @@ -3626,7 +3707,7 @@ Texture_Id Device::create_texture(  	ii.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;  	ii.usage = get_texture_usage(flags);  	ii.sharingMode = VK_SHARING_MODE_EXCLUSIVE; -	ii.samples = VK_SAMPLE_COUNT_1_BIT; +	ii.samples = dev->get_samples(samples);  	ii.flags = image_flags;  	r = vkCreateImage(dev->dev, &ii, &dev->ac, &image);  	if (r != VK_SUCCESS) { @@ -3684,7 +3765,8 @@ Texture_Id Device::create_texture(  		array_size,  		0,  		0, -		false +		false, +		samples  	);  	if (init) {  		Context& ctx = dev->acquire(); @@ -3747,7 +3829,8 @@ Texture_Id Device::alias_texture(  		array_size,  		start_mip,  		start_array, -		true +		true, +		texture.samples  	);  	nt.set_name(dev, name);  	return ntid; @@ -4049,7 +4132,8 @@ void Texture_Vk::init(  	int array_size,  	int start_mip,  	int start_array, -	bool alias +	bool alias, +	int samples  ) {  	t->id = id;  	t->parent = parent; @@ -4069,6 +4153,7 @@ void Texture_Vk::init(  	t->start_mip = start_mip;  	t->start_array = start_array;  	t->alias = alias; +	t->samples = samples;  }  void Texture_Vk::destroy(Device_Vk* dev) { @@ -133,6 +133,7 @@ struct Pipeline {  	Cull_Mode cull_mode;  	Vertex_Format_Id vertex_format;  	Shader_Id shader; +	int samples;  	Descriptor descriptors[pipeline_max_descriptors];  	int descriptor_count; @@ -161,7 +162,8 @@ struct Pipeline {  			blend_dst_alpha == other.blend_dst_alpha &&  			blend_mode == other.blend_mode &&  			blend_mode_alpha == other.blend_mode_alpha && -			cull_mode == other.cull_mode; +			cull_mode == other.cull_mode && +			samples == other.samples;  	}  	bool desc_layout_eq(const Pipeline& other) const { @@ -228,6 +230,7 @@ struct Render_Pass {  	struct Target {  		Texture_Id id;  		Texture_Format fmt; +		int samples;  		Clear_Mode mode;  		union {  			Colour colour; @@ -266,6 +269,11 @@ struct Render_Pass {  		}  		return true;  	} + +	int get_samples() const { +		if (colour_count) return colours[0].samples; +		return depth.samples; +	}  };  struct Vertex_Buffer_Binding { @@ -359,6 +367,7 @@ struct Texture : public Asset {  	int w, h, d;  	int mip_count, array_size;  	int start_mip, start_array; +	int samples;  	bool alias;  }; @@ -486,7 +495,8 @@ struct Device {  		int d,  		int mip_count,  		int array_size, -		Buffer_Id init +		Buffer_Id init, +		int samples = 1  	);  	Texture_Id alias_texture(  		Texture_Id o, @@ -562,6 +572,7 @@ struct Context {  		int w,  		int h  	); +	void resolve(Texture_Id dst, Texture_Id src);  	void transition(Texture_Id id, Resource_State state);  	void debug_push(const char* name);  	void debug_pop();  |