diff options
| -rw-r--r-- | c2.cpp | 4 | ||||
| -rw-r--r-- | video.cpp | 273 | 
2 files changed, 217 insertions, 60 deletions
@@ -236,6 +236,7 @@ struct Sky {  		cb->iview = cam.get_view().inverse();  		cb->iprojection = cam.get_proj().inverse();  		config.unmap(d); +		config.update(d->get_ctx());  		render_imp(  			d,  			a, @@ -284,7 +285,6 @@ struct Sky {  		draw.verts = vbb;  		draw.vertex_count = 3;  		draw.instance_count = 1; -		config.update(ctx);  		ctx.submit(draw, pip, pass);  	}  }; @@ -407,7 +407,6 @@ struct Env_Probe {  		Context& ctx = dev->get_ctx();  		update_cbuffer(dev);  		for (i = 0; i < 6; i++) { -			ctx.transition(faces[i], Resource_State::render_target);  			pb.begin_rp();  			pb.rp_target(faces[i], Clear_Mode::discard);  			pb.rp_depth_target(cubemap_depth, 1.0f); @@ -421,7 +420,6 @@ struct Env_Probe {  				cubemap_res,  				cubemap_res  			); -			ctx.transition(faces[i], Resource_State::shader_read);  		}  	}  }; @@ -3,6 +3,7 @@  #define device_heap_size (1024 * 1024 * 8)  #define max_textures 1024 +#define max_texture_alias 32  #define max_buffers 1024  #define max_vertex_formats 64  #define max_rpos 64 @@ -379,19 +380,27 @@ static VkImageViewType get_view_type(int a, int d, int flags) {  	return t;  } +template <bool Depth>  VkImageLayout state_to_image_layout(Resource_State s) {  	switch (s) {  		case undefined:     return VK_IMAGE_LAYOUT_UNDEFINED;  		case copy_dst:      return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;  		case copy_src:      return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;  		case shader_read:   return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; -		case render_target: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; +		case render_target: +			return Depth? +				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: +				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;  		case presentable:   return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;  	}  	assert(0);  	return VK_IMAGE_LAYOUT_UNDEFINED;  } +VkImageLayout state_to_image_layout(Resource_State s) { +	return state_to_image_layout<false>(s); +} +  static void* __stdcall vk_alloc(  	void* uptr,  	size_t size, @@ -616,6 +625,8 @@ struct Shader_Vk : public Shader, public Late_Terminated {  struct Renderpass_Vk;  struct Framebuffer_Vk; +struct Pipeline_Vk; +struct Rpo_Key;  struct Context_Vk : public Context {  	int state;  	Device_Vk* dev; @@ -639,10 +650,19 @@ struct Context_Vk : public Context {  	void destroy();  	std::pair<Renderpass_Vk&, Framebuffer_Vk&> begin_rp( -		const Render_Pass& rp +		const Rpo_Key& rp +	); +	void end_rp( +		const Render_Pass& rp, +		Renderpass_Vk& rpo, +		Framebuffer_Vk& fbo  	); -	void end_rp(Renderpass_Vk& rpo, Framebuffer_Vk& fbo);  	void check_end_rp(); + +	void submit_descriptors( +		const Pipeline_Vk& pso, +		const Pipeline& p +	);  };  struct Texture_Vk : public Texture, public Late_Terminated { @@ -650,10 +670,14 @@ struct Texture_Vk : public Texture, public Late_Terminated {  	VkImageView view;  	Vram_Allocator::Allocation memory;  	Resource_State state; +	Texture_Id parent; +	Texture_Id children[max_texture_alias]; +	int child_count;  	static void init(  		Texture_Vk* t,  		Texture_Id id, +		Texture_Id parent,  		VkImage img,  		VkImageView v,  		Vram_Allocator::Allocation mem, @@ -671,6 +695,9 @@ struct Texture_Vk : public Texture, public Late_Terminated {  	);  	void destroy(Device_Vk*) override;  	void set_name(Device_Vk* dev, const char* name); +	void add_child(Texture_Id id); +	void rem_child(Texture_Id id); +	bool child_states_same(Device_Vk* dev);  };  struct Buffer_Vk : public Buffer, public Late_Terminated { @@ -711,14 +738,30 @@ struct Buffer_Vk : public Buffer, public Late_Terminated {  	}  }; +struct Render_Pass_States { +	Resource_State colours[max_colour_attachments]; +	Resource_State depth; +	int colour_count; + +	bool operator==(const Render_Pass_States& other) const { +		int i; +		if (colour_count != other.colour_count) return false; +		if (depth != other.depth) return false; +		for (i = 0; i < colour_count; i++) +			if (colours[i] != other.colours[i]) +				return false; +		return true; +	} +}; +  struct Rpo_Key { -	bool is_first;  	Render_Pass rpo; +	Render_Pass_States states;  	bool operator==(const Rpo_Key& other) const {  		return -			is_first == other.is_first && -			rpo.layout_eq(other.rpo); +			rpo.layout_eq(other.rpo) && +			states == other.states;  	}  }; @@ -902,8 +945,8 @@ struct Hash_Function<Rpo_Key> {  	size_t operator()(const Rpo_Key& k) const {  		return (size_t)fnv1a64_2(  			k.rpo.layout_hash, -			(uint8_t*)&k.is_first, -			1 +			(uint8_t*)&k.states, +			sizeof k.states  		);  	}  }; @@ -1061,7 +1104,6 @@ struct Device_Vk : public Device {  	Terminator* terminators;  	uint32_t terminator_index; -	bool first_rp;  	Texture_Id depth; @@ -1116,6 +1158,7 @@ struct Device_Vk : public Device {  		uint32_t filter,  		VkMemoryPropertyFlags flags  	); +	Render_Pass_States get_rp_states(const Render_Pass& p);  };  #ifdef DEBUG @@ -1682,6 +1725,25 @@ int Device_Vk::find_memory_type(  	return -1;  } +Render_Pass_States Device_Vk::get_rp_states( +	const Render_Pass& p +) { +	int i; +	Render_Pass_States s{}; +	s.colour_count = p.colour_count; +	for (i = 0; i < p.colour_count; i++) { +		Texture_Vk& t = +			*(Texture_Vk*)&get_texture(p.colours[i].id); +		s.colours[i] = t.state; +	} +	if (p.depth.id) { +		Texture_Vk& t = +			*(Texture_Vk*)&get_texture(p.depth.id); +		s.depth = t.state; +	} +	return s; +} +  VkAttachmentLoadOp Renderpass_Vk::load_op_from_mode(  	Clear_Mode m  ) { @@ -1704,6 +1766,7 @@ void Renderpass_Vk::init(  	VkSubpassDescription sd{};  	VkResult r;  	auto& rp = rpk.rpo; +	auto& states = rpk.states;  	bool has_depth = rp.depth.id;  	int count = 0, i, c = rp.colour_count;  	zero(ads, sizeof ads); @@ -1717,10 +1780,11 @@ void Renderpass_Vk::init(  		ad.storeOp = VK_ATTACHMENT_STORE_OP_STORE;  		ad.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;  		ad.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; -		if (rpk.is_first) -			ad.initialLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; -		else -			ad.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; +		if (colour.mode == Clear_Mode::restore) { +			Resource_State state = states.colours[i]; +			ad.initialLayout = state_to_image_layout(state); +		} else +			ad.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;  		ad.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;  		car.attachment = index;  		car.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; @@ -1734,10 +1798,11 @@ void Renderpass_Vk::init(  		ad.storeOp = VK_ATTACHMENT_STORE_OP_STORE;  		ad.stencilLoadOp = ad.loadOp;  		ad.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; -		if (rp.depth.mode != Clear_Mode::restore) +		if (rp.depth.mode == Clear_Mode::restore) { +			Resource_State state = states.depth; +			ad.initialLayout = state_to_image_layout<true>(state); +		} else  			ad.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; -		else -			ad.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;  		ad.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;  		dar.attachment = i;  		dar.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; @@ -1934,6 +1999,7 @@ Texture_Id Swapchain::create_image(  	Texture_Vk::init(  		&tex,  		id, +		0,  		image,  		view,  		Vram_Allocator::Allocation::null(), @@ -1982,9 +2048,6 @@ void Swapchain::get_images(Device_Vk* dev) {  			size.width,  			size.height  		); -		/* needs to be presentable since the first renderpass -		 * will expect it to be presentable from "last" frame */ -		ctx.transition(textures[i], Resource_State::presentable);  	}  	dev->submit(ctx);  	heap_free(dev->heap, images); @@ -2047,7 +2110,6 @@ void Device::begin_frame() {  		&dev->backbuffer_index  	);  	dev->backbuffer_id = dev->swapchain.textures[dev->backbuffer_index]; -	dev->first_rp = true;  }  void Device::submit(Context& ctx_) { @@ -2205,13 +2267,9 @@ void Context::submit(  	Context_Vk* ctx = (Context_Vk*)this;  	Device_Vk* dev = ctx->dev;  	Vertex_Buffer_Binding* binding; -	Rpo_Key rpo_key = { dev->first_rp, rp }; +	Rpo_Key rpo_key = { rp, dev->get_rp_states(rp) };  	Pso_Key pso_key = { p, rpo_key };  	Pipeline_Vk& pso = dev->get_pso(pso_key); -	Descriptor_Set_Vk* dso = 0; -	if (p.descriptor_count) -		dso = &dev->get_dso(pso, *(Dso_Key*)&p); -	auto [rpo, fbo] = ctx->begin_rp(rp);  	Texture_Vk& target = *(Texture_Vk*)&dev->get_texture(  		dev->get_backbuffer()  	); @@ -2223,19 +2281,8 @@ void Context::submit(  			pso.pip  		);  	ctx->last_pso = pso.pip; -	if (dso && dso->dset != ctx->last_dso) { -		vkCmdBindDescriptorSets( -			ctx->cb, -			VK_PIPELINE_BIND_POINT_GRAPHICS, -			pso.lay, -			0, -			1, -			&dso->dset, -			0, -			0 -		); -		ctx->last_dso = dso->dset; -	} +	ctx->submit_descriptors(pso, p); +	auto [rpo, fbo] = ctx->begin_rp(rpo_key);  	for (binding = draw.verts; binding->id; binding++) {  		VkBuffer buf = ((Buffer_Vk*)&dev->get_buffer(binding->id))->buf;  		VkDeviceSize offset = (VkDeviceSize)binding->offset; @@ -2268,10 +2315,8 @@ void Context::submit(  			draw.first_instance  		);  	} -	ctx->end_rp(rpo, fbo); +	ctx->end_rp(rp, rpo, fbo);  	pso.on_submit(); -	if (dso) -		dso->on_submit();  }  void Context::submit( @@ -2316,6 +2361,7 @@ void Context::copy(Texture_Id dst, Buffer_Id src) {  	Texture_Vk& a = *(Texture_Vk*)&dev->get_texture(dst);  	Buffer_Vk& b = *(Buffer_Vk*)&dev->get_buffer(src);  	VkBufferImageCopy c{}; +	transition(dst, Resource_State::copy_dst);  	c.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;  	c.imageSubresource.layerCount = 1;  	c.imageExtent.width = a.w; @@ -2337,12 +2383,35 @@ void Context::transition(Texture_Id id, Resource_State state) {  	Device_Vk* dev = ctx->dev;  	Texture_Vk& tex = *(Texture_Vk*)&dev->get_texture(id);  	VkImageMemoryBarrier b{}; +	int c = tex.child_count;  	VkImageLayout src_layout = state_to_image_layout(tex.state);  	VkImageLayout dst_layout = state_to_image_layout(state);  	VkPipelineStageFlags src_stage, dst_stage; +	if (c) { +		if (tex.child_states_same(dev)) { +			tex.state = +				((Texture_Vk*)&dev->get_texture(tex.children[0]))->state; +			src_layout = state_to_image_layout(tex.state); +		} else { +			ctx->check_end_rp(); +			int i; +			for (i = 0; i < c; i++) { +				transition(tex.children[i], state); +			} +			tex.state = state; +			return; +		} +	}  	if (tex.state == state) return;  	ctx->check_end_rp(); -	tex.state = state; +	tex.state = state; { +		int i; +		for (i = 0; i < c; i++) { +			Texture_Vk& child = +				*(Texture_Vk*)&dev->get_texture(tex.children[i]); +			child.state = state; +		} +	}  	b.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;  	b.oldLayout = src_layout;  	b.newLayout = dst_layout; @@ -2489,9 +2558,10 @@ void Context::debug_pop() {  }  std::pair<Renderpass_Vk&, Framebuffer_Vk&> Context_Vk::begin_rp( -	const Render_Pass& rp +	const Rpo_Key& rpk  ) { -	Renderpass_Vk& rpo = dev->get_rpo({ dev->first_rp, rp}); +	const Render_Pass& rp = rpk.rpo; +	Renderpass_Vk& rpo = dev->get_rpo(rpk);  	Framebuffer_Vk& fbo = dev->get_fbo(rpo, { rp });  	VkRenderPassBeginInfo rpbi{};  	VkClearValue clears[max_colour_attachments + 1]; @@ -2518,8 +2588,6 @@ std::pair<Renderpass_Vk&, Framebuffer_Vk&> Context_Vk::begin_rp(  		dc.depthStencil.depth = rp.depth.clear.depth;  		dc.depthStencil.stencil = 0; /* todo */  		clears[clear_count++] = dc; -		if (rp.depth.mode == Clear_Mode::restore) -			transition(rp.depth.id, Resource_State::render_target);  	}  	rpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;  	rpbi.renderPass = rpo.rpo; @@ -2532,13 +2600,28 @@ std::pair<Renderpass_Vk&, Framebuffer_Vk&> Context_Vk::begin_rp(  		&rpbi,  		VK_SUBPASS_CONTENTS_INLINE  	); -	dev->first_rp = false;  	last_rpo = rpo.rpo;  	last_fbo = fbo.fbo;  	return { rpo, fbo };  } -void Context_Vk::end_rp(Renderpass_Vk& rpo, Framebuffer_Vk& fbo) { +void Context_Vk::end_rp( +	const Render_Pass& rp, +	Renderpass_Vk& rpo, +	Framebuffer_Vk& fbo +) { +	bool has_depth = rp.depth.id; +	int i, c = rp.colour_count; +	for (i = 0; i < c; i++){ +		Texture_Vk& tex = +			*(Texture_Vk*)&dev->get_texture(rp.colours[i].id); +		tex.state = Resource_State::render_target; +	} +	if (has_depth) { +		Texture_Vk& tex = +			*(Texture_Vk*)&dev->get_texture(rp.depth.id); +		tex.state = Resource_State::render_target; +	}  	rpo.on_submit();  	fbo.on_submit();  } @@ -2550,10 +2633,49 @@ void Context_Vk::check_end_rp() {  	}  } +void Context_Vk::submit_descriptors( +	const Pipeline_Vk& pso, +	const Pipeline& p +) { +	Descriptor_Set_Vk* dso = 0; +	if (p.descriptor_count) { +		dso = &dev->get_dso(pso, *(Dso_Key*)&p); +		if (dso->dset == last_dso) return; + +		int i, c = p.descriptor_count; +		for (i = 0; i < c; i++) { +			const auto& desc = p.descriptors[i]; +			switch (desc.type) { +				case Descriptor::Type::texture: { +					const auto& td = *(const Texture_Descriptor*)desc.payload; +					transition(td.texture, Resource_State::shader_read); +				} break; +				case Descriptor::Type::constant_buffer: +					break; /* todo */ +			} +		} +		vkCmdBindDescriptorSets( +			cb, +			VK_PIPELINE_BIND_POINT_GRAPHICS, +			pso.lay, +			0, +			1, +			&dso->dset, +			0, +			0 +		); +		last_dso = dso->dset; +		dso->on_submit(); +	} +} +  void Context::submit(const Render_Pass& rp) {  	Context_Vk* ctx = (Context_Vk*)this; -	auto [rpo, fbo] = ctx->begin_rp(rp); -	ctx->end_rp(rpo, fbo); +	auto [rpo, fbo] = ctx->begin_rp({ +		rp, +		ctx->dev->get_rp_states(rp) +	}); +	ctx->end_rp(rp, rpo, fbo);  }  void Context_Vk::init_pool() { @@ -3538,9 +3660,8 @@ Texture_Id Device::create_texture(  	VkImageAspectFlags aspect = get_image_aspect(fmt, flags);  	VkImageViewCreateInfo vi{};  	VkImageCreateFlags image_flags = 0; -	int array_count = array_size;  	if (flags & Texture_Flags::cubemap) { -		array_count *= 6; +		array_size *= 6;  		image_flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;  	}  	if (mip_count == 0) @@ -3551,7 +3672,7 @@ Texture_Id Device::create_texture(  	ii.extent.height = h;  	ii.extent.depth = d;  	ii.mipLevels = mip_count; -	ii.arrayLayers = array_count; +	ii.arrayLayers = array_size;  	ii.format = get_vk_format(fmt);  	ii.tiling = VK_IMAGE_TILING_OPTIMAL;  	ii.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -3586,13 +3707,13 @@ Texture_Id Device::create_texture(  	);  	vi.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;  	vi.image = image; -	vi.viewType = get_view_type(array_count, d, flags); +	vi.viewType = get_view_type(array_size, d, flags);  	vi.format = ii.format;  	vi.subresourceRange.aspectMask = aspect;  	vi.subresourceRange.baseMipLevel = 0;  	vi.subresourceRange.levelCount = mip_count;  	vi.subresourceRange.baseArrayLayer = 0; -	vi.subresourceRange.layerCount = array_count; +	vi.subresourceRange.layerCount = array_size;  	r = vkCreateImageView(dev->dev, &vi, &dev->ac, &view);  	if (r != VK_SUCCESS) {  		print_err("Failed to make image view.\n"); @@ -3601,6 +3722,7 @@ Texture_Id Device::create_texture(  	Texture_Vk::init(  		&tex,  		id, +		0,  		image,  		view,  		mem, @@ -3618,9 +3740,7 @@ Texture_Id Device::create_texture(  	);  	if (init) {  		Context& ctx = dev->acquire(); -		ctx.transition(id, Resource_State::copy_dst);  		ctx.copy(id, init); -		ctx.transition(id, Resource_State::shader_read);  		dev->submit(ctx);  	}  	tex.set_name(dev, name); @@ -3665,6 +3785,7 @@ Texture_Id Device::alias_texture(  	Texture_Vk::init(  		&nt,  		ntid, +		o,  		texture.image,  		view,  		Vram_Allocator::Allocation::null(), @@ -3680,6 +3801,7 @@ Texture_Id Device::alias_texture(  		start_array,  		true  	); +	texture.add_child(ntid);  	nt.set_name(dev, name);  	return ntid;  } @@ -3703,6 +3825,37 @@ void Texture_Vk::set_name(Device_Vk* dev, const char* name) {  #endif  } +void Texture_Vk::add_child(Texture_Id id) { +	assert(child_count < max_texture_alias); +	children[child_count++] = id; +} + +void Texture_Vk::rem_child(Texture_Id id) { +	int i; +	for (i = 0; i < child_count; i++) { +		if (children[i] == id) { +			children[i] = children[child_count - 1]; +			return; +		} +	} +} + +bool Texture_Vk::child_states_same(Device_Vk* dev) { +	int i, c = child_count; +	bool r = true; +	for (i = 0; i < c; i++) { +		Texture_Vk& a = +			*(Texture_Vk*)&dev->get_texture(children[i]); +		int j; +		for (j = i + 1; j < c; j++) { +			Texture_Vk& b = +				*(Texture_Vk*)&dev->get_texture(children[j]); +			if (a.state != b.state) r = false; +		} +	} +	return r; +} +  Shader& Device::get_shader(Shader_Id id) {  	Device_Vk* dev = (Device_Vk*)this;  	assert(id.index); @@ -3943,6 +4096,7 @@ void Texture_Loader::unload(Asset* a) {  void Texture_Vk::init(  	Texture_Vk* t,  	Texture_Id id, +	Texture_Id parent,  	VkImage img,  	VkImageView v,  	Vram_Allocator::Allocation mem, @@ -3959,6 +4113,7 @@ void Texture_Vk::init(  	bool alias  ) {  	t->id = id; +	t->parent = parent;  	t->image = img;  	t->view = v;  	t->memory = mem; @@ -3982,6 +4137,10 @@ void Texture_Vk::destroy(Device_Vk* dev) {  		vkDestroyImage(dev->dev, image, &dev->ac);  		dev->vrama.free(memory);  	} +	if (parent) { +		Texture_Vk& t = *(Texture_Vk*)&dev->get_texture(parent); +		t.rem_child(id); +	}  	vkDestroyImageView(dev->dev, view, &dev->ac);  	dev->textures.remove(id);  }  |