Kaynağa Gözat

Merge pull request #37808 from reduz/port-effects-to-compute

Moved most of the effect code to compute.
Juan Linietsky 5 yıl önce
ebeveyn
işleme
9dc19f7619

+ 55 - 31
drivers/vulkan/rendering_device_vulkan.cpp

@@ -1568,17 +1568,22 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
 #ifndef _MSC_VER
 #warning TODO check for support via RenderingDevice to enable on mobile when possible
 #endif
-	// vkCreateImage fails with format list on Android (VK_ERROR_OUT_OF_HOST_MEMORY)
+
 #ifndef ANDROID_ENABLED
+
+	// vkCreateImage fails with format list on Android (VK_ERROR_OUT_OF_HOST_MEMORY)
+	VkImageFormatListCreateInfoKHR format_list_create_info; //keep out of the if, needed for creation
+	Vector<VkFormat> allowed_formats; //keep out of the if, needed for creation
+#endif
 	if (p_format.shareable_formats.size()) {
 		image_create_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
 
-		Vector<VkFormat> allowed_formats;
+#ifndef ANDROID_ENABLED
+
 		for (int i = 0; i < p_format.shareable_formats.size(); i++) {
 			allowed_formats.push_back(vulkan_formats[p_format.shareable_formats[i]]);
 		}
 
-		VkImageFormatListCreateInfoKHR format_list_create_info;
 		format_list_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR;
 		format_list_create_info.pNext = nullptr;
 		format_list_create_info.viewFormatCount = allowed_formats.size();
@@ -1589,8 +1594,9 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
 				"If supplied a list of shareable formats, the current format must be present in the list");
 		ERR_FAIL_COND_V_MSG(p_view.format_override != DATA_FORMAT_MAX && p_format.shareable_formats.find(p_view.format_override) == -1, RID(),
 				"If supplied a list of shareable formats, the current view format override must be present in the list");
-	}
 #endif
+	}
+
 	if (p_format.type == TEXTURE_TYPE_CUBE || p_format.type == TEXTURE_TYPE_CUBE_ARRAY) {
 		image_create_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
 	}
@@ -1766,6 +1772,8 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
 	texture.depth = image_create_info.extent.depth;
 	texture.layers = image_create_info.arrayLayers;
 	texture.mipmaps = image_create_info.mipLevels;
+	texture.base_mipmap = 0;
+	texture.base_layer = 0;
 	texture.usage_flags = p_format.usage_bits;
 	texture.samples = p_format.samples;
 	texture.allowed_shared_formats = p_format.shareable_formats;
@@ -2006,6 +2014,8 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
 	get_image_format_required_size(texture.format, texture.width, texture.height, texture.depth, p_mipmap + 1, &texture.width, &texture.height);
 	texture.mipmaps = 1;
 	texture.layers = p_slice_type == TEXTURE_SLICE_CUBEMAP ? 6 : 1;
+	texture.base_mipmap = p_mipmap;
+	texture.base_layer = p_layer;
 
 	VkImageViewCreateInfo image_view_create_info;
 	image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
@@ -2688,8 +2698,8 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
 		src_layer_count *= 6;
 	}
 
-	ERR_FAIL_COND_V(p_base_mipmap + p_mipmaps > src_tex->mipmaps, ERR_INVALID_PARAMETER);
-	ERR_FAIL_COND_V(p_base_layer + p_layers > src_layer_count, ERR_INVALID_PARAMETER);
+	ERR_FAIL_COND_V(src_tex->base_mipmap + p_base_mipmap + p_mipmaps > src_tex->mipmaps, ERR_INVALID_PARAMETER);
+	ERR_FAIL_COND_V(src_tex->base_layer + p_base_layer + p_layers > src_layer_count, ERR_INVALID_PARAMETER);
 
 	VkCommandBuffer command_buffer = p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer;
 
@@ -2708,9 +2718,9 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
 		image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
 		image_memory_barrier.image = src_tex->image;
 		image_memory_barrier.subresourceRange.aspectMask = src_tex->read_aspect_mask;
-		image_memory_barrier.subresourceRange.baseMipLevel = p_base_mipmap;
+		image_memory_barrier.subresourceRange.baseMipLevel = src_tex->base_mipmap + p_base_mipmap;
 		image_memory_barrier.subresourceRange.levelCount = p_mipmaps;
-		image_memory_barrier.subresourceRange.baseArrayLayer = p_base_layer;
+		image_memory_barrier.subresourceRange.baseArrayLayer = src_tex->base_layer + p_base_layer;
 		image_memory_barrier.subresourceRange.layerCount = p_layers;
 
 		layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
@@ -2746,9 +2756,9 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
 		image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
 		image_memory_barrier.image = src_tex->image;
 		image_memory_barrier.subresourceRange.aspectMask = src_tex->read_aspect_mask;
-		image_memory_barrier.subresourceRange.baseMipLevel = p_base_mipmap;
+		image_memory_barrier.subresourceRange.baseMipLevel = src_tex->base_mipmap + p_base_mipmap;
 		image_memory_barrier.subresourceRange.levelCount = p_mipmaps;
-		image_memory_barrier.subresourceRange.baseArrayLayer = p_base_layer;
+		image_memory_barrier.subresourceRange.baseArrayLayer = src_tex->base_layer + p_base_layer;
 		image_memory_barrier.subresourceRange.layerCount = p_layers;
 
 		vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
@@ -2846,6 +2856,21 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
 					description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
 				}
 			} break;
+			case INITIAL_ACTION_DROP: {
+				if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
+					description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+					description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+					description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+				} else if (p_format[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+					description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+					description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
+					description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+				} else {
+					description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+					description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+					description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
+				}
+			} break;
 			case INITIAL_ACTION_CONTINUE: {
 				if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
 					description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
@@ -4325,6 +4350,10 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 						attachable_textures.push_back(texture->owner.is_valid() ? texture->owner : uniform.ids[j + 1]);
 					}
 
+					if (texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT) {
+						//can also be used as storage, add to mutable sampled
+						mutable_sampled_textures.push_back(texture);
+					}
 					if (texture->owner.is_valid()) {
 						texture = texture_owner.getornull(texture->owner);
 						ERR_FAIL_COND_V(!texture, RID()); //bug, should never happen
@@ -4333,11 +4362,6 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 					img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 
 					image_info.push_back(img_info);
-
-					if (texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT) {
-						//can also be used as storage, add to mutable sampled
-						mutable_sampled_textures.push_back(texture);
-					}
 				}
 
 				write.dstArrayElement = 0;
@@ -4377,6 +4401,11 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 						attachable_textures.push_back(texture->owner.is_valid() ? texture->owner : uniform.ids[j]);
 					}
 
+					if (texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT) {
+						//can also be used as storage, add to mutable sampled
+						mutable_sampled_textures.push_back(texture);
+					}
+
 					if (texture->owner.is_valid()) {
 						texture = texture_owner.getornull(texture->owner);
 						ERR_FAIL_COND_V(!texture, RID()); //bug, should never happen
@@ -4385,11 +4414,6 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 					img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 
 					image_info.push_back(img_info);
-
-					if (texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT) {
-						//can also be used as storage, add to mutable sampled
-						mutable_sampled_textures.push_back(texture);
-					}
 				}
 
 				write.dstArrayElement = 0;
@@ -4426,6 +4450,11 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 					img_info.sampler = VK_NULL_HANDLE;
 					img_info.imageView = texture->view;
 
+					if (texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT) {
+						//can also be used as storage, add to mutable sampled
+						mutable_storage_textures.push_back(texture);
+					}
+
 					if (texture->owner.is_valid()) {
 						texture = texture_owner.getornull(texture->owner);
 						ERR_FAIL_COND_V(!texture, RID()); //bug, should never happen
@@ -4434,11 +4463,6 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 					img_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
 
 					image_info.push_back(img_info);
-
-					if (texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT) {
-						//can also be used as storage, add to mutable sampled
-						mutable_storage_textures.push_back(texture);
-					}
 				}
 
 				write.dstArrayElement = 0;
@@ -6206,9 +6230,9 @@ void RenderingDeviceVulkan::compute_list_bind_uniform_set(ComputeListID p_list,
 			image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
 			image_memory_barrier.image = textures_to_sampled[i]->image;
 			image_memory_barrier.subresourceRange.aspectMask = textures_to_sampled[i]->read_aspect_mask;
-			image_memory_barrier.subresourceRange.baseMipLevel = 0;
+			image_memory_barrier.subresourceRange.baseMipLevel = textures_to_sampled[i]->base_mipmap;
 			image_memory_barrier.subresourceRange.levelCount = textures_to_sampled[i]->mipmaps;
-			image_memory_barrier.subresourceRange.baseArrayLayer = 0;
+			image_memory_barrier.subresourceRange.baseArrayLayer = textures_to_sampled[i]->base_layer;
 			image_memory_barrier.subresourceRange.layerCount = textures_to_sampled[i]->layers;
 
 			vkCmdPipelineBarrier(cl->command_buffer, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
@@ -6237,9 +6261,9 @@ void RenderingDeviceVulkan::compute_list_bind_uniform_set(ComputeListID p_list,
 			image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
 			image_memory_barrier.image = textures_to_storage[i]->image;
 			image_memory_barrier.subresourceRange.aspectMask = textures_to_storage[i]->read_aspect_mask;
-			image_memory_barrier.subresourceRange.baseMipLevel = 0;
+			image_memory_barrier.subresourceRange.baseMipLevel = textures_to_storage[i]->base_mipmap;
 			image_memory_barrier.subresourceRange.levelCount = textures_to_storage[i]->mipmaps;
-			image_memory_barrier.subresourceRange.baseArrayLayer = 0;
+			image_memory_barrier.subresourceRange.baseArrayLayer = textures_to_storage[i]->base_layer;
 			image_memory_barrier.subresourceRange.layerCount = textures_to_storage[i]->layers;
 
 			vkCmdPipelineBarrier(cl->command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
@@ -6369,9 +6393,9 @@ void RenderingDeviceVulkan::compute_list_end() {
 		image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
 		image_memory_barrier.image = E->get()->image;
 		image_memory_barrier.subresourceRange.aspectMask = E->get()->read_aspect_mask;
-		image_memory_barrier.subresourceRange.baseMipLevel = 0;
+		image_memory_barrier.subresourceRange.baseMipLevel = E->get()->base_mipmap;
 		image_memory_barrier.subresourceRange.levelCount = E->get()->mipmaps;
-		image_memory_barrier.subresourceRange.baseArrayLayer = 0;
+		image_memory_barrier.subresourceRange.baseArrayLayer = E->get()->base_layer;
 		image_memory_barrier.subresourceRange.layerCount = E->get()->layers;
 
 		vkCmdPipelineBarrier(compute_list->command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);

+ 2 - 0
drivers/vulkan/rendering_device_vulkan.h

@@ -138,6 +138,8 @@ class RenderingDeviceVulkan : public RenderingDevice {
 		uint32_t layers;
 		uint32_t mipmaps;
 		uint32_t usage_flags;
+		uint32_t base_mipmap;
+		uint32_t base_layer;
 
 		Vector<DataFormat> allowed_shared_formats;
 

+ 207 - 147
servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp

@@ -99,7 +99,7 @@ RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use
 	u.ids.push_back(p_texture);
 	uniforms.push_back(u);
 	//any thing with the same configuration (one texture in binding 0 for set 0), is good
-	RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, blur.shader.version_get_shader(blur.shader_version, 0), 0);
+	RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, 0), 0);
 
 	texture_to_uniform_set_cache[p_texture] = uniform_set;
 
@@ -204,154 +204,199 @@ RID RasterizerEffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1
 	return uniform_set;
 }
 
-void RasterizerEffectsRD::copy_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y, float p_z_near, float p_z_far) {
+void RasterizerEffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance) {
+	zeromem(&copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
 
-	zeromem(&blur.push_constant, sizeof(BlurPushConstant));
 	if (p_flip_y) {
-		blur.push_constant.flags |= BLUR_FLAG_FLIP_Y;
+		copy_to_fb.push_constant.flip_y = true;
+	}
+	if (p_force_luminance) {
+		copy_to_fb.push_constant.force_luminance = true;
 	}
-
-	blur.push_constant.camera_z_near = p_z_near;
-	blur.push_constant.camera_z_far = p_z_far;
 
 	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect);
-	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_LINEARIZE_DEPTH].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
 	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
 	RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-	RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
+	RD::get_singleton()->draw_list_set_push_constant(draw_list, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
 	RD::get_singleton()->draw_list_draw(draw_list, true);
 	RD::get_singleton()->draw_list_end();
 }
 
-void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y, bool p_force_luminance) {
+void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_all_source, bool p_8_bit_dst) {
 
-	zeromem(&blur.push_constant, sizeof(BlurPushConstant));
+	zeromem(&copy.push_constant, sizeof(CopyPushConstant));
 	if (p_flip_y) {
-		blur.push_constant.flags |= BLUR_FLAG_FLIP_Y;
+		copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
 	}
+
 	if (p_force_luminance) {
-		blur.push_constant.flags |= BLUR_COPY_FORCE_LUMINANCE;
+		copy.push_constant.flags |= COPY_FLAG_FORCE_LUMINANCE;
 	}
 
-	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect);
-	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_SIMPLY_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
-	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
-	RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-	RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
-	RD::get_singleton()->draw_list_draw(draw_list, true);
-	RD::get_singleton()->draw_list_end();
+	if (p_all_source) {
+		copy.push_constant.flags |= COPY_FLAG_ALL_SOURCE;
+	}
+
+	copy.push_constant.section[0] = 0;
+	copy.push_constant.section[1] = 0;
+	copy.push_constant.section[2] = p_rect.size.width;
+	copy.push_constant.section[3] = p_rect.size.height;
+	copy.push_constant.target[0] = p_rect.position.x;
+	copy.push_constant.target[1] = p_rect.position.y;
+
+	int32_t x_groups = (p_rect.size.width - 1) / 8 + 1;
+	int32_t y_groups = (p_rect.size.height - 1) / 8 + 1;
+
+	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8_bit_dst ? COPY_MODE_SIMPLY_COPY_8BIT : COPY_MODE_SIMPLY_COPY]);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
+	RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+	RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+	RD::get_singleton()->compute_list_end();
 }
 
-void RasterizerEffectsRD::region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region) {
+void RasterizerEffectsRD::copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far) {
+
+	zeromem(&copy.push_constant, sizeof(CopyPushConstant));
+	if (p_flip_y) {
+		copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
+	}
+
+	copy.push_constant.section[0] = 0;
+	copy.push_constant.section[1] = 0;
+	copy.push_constant.section[2] = p_rect.size.width;
+	copy.push_constant.section[3] = p_rect.size.height;
+	copy.push_constant.target[0] = p_rect.position.x;
+	copy.push_constant.target[1] = p_rect.position.y;
+	copy.push_constant.camera_z_far = p_z_far;
+	copy.push_constant.camera_z_near = p_z_near;
+
+	int32_t x_groups = (p_rect.size.width - 1) / 8 + 1;
+	int32_t y_groups = (p_rect.size.height - 1) / 8 + 1;
+
+	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_LINEARIZE_DEPTH]);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
+	RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+	RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+	RD::get_singleton()->compute_list_end();
+}
 
-	zeromem(&blur.push_constant, sizeof(BlurPushConstant));
+void RasterizerEffectsRD::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y) {
 
-	if (p_region != Rect2()) {
-		blur.push_constant.flags = BLUR_FLAG_USE_BLUR_SECTION;
-		blur.push_constant.section[0] = p_region.position.x;
-		blur.push_constant.section[1] = p_region.position.y;
-		blur.push_constant.section[2] = p_region.size.width;
-		blur.push_constant.section[3] = p_region.size.height;
+	zeromem(&copy.push_constant, sizeof(CopyPushConstant));
+	if (p_flip_y) {
+		copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
 	}
 
-	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
-	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_SIMPLY_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
-	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
-	RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-	RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
-	RD::get_singleton()->draw_list_draw(draw_list, true);
-	RD::get_singleton()->draw_list_end();
+	copy.push_constant.section[0] = 0;
+	copy.push_constant.section[1] = 0;
+	copy.push_constant.section[2] = p_rect.size.width;
+	copy.push_constant.section[3] = p_rect.size.height;
+	copy.push_constant.target[0] = p_rect.position.x;
+	copy.push_constant.target[1] = p_rect.position.y;
+
+	int32_t x_groups = (p_rect.size.width - 1) / 8 + 1;
+	int32_t y_groups = (p_rect.size.height - 1) / 8 + 1;
+
+	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_SIMPLY_COPY_DEPTH]);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
+	RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+	RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+	RD::get_singleton()->compute_list_end();
 }
 
-void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region) {
+void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst) {
 
-	zeromem(&blur.push_constant, sizeof(BlurPushConstant));
+	zeromem(&copy.push_constant, sizeof(CopyPushConstant));
 
 	uint32_t base_flags = 0;
-	if (p_region != Rect2()) {
-		base_flags = BLUR_FLAG_USE_BLUR_SECTION;
-		blur.push_constant.section[0] = p_region.position.x;
-		blur.push_constant.section[1] = p_region.position.y;
-		blur.push_constant.section[2] = p_region.size.width;
-		blur.push_constant.section[3] = p_region.size.height;
-	}
-
-	blur.push_constant.pixel_size[0] = p_pixel_size.x;
-	blur.push_constant.pixel_size[1] = p_pixel_size.y;
+	copy.push_constant.section[0] = p_region.position.x;
+	copy.push_constant.section[1] = p_region.position.y;
+	copy.push_constant.section[2] = p_region.size.width;
+	copy.push_constant.section[3] = p_region.size.height;
 
+	int32_t x_groups = (p_region.size.width - 1) / 8 + 1;
+	int32_t y_groups = (p_region.size.height - 1) / 8 + 1;
 	//HORIZONTAL
-	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
-	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_GAUSSIAN_BLUR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half)));
-	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
-	RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+	RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin();
+	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_GAUSSIAN_COPY_8BIT : COPY_MODE_GAUSSIAN_COPY]);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_back_texture), 0);
 
-	blur.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL;
-	RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
+	copy.push_constant.flags = base_flags | COPY_FLAG_HORIZONTAL;
+	RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
 
-	RD::get_singleton()->draw_list_draw(draw_list, true);
-	RD::get_singleton()->draw_list_end();
+	RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+
+	RD::get_singleton()->compute_list_add_barrier(compute_list);
 
 	//VERTICAL
-	draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
-	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_GAUSSIAN_BLUR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
-	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_rd_texture_half), 0);
-	RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_back_texture), 0);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_texture), 0);
 
-	blur.push_constant.flags = base_flags;
-	RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
+	copy.push_constant.flags = base_flags;
+	RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
 
-	RD::get_singleton()->draw_list_draw(draw_list, true);
-	RD::get_singleton()->draw_list_end();
+	RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+	RD::get_singleton()->compute_list_end();
 }
 
-void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
 
-	zeromem(&blur.push_constant, sizeof(BlurPushConstant));
+	zeromem(&copy.push_constant, sizeof(CopyPushConstant));
 
-	BlurMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW;
+	CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW;
 	uint32_t base_flags = 0;
 
-	blur.push_constant.pixel_size[0] = p_pixel_size.x;
-	blur.push_constant.pixel_size[1] = p_pixel_size.y;
+	int32_t x_groups = (p_size.width - 1) / 8 + 1;
+	int32_t y_groups = (p_size.height - 1) / 8 + 1;
 
-	blur.push_constant.glow_strength = p_strength;
-	blur.push_constant.glow_bloom = p_bloom;
-	blur.push_constant.glow_hdr_threshold = p_hdr_bleed_treshold;
-	blur.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
-	blur.push_constant.glow_exposure = p_exposure;
-	blur.push_constant.glow_white = 0; //actually unused
-	blur.push_constant.glow_luminance_cap = p_luminance_cap;
+	copy.push_constant.section[2] = p_size.x;
+	copy.push_constant.section[3] = p_size.y;
 
-	blur.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
+	copy.push_constant.glow_strength = p_strength;
+	copy.push_constant.glow_bloom = p_bloom;
+	copy.push_constant.glow_hdr_threshold = p_hdr_bleed_treshold;
+	copy.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
+	copy.push_constant.glow_exposure = p_exposure;
+	copy.push_constant.glow_white = 0; //actually unused
+	copy.push_constant.glow_luminance_cap = p_luminance_cap;
+
+	copy.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
 
 	//HORIZONTAL
-	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
-	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half)));
-	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
+	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_back_texture), 3);
 	if (p_auto_exposure.is_valid() && p_first_pass) {
-		RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_auto_exposure), 1);
+		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_auto_exposure), 1);
 	}
-	RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
 
-	blur.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0);
-	RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
+	copy.push_constant.flags = base_flags | COPY_FLAG_HORIZONTAL | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0);
+	RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
 
-	RD::get_singleton()->draw_list_draw(draw_list, true);
-	RD::get_singleton()->draw_list_end();
+	RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+	RD::get_singleton()->compute_list_add_barrier(compute_list);
 
-	blur_mode = BLUR_MODE_GAUSSIAN_GLOW;
+	copy_mode = COPY_MODE_GAUSSIAN_GLOW;
 
 	//VERTICAL
-	draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
-	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
-	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_rd_texture_half), 0);
-	RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_back_texture), 0);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_texture), 3);
 
-	blur.push_constant.flags = base_flags;
-	RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
+	copy.push_constant.flags = base_flags;
+	RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
 
-	RD::get_singleton()->draw_list_draw(draw_list, true);
-	RD::get_singleton()->draw_list_end();
+	RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+	RD::get_singleton()->compute_list_end();
 }
 
 void RasterizerEffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_roughness, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) {
@@ -560,37 +605,49 @@ void RasterizerEffectsRD::merge_specular(RID p_dest_framebuffer, RID p_specular,
 	RD::get_singleton()->draw_list_end();
 }
 
-void RasterizerEffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_framebuffer, const Vector2 &p_pixel_size) {
+void RasterizerEffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) {
 
-	zeromem(&blur.push_constant, sizeof(BlurPushConstant));
+	zeromem(&copy.push_constant, sizeof(CopyPushConstant));
 
-	blur.push_constant.pixel_size[0] = p_pixel_size.x;
-	blur.push_constant.pixel_size[1] = p_pixel_size.y;
+	copy.push_constant.section[0] = 0;
+	copy.push_constant.section[1] = 0;
+	copy.push_constant.section[2] = p_size.width;
+	copy.push_constant.section[3] = p_size.height;
 
-	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
-	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_MIPMAP].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
-	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
-	RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-	RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
-	RD::get_singleton()->draw_list_draw(draw_list, true);
-	RD::get_singleton()->draw_list_end();
+	int32_t x_groups = (p_size.width - 1) / 8 + 1;
+	int32_t y_groups = (p_size.height - 1) / 8 + 1;
+
+	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_MIPMAP]);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
+	RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+	RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+	RD::get_singleton()->compute_list_end();
 }
 
-void RasterizerEffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip) {
+void RasterizerEffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip) {
 
 	CopyToDPPushConstant push_constant;
+	push_constant.screen_size[0] = p_rect.size.x;
+	push_constant.screen_size[1] = p_rect.size.y;
+	push_constant.dest_offset[0] = p_rect.position.x;
+	push_constant.dest_offset[1] = p_rect.position.y;
 	push_constant.bias = p_bias;
 	push_constant.z_far = p_z_far;
 	push_constant.z_near = p_z_near;
 	push_constant.z_flip = p_dp_flip;
 
-	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect);
-	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy.pipelines[COPY_MODE_CUBE_TO_DP].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
-	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
-	RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-	RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CopyToDPPushConstant));
-	RD::get_singleton()->draw_list_draw(draw_list, true);
-	RD::get_singleton()->draw_list_end();
+	int32_t x_groups = (p_rect.size.width - 1) / 8 + 1;
+	int32_t y_groups = (p_rect.size.height - 1) / 8 + 1;
+
+	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cube_to_dp.pipeline);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
+	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 1);
+	RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(CopyToDPPushConstant));
+	RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+	RD::get_singleton()->compute_list_end();
 }
 
 void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings) {
@@ -619,7 +676,7 @@ void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer,
 
 	tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
 
-	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD);
 	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer)));
 	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_color), 0);
 	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1);
@@ -1129,33 +1186,38 @@ void RasterizerEffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_
 
 RasterizerEffectsRD::RasterizerEffectsRD() {
 
-	{ // Initialize blur
-		Vector<String> blur_modes;
-		blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n");
-		blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n");
-		blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n");
-		blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_LOW\n");
-		blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_MEDIUM\n");
-		blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_HIGH\n");
-		blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_LOW\n#define DOF_NEAR_BLUR_MERGE\n");
-		blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_MEDIUM\n#define DOF_NEAR_BLUR_MERGE\n");
-		blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_HIGH\n#define DOF_NEAR_BLUR_MERGE\n");
-		blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_LOW\n");
-		blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_MEDIUM\n");
-		blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_HIGH\n");
-		blur_modes.push_back("\n#define MODE_SSAO_MERGE\n");
-		blur_modes.push_back("\n#define MODE_SIMPLE_COPY\n");
-		blur_modes.push_back("\n#define MODE_MIPMAP\n");
-		blur_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n");
-
-		blur.shader.initialize(blur_modes);
-		zeromem(&blur.push_constant, sizeof(BlurPushConstant));
-		blur.shader_version = blur.shader.version_create();
-
-		for (int i = 0; i < BLUR_MODE_MAX; i++) {
-			blur.pipelines[i].setup(blur.shader.version_get_shader(blur.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+	{ // Initialize copy
+		Vector<String> copy_modes;
+		copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n");
+		copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define DST_IMAGE_8BIT\n");
+		copy_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n");
+		copy_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n");
+		copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n");
+		copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n#define DST_IMAGE_8BIT\n");
+		copy_modes.push_back("\n#define MODE_SIMPLE_COPY_DEPTH\n");
+		copy_modes.push_back("\n#define MODE_MIPMAP\n");
+		copy_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n");
+
+		copy.shader.initialize(copy_modes);
+		zeromem(&copy.push_constant, sizeof(CopyPushConstant));
+		copy.shader_version = copy.shader.version_create();
+
+		for (int i = 0; i < COPY_MODE_MAX; i++) {
+			copy.pipelines[i] = RD::get_singleton()->compute_pipeline_create(copy.shader.version_get_shader(copy.shader_version, i));
 		}
 	}
+	{
+		Vector<String> copy_modes;
+		copy_modes.push_back("\n");
+
+		copy_to_fb.shader.initialize(copy_modes);
+
+		copy_to_fb.shader_version = copy_to_fb.shader.version_create();
+
+		//use additive
+
+		copy_to_fb.pipeline.setup(copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+	}
 
 	{
 		// Initialize roughness
@@ -1202,15 +1264,13 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
 	{
 		// Initialize copier
 		Vector<String> copy_modes;
-		copy_modes.push_back("\n#define MODE_CUBE_TO_DP\n");
+		copy_modes.push_back("\n");
 
-		copy.shader.initialize(copy_modes);
+		cube_to_dp.shader.initialize(copy_modes);
 
-		copy.shader_version = copy.shader.version_create();
+		cube_to_dp.shader_version = cube_to_dp.shader.version_create();
 
-		for (int i = 0; i < COPY_MODE_MAX; i++) {
-			copy.pipelines[i].setup(copy.shader.version_get_shader(copy.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
-		}
+		cube_to_dp.pipeline = RD::get_singleton()->compute_pipeline_create(cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0));
 	}
 
 	{
@@ -1482,9 +1542,9 @@ RasterizerEffectsRD::~RasterizerEffectsRD() {
 	RD::get_singleton()->free(index_buffer); //array gets freed as dependency
 	RD::get_singleton()->free(filter.coefficient_buffer);
 
-	blur.shader.version_free(blur.shader_version);
-	bokeh.shader.version_free(bokeh.shader_version);
 	copy.shader.version_free(copy.shader_version);
+	bokeh.shader.version_free(bokeh.shader_version);
+	cube_to_dp.shader.version_free(cube_to_dp.shader_version);
 	cubemap_downsampler.shader.version_free(cubemap_downsampler.shader_version);
 	filter.shader.version_free(filter.shader_version);
 	luminance_reduce.shader.version_free(luminance_reduce.shader_version);

+ 73 - 62
servers/rendering/rasterizer_rd/rasterizer_effects_rd.h

@@ -33,9 +33,10 @@
 
 #include "core/math/camera_matrix.h"
 #include "servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h"
-#include "servers/rendering/rasterizer_rd/shaders/blur.glsl.gen.h"
 #include "servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl.gen.h"
 #include "servers/rendering/rasterizer_rd/shaders/copy.glsl.gen.h"
+#include "servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl.gen.h"
+#include "servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl.gen.h"
 #include "servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl.gen.h"
 #include "servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl.gen.h"
 #include "servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl.gen.h"
@@ -55,71 +56,78 @@
 
 class RasterizerEffectsRD {
 
-	enum BlurMode {
-		BLUR_MODE_GAUSSIAN_BLUR,
-		BLUR_MODE_GAUSSIAN_GLOW,
-		BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
-		BLUR_MODE_DOF_NEAR_LOW,
-		BLUR_MODE_DOF_NEAR_MEDIUM,
-		BLUR_MODE_DOF_NEAR_HIGH,
-		BLUR_MODE_DOF_NEAR_MERGE_LOW,
-		BLUR_MODE_DOF_NEAR_MERGE_MEDIUM,
-		BLUR_MODE_DOF_NEAR_MERGE_HIGH,
-		BLUR_MODE_DOF_FAR_LOW,
-		BLUR_MODE_DOF_FAR_MEDIUM,
-		BLUR_MODE_DOF_FAR_HIGH,
-		BLUR_MODE_SSAO_MERGE,
-		BLUR_MODE_SIMPLY_COPY,
-		BLUR_MODE_MIPMAP,
-		BLUR_MODE_LINEARIZE_DEPTH,
-		BLUR_MODE_MAX,
+	enum CopyMode {
+		COPY_MODE_GAUSSIAN_COPY,
+		COPY_MODE_GAUSSIAN_COPY_8BIT,
+		COPY_MODE_GAUSSIAN_GLOW,
+		COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
+		COPY_MODE_SIMPLY_COPY,
+		COPY_MODE_SIMPLY_COPY_8BIT,
+		COPY_MODE_SIMPLY_COPY_DEPTH,
+		COPY_MODE_MIPMAP,
+		COPY_MODE_LINEARIZE_DEPTH,
+		COPY_MODE_MAX,
 
 	};
 
 	enum {
-		BLUR_FLAG_HORIZONTAL = (1 << 0),
-		BLUR_FLAG_USE_BLUR_SECTION = (1 << 1),
-		BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2),
-		BLUR_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3),
-		BLUR_FLAG_GLOW_FIRST_PASS = (1 << 4),
-		BLUR_FLAG_FLIP_Y = (1 << 5),
-		BLUR_COPY_FORCE_LUMINANCE = (1 << 6)
+		COPY_FLAG_HORIZONTAL = (1 << 0),
+		COPY_FLAG_USE_COPY_SECTION = (1 << 1),
+		COPY_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2),
+		COPY_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3),
+		COPY_FLAG_GLOW_FIRST_PASS = (1 << 4),
+		COPY_FLAG_FLIP_Y = (1 << 5),
+		COPY_FLAG_FORCE_LUMINANCE = (1 << 6),
+		COPY_FLAG_ALL_SOURCE = (1 << 7)
 	};
 
-	struct BlurPushConstant {
-		float section[4];
-		float pixel_size[2];
+	struct CopyPushConstant {
+
+		int32_t section[4];
+		int32_t target[2];
 		uint32_t flags;
 		uint32_t pad;
-		//glow
+		// Glow.
 		float glow_strength;
 		float glow_bloom;
 		float glow_hdr_threshold;
 		float glow_hdr_scale;
+
 		float glow_exposure;
 		float glow_white;
 		float glow_luminance_cap;
 		float glow_auto_exposure_grey;
-		//dof
-		float dof_begin;
-		float dof_end;
-		float dof_radius;
-		float dof_pad;
-
-		float dof_dir[2];
+		// DOF.
 		float camera_z_far;
 		float camera_z_near;
+		uint32_t pad2[2];
+	};
+
+	struct Copy {
+		CopyPushConstant push_constant;
+		CopyShaderRD shader;
+		RID shader_version;
+		RID pipelines[COPY_MODE_MAX];
+
+	} copy;
+
+	struct CopyToFbPushConstant {
 
-		float ssao_color[4];
+		float section[4];
+		float pixel_size[2];
+		uint32_t flip_y;
+		uint32_t use_section;
+		uint32_t force_luminance;
+		uint32_t pad[3];
 	};
 
-	struct Blur {
-		BlurPushConstant push_constant;
-		BlurShaderRD shader;
+	struct CopyToFb {
+		CopyToFbPushConstant push_constant;
+		CopyToFbShaderRD shader;
 		RID shader_version;
-		RenderPipelineVertexFormatCacheRD pipelines[BLUR_MODE_MAX];
+		RenderPipelineVertexFormatCacheRD pipeline;
 
-	} blur;
+	} copy_to_fb;
 
 	struct CubemapRoughnessPushConstant {
 		uint32_t face_id;
@@ -164,8 +172,11 @@ class RasterizerEffectsRD {
 		float auto_exposure_grey;
 	};
 
+	/* tonemap actually writes to a framebuffer, which is
+	 * better to do using the raster pipeline rather than
+	 * comptute, as that framebuffer might be in different formats
+	 */
 	struct Tonemap {
-
 		TonemapPushConstant push_constant;
 		TonemapShaderRD shader;
 		RID shader_version;
@@ -196,23 +207,20 @@ class RasterizerEffectsRD {
 	} luminance_reduce;
 
 	struct CopyToDPPushConstant {
+		int32_t screen_size[2];
+		int32_t dest_offset[2];
 		float bias;
 		float z_far;
 		float z_near;
 		uint32_t z_flip;
 	};
 
-	enum CopyMode {
-		COPY_MODE_CUBE_TO_DP,
-		COPY_MODE_MAX
-	};
-
-	struct Copy {
+	struct CoptToDP {
 
-		CopyShaderRD shader;
+		CubeToDpShaderRD shader;
 		RID shader_version;
-		RenderPipelineVertexFormatCacheRD pipelines[COPY_MODE_MAX];
-	} copy;
+		RID pipeline;
+	} cube_to_dp;
 
 	struct BokehPushConstant {
 		uint32_t size[2];
@@ -392,6 +400,10 @@ class RasterizerEffectsRD {
 		SPECULAR_MERGE_MAX
 	};
 
+	/* Specular merge must be done using raster, rather than compute
+	 * because it must continue the existing color buffer
+	 */
+
 	struct SpecularMerge {
 
 		SpecularMergeShaderRD shader;
@@ -537,17 +549,16 @@ class RasterizerEffectsRD {
 	RID _get_compute_uniform_set_from_image_pair(RID p_texture, RID p_texture2);
 
 public:
-	//TODO must re-do most of the shaders in compute
-
-	void region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region);
-	void copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y = false, bool p_force_luminance = false);
-	void copy_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
-	void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region);
-	void gaussian_glow(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
+	void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false);
+	void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false);
+	void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false);
+	void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
+	void gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst = false);
+	void gaussian_glow(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
 
 	void cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
-	void make_mipmap(RID p_source_rd_texture, RID p_framebuffer_half, const Vector2 &p_pixel_size);
-	void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip);
+	void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
+	void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip);
 	void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
 	void bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_secondary_texture, RID p_bokeh_texture1, RID p_bokeh_texture2, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
 

+ 21 - 41
servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp

@@ -181,10 +181,9 @@ void RasterizerSceneRD::_update_reflection_mipmaps(ReflectionData &rd) {
 			for (int j = 0; j < rd.layers[i].mipmaps.size() - 1; j++) {
 				for (int k = 0; k < 6; k++) {
 					RID view = rd.layers[i].mipmaps[j].views[k];
-					RID fb = rd.layers[i].mipmaps[j + 1].framebuffers[k];
-					Vector2 size = rd.layers[i].mipmaps[j].size;
-					size = Vector2(1.0 / size.x, 1.0 / size.y);
-					storage->get_effects()->make_mipmap(view, fb, size);
+					RID texture = rd.layers[i].mipmaps[j + 1].views[k];
+					Size2i size = rd.layers[i].mipmaps[j + 1].size;
+					storage->get_effects()->make_mipmap(view, texture, size);
 				}
 			}
 		}
@@ -1599,7 +1598,6 @@ void RasterizerSceneRD::shadow_atlas_set_size(RID p_atlas, int p_size) {
 	if (shadow_atlas->depth.is_valid()) {
 		RD::get_singleton()->free(shadow_atlas->depth);
 		shadow_atlas->depth = RID();
-		shadow_atlas->fb = RID();
 	}
 	for (int i = 0; i < 4; i++) {
 		//clear subdivisions
@@ -1625,13 +1623,9 @@ void RasterizerSceneRD::shadow_atlas_set_size(RID p_atlas, int p_size) {
 		tf.format = RD::DATA_FORMAT_R32_SFLOAT;
 		tf.width = shadow_atlas->size;
 		tf.height = shadow_atlas->size;
-		tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+		tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
 
 		shadow_atlas->depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
-		Vector<RID> fb;
-		fb.push_back(shadow_atlas->depth);
-		shadow_atlas->fb = RD::get_singleton()->framebuffer_create(fb);
 	}
 }
 
@@ -1901,7 +1895,6 @@ void RasterizerSceneRD::directional_shadow_atlas_set_size(int p_size) {
 	if (directional_shadow.depth.is_valid()) {
 		RD::get_singleton()->free(directional_shadow.depth);
 		directional_shadow.depth = RID();
-		directional_shadow.fb = RID();
 	}
 
 	if (p_size > 0) {
@@ -1910,12 +1903,9 @@ void RasterizerSceneRD::directional_shadow_atlas_set_size(int p_size) {
 		tf.format = RD::DATA_FORMAT_R32_SFLOAT;
 		tf.width = p_size;
 		tf.height = p_size;
-		tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+		tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
 
 		directional_shadow.depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
-		Vector<RID> fb;
-		fb.push_back(directional_shadow.depth);
-		directional_shadow.fb = RD::get_singleton()->framebuffer_create(fb);
 	}
 
 	_base_uniforms_changed();
@@ -3062,7 +3052,7 @@ void RasterizerSceneRD::_allocate_blur_textures(RenderBuffers *rb) {
 	tf.width = rb->width;
 	tf.height = rb->height;
 	tf.type = RD::TEXTURE_TYPE_2D;
-	tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+	tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
 	tf.mipmaps = mipmaps_required;
 
 	rb->blur[0].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
@@ -3079,11 +3069,6 @@ void RasterizerSceneRD::_allocate_blur_textures(RenderBuffers *rb) {
 
 		RenderBuffers::Blur::Mipmap mm;
 		mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[0].texture, 0, i);
-		{
-			Vector<RID> fbs;
-			fbs.push_back(mm.texture);
-			mm.framebuffer = RD::get_singleton()->framebuffer_create(fbs);
-		}
 
 		mm.width = base_width;
 		mm.height = base_height;
@@ -3093,11 +3078,6 @@ void RasterizerSceneRD::_allocate_blur_textures(RenderBuffers *rb) {
 		if (i > 0) {
 
 			mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, 0, i - 1);
-			{
-				Vector<RID> fbs;
-				fbs.push_back(mm.texture);
-				mm.framebuffer = RD::get_singleton()->framebuffer_create(fbs);
-			}
 
 			rb->blur[1].mipmaps.push_back(mm);
 		}
@@ -3424,9 +3404,9 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu
 				if (env->auto_exposure && rb->luminance.current.is_valid()) {
 					luminance_texture = rb->luminance.current;
 				}
-				storage->get_effects()->gaussian_glow(rb->texture, rb->blur[0].mipmaps[i + 1].framebuffer, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].framebuffer, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+				storage->get_effects()->gaussian_glow(rb->texture, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
 			} else {
-				storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i + 1].framebuffer, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].framebuffer, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength);
+				storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength);
 			}
 		}
 	}
@@ -3482,7 +3462,7 @@ void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_s
 			RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas);
 			Size2 rtsize = storage->render_target_get_size(rb->render_target);
 
-			effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 2), false, true);
+			effects->copy_to_fb_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
 		}
 	}
 
@@ -3491,7 +3471,7 @@ void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_s
 			RID shadow_atlas_texture = directional_shadow_get_texture();
 			Size2 rtsize = storage->render_target_get_size(rb->render_target);
 
-			effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 2), false, true);
+			effects->copy_to_fb_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
 		}
 	}
 
@@ -3499,24 +3479,24 @@ void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_s
 		if (rb->luminance.current.is_valid()) {
 			Size2 rtsize = storage->render_target_get_size(rb->render_target);
 
-			effects->copy_to_rect(rb->luminance.current, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true);
+			effects->copy_to_fb_rect(rb->luminance.current, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true);
 		}
 	}
 
 	if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb->ssao.ao[0].is_valid()) {
 		Size2 rtsize = storage->render_target_get_size(rb->render_target);
 		RID ao_buf = rb->ssao.ao_full.is_valid() ? rb->ssao.ao_full : rb->ssao.ao[0];
-		effects->copy_to_rect(ao_buf, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
+		effects->copy_to_fb_rect(ao_buf, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
 	}
 
 	if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER && _render_buffers_get_roughness_texture(p_render_buffers).is_valid()) {
 		Size2 rtsize = storage->render_target_get_size(rb->render_target);
-		effects->copy_to_rect(_render_buffers_get_roughness_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
+		effects->copy_to_fb_rect(_render_buffers_get_roughness_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
 	}
 
 	if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(p_render_buffers).is_valid()) {
 		Size2 rtsize = storage->render_target_get_size(rb->render_target);
-		effects->copy_to_rect(_render_buffers_get_normal_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize));
+		effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
 	}
 }
 
@@ -3628,7 +3608,7 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
 	ERR_FAIL_COND(!light_instance);
 
 	Rect2i atlas_rect;
-	RID atlas_fb;
+	RID atlas_texture;
 
 	bool using_dual_paraboloid = false;
 	bool using_dual_paraboloid_flip = false;
@@ -3702,7 +3682,7 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
 		ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size);
 		render_fb = shadow_map->fb;
 		render_texture = shadow_map->depth;
-		atlas_fb = directional_shadow.fb;
+		atlas_texture = directional_shadow.depth;
 
 	} else {
 		//set from shadow atlas
@@ -3729,7 +3709,7 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
 
 		atlas_rect.size.width = shadow_size;
 		atlas_rect.size.height = shadow_size;
-		atlas_fb = shadow_atlas->fb;
+		atlas_texture = shadow_atlas->depth;
 
 		zfar = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
 		bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_BIAS);
@@ -3785,9 +3765,9 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
 		if (finalize_cubemap) {
 			//reblit
 			atlas_rect.size.height /= 2;
-			storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), 0.0, false);
+			storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_texture, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), 0.0, false);
 			atlas_rect.position.y += atlas_rect.size.height;
-			storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), 0.0, true);
+			storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_texture, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), 0.0, true);
 		}
 	} else {
 		//render shadow
@@ -3796,9 +3776,9 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
 
 		//copy to atlas
 		if (use_linear_depth) {
-			storage->get_effects()->copy_to_rect_and_linearize(render_texture, atlas_fb, atlas_rect, true, znear, zfar);
+			storage->get_effects()->copy_depth_to_rect_and_linearize(render_texture, atlas_texture, atlas_rect, true, znear, zfar);
 		} else {
-			storage->get_effects()->copy_to_rect(render_texture, atlas_fb, atlas_rect, true);
+			storage->get_effects()->copy_depth_to_rect(render_texture, atlas_texture, atlas_rect, true);
 		}
 
 		//does not work from depth to color

+ 0 - 2
servers/rendering/rasterizer_rd/rasterizer_scene_rd.h

@@ -533,7 +533,6 @@ private:
 
 	struct DirectionalShadow {
 		RID depth;
-		RID fb; //for copying
 
 		int light_count = 0;
 		int size = 0;
@@ -730,7 +729,6 @@ private:
 
 			struct Mipmap {
 				RID texture;
-				RID framebuffer;
 				int width;
 				int height;
 			};

+ 14 - 24
servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp

@@ -3914,7 +3914,6 @@ void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) {
 	if (rt->backbuffer.is_valid()) {
 		RD::get_singleton()->free(rt->backbuffer);
 		rt->backbuffer = RID();
-		rt->backbuffer_fb = RID();
 		for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
 			//just erase copies, since the rest are erased by dependency
 			RD::get_singleton()->free(rt->backbuffer_mipmaps[i].mipmap_copy);
@@ -4028,17 +4027,11 @@ void RasterizerStorageRD::_create_render_target_backbuffer(RenderTarget *rt) {
 	tf.width = rt->size.width;
 	tf.height = rt->size.height;
 	tf.type = RD::TEXTURE_TYPE_2D;
-	tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+	tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
 	tf.mipmaps = mipmaps_required;
 
 	rt->backbuffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
-	{
-		Vector<RID> backbuffer_att;
-		RID backbuffer_fb_tex = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, 0);
-		backbuffer_att.push_back(backbuffer_fb_tex);
-		rt->backbuffer_fb = RD::get_singleton()->framebuffer_create(backbuffer_att);
-	}
+	rt->backbuffer_mipmap0 = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, 0);
 
 	//create mipmaps
 	for (uint32_t i = 1; i < mipmaps_required; i++) {
@@ -4046,9 +4039,6 @@ void RasterizerStorageRD::_create_render_target_backbuffer(RenderTarget *rt) {
 		RenderTarget::BackbufferMipmap mm;
 		{
 			mm.mipmap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, i);
-			Vector<RID> mm_fb_at;
-			mm_fb_at.push_back(mm.mipmap);
-			mm.mipmap_fb = RD::get_singleton()->framebuffer_create(mm_fb_at);
 		}
 
 		{
@@ -4060,9 +4050,6 @@ void RasterizerStorageRD::_create_render_target_backbuffer(RenderTarget *rt) {
 			mmtf.mipmaps = 1;
 
 			mm.mipmap_copy = RD::get_singleton()->texture_create(mmtf, RD::TextureView());
-			Vector<RID> mm_fb_at;
-			mm_fb_at.push_back(mm.mipmap_copy);
-			mm.mipmap_copy_fb = RD::get_singleton()->framebuffer_create(mm_fb_at);
 		}
 
 		rt->backbuffer_mipmaps.push_back(mm);
@@ -4138,7 +4125,12 @@ RID RasterizerStorageRD::render_target_get_rd_framebuffer(RID p_render_target) {
 
 	return rt->framebuffer;
 }
+RID RasterizerStorageRD::render_target_get_rd_texture(RID p_render_target) {
+	RenderTarget *rt = render_target_owner.getornull(p_render_target);
+	ERR_FAIL_COND_V(!rt, RID());
 
+	return rt->color;
+}
 void RasterizerStorageRD::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
 	RenderTarget *rt = render_target_owner.getornull(p_render_target);
 	ERR_FAIL_COND(!rt);
@@ -4188,27 +4180,25 @@ void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target,
 	}
 
 	Rect2i region = p_region;
-	Rect2 blur_region;
 	if (region == Rect2i()) {
 		region.size = rt->size;
-	} else {
-		blur_region = region;
-		blur_region.position /= rt->size;
-		blur_region.size /= rt->size;
 	}
 
 	//single texture copy for backbuffer
-	RD::get_singleton()->texture_copy(rt->color, rt->backbuffer, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true);
+	RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true);
 	//effects.copy(rt->color, rt->backbuffer_fb, blur_region);
 
 	//then mipmap blur
 	RID prev_texture = rt->color; //use color, not backbuffer, as bb has mipmaps.
-	Vector2 pixel_size = Vector2(1.0 / rt->size.width, 1.0 / rt->size.height);
 
 	for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
-		pixel_size *= 2.0; //go halfway
+		region.position.x >>= 1;
+		region.position.y >>= 1;
+		region.size.x = MAX(1, region.size.x >> 1);
+		region.size.y = MAX(1, region.size.y >> 1);
+
 		const RenderTarget::BackbufferMipmap &mm = rt->backbuffer_mipmaps[i];
-		effects.gaussian_blur(prev_texture, mm.mipmap_copy_fb, mm.mipmap_copy, mm.mipmap_fb, pixel_size, blur_region);
+		effects.gaussian_blur(prev_texture, mm.mipmap, mm.mipmap_copy, region, true);
 		prev_texture = mm.mipmap;
 	}
 }

+ 2 - 3
servers/rendering/rasterizer_rd/rasterizer_storage_rd.h

@@ -463,13 +463,11 @@ private:
 		bool flags[RENDER_TARGET_FLAG_MAX];
 
 		RID backbuffer; //used for effects
-		RID backbuffer_fb;
+		RID backbuffer_mipmap0;
 
 		struct BackbufferMipmap {
 			RID mipmap;
-			RID mipmap_fb;
 			RID mipmap_copy;
-			RID mipmap_copy_fb;
 		};
 
 		Vector<BackbufferMipmap> backbuffer_mipmaps;
@@ -1105,6 +1103,7 @@ public:
 
 	Size2 render_target_get_size(RID p_render_target);
 	RID render_target_get_rd_framebuffer(RID p_render_target);
+	RID render_target_get_rd_texture(RID p_render_target);
 
 	RS::InstanceType get_base_type(RID p_rid) const;
 

+ 3 - 2
servers/rendering/rasterizer_rd/shaders/SCsub

@@ -5,14 +5,15 @@ Import("env")
 if "RD_GLSL" in env["BUILDERS"]:
     env.RD_GLSL("canvas.glsl")
     env.RD_GLSL("canvas_occlusion.glsl")
-    env.RD_GLSL("blur.glsl")
+    env.RD_GLSL("copy.glsl")
+    env.RD_GLSL("copy_to_fb.glsl")
     env.RD_GLSL("cubemap_roughness.glsl")
     env.RD_GLSL("cubemap_downsampler.glsl")
     env.RD_GLSL("cubemap_filter.glsl")
     env.RD_GLSL("scene_high_end.glsl")
     env.RD_GLSL("sky.glsl")
     env.RD_GLSL("tonemap.glsl")
-    env.RD_GLSL("copy.glsl")
+    env.RD_GLSL("cube_to_dp.glsl")
     env.RD_GLSL("giprobe.glsl")
     env.RD_GLSL("giprobe_debug.glsl")
     env.RD_GLSL("giprobe_sdf.glsl")

+ 0 - 301
servers/rendering/rasterizer_rd/shaders/blur.glsl

@@ -1,301 +0,0 @@
-/* clang-format off */
-[vertex]
-
-#version 450
-
-VERSION_DEFINES
-
-#include "blur_inc.glsl"
-
-layout(location = 0) out vec2 uv_interp;
-/* clang-format on */
-
-void main() {
-
-	vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
-	uv_interp = base_arr[gl_VertexIndex];
-
-	if (bool(blur.flags & FLAG_USE_BLUR_SECTION)) {
-		uv_interp = blur.section.xy + uv_interp * blur.section.zw;
-	}
-
-	gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
-
-	if (bool(blur.flags & FLAG_FLIP_Y)) {
-		uv_interp.y = 1.0 - uv_interp.y;
-	}
-}
-
-/* clang-format off */
-[fragment]
-
-#version 450
-
-VERSION_DEFINES
-
-#include "blur_inc.glsl"
-
-layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
-
-layout(set = 0, binding = 0) uniform sampler2D source_color;
-
-#ifdef MODE_SSAO_MERGE
-layout(set = 1, binding = 0) uniform sampler2D source_ssao;
-#endif
-
-#ifdef GLOW_USE_AUTO_EXPOSURE
-layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
-#endif
-
-layout(location = 0) out vec4 frag_color;
-
-//DOF
-#if defined(MODE_DOF_FAR_BLUR) || defined(MODE_DOF_NEAR_BLUR)
-
-layout(set = 1, binding = 0) uniform sampler2D dof_source_depth;
-
-#ifdef DOF_NEAR_BLUR_MERGE
-layout(set = 2, binding = 0) uniform sampler2D source_dof_original;
-#endif
-
-#ifdef DOF_QUALITY_LOW
-const int dof_kernel_size = 5;
-const int dof_kernel_from = 2;
-const float dof_kernel[5] = float[](0.153388, 0.221461, 0.250301, 0.221461, 0.153388);
-#endif
-
-#ifdef DOF_QUALITY_MEDIUM
-const int dof_kernel_size = 11;
-const int dof_kernel_from = 5;
-const float dof_kernel[11] = float[](0.055037, 0.072806, 0.090506, 0.105726, 0.116061, 0.119726, 0.116061, 0.105726, 0.090506, 0.072806, 0.055037);
-
-#endif
-
-#ifdef DOF_QUALITY_HIGH
-const int dof_kernel_size = 21;
-const int dof_kernel_from = 10;
-const float dof_kernel[21] = float[](0.028174, 0.032676, 0.037311, 0.041944, 0.046421, 0.050582, 0.054261, 0.057307, 0.059587, 0.060998, 0.061476, 0.060998, 0.059587, 0.057307, 0.054261, 0.050582, 0.046421, 0.041944, 0.037311, 0.032676, 0.028174);
-#endif
-
-#endif
-
-void main() {
-
-#ifdef MODE_MIPMAP
-
-	vec2 pix_size = blur.pixel_size;
-	vec4 color = texture(source_color, uv_interp + vec2(-0.5, -0.5) * pix_size);
-	color += texture(source_color, uv_interp + vec2(0.5, -0.5) * pix_size);
-	color += texture(source_color, uv_interp + vec2(0.5, 0.5) * pix_size);
-	color += texture(source_color, uv_interp + vec2(-0.5, 0.5) * pix_size);
-	frag_color = color / 4.0;
-
-#endif
-
-#ifdef MODE_GAUSSIAN_BLUR
-
-	//Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect
-
-	if (bool(blur.flags & FLAG_HORIZONTAL)) {
-
-		vec2 pix_size = blur.pixel_size;
-		pix_size *= 0.5; //reading from larger buffer, so use more samples
-		vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.214607;
-		color += texture(source_color, uv_interp + vec2(1.0, 0.0) * pix_size) * 0.189879;
-		color += texture(source_color, uv_interp + vec2(2.0, 0.0) * pix_size) * 0.131514;
-		color += texture(source_color, uv_interp + vec2(3.0, 0.0) * pix_size) * 0.071303;
-		color += texture(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size) * 0.189879;
-		color += texture(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size) * 0.131514;
-		color += texture(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size) * 0.071303;
-		frag_color = color;
-	} else {
-
-		vec2 pix_size = blur.pixel_size;
-		vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.38774;
-		color += texture(source_color, uv_interp + vec2(0.0, 1.0) * pix_size) * 0.24477;
-		color += texture(source_color, uv_interp + vec2(0.0, 2.0) * pix_size) * 0.06136;
-		color += texture(source_color, uv_interp + vec2(0.0, -1.0) * pix_size) * 0.24477;
-		color += texture(source_color, uv_interp + vec2(0.0, -2.0) * pix_size) * 0.06136;
-		frag_color = color;
-	}
-#endif
-
-#ifdef MODE_GAUSSIAN_GLOW
-
-	//Glow uses larger sigma 1 for a more rounded blur effect
-
-#define GLOW_ADD(m_ofs, m_mult)                                                  \
-	{                                                                            \
-		vec2 ofs = uv_interp + m_ofs * pix_size;                                 \
-		vec4 c = texture(source_color, ofs) * m_mult;                            \
-		if (any(lessThan(ofs, vec2(0.0))) || any(greaterThan(ofs, vec2(1.0)))) { \
-			c *= 0.0;                                                            \
-		}                                                                        \
-		color += c;                                                              \
-	}
-
-	if (bool(blur.flags & FLAG_HORIZONTAL)) {
-
-		vec2 pix_size = blur.pixel_size;
-		pix_size *= 0.5; //reading from larger buffer, so use more samples
-		vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.174938;
-		GLOW_ADD(vec2(1.0, 0.0), 0.165569);
-		GLOW_ADD(vec2(2.0, 0.0), 0.140367);
-		GLOW_ADD(vec2(3.0, 0.0), 0.106595);
-		GLOW_ADD(vec2(-1.0, 0.0), 0.165569);
-		GLOW_ADD(vec2(-2.0, 0.0), 0.140367);
-		GLOW_ADD(vec2(-3.0, 0.0), 0.106595);
-		color *= blur.glow_strength;
-		frag_color = color;
-	} else {
-
-		vec2 pix_size = blur.pixel_size;
-		vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.288713;
-		GLOW_ADD(vec2(0.0, 1.0), 0.233062);
-		GLOW_ADD(vec2(0.0, 2.0), 0.122581);
-		GLOW_ADD(vec2(0.0, -1.0), 0.233062);
-		GLOW_ADD(vec2(0.0, -2.0), 0.122581);
-		color *= blur.glow_strength;
-		frag_color = color;
-	}
-
-#undef GLOW_ADD
-
-	if (bool(blur.flags & FLAG_GLOW_FIRST_PASS)) {
-#ifdef GLOW_USE_AUTO_EXPOSURE
-
-		frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_grey;
-#endif
-		frag_color *= blur.glow_exposure;
-
-		float luminance = max(frag_color.r, max(frag_color.g, frag_color.b));
-		float feedback = max(smoothstep(blur.glow_hdr_threshold, blur.glow_hdr_threshold + blur.glow_hdr_scale, luminance), blur.glow_bloom);
-
-		frag_color = min(frag_color * feedback, vec4(blur.glow_luminance_cap));
-	}
-
-#endif
-
-#ifdef MODE_DOF_FAR_BLUR
-
-	vec4 color_accum = vec4(0.0);
-
-	float depth = texture(dof_source_depth, uv_interp, 0.0).r;
-	depth = depth * 2.0 - 1.0;
-
-	if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) {
-		depth = ((depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
-	} else {
-		depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - depth * (blur.camera_z_far - blur.camera_z_near));
-	}
-
-	float amount = smoothstep(blur.dof_begin, blur.dof_end, depth);
-	float k_accum = 0.0;
-
-	for (int i = 0; i < dof_kernel_size; i++) {
-
-		int int_ofs = i - dof_kernel_from;
-		vec2 tap_uv = uv_interp + blur.dof_dir * float(int_ofs) * amount * blur.dof_radius;
-
-		float tap_k = dof_kernel[i];
-
-		float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r;
-		tap_depth = tap_depth * 2.0 - 1.0;
-
-		if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) {
-
-			tap_depth = ((tap_depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
-		} else {
-			tap_depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - tap_depth * (blur.camera_z_far - blur.camera_z_near));
-		}
-
-		float tap_amount = mix(smoothstep(blur.dof_begin, blur.dof_end, tap_depth), 1.0, int_ofs == 0);
-		tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
-
-		vec4 tap_color = texture(source_color, tap_uv, 0.0) * tap_k;
-
-		k_accum += tap_k * tap_amount;
-		color_accum += tap_color * tap_amount;
-	}
-
-	if (k_accum > 0.0) {
-		color_accum /= k_accum;
-	}
-
-	frag_color = color_accum; ///k_accum;
-
-#endif
-
-#ifdef MODE_DOF_NEAR_BLUR
-
-	vec4 color_accum = vec4(0.0);
-
-	float max_accum = 0.0;
-
-	for (int i = 0; i < dof_kernel_size; i++) {
-
-		int int_ofs = i - dof_kernel_from;
-		vec2 tap_uv = uv_interp + blur.dof_dir * float(int_ofs) * blur.dof_radius;
-		float ofs_influence = max(0.0, 1.0 - float(abs(int_ofs)) / float(dof_kernel_from));
-
-		float tap_k = dof_kernel[i];
-
-		vec4 tap_color = texture(source_color, tap_uv, 0.0);
-
-		float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r;
-		tap_depth = tap_depth * 2.0 - 1.0;
-		if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) {
-
-			tap_depth = ((tap_depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
-		} else {
-			tap_depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - tap_depth * (blur.camera_z_far - blur.camera_z_near));
-		}
-		float tap_amount = 1.0 - smoothstep(blur.dof_end, blur.dof_begin, tap_depth);
-		tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
-
-		if (bool(blur.flags & FLAG_DOF_NEAR_FIRST_TAP)) {
-			tap_color.a = 1.0 - smoothstep(blur.dof_end, blur.dof_begin, tap_depth);
-		}
-
-		max_accum = max(max_accum, tap_amount * ofs_influence);
-
-		color_accum += tap_color * tap_k;
-	}
-
-	color_accum.a = max(color_accum.a, sqrt(max_accum));
-
-#ifdef DOF_NEAR_BLUR_MERGE
-	{
-		vec4 original = texture(source_dof_original, uv_interp, 0.0);
-		color_accum = mix(original, color_accum, color_accum.a);
-	}
-#endif
-
-	if (bool(blur.flags & FLAG_DOF_NEAR_FIRST_TAP)) {
-		frag_color = color_accum;
-	}
-#endif
-
-#ifdef MODE_SIMPLE_COPY
-	vec4 color = texture(source_color, uv_interp, 0.0);
-	if (bool(blur.flags & FLAG_COPY_FORCE_LUMINANCE)) {
-		color.rgb = vec3(max(max(color.r, color.g), color.b));
-	}
-	frag_color = color;
-#endif
-
-#ifdef MODE_LINEARIZE_DEPTH_COPY
-	float depth = texture(source_color, uv_interp, 0.0).r;
-	depth = depth * 2.0 - 1.0;
-	depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - depth * (blur.camera_z_far - blur.camera_z_near));
-	frag_color = vec4(depth / blur.camera_z_far);
-#endif
-
-#ifdef MODE_SSAO_MERGE
-	vec4 color = texture(source_color, uv_interp, 0.0);
-	float ssao = texture(source_ssao, uv_interp, 0.0).r;
-	frag_color = vec4(mix(color.rgb, color.rgb * mix(blur.ssao_color.rgb, vec3(1.0), ssao), color.a), 1.0);
-
-#endif
-}

+ 0 - 35
servers/rendering/rasterizer_rd/shaders/blur_inc.glsl

@@ -1,35 +0,0 @@
-#define FLAG_HORIZONTAL (1 << 0)
-#define FLAG_USE_BLUR_SECTION (1 << 1)
-#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 2)
-#define FLAG_DOF_NEAR_FIRST_TAP (1 << 3)
-#define FLAG_GLOW_FIRST_PASS (1 << 4)
-#define FLAG_FLIP_Y (1 << 5)
-#define FLAG_COPY_FORCE_LUMINANCE (1 << 6)
-
-layout(push_constant, binding = 1, std430) uniform Blur {
-	vec4 section;
-	vec2 pixel_size;
-	uint flags;
-	uint pad;
-	// Glow.
-	float glow_strength;
-	float glow_bloom;
-	float glow_hdr_threshold;
-	float glow_hdr_scale;
-	float glow_exposure;
-	float glow_white;
-	float glow_luminance_cap;
-	float glow_auto_exposure_grey;
-	// DOF.
-	float dof_begin;
-	float dof_end;
-	float dof_radius;
-	float dof_pad;
-
-	vec2 dof_dir;
-	float camera_z_far;
-	float camera_z_near;
-
-	vec4 ssao_color;
-}
-blur;

+ 186 - 53
servers/rendering/rasterizer_rd/shaders/copy.glsl

@@ -1,87 +1,220 @@
 /* clang-format off */
-[vertex]
+[compute]
 
 #version 450
 
 VERSION_DEFINES
 
-layout(location = 0) out vec2 uv_interp;
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
 /* clang-format on */
 
-void main() {
+#define FLAG_HORIZONTAL (1 << 0)
+#define FLAG_USE_BLUR_SECTION (1 << 1)
+#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 2)
+#define FLAG_DOF_NEAR_FIRST_TAP (1 << 3)
+#define FLAG_GLOW_FIRST_PASS (1 << 4)
+#define FLAG_FLIP_Y (1 << 5)
+#define FLAG_FORCE_LUMINANCE (1 << 6)
+#define FLAG_COPY_ALL_SOURCE (1 << 7)
+
+layout(push_constant, binding = 1, std430) uniform Params {
+	ivec4 section;
+	ivec2 target;
+	uint flags;
+	uint pad;
+	// Glow.
+	float glow_strength;
+	float glow_bloom;
+	float glow_hdr_threshold;
+	float glow_hdr_scale;
+
+	float glow_exposure;
+	float glow_white;
+	float glow_luminance_cap;
+	float glow_auto_exposure_grey;
+	// DOF.
+	float camera_z_far;
+	float camera_z_near;
+	uvec2 pad2;
+}
+params;
 
-	vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
-	uv_interp = base_arr[gl_VertexIndex];
+layout(set = 0, binding = 0) uniform sampler2D source_color;
 
-	gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
-}
+#ifdef GLOW_USE_AUTO_EXPOSURE
+layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
+#endif
 
-/* clang-format off */
-[fragment]
+#if defined(MODE_LINEARIZE_DEPTH_COPY) || defined(MODE_SIMPLE_COPY_DEPTH)
+layout(r32f, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
+#elif defined(DST_IMAGE_8BIT)
+layout(rgba8, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
+#else
+layout(rgba32f, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
+#endif
 
-#version 450
+void main() {
 
-VERSION_DEFINES
+	// Pixel being shaded
+	ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
+	if (any(greaterThan(pos, params.section.zw))) { //too large, do nothing
+		return;
+	}
 
-layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
+#ifdef MODE_MIPMAP
 
-#ifdef MODE_CUBE_TO_DP
+	ivec2 base_pos = (pos + params.section.xy) << 1;
+	vec4 color = texelFetch(source_color, base_pos, 0);
+	color += texelFetch(source_color, base_pos + ivec2(0, 1), 0);
+	color += texelFetch(source_color, base_pos + ivec2(1, 0), 0);
+	color += texelFetch(source_color, base_pos + ivec2(1, 1), 0);
+	color /= 4.0;
 
-layout(set = 0, binding = 0) uniform samplerCube source_cube;
+	imageStore(dest_buffer, pos + params.target, color);
+#endif
 
-layout(push_constant, binding = 0, std430) uniform Params {
-	float bias;
-	float z_far;
-	float z_near;
-	bool z_flip;
-}
-params;
+#ifdef MODE_GAUSSIAN_BLUR
+
+	//Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect
 
-layout(location = 0) out float depth_buffer;
+	if (bool(params.flags & FLAG_HORIZONTAL)) {
+
+		ivec2 base_pos = (pos + params.section.xy) << 1;
+		vec4 color = texelFetch(source_color, base_pos + ivec2(0, 0), 0) * 0.214607;
+		color += texelFetch(source_color, base_pos + ivec2(1, 0), 0) * 0.189879;
+		color += texelFetch(source_color, base_pos + ivec2(2, 0), 0) * 0.131514;
+		color += texelFetch(source_color, base_pos + ivec2(3, 0), 0) * 0.071303;
+		color += texelFetch(source_color, base_pos + ivec2(-1, 0), 0) * 0.189879;
+		color += texelFetch(source_color, base_pos + ivec2(-2, 0), 0) * 0.131514;
+		color += texelFetch(source_color, base_pos + ivec2(-3, 0), 0) * 0.071303;
+		imageStore(dest_buffer, pos + params.target, color);
+	} else {
 
+		ivec2 base_pos = (pos + params.section.xy);
+		vec4 color = texelFetch(source_color, base_pos + ivec2(0, 0), 0) * 0.38774;
+		color += texelFetch(source_color, base_pos + ivec2(0, 1), 0) * 0.24477;
+		color += texelFetch(source_color, base_pos + ivec2(0, 2), 0) * 0.06136;
+		color += texelFetch(source_color, base_pos + ivec2(0, -1), 0) * 0.24477;
+		color += texelFetch(source_color, base_pos + ivec2(0, -2), 0) * 0.06136;
+		imageStore(dest_buffer, pos + params.target, color);
+	}
 #endif
 
-void main() {
+#ifdef MODE_GAUSSIAN_GLOW
 
-#ifdef MODE_CUBE_TO_DP
+	//Glow uses larger sigma 1 for a more rounded blur effect
 
-	vec3 normal = vec3(uv_interp * 2.0 - 1.0, 0.0);
+#define GLOW_ADD(m_ofs, m_mult)                                                             \
+	{                                                                                       \
+		ivec2 ofs = base_pos + m_ofs;                                                       \
+		if (all(greaterThanEqual(ofs, section_begin)) && all(lessThan(ofs, section_end))) { \
+			color += texelFetch(source_color, ofs, 0) * m_mult;                             \
+		}                                                                                   \
+	}
 
-	normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
-	normal = normalize(normal);
+	vec4 color = vec4(0.0);
 
-	normal.y = -normal.y; //needs to be flipped to match projection matrix
-	if (!params.z_flip) {
-		normal.z = -normal.z;
+	if (bool(params.flags & FLAG_HORIZONTAL)) {
+
+		ivec2 base_pos = (pos + params.section.xy) << 1;
+		ivec2 section_begin = params.section.xy << 1;
+		ivec2 section_end = section_begin + (params.section.zw << 1);
+
+		GLOW_ADD(ivec2(0, 0), 0.174938);
+		GLOW_ADD(ivec2(1, 0), 0.165569);
+		GLOW_ADD(ivec2(2, 0), 0.140367);
+		GLOW_ADD(ivec2(3, 0), 0.106595);
+		GLOW_ADD(ivec2(-1, 0), 0.165569);
+		GLOW_ADD(ivec2(-2, 0), 0.140367);
+		GLOW_ADD(ivec2(-3, 0), 0.106595);
+		color *= params.glow_strength;
+	} else {
+
+		ivec2 base_pos = pos + params.section.xy;
+		ivec2 section_begin = params.section.xy;
+		ivec2 section_end = section_begin + params.section.zw;
+
+		GLOW_ADD(ivec2(0, 0), 0.288713);
+		GLOW_ADD(ivec2(0, 1), 0.233062);
+		GLOW_ADD(ivec2(0, 2), 0.122581);
+		GLOW_ADD(ivec2(0, -1), 0.233062);
+		GLOW_ADD(ivec2(0, -2), 0.122581);
+		color *= params.glow_strength;
 	}
 
-	float depth = texture(source_cube, normal).r;
-	depth_buffer = depth;
-
-	// absolute values for direction cosines, bigger value equals closer to basis axis
-	vec3 unorm = abs(normal);
-
-	if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
-		// x code
-		unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
-	} else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
-		// y code
-		unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
-	} else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
-		// z code
-		unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
+#undef GLOW_ADD
+
+	if (bool(params.flags & FLAG_GLOW_FIRST_PASS)) {
+#ifdef GLOW_USE_AUTO_EXPOSURE
+
+		color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.glow_auto_exposure_grey;
+#endif
+		color *= params.glow_exposure;
+
+		float luminance = max(color.r, max(color.g, color.b));
+		float feedback = max(smoothstep(params.glow_hdr_threshold, params.glow_hdr_threshold + params.glow_hdr_scale, luminance), params.glow_bloom);
+
+		color = min(color * feedback, vec4(params.glow_luminance_cap));
+	}
+
+	imageStore(dest_buffer, pos + params.target, color);
+
+#endif
+
+#ifdef MODE_SIMPLE_COPY
+
+	vec4 color;
+	if (bool(params.flags & FLAG_COPY_ALL_SOURCE)) {
+		vec2 uv = vec2(pos) / vec2(params.section.zw);
+		if (bool(params.flags & FLAG_FLIP_Y)) {
+			uv.y = 1.0 - uv.y;
+		}
+		color = textureLod(source_color, uv, 0.0);
+
+		if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
+			color.rgb = vec3(max(max(color.r, color.g), color.b));
+		}
+		imageStore(dest_buffer, pos + params.target, color);
+
 	} else {
-		// oh-no we messed up code
-		// has to be
-		unorm = vec3(1.0, 0.0, 0.0);
+		color = texelFetch(source_color, pos + params.section.xy, 0);
+
+		if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
+			color.rgb = vec3(max(max(color.r, color.g), color.b));
+		}
+
+		if (bool(params.flags & FLAG_FLIP_Y)) {
+			pos.y = params.section.w - pos.y - 1;
+		}
+
+		imageStore(dest_buffer, pos + params.target, color);
 	}
 
-	float depth_fix = 1.0 / dot(normal, unorm);
+#endif
+
+#ifdef MODE_SIMPLE_COPY_DEPTH
+
+	vec4 color = texelFetch(source_color, pos + params.section.xy, 0);
+
+	if (bool(params.flags & FLAG_FLIP_Y)) {
+		pos.y = params.section.w - pos.y - 1;
+	}
 
-	depth = 2.0 * depth - 1.0;
-	float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
-	depth_buffer = (linear_depth * depth_fix) / params.z_far;
+	imageStore(dest_buffer, pos + params.target, vec4(color.r));
+
+#endif
+
+#ifdef MODE_LINEARIZE_DEPTH_COPY
+
+	float depth = texelFetch(source_color, pos + params.section.xy, 0).r;
+	depth = depth * 2.0 - 1.0;
+	depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
+	vec4 color = vec4(depth / params.camera_z_far);
+
+	if (bool(params.flags & FLAG_FLIP_Y)) {
+		pos.y = params.section.w - pos.y - 1;
+	}
 
+	imageStore(dest_buffer, pos + params.target, color);
 #endif
 }

+ 68 - 0
servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl

@@ -0,0 +1,68 @@
+/* clang-format off */
+[vertex]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(location = 0) out vec2 uv_interp;
+/* clang-format on */
+
+layout(push_constant, binding = 1, std430) uniform Params {
+	vec4 section;
+	vec2 pixel_size;
+	bool flip_y;
+	bool use_section;
+	bool force_luminance;
+	uint pad[3];
+}
+params;
+
+void main() {
+
+	vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
+	uv_interp = base_arr[gl_VertexIndex];
+
+	if (params.use_section) {
+		uv_interp = params.section.xy + uv_interp * params.section.zw;
+	}
+
+	gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
+
+	if (params.flip_y) {
+		uv_interp.y = 1.0 - uv_interp.y;
+	}
+}
+
+/* clang-format off */
+[fragment]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(push_constant, binding = 1, std430) uniform Params {
+	vec4 section;
+	vec2 pixel_size;
+	bool flip_y;
+	bool use_section;
+	bool force_luminance;
+	uint pad[3];
+} params;
+
+
+layout(location = 0) in vec2 uv_interp;
+/* clang-format on */
+
+layout(set = 0, binding = 0) uniform sampler2D source_color;
+
+layout(location = 0) out vec4 frag_color;
+
+void main() {
+
+	vec4 color = texture(source_color, uv_interp, 0.0);
+	if (params.force_luminance) {
+		color.rgb = vec3(max(max(color.r, color.g), color.b));
+	}
+	frag_color = color;
+}

+ 72 - 0
servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl

@@ -0,0 +1,72 @@
+/* clang-format off */
+[compute]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+/* clang-format on */
+
+layout(set = 0, binding = 0) uniform samplerCube source_cube;
+
+layout(push_constant, binding = 1, std430) uniform Params {
+	ivec2 screen_size;
+	ivec2 offset;
+	float bias;
+	float z_far;
+	float z_near;
+	bool z_flip;
+}
+params;
+
+layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D depth_buffer;
+
+void main() {
+
+	ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
+	if (any(greaterThan(pos, params.screen_size))) { //too large, do nothing
+		return;
+	}
+
+	vec2 pixel_size = 1.0 / vec2(params.screen_size);
+	vec2 uv = (vec2(pos) + 0.5) * pixel_size;
+
+	vec3 normal = vec3(uv * 2.0 - 1.0, 0.0);
+
+	normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
+	normal = normalize(normal);
+
+	normal.y = -normal.y; //needs to be flipped to match projection matrix
+	if (!params.z_flip) {
+		normal.z = -normal.z;
+	}
+
+	float depth = texture(source_cube, normal).r;
+
+	// absolute values for direction cosines, bigger value equals closer to basis axis
+	vec3 unorm = abs(normal);
+
+	if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
+		// x code
+		unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
+	} else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
+		// y code
+		unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
+	} else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
+		// z code
+		unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
+	} else {
+		// oh-no we messed up code
+		// has to be
+		unorm = vec3(1.0, 0.0, 0.0);
+	}
+
+	float depth_fix = 1.0 / dot(normal, unorm);
+
+	depth = 2.0 * depth - 1.0;
+	float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
+	depth = (linear_depth * depth_fix) / params.z_far;
+
+	imageStore(depth_buffer, pos + params.offset, vec4(depth));
+}

+ 1 - 0
servers/rendering/rendering_device.h

@@ -908,6 +908,7 @@ public:
 	enum InitialAction {
 		INITIAL_ACTION_CLEAR, //start rendering and clear the framebuffer (supply params)
 		INITIAL_ACTION_KEEP, //start rendering, but keep attached color texture contents (depth will be cleared)
+		INITIAL_ACTION_DROP, //start rendering, ignore what is there, just write above it
 		INITIAL_ACTION_CONTINUE, //continue rendering (framebuffer must have been left in "continue" state as final action previously)
 		INITIAL_ACTION_MAX
 	};