summaryrefslogtreecommitdiff
path: root/drivers/vulkan
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vulkan')
-rw-r--r--drivers/vulkan/SCsub29
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp892
-rw-r--r--drivers/vulkan/rendering_device_vulkan.h71
-rw-r--r--drivers/vulkan/vulkan_context.cpp145
-rw-r--r--drivers/vulkan/vulkan_context.h19
5 files changed, 967 insertions, 189 deletions
diff --git a/drivers/vulkan/SCsub b/drivers/vulkan/SCsub
index 13fcaf16d2..14b9d63204 100644
--- a/drivers/vulkan/SCsub
+++ b/drivers/vulkan/SCsub
@@ -2,7 +2,7 @@
Import("env")
-env.add_source_files(env.drivers_sources, "*.cpp")
+thirdparty_obj = []
# FIXME: Refactor all this to reduce code duplication.
if env["platform"] == "android":
@@ -22,7 +22,8 @@ if env["platform"] == "android":
thirdparty_dir = "#thirdparty/vulkan"
vma_sources = [thirdparty_dir + "/android/vk_mem_alloc.cpp"]
- env_thirdparty.add_source_files(env.drivers_sources, vma_sources)
+ env_thirdparty.add_source_files(thirdparty_obj, vma_sources)
+
elif env["platform"] == "iphone":
# Use bundled Vulkan headers
thirdparty_dir = "#thirdparty/vulkan"
@@ -33,7 +34,8 @@ elif env["platform"] == "iphone":
env_thirdparty.disable_warnings()
vma_sources = [thirdparty_dir + "/vk_mem_alloc.cpp"]
- env_thirdparty.add_source_files(env.drivers_sources, vma_sources)
+ env_thirdparty.add_source_files(thirdparty_obj, vma_sources)
+
elif env["builtin_vulkan"]:
# Use bundled Vulkan headers
thirdparty_dir = "#thirdparty/vulkan"
@@ -98,8 +100,9 @@ elif env["builtin_vulkan"]:
env_thirdparty.AppendUnique(CPPDEFINES=["HAVE_SECURE_GETENV"])
loader_sources = [thirdparty_dir + "/loader/" + file for file in loader_sources]
- env_thirdparty.add_source_files(env.drivers_sources, loader_sources)
- env_thirdparty.add_source_files(env.drivers_sources, vma_sources)
+ env_thirdparty.add_source_files(thirdparty_obj, loader_sources)
+ env_thirdparty.add_source_files(thirdparty_obj, vma_sources)
+
else: # Always build VMA.
thirdparty_dir = "#thirdparty/vulkan"
env.Prepend(CPPPATH=[thirdparty_dir])
@@ -109,4 +112,18 @@ else: # Always build VMA.
env_thirdparty.disable_warnings()
vma_sources = [thirdparty_dir + "/vk_mem_alloc.cpp"]
- env_thirdparty.add_source_files(env.drivers_sources, vma_sources)
+ env_thirdparty.add_source_files(thirdparty_obj, vma_sources)
+
+
+env.drivers_sources += thirdparty_obj
+
+
+# Godot source files
+
+driver_obj = []
+
+env.add_source_files(driver_obj, "*.cpp")
+env.drivers_sources += driver_obj
+
+# Needed to force rebuilding the driver files when the thirdparty code is updated.
+env.Depends(driver_obj, thirdparty_obj)
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 23e6b3bfb6..9584dd3f67 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -41,28 +41,62 @@
//#define FORCE_FULL_BARRIER
// Get the Vulkan object information and possible stage access types (bitwise OR'd with incoming values)
-RenderingDeviceVulkan::Buffer *RenderingDeviceVulkan::_get_buffer_from_owner(RID p_buffer, VkPipelineStageFlags &stage_mask, VkAccessFlags &access_mask) {
+RenderingDeviceVulkan::Buffer *RenderingDeviceVulkan::_get_buffer_from_owner(RID p_buffer, VkPipelineStageFlags &r_stage_mask, VkAccessFlags &r_access_mask, uint32_t p_post_barrier) {
Buffer *buffer = nullptr;
if (vertex_buffer_owner.owns(p_buffer)) {
- stage_mask |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
- access_mask |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
buffer = vertex_buffer_owner.getornull(p_buffer);
+
+ r_stage_mask |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
+ r_access_mask |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
+ if (buffer->usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) {
+ if (p_post_barrier & BARRIER_MASK_RASTER) {
+ r_access_mask |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ r_stage_mask |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ }
+ if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ r_access_mask |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ r_stage_mask |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ }
+ }
} else if (index_buffer_owner.owns(p_buffer)) {
- stage_mask |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
- access_mask |= VK_ACCESS_INDEX_READ_BIT;
+ r_stage_mask |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
+ r_access_mask |= VK_ACCESS_INDEX_READ_BIT;
buffer = index_buffer_owner.getornull(p_buffer);
} else if (uniform_buffer_owner.owns(p_buffer)) {
- stage_mask |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- access_mask |= VK_ACCESS_UNIFORM_READ_BIT;
+ if (p_post_barrier & BARRIER_MASK_RASTER) {
+ r_stage_mask |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ }
+ if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ r_stage_mask |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ }
+ r_access_mask |= VK_ACCESS_UNIFORM_READ_BIT;
buffer = uniform_buffer_owner.getornull(p_buffer);
} else if (texture_buffer_owner.owns(p_buffer)) {
- stage_mask |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- access_mask |= VK_ACCESS_SHADER_READ_BIT;
+ if (p_post_barrier & BARRIER_MASK_RASTER) {
+ r_stage_mask |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ r_access_mask |= VK_ACCESS_SHADER_READ_BIT;
+ }
+ if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ r_stage_mask |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ r_access_mask |= VK_ACCESS_SHADER_READ_BIT;
+ }
+
buffer = &texture_buffer_owner.getornull(p_buffer)->buffer;
} else if (storage_buffer_owner.owns(p_buffer)) {
- stage_mask |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- access_mask |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
buffer = storage_buffer_owner.getornull(p_buffer);
+ if (p_post_barrier & BARRIER_MASK_RASTER) {
+ r_stage_mask |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ r_access_mask |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ }
+ if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ r_stage_mask |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ r_access_mask |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ }
+
+ if (buffer->usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) {
+ r_stage_mask |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
+ r_access_mask |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
+ }
}
return buffer;
}
@@ -615,6 +649,7 @@ int RenderingDeviceVulkan::get_format_vertex_size(DataFormat p_format) {
case DATA_FORMAT_B8G8R8A8_SNORM:
case DATA_FORMAT_B8G8R8A8_UINT:
case DATA_FORMAT_B8G8R8A8_SINT:
+ case DATA_FORMAT_A2B10G10R10_UNORM_PACK32:
return 4;
case DATA_FORMAT_R16_UNORM:
case DATA_FORMAT_R16_SNORM:
@@ -1361,6 +1396,7 @@ Error RenderingDeviceVulkan::_buffer_allocate(Buffer *p_buffer, uint32_t p_size,
p_buffer->buffer_info.buffer = p_buffer->buffer;
p_buffer->buffer_info.offset = 0;
p_buffer->buffer_info.range = p_size;
+ p_buffer->usage = p_usage;
return OK;
}
@@ -1593,6 +1629,9 @@ void RenderingDeviceVulkan::_memory_barrier(VkPipelineStageFlags p_src_stage_mas
mem_barrier.srcAccessMask = p_src_access;
mem_barrier.dstAccessMask = p_dst_sccess;
+ if (p_src_stage_mask == 0 || p_dst_stage_mask == 0) {
+ return; //no barrier, since this is invalid
+ }
vkCmdPipelineBarrier(p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer, p_src_stage_mask, p_dst_stage_mask, 0, 1, &mem_barrier, 0, nullptr, 0, nullptr);
}
@@ -1691,16 +1730,16 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
#endif
}
- if (p_format.type == TEXTURE_TYPE_CUBE || p_format.type == TEXTURE_TYPE_CUBE_ARRAY) {
+ if (p_format.texture_type == TEXTURE_TYPE_CUBE || p_format.texture_type == TEXTURE_TYPE_CUBE_ARRAY) {
image_create_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
}
/*if (p_format.type == TEXTURE_TYPE_2D || p_format.type == TEXTURE_TYPE_2D_ARRAY) {
image_create_info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
}*/
- ERR_FAIL_INDEX_V(p_format.type, TEXTURE_TYPE_MAX, RID());
+ ERR_FAIL_INDEX_V(p_format.texture_type, TEXTURE_TYPE_MAX, RID());
- image_create_info.imageType = vulkan_image_type[p_format.type];
+ image_create_info.imageType = vulkan_image_type[p_format.texture_type];
ERR_FAIL_COND_V_MSG(p_format.width < 1, RID(), "Width must be equal or greater than 1 for all textures");
@@ -1725,10 +1764,10 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
image_create_info.mipLevels = p_format.mipmaps;
- if (p_format.type == TEXTURE_TYPE_1D_ARRAY || p_format.type == TEXTURE_TYPE_2D_ARRAY || p_format.type == TEXTURE_TYPE_CUBE_ARRAY || p_format.type == TEXTURE_TYPE_CUBE) {
+ if (p_format.texture_type == TEXTURE_TYPE_1D_ARRAY || p_format.texture_type == TEXTURE_TYPE_2D_ARRAY || p_format.texture_type == TEXTURE_TYPE_CUBE_ARRAY || p_format.texture_type == TEXTURE_TYPE_CUBE) {
ERR_FAIL_COND_V_MSG(p_format.array_layers < 1, RID(),
"Amount of layers must be equal or greater than 1 for arrays and cubemaps.");
- ERR_FAIL_COND_V_MSG((p_format.type == TEXTURE_TYPE_CUBE_ARRAY || p_format.type == TEXTURE_TYPE_CUBE) && (p_format.array_layers % 6) != 0, RID(),
+ ERR_FAIL_COND_V_MSG((p_format.texture_type == TEXTURE_TYPE_CUBE_ARRAY || p_format.texture_type == TEXTURE_TYPE_CUBE) && (p_format.array_layers % 6) != 0, RID(),
"Cubemap and cubemap array textures must provide a layer number that is multiple of 6");
image_create_info.arrayLayers = p_format.array_layers;
} else {
@@ -1858,7 +1897,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
VkResult err = vmaCreateImage(allocator, &image_create_info, &allocInfo, &texture.image, &texture.allocation, &texture.allocation_info);
ERR_FAIL_COND_V_MSG(err, RID(), "vmaCreateImage failed with error " + itos(err) + ".");
- texture.type = p_format.type;
+ texture.type = p_format.texture_type;
texture.format = p_format.format;
texture.width = image_create_info.extent.width;
texture.height = image_create_info.extent.height;
@@ -1926,7 +1965,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,
};
- image_view_create_info.viewType = view_types[p_format.type];
+ image_view_create_info.viewType = view_types[p_format.texture_type];
if (p_view.format_override == DATA_FORMAT_MAX) {
image_view_create_info.format = image_create_info.format;
} else {
@@ -2065,6 +2104,48 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID
image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
}
+ VkImageViewUsageCreateInfo usage_info;
+ usage_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO;
+ usage_info.pNext = nullptr;
+ if (p_view.format_override != DATA_FORMAT_MAX) {
+ //need to validate usage with vulkan
+
+ usage_info.usage = 0;
+
+ if (texture.usage_flags & TEXTURE_USAGE_SAMPLING_BIT) {
+ usage_info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
+ }
+
+ if (texture.usage_flags & TEXTURE_USAGE_STORAGE_BIT) {
+ if (texture_is_format_supported_for_usage(p_view.format_override, TEXTURE_USAGE_STORAGE_BIT)) {
+ usage_info.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
+ }
+ }
+
+ if (texture.usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
+ if (texture_is_format_supported_for_usage(p_view.format_override, TEXTURE_USAGE_COLOR_ATTACHMENT_BIT)) {
+ usage_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ }
+ }
+
+ if (texture.usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+ usage_info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ }
+
+ if (texture.usage_flags & TEXTURE_USAGE_CAN_UPDATE_BIT) {
+ usage_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ }
+ if (texture.usage_flags & TEXTURE_USAGE_CAN_COPY_FROM_BIT) {
+ usage_info.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+ }
+
+ if (texture.usage_flags & TEXTURE_USAGE_CAN_COPY_TO_BIT) {
+ usage_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ }
+
+ image_view_create_info.pNext = &usage_info;
+ }
+
VkResult err = vkCreateImageView(device, &image_view_create_info, nullptr, &texture.view);
ERR_FAIL_COND_V_MSG(err, RID(), "vkCreateImageView failed with error " + itos(err) + ".");
@@ -2093,15 +2174,26 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
ERR_FAIL_COND_V_MSG(p_slice_type == TEXTURE_SLICE_3D && src_texture->type != TEXTURE_TYPE_3D, RID(),
"Can only create a 3D slice from a 3D texture");
+ ERR_FAIL_COND_V_MSG(p_slice_type == TEXTURE_SLICE_2D_ARRAY && (src_texture->type != TEXTURE_TYPE_2D_ARRAY), RID(),
+ "Can only create an array slice from a 2D array mipmap");
+
//create view
ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, src_texture->mipmaps, RID());
ERR_FAIL_UNSIGNED_INDEX_V(p_layer, src_texture->layers, RID());
+ int slice_layers = 1;
+ if (p_slice_type == TEXTURE_SLICE_2D_ARRAY) {
+ ERR_FAIL_COND_V_MSG(p_layer != 0, RID(), "layer must be 0 when obtaining a 2D array mipmap slice");
+ slice_layers = src_texture->layers;
+ } else if (p_slice_type == TEXTURE_SLICE_CUBEMAP) {
+ slice_layers = 6;
+ }
+
Texture texture = *src_texture;
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.layers = slice_layers;
texture.base_mipmap = p_mipmap;
texture.base_layer = p_layer;
@@ -2121,7 +2213,16 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
VK_IMAGE_VIEW_TYPE_2D,
};
- image_view_create_info.viewType = p_slice_type == TEXTURE_SLICE_CUBEMAP ? VK_IMAGE_VIEW_TYPE_CUBE : (p_slice_type == TEXTURE_SLICE_3D ? VK_IMAGE_VIEW_TYPE_3D : view_types[texture.type]);
+ image_view_create_info.viewType = view_types[texture.type];
+
+ if (p_slice_type == TEXTURE_SLICE_CUBEMAP) {
+ image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
+ } else if (p_slice_type == TEXTURE_SLICE_3D) {
+ image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_3D;
+ } else if (p_slice_type == TEXTURE_SLICE_2D_ARRAY) {
+ image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ }
+
if (p_view.format_override == DATA_FORMAT_MAX || p_view.format_override == texture.format) {
image_view_create_info.format = vulkan_formats[texture.format];
} else {
@@ -2155,7 +2256,7 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
}
image_view_create_info.subresourceRange.baseMipLevel = p_mipmap;
image_view_create_info.subresourceRange.levelCount = 1;
- image_view_create_info.subresourceRange.layerCount = p_slice_type == TEXTURE_SLICE_CUBEMAP ? 6 : 1;
+ image_view_create_info.subresourceRange.layerCount = slice_layers;
image_view_create_info.subresourceRange.baseArrayLayer = p_layer;
if (texture.usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
@@ -2174,11 +2275,11 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
return id;
}
-Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, bool p_sync_with_draw) {
+Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, uint32_t p_post_barrier) {
_THREAD_SAFE_METHOD_
- ERR_FAIL_COND_V_MSG(draw_list && p_sync_with_draw, ERR_INVALID_PARAMETER,
- "Updating textures in 'sync to draw' mode is forbidden during creation of a draw list");
+ ERR_FAIL_COND_V_MSG(draw_list || compute_list, ERR_INVALID_PARAMETER,
+ "Updating textures in is forbidden during creation of a draw or compute list");
Texture *texture = texture_owner.getornull(p_texture);
ERR_FAIL_COND_V(!texture, ERR_INVALID_PARAMETER);
@@ -2219,7 +2320,7 @@ Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, con
const uint8_t *r = p_data.ptr();
- VkCommandBuffer command_buffer = p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer;
+ VkCommandBuffer command_buffer = p_post_barrier ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer;
//barrier to transfer
{
@@ -2244,6 +2345,10 @@ Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, con
}
uint32_t mipmap_offset = 0;
+
+ uint32_t logic_width = texture->width;
+ uint32_t logic_height = texture->height;
+
for (uint32_t mm_i = 0; mm_i < texture->mipmaps; mm_i++) {
uint32_t depth;
uint32_t image_total = get_image_format_required_size(texture->format, texture->width, texture->height, texture->depth, mm_i + 1, &width, &height, &depth);
@@ -2260,12 +2365,15 @@ Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, con
uint32_t region_w = MIN(region_size, width - x);
uint32_t region_h = MIN(region_size, height - y);
+ uint32_t region_logic_w = MIN(region_size, logic_width - x);
+ uint32_t region_logic_h = MIN(region_size, logic_height - y);
+
uint32_t pixel_size = get_image_format_pixel_size(texture->format);
uint32_t to_allocate = region_w * region_h * pixel_size;
to_allocate >>= get_compressed_image_format_pixel_rshift(texture->format);
uint32_t alloc_offset, alloc_size;
- Error err = _staging_buffer_allocate(to_allocate, required_align, alloc_offset, alloc_size, false, p_sync_with_draw);
+ Error err = _staging_buffer_allocate(to_allocate, required_align, alloc_offset, alloc_size, false, p_post_barrier);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
uint8_t *write_ptr;
@@ -2341,8 +2449,8 @@ Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, con
buffer_image_copy.imageOffset.y = y;
buffer_image_copy.imageOffset.z = z;
- buffer_image_copy.imageExtent.width = region_w;
- buffer_image_copy.imageExtent.height = region_h;
+ buffer_image_copy.imageExtent.width = region_logic_w;
+ buffer_image_copy.imageExtent.height = region_logic_h;
buffer_image_copy.imageExtent.depth = 1;
vkCmdCopyBufferToImage(command_buffer, staging_buffer_blocks[staging_buffer_current].buffer, texture->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_image_copy);
@@ -2353,15 +2461,36 @@ Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, con
}
mipmap_offset = image_total;
+ logic_width = MAX(1, logic_width >> 1);
+ logic_height = MAX(1, logic_height >> 1);
}
//barrier to restore layout
{
+ uint32_t barrier_flags = 0;
+ uint32_t access_flags = 0;
+ if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ access_flags |= VK_ACCESS_SHADER_READ_BIT;
+ }
+ if (p_post_barrier & BARRIER_MASK_RASTER) {
+ barrier_flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ access_flags |= VK_ACCESS_SHADER_READ_BIT;
+ }
+ if (p_post_barrier & BARRIER_MASK_TRANSFER) {
+ barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
+ access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
+ }
+
+ if (barrier_flags == 0) {
+ barrier_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
- image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ image_memory_barrier.dstAccessMask = access_flags;
image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
image_memory_barrier.newLayout = texture->layout;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
@@ -2373,9 +2502,16 @@ Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, con
image_memory_barrier.subresourceRange.baseArrayLayer = p_layer;
image_memory_barrier.subresourceRange.layerCount = 1;
- vkCmdPipelineBarrier(command_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
+ vkCmdPipelineBarrier(command_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, barrier_flags, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
}
+ if (texture->used_in_frame != frames_drawn) {
+ texture->used_in_raster = false;
+ texture->used_in_compute = false;
+ texture->used_in_frame = frames_drawn;
+ }
+ texture->used_in_transfer = true;
+
return OK;
}
@@ -2586,13 +2722,13 @@ bool RenderingDeviceVulkan::texture_is_valid(RID p_texture) {
return texture_owner.owns(p_texture);
}
-Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, bool p_sync_with_draw) {
+Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, uint32_t p_post_barrier) {
_THREAD_SAFE_METHOD_
Texture *src_tex = texture_owner.getornull(p_from_texture);
ERR_FAIL_COND_V(!src_tex, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V_MSG(p_sync_with_draw && src_tex->bound, ERR_INVALID_PARAMETER,
+ ERR_FAIL_COND_V_MSG(src_tex->bound, ERR_INVALID_PARAMETER,
"Source texture can't be copied while a render pass that uses it is being created. Ensure render pass is finalized (and that it was created with RENDER_PASS_CONTENTS_FINISH) to unbind this texture.");
ERR_FAIL_COND_V_MSG(!(src_tex->usage_flags & TEXTURE_USAGE_CAN_COPY_FROM_BIT), ERR_INVALID_PARAMETER,
"Source texture requires the TEXTURE_USAGE_CAN_COPY_FROM_BIT in order to be retrieved.");
@@ -2613,7 +2749,7 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
Texture *dst_tex = texture_owner.getornull(p_to_texture);
ERR_FAIL_COND_V(!dst_tex, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V_MSG(p_sync_with_draw && dst_tex->bound, ERR_INVALID_PARAMETER,
+ ERR_FAIL_COND_V_MSG(dst_tex->bound, ERR_INVALID_PARAMETER,
"Destination texture can't be copied while a render pass that uses it is being created. Ensure render pass is finalized (and that it was created with RENDER_PASS_CONTENTS_FINISH) to unbind this texture.");
ERR_FAIL_COND_V_MSG(!(dst_tex->usage_flags & TEXTURE_USAGE_CAN_COPY_TO_BIT), ERR_INVALID_PARAMETER,
"Destination texture requires the TEXTURE_USAGE_CAN_COPY_TO_BIT in order to be retrieved.");
@@ -2634,7 +2770,7 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
ERR_FAIL_COND_V_MSG(src_tex->read_aspect_mask != dst_tex->read_aspect_mask, ERR_INVALID_PARAMETER,
"Source and destination texture must be of the same type (color or depth).");
- VkCommandBuffer command_buffer = p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer;
+ VkCommandBuffer command_buffer = frames[frame].draw_command_buffer;
{
//PRE Copy the image
@@ -2709,12 +2845,31 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
// RESTORE LAYOUT for SRC and DST
+ uint32_t barrier_flags = 0;
+ uint32_t access_flags = 0;
+ if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ }
+ if (p_post_barrier & BARRIER_MASK_RASTER) {
+ barrier_flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ }
+ if (p_post_barrier & BARRIER_MASK_TRANSFER) {
+ barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
+ access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
+ }
+
+ if (barrier_flags == 0) {
+ barrier_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+
{ //restore src
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
- image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ image_memory_barrier.dstAccessMask = access_flags;
image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
image_memory_barrier.newLayout = src_tex->layout;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
@@ -2726,7 +2881,7 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
image_memory_barrier.subresourceRange.baseArrayLayer = p_src_layer;
image_memory_barrier.subresourceRange.layerCount = 1;
- vkCmdPipelineBarrier(command_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
+ vkCmdPipelineBarrier(command_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, barrier_flags, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
}
{ //make dst readable
@@ -2735,7 +2890,7 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
- image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ image_memory_barrier.dstAccessMask = access_flags;
image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
image_memory_barrier.newLayout = dst_tex->layout;
@@ -2748,20 +2903,20 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
image_memory_barrier.subresourceRange.baseArrayLayer = p_src_layer;
image_memory_barrier.subresourceRange.layerCount = 1;
- vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
+ vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, barrier_flags, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
}
}
return OK;
}
-Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID p_to_texture, bool p_sync_with_draw) {
+Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID p_to_texture, uint32_t p_post_barrier) {
_THREAD_SAFE_METHOD_
Texture *src_tex = texture_owner.getornull(p_from_texture);
ERR_FAIL_COND_V(!src_tex, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V_MSG(p_sync_with_draw && src_tex->bound, ERR_INVALID_PARAMETER,
+ ERR_FAIL_COND_V_MSG(src_tex->bound, ERR_INVALID_PARAMETER,
"Source texture can't be copied while a render pass that uses it is being created. Ensure render pass is finalized (and that it was created with RENDER_PASS_CONTENTS_FINISH) to unbind this texture.");
ERR_FAIL_COND_V_MSG(!(src_tex->usage_flags & TEXTURE_USAGE_CAN_COPY_FROM_BIT), ERR_INVALID_PARAMETER,
"Source texture requires the TEXTURE_USAGE_CAN_COPY_FROM_BIT in order to be retrieved.");
@@ -2772,7 +2927,7 @@ Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID
Texture *dst_tex = texture_owner.getornull(p_to_texture);
ERR_FAIL_COND_V(!dst_tex, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V_MSG(p_sync_with_draw && dst_tex->bound, ERR_INVALID_PARAMETER,
+ ERR_FAIL_COND_V_MSG(dst_tex->bound, ERR_INVALID_PARAMETER,
"Destination texture can't be copied while a render pass that uses it is being created. Ensure render pass is finalized (and that it was created with RENDER_PASS_CONTENTS_FINISH) to unbind this texture.");
ERR_FAIL_COND_V_MSG(!(dst_tex->usage_flags & TEXTURE_USAGE_CAN_COPY_TO_BIT), ERR_INVALID_PARAMETER,
"Destination texture requires the TEXTURE_USAGE_CAN_COPY_TO_BIT in order to be retrieved.");
@@ -2786,7 +2941,7 @@ Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID
ERR_FAIL_COND_V_MSG(src_tex->read_aspect_mask != dst_tex->read_aspect_mask, ERR_INVALID_PARAMETER,
"Source and destination texture must be of the same type (color or depth).");
- VkCommandBuffer command_buffer = p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer;
+ VkCommandBuffer command_buffer = frames[frame].draw_command_buffer;
{
//PRE Copy the image
@@ -2861,12 +3016,31 @@ Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID
// RESTORE LAYOUT for SRC and DST
+ uint32_t barrier_flags = 0;
+ uint32_t access_flags = 0;
+ if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ }
+ if (p_post_barrier & BARRIER_MASK_RASTER) {
+ barrier_flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ }
+ if (p_post_barrier & BARRIER_MASK_TRANSFER) {
+ barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
+ access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
+ }
+
+ if (barrier_flags == 0) {
+ barrier_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+
{ //restore src
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
- image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ image_memory_barrier.dstAccessMask = access_flags;
image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
image_memory_barrier.newLayout = src_tex->layout;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
@@ -2878,7 +3052,7 @@ Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID
image_memory_barrier.subresourceRange.baseArrayLayer = src_tex->base_layer;
image_memory_barrier.subresourceRange.layerCount = 1;
- vkCmdPipelineBarrier(command_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
+ vkCmdPipelineBarrier(command_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, barrier_flags, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
}
{ //make dst readable
@@ -2887,7 +3061,7 @@ Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
- image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ image_memory_barrier.dstAccessMask = access_flags;
image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
image_memory_barrier.newLayout = dst_tex->layout;
@@ -2900,20 +3074,20 @@ Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID
image_memory_barrier.subresourceRange.baseArrayLayer = dst_tex->base_layer;
image_memory_barrier.subresourceRange.layerCount = 1;
- vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
+ vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, barrier_flags, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
}
}
return OK;
}
-Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, bool p_sync_with_draw) {
+Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, uint32_t p_post_barrier) {
_THREAD_SAFE_METHOD_
Texture *src_tex = texture_owner.getornull(p_texture);
ERR_FAIL_COND_V(!src_tex, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V_MSG(p_sync_with_draw && src_tex->bound, ERR_INVALID_PARAMETER,
+ ERR_FAIL_COND_V_MSG(src_tex->bound, ERR_INVALID_PARAMETER,
"Source texture can't be cleared while a render pass that uses it is being created. Ensure render pass is finalized (and that it was created with RENDER_PASS_CONTENTS_FINISH) to unbind this texture.");
ERR_FAIL_COND_V(p_layers == 0, ERR_INVALID_PARAMETER);
@@ -2930,7 +3104,7 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
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);
- VkCommandBuffer command_buffer = p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer;
+ VkCommandBuffer command_buffer = frames[frame].draw_command_buffer;
VkImageLayout clear_layout = (src_tex->layout == VK_IMAGE_LAYOUT_GENERAL) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
@@ -2977,11 +3151,31 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
vkCmdClearColorImage(command_buffer, src_tex->image, clear_layout, &clear_color, 1, &range);
{ // Barrier to post clear accesses (changing back the layout if needed)
+
+ uint32_t barrier_flags = 0;
+ uint32_t access_flags = 0;
+ if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ }
+ if (p_post_barrier & BARRIER_MASK_RASTER) {
+ barrier_flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ }
+ if (p_post_barrier & BARRIER_MASK_TRANSFER) {
+ barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
+ access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
+ }
+
+ if (barrier_flags == 0) {
+ barrier_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
- image_memory_barrier.dstAccessMask = valid_texture_access;
+ image_memory_barrier.dstAccessMask = access_flags;
image_memory_barrier.oldLayout = clear_layout;
image_memory_barrier.newLayout = src_tex->layout;
@@ -2994,9 +3188,16 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
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, valid_texture_stages, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
+ vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, barrier_flags, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
}
+ if (src_tex->used_in_frame != frames_drawn) {
+ src_tex->used_in_raster = false;
+ src_tex->used_in_compute = false;
+ src_tex->used_in_frame = frames_drawn;
+ }
+ src_tex->used_in_transfer = true;
+
return OK;
}
@@ -3082,6 +3283,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
// the read. If this is a performance issue, one could track the actual last accessor of each resource, adding only that
// stage
switch (is_depth_stencil ? p_initial_depth_action : p_initial_color_action) {
+ case INITIAL_ACTION_CLEAR_REGION:
case INITIAL_ACTION_CLEAR: {
description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
@@ -3094,9 +3296,9 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
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_CLEAR;
- description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
- description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
dependency_from_external.srcStageMask |= reading_stages;
} else {
description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
@@ -3122,6 +3324,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
dependency_from_external.srcStageMask |= reading_stages;
}
} break;
+ case INITIAL_ACTION_CLEAR_REGION_CONTINUE:
case INITIAL_ACTION_CONTINUE: {
if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
@@ -3129,7 +3332,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
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_LOAD;
- description.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; //don't care what is there
+ description.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
} else {
description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
@@ -3258,8 +3461,13 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
render_pass_create_info.pAttachments = attachments.ptr();
render_pass_create_info.subpassCount = 1;
render_pass_create_info.pSubpasses = &subpass;
- render_pass_create_info.dependencyCount = 2;
- render_pass_create_info.pDependencies = dependencies;
+ // Commenting this because it seems it just avoids raster and compute to work at the same time.
+ // Other barriers seem to be protecting the render pass fine.
+ // render_pass_create_info.dependencyCount = 2;
+ // render_pass_create_info.pDependencies = dependencies;
+
+ render_pass_create_info.dependencyCount = 0;
+ render_pass_create_info.pDependencies = nullptr;
VkRenderPass render_pass;
VkResult res = vkCreateRenderPass(device, &render_pass_create_info, nullptr, &render_pass);
@@ -3301,11 +3509,8 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c
return id;
}
-RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_create_empty(const Size2i &p_size) {
- ERR_FAIL_COND_V(p_size.width <= 0 || p_size.height <= 0, INVALID_FORMAT_ID);
-
+RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_create_empty(TextureSamples p_samples) {
FramebufferFormatKey key;
- key.empty_size = p_size;
const Map<FramebufferFormatKey, FramebufferFormatID>::Element *E = framebuffer_format_cache.find(key);
if (E) {
@@ -3353,7 +3558,7 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c
fb_format.E = E;
fb_format.color_attachments = 0;
fb_format.render_pass = render_pass;
- fb_format.samples = TEXTURE_SAMPLES_1;
+ fb_format.samples = p_samples;
framebuffer_formats[id] = fb_format;
return id;
}
@@ -3369,10 +3574,10 @@ RenderingDevice::TextureSamples RenderingDeviceVulkan::framebuffer_format_get_te
/**** RENDER TARGET ****/
/***********************/
-RID RenderingDeviceVulkan::framebuffer_create_empty(const Size2i &p_size, FramebufferFormatID p_format_check) {
+RID RenderingDeviceVulkan::framebuffer_create_empty(const Size2i &p_size, TextureSamples p_samples, FramebufferFormatID p_format_check) {
_THREAD_SAFE_METHOD_
Framebuffer framebuffer;
- framebuffer.format_id = framebuffer_format_create_empty(p_size);
+ framebuffer.format_id = framebuffer_format_create_empty(p_samples);
ERR_FAIL_COND_V(p_format_check != INVALID_FORMAT_ID && framebuffer.format_id != p_format_check, RID());
framebuffer.size = p_size;
@@ -3484,7 +3689,7 @@ RID RenderingDeviceVulkan::sampler_create(const SamplerState &p_state) {
/**** VERTEX ARRAY ****/
/**********************/
-RID RenderingDeviceVulkan::vertex_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data) {
+RID RenderingDeviceVulkan::vertex_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data, bool p_use_as_storage) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(p_data.size() && (uint32_t)p_data.size() != p_size_bytes, RID());
@@ -3493,8 +3698,12 @@ RID RenderingDeviceVulkan::vertex_buffer_create(uint32_t p_size_bytes, const Vec
ERR_FAIL_COND_V_MSG(compute_list != nullptr && p_data.size(), RID(),
"Creating buffers with data is forbidden during creation of a draw list");
+ uint32_t usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+ if (p_use_as_storage) {
+ usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+ }
Buffer buffer;
- _buffer_allocate(&buffer, p_size_bytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
+ _buffer_allocate(&buffer, p_size_bytes, usage, VMA_MEMORY_USAGE_GPU_ONLY);
if (p_data.size()) {
uint64_t data_size = p_data.size();
const uint8_t *r = p_data.ptr();
@@ -3528,7 +3737,7 @@ RenderingDevice::VertexFormatID RenderingDeviceVulkan::vertex_format_create(cons
ERR_FAIL_COND_V(used_locations.has(p_vertex_formats[i].location), INVALID_ID);
ERR_FAIL_COND_V_MSG(get_format_vertex_size(p_vertex_formats[i].format) == 0, INVALID_ID,
- "Data format for attachment (" + itos(i) + ") is not valid for a vertex array.");
+ "Data format for attachment (" + itos(i) + "), '" + named_formats[p_vertex_formats[i].format] + "', is not valid for a vertex array.");
vdcache.bindings[i].binding = i;
vdcache.bindings[i].stride = p_vertex_formats[i].stride;
@@ -3940,6 +4149,8 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
bool is_compute = false;
+ uint32_t compute_local_size[3] = { 0, 0, 0 };
+
for (int i = 0; i < p_stages.size(); i++) {
if (p_stages[i].shader_stage == SHADER_STAGE_COMPUTE) {
is_compute = true;
@@ -3956,6 +4167,11 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
"Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed parsing shader.");
+ if (is_compute) {
+ compute_local_size[0] = module.entry_points->local_size.x;
+ compute_local_size[1] = module.entry_points->local_size.y;
+ compute_local_size[2] = module.entry_points->local_size.z;
+ }
uint32_t binding_count = 0;
result = spvReflectEnumerateDescriptorBindings(&module, &binding_count, nullptr);
ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
@@ -4035,6 +4251,10 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
info.type = UNIFORM_TYPE_INPUT_ATTACHMENT;
} break;
+ case SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: {
+ ERR_PRINT("Acceleration structure not supported.");
+ continue;
+ } break;
}
if (need_array_dimensions) {
@@ -4156,6 +4376,7 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
}
}
}
+
uint32_t pc_count = 0;
result = spvReflectEnumeratePushConstantBlocks(&module, &pc_count, nullptr);
ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
@@ -4204,6 +4425,9 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
shader.fragment_outputs = fragment_outputs;
shader.push_constant = push_constant;
shader.is_compute = is_compute;
+ shader.compute_local_size[0] = compute_local_size[0];
+ shader.compute_local_size[1] = compute_local_size[1];
+ shader.compute_local_size[2] = compute_local_size[2];
String error_text;
@@ -4560,7 +4784,7 @@ void RenderingDeviceVulkan::_descriptor_pool_free(const DescriptorPoolKey &p_key
vkDestroyDescriptorPool(device, p_pool->pool, nullptr);
descriptor_pools[p_key].erase(p_pool);
memdelete(p_pool);
- if (descriptor_pools[p_key].empty()) {
+ if (descriptor_pools[p_key].is_empty()) {
descriptor_pools.erase(p_key);
}
}
@@ -4594,7 +4818,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
List<Vector<VkBufferView>> buffer_views;
List<Vector<VkDescriptorImageInfo>> image_infos;
//used for verification to make sure a uniform set does not use a framebuffer bound texture
- Vector<RID> attachable_textures;
+ LocalVector<UniformSet::AttachableTexture> attachable_textures;
Vector<Texture *> mutable_sampled_textures;
Vector<Texture *> mutable_storage_textures;
@@ -4611,8 +4835,8 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
const Uniform &uniform = uniforms[uniform_idx];
- ERR_FAIL_COND_V_MSG(uniform.type != set_uniform.type, RID(),
- "Mismatch uniform type for binding (" + itos(set_uniform.binding) + "), set (" + itos(p_shader_set) + "). Expected '" + shader_uniform_names[set_uniform.type] + "', supplied: '" + shader_uniform_names[uniform.type] + "'.");
+ ERR_FAIL_COND_V_MSG(uniform.uniform_type != set_uniform.type, RID(),
+ "Mismatch uniform type for binding (" + itos(set_uniform.binding) + "), set (" + itos(p_shader_set) + "). Expected '" + shader_uniform_names[set_uniform.type] + "', supplied: '" + shader_uniform_names[uniform.uniform_type] + "'.");
VkWriteDescriptorSet write; //common header
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
@@ -4627,7 +4851,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
write.pTexelBufferView = nullptr;
uint32_t type_size = 1;
- switch (uniform.type) {
+ switch (uniform.uniform_type) {
case UNIFORM_TYPE_SAMPLER: {
if (uniform.ids.size() != set_uniform.length) {
if (set_uniform.length > 1) {
@@ -4687,7 +4911,10 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
img_info.imageView = texture->view;
if (texture->usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_RESOLVE_ATTACHMENT_BIT)) {
- attachable_textures.push_back(texture->owner.is_valid() ? texture->owner : uniform.ids[j + 1]);
+ UniformSet::AttachableTexture attachable_texture;
+ attachable_texture.bind = set_uniform.binding;
+ attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.ids[j + 1];
+ attachable_textures.push_back(attachable_texture);
}
if (texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT) {
@@ -4737,7 +4964,10 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
img_info.imageView = texture->view;
if (texture->usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_RESOLVE_ATTACHMENT_BIT)) {
- attachable_textures.push_back(texture->owner.is_valid() ? texture->owner : uniform.ids[j]);
+ UniformSet::AttachableTexture attachable_texture;
+ attachable_texture.bind = set_uniform.binding;
+ attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.ids[j];
+ attachable_textures.push_back(attachable_texture);
}
if (texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT) {
@@ -4910,7 +5140,15 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
ERR_FAIL_COND_V_MSG(uniform.ids.size() != 1, RID(),
"Storage buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.ids.size()) + " provided).");
- Buffer *buffer = storage_buffer_owner.getornull(uniform.ids[0]);
+ Buffer *buffer = nullptr;
+
+ if (storage_buffer_owner.owns(uniform.ids[0])) {
+ buffer = storage_buffer_owner.getornull(uniform.ids[0]);
+ } else if (vertex_buffer_owner.owns(uniform.ids[0])) {
+ buffer = vertex_buffer_owner.getornull(uniform.ids[0]);
+
+ ERR_FAIL_COND_V_MSG(!(buffer->usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), RID(), "Vertex buffer supplied (binding: " + itos(uniform.binding) + ") was not created with storage flag.");
+ }
ERR_FAIL_COND_V_MSG(!buffer, RID(), "Storage buffer supplied (binding: " + itos(uniform.binding) + ") is invalid.");
//if 0, then its sized on link time
@@ -4996,19 +5234,22 @@ bool RenderingDeviceVulkan::uniform_set_is_valid(RID p_uniform_set) {
return uniform_set_owner.owns(p_uniform_set);
}
-Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, bool p_sync_with_draw) {
+Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier) {
_THREAD_SAFE_METHOD_
- ERR_FAIL_COND_V_MSG(draw_list && p_sync_with_draw, ERR_INVALID_PARAMETER,
- "Updating buffers in 'sync to draw' mode is forbidden during creation of a draw list");
- ERR_FAIL_COND_V_MSG(compute_list && p_sync_with_draw, ERR_INVALID_PARAMETER,
- "Updating buffers in 'sync to draw' mode is forbidden during creation of a compute list");
-
- // Protect subsequent updates...
- VkPipelineStageFlags dst_stage_mask = VK_PIPELINE_STAGE_TRANSFER_BIT;
- VkAccessFlags dst_access = VK_ACCESS_TRANSFER_WRITE_BIT;
+ ERR_FAIL_COND_V_MSG(draw_list, ERR_INVALID_PARAMETER,
+ "Updating buffers is forbidden during creation of a draw list");
+ ERR_FAIL_COND_V_MSG(compute_list, ERR_INVALID_PARAMETER,
+ "Updating buffers is forbidden during creation of a compute list");
- Buffer *buffer = _get_buffer_from_owner(p_buffer, dst_stage_mask, dst_access);
+ VkPipelineStageFlags dst_stage_mask = 0;
+ VkAccessFlags dst_access = 0;
+ if (p_post_barrier & BARRIER_MASK_TRANSFER) {
+ // Protect subsequent updates...
+ dst_stage_mask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+ dst_access = VK_ACCESS_TRANSFER_WRITE_BIT;
+ }
+ Buffer *buffer = _get_buffer_from_owner(p_buffer, dst_stage_mask, dst_access, p_post_barrier);
if (!buffer) {
ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Buffer argument is not a valid buffer of any type.");
}
@@ -5016,20 +5257,73 @@ Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint
ERR_FAIL_COND_V_MSG(p_offset + p_size > buffer->size, ERR_INVALID_PARAMETER,
"Attempted to write buffer (" + itos((p_offset + p_size) - buffer->size) + " bytes) past the end.");
- _buffer_memory_barrier(buffer->buffer, p_offset, p_size, dst_stage_mask, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_access, VK_ACCESS_TRANSFER_WRITE_BIT, p_sync_with_draw);
- Error err = _buffer_update(buffer, p_offset, (uint8_t *)p_data, p_size, p_sync_with_draw);
+ // no barrier should be needed here
+ // _buffer_memory_barrier(buffer->buffer, p_offset, p_size, dst_stage_mask, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_access, VK_ACCESS_TRANSFER_WRITE_BIT, true);
+
+ Error err = _buffer_update(buffer, p_offset, (uint8_t *)p_data, p_size, p_post_barrier);
if (err) {
return err;
}
#ifdef FORCE_FULL_BARRIER
- _full_barrier(p_sync_with_draw);
+ _full_barrier(true);
#else
- _buffer_memory_barrier(buffer->buffer, p_offset, p_size, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage_mask, VK_ACCESS_TRANSFER_WRITE_BIT, dst_access, p_sync_with_draw);
+ if (dst_stage_mask == 0) {
+ dst_stage_mask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+
+ if (p_post_barrier != RD::BARRIER_MASK_NO_BARRIER) {
+ _buffer_memory_barrier(buffer->buffer, p_offset, p_size, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage_mask, VK_ACCESS_TRANSFER_WRITE_BIT, dst_access, true);
+ }
+
#endif
return err;
}
+Error RenderingDeviceVulkan::buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, uint32_t p_post_barrier) {
+ _THREAD_SAFE_METHOD_
+
+ ERR_FAIL_COND_V_MSG((p_size % 4) != 0, ERR_INVALID_PARAMETER,
+ "Size must be a multiple of four");
+ ERR_FAIL_COND_V_MSG(draw_list, ERR_INVALID_PARAMETER,
+ "Updating buffers in is forbidden during creation of a draw list");
+ ERR_FAIL_COND_V_MSG(compute_list, ERR_INVALID_PARAMETER,
+ "Updating buffers is forbidden during creation of a compute list");
+
+ VkPipelineStageFlags dst_stage_mask = 0;
+ VkAccessFlags dst_access = 0;
+ if (p_post_barrier & BARRIER_MASK_TRANSFER) {
+ // Protect subsequent updates...
+ dst_stage_mask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+ dst_access = VK_ACCESS_TRANSFER_WRITE_BIT;
+ }
+
+ Buffer *buffer = _get_buffer_from_owner(p_buffer, dst_stage_mask, dst_access, p_post_barrier);
+ if (!buffer) {
+ ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Buffer argument is not a valid buffer of any type.");
+ }
+
+ ERR_FAIL_COND_V_MSG(p_offset + p_size > buffer->size, ERR_INVALID_PARAMETER,
+ "Attempted to write buffer (" + itos((p_offset + p_size) - buffer->size) + " bytes) past the end.");
+
+ // should not be needed
+ // _buffer_memory_barrier(buffer->buffer, p_offset, p_size, dst_stage_mask, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_access, VK_ACCESS_TRANSFER_WRITE_BIT, p_post_barrier);
+
+ vkCmdFillBuffer(frames[frame].draw_command_buffer, buffer->buffer, p_offset, p_size, 0);
+
+#ifdef FORCE_FULL_BARRIER
+ _full_barrier(true);
+#else
+ if (dst_stage_mask == 0) {
+ dst_stage_mask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+
+ _buffer_memory_barrier(buffer->buffer, p_offset, p_size, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage_mask, VK_ACCESS_TRANSFER_WRITE_BIT, dst_access, dst_stage_mask);
+
+#endif
+ return OK;
+}
+
Vector<uint8_t> RenderingDeviceVulkan::buffer_get_data(RID p_buffer) {
_THREAD_SAFE_METHOD_
@@ -5037,7 +5331,7 @@ Vector<uint8_t> RenderingDeviceVulkan::buffer_get_data(RID p_buffer) {
VkPipelineShaderStageCreateFlags src_stage_mask = VK_PIPELINE_STAGE_TRANSFER_BIT;
VkAccessFlags src_access_mask = VK_ACCESS_TRANSFER_WRITE_BIT;
// Get the vulkan buffer and the potential stage/access possible
- Buffer *buffer = _get_buffer_from_owner(p_buffer, src_stage_mask, src_access_mask);
+ Buffer *buffer = _get_buffer_from_owner(p_buffer, src_stage_mask, src_access_mask, BARRIER_MASK_ALL);
if (!buffer) {
ERR_FAIL_V_MSG(Vector<uint8_t>(), "Buffer is either invalid or this type of buffer can't be retrieved. Only Index and Vertex buffers allow retrieving.");
}
@@ -5480,6 +5774,9 @@ RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader) {
pipeline.pipeline_layout = shader->pipeline_layout;
pipeline.shader = p_shader;
pipeline.push_constant_size = shader->push_constant.push_constant_size;
+ pipeline.local_group_size[0] = shader->compute_local_size[0];
+ pipeline.local_group_size[1] = shader->compute_local_size[1];
+ pipeline.local_group_size[2] = shader->compute_local_size[2];
//create ID to associate with this pipeline
RID id = compute_pipeline_owner.make_rid(pipeline);
@@ -5598,7 +5895,7 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin_for_screen(Di
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
- return ID_TYPE_DRAW_LIST;
+ return int64_t(ID_TYPE_DRAW_LIST) << ID_BASE_SHIFT;
}
Error RenderingDeviceVulkan::_draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, VkFramebuffer *r_framebuffer, VkRenderPass *r_render_pass) {
@@ -5651,11 +5948,18 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff
render_pass_begin.pNext = nullptr;
render_pass_begin.renderPass = render_pass;
render_pass_begin.framebuffer = vkframebuffer;
-
+ /*
+ * Given how API works, it makes sense to always fully operate on the whole framebuffer.
+ * This allows better continue operations for operations like shadowmapping.
render_pass_begin.renderArea.extent.width = viewport_size.width;
render_pass_begin.renderArea.extent.height = viewport_size.height;
render_pass_begin.renderArea.offset.x = viewport_offset.x;
render_pass_begin.renderArea.offset.y = viewport_offset.y;
+ */
+ render_pass_begin.renderArea.extent.width = framebuffer->size.width;
+ render_pass_begin.renderArea.extent.height = framebuffer->size.height;
+ render_pass_begin.renderArea.offset.x = 0;
+ render_pass_begin.renderArea.offset.y = 0;
Vector<VkClearValue> clear_values;
clear_values.resize(framebuffer->texture_ids.size());
@@ -5782,7 +6086,7 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V_MSG(draw_list != nullptr, INVALID_ID, "Only one draw list can be active at the same time.");
- ERR_FAIL_COND_V_MSG(compute_list != nullptr, INVALID_ID, "Only one draw/compute list can be active at the same time.");
+ ERR_FAIL_COND_V_MSG(compute_list != nullptr && !compute_list->state.allow_draw_overlap, INVALID_ID, "Only one draw/compute list can be active at the same time.");
Framebuffer *framebuffer = framebuffer_owner.getornull(p_framebuffer);
ERR_FAIL_COND_V(!framebuffer, INVALID_ID);
@@ -5803,12 +6107,19 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
viewport_offset = regioni.position;
viewport_size = regioni.size;
-
- if (p_initial_color_action == INITIAL_ACTION_CLEAR) {
+ if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION_CONTINUE) {
+ needs_clear_color = true;
+ p_initial_color_action = INITIAL_ACTION_CONTINUE;
+ }
+ if (p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION_CONTINUE) {
+ needs_clear_depth = true;
+ p_initial_depth_action = INITIAL_ACTION_CONTINUE;
+ }
+ if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION) {
needs_clear_color = true;
p_initial_color_action = INITIAL_ACTION_KEEP;
}
- if (p_initial_depth_action == INITIAL_ACTION_CLEAR) {
+ if (p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION) {
needs_clear_depth = true;
p_initial_depth_action = INITIAL_ACTION_KEEP;
}
@@ -5865,7 +6176,7 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
draw_list->viewport = Rect2i(viewport_offset, viewport_size);
- return ID_TYPE_DRAW_LIST;
+ return int64_t(ID_TYPE_DRAW_LIST) << ID_BASE_SHIFT;
}
Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) {
@@ -5894,11 +6205,11 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
viewport_offset = regioni.position;
viewport_size = regioni.size;
- if (p_initial_color_action == INITIAL_ACTION_CLEAR) {
+ if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION) {
needs_clear_color = true;
p_initial_color_action = INITIAL_ACTION_KEEP;
}
- if (p_initial_depth_action == INITIAL_ACTION_CLEAR) {
+ if (p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION) {
needs_clear_depth = true;
p_initial_depth_action = INITIAL_ACTION_KEEP;
}
@@ -5962,7 +6273,7 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
for (uint32_t i = 0; i < p_splits; i++) {
//take a command buffer and initialize it
- VkCommandBuffer command_buffer = split_draw_list_allocators[p_splits].command_buffers[frame];
+ VkCommandBuffer command_buffer = split_draw_list_allocators[i].command_buffers[frame];
VkCommandBufferInheritanceInfo inheritance_info;
inheritance_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
@@ -6020,7 +6331,7 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
scissor.extent.height = viewport_size.height;
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
- r_split_ids[i] = (DrawListID(1) << DrawListID(ID_TYPE_SPLIT_DRAW_LIST)) + i;
+ r_split_ids[i] = (int64_t(ID_TYPE_SPLIT_DRAW_LIST) << ID_BASE_SHIFT) + i;
draw_list[i].viewport = Rect2i(viewport_offset, viewport_size);
}
@@ -6035,7 +6346,7 @@ RenderingDeviceVulkan::DrawList *RenderingDeviceVulkan::_get_draw_list_ptr(DrawL
if (!draw_list) {
return nullptr;
- } else if (p_id == ID_TYPE_DRAW_LIST) {
+ } else if (p_id == (int64_t(ID_TYPE_DRAW_LIST) << ID_BASE_SHIFT)) {
if (draw_list_split) {
return nullptr;
}
@@ -6129,7 +6440,7 @@ void RenderingDeviceVulkan::draw_list_bind_render_pipeline(DrawListID p_list, RI
void RenderingDeviceVulkan::draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index) {
#ifdef DEBUG_ENABLED
- ERR_FAIL_COND_MSG(p_index >= limits.maxBoundDescriptorSets || p_index > MAX_UNIFORM_SETS,
+ ERR_FAIL_COND_MSG(p_index >= limits.maxBoundDescriptorSets || p_index >= MAX_UNIFORM_SETS,
"Attempting to bind a descriptor set (" + itos(p_index) + ") greater than what the hardware supports (" + itos(limits.maxBoundDescriptorSets) + ").");
#endif
DrawList *dl = _get_draw_list_ptr(p_list);
@@ -6151,16 +6462,29 @@ void RenderingDeviceVulkan::draw_list_bind_uniform_set(DrawListID p_list, RID p_
dl->state.sets[p_index].uniform_set_format = uniform_set->format;
dl->state.sets[p_index].uniform_set = p_uniform_set;
+ uint32_t mst_count = uniform_set->mutable_storage_textures.size();
+ if (mst_count) {
+ Texture **mst_textures = const_cast<UniformSet *>(uniform_set)->mutable_storage_textures.ptrw();
+ for (uint32_t i = 0; i < mst_count; i++) {
+ if (mst_textures[i]->used_in_frame != frames_drawn) {
+ mst_textures[i]->used_in_frame = frames_drawn;
+ mst_textures[i]->used_in_transfer = false;
+ mst_textures[i]->used_in_compute = false;
+ }
+ mst_textures[i]->used_in_raster = true;
+ }
+ }
+
#ifdef DEBUG_ENABLED
{ //validate that textures bound are not attached as framebuffer bindings
uint32_t attachable_count = uniform_set->attachable_textures.size();
- const RID *attachable_ptr = uniform_set->attachable_textures.ptr();
+ const UniformSet::AttachableTexture *attachable_ptr = uniform_set->attachable_textures.ptr();
uint32_t bound_count = draw_list_bound_textures.size();
const RID *bound_ptr = draw_list_bound_textures.ptr();
for (uint32_t i = 0; i < attachable_count; i++) {
for (uint32_t j = 0; j < bound_count; j++) {
- ERR_FAIL_COND_MSG(attachable_ptr[i] == bound_ptr[j],
- "Attempted to use the same texture in framebuffer attachment and a uniform set, this is not allowed.");
+ ERR_FAIL_COND_MSG(attachable_ptr[i].texture == bound_ptr[j],
+ "Attempted to use the same texture in framebuffer attachment and a uniform (set: " + itos(p_index) + ", binding: " + itos(attachable_ptr[i].bind) + "), this is not allowed.");
}
}
}
@@ -6364,7 +6688,7 @@ void RenderingDeviceVulkan::draw_list_enable_scissor(DrawListID p_list, const Re
Rect2i rect = p_rect;
rect.position += dl->viewport.position;
- rect = dl->viewport.clip(rect);
+ rect = dl->viewport.intersection(rect);
if (rect.get_area() == 0) {
return;
@@ -6393,7 +6717,7 @@ void RenderingDeviceVulkan::draw_list_disable_scissor(DrawListID p_list) {
vkCmdSetScissor(dl->command_buffer, 0, 1, &scissor);
}
-void RenderingDeviceVulkan::draw_list_end() {
+void RenderingDeviceVulkan::draw_list_end(uint32_t p_post_barrier) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_MSG(!draw_list, "Immediate draw list is already inactive.");
@@ -6402,8 +6726,8 @@ void RenderingDeviceVulkan::draw_list_end() {
//send all command buffers
VkCommandBuffer *command_buffers = (VkCommandBuffer *)alloca(sizeof(VkCommandBuffer) * draw_list_count);
for (uint32_t i = 0; i < draw_list_count; i++) {
- vkEndCommandBuffer(draw_list->command_buffer);
- command_buffers[i] = draw_list->command_buffer;
+ vkEndCommandBuffer(draw_list[i].command_buffer);
+ command_buffers[i] = draw_list[i].command_buffer;
}
vkCmdExecuteCommands(frames[frame].draw_command_buffer, draw_list_count, command_buffers);
@@ -6429,16 +6753,51 @@ void RenderingDeviceVulkan::draw_list_end() {
}
}
+ uint32_t barrier_flags = 0;
+ uint32_t access_flags = 0;
+ if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ }
+ if (p_post_barrier & BARRIER_MASK_RASTER) {
+ barrier_flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT /*| VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT*/;
+ access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT /*| VK_ACCESS_INDIRECT_COMMAND_READ_BIT*/;
+ }
+ if (p_post_barrier & BARRIER_MASK_TRANSFER) {
+ barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
+ access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT;
+ }
+
+ if (barrier_flags == 0) {
+ barrier_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+
draw_list_bound_textures.clear();
- for (int i = 0; i < draw_list_storage_textures.size(); i++) {
+ VkImageMemoryBarrier *image_barriers = nullptr;
+
+ uint32_t image_barrier_count = draw_list_storage_textures.size();
+
+ if (image_barrier_count) {
+ image_barriers = (VkImageMemoryBarrier *)alloca(sizeof(VkImageMemoryBarrier) * draw_list_storage_textures.size());
+ }
+
+ uint32_t src_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ uint32_t src_access = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
+ if (image_barrier_count) {
+ src_stage |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ src_access |= VK_ACCESS_SHADER_WRITE_BIT;
+ }
+
+ for (uint32_t i = 0; i < image_barrier_count; i++) {
Texture *texture = texture_owner.getornull(draw_list_storage_textures[i]);
- VkImageMemoryBarrier image_memory_barrier;
+ VkImageMemoryBarrier &image_memory_barrier = image_barriers[i];
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
- image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
- image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ image_memory_barrier.srcAccessMask = src_access;
+ image_memory_barrier.dstAccessMask = access_flags;
image_memory_barrier.oldLayout = texture->layout;
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
@@ -6451,8 +6810,6 @@ void RenderingDeviceVulkan::draw_list_end() {
image_memory_barrier.subresourceRange.baseArrayLayer = texture->base_layer;
image_memory_barrier.subresourceRange.layerCount = texture->layers;
- vkCmdPipelineBarrier(frames[frame].draw_command_buffer, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
-
texture->layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
}
@@ -6465,7 +6822,17 @@ void RenderingDeviceVulkan::draw_list_end() {
#ifdef FORCE_FULL_BARRIER
_full_barrier(true);
#else
- _memory_barrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, true);
+
+ VkMemoryBarrier mem_barrier;
+ mem_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+ mem_barrier.pNext = nullptr;
+ mem_barrier.srcAccessMask = src_access;
+ mem_barrier.dstAccessMask = access_flags;
+
+ if (image_barrier_count > 0 || p_post_barrier != BARRIER_MASK_NO_BARRIER) {
+ vkCmdPipelineBarrier(frames[frame].draw_command_buffer, src_stage, barrier_flags, 0, 1, &mem_barrier, 0, nullptr, image_barrier_count, image_barriers);
+ }
+
#endif
}
@@ -6473,12 +6840,13 @@ void RenderingDeviceVulkan::draw_list_end() {
/**** COMPUTE LISTS ****/
/***********************/
-RenderingDevice::ComputeListID RenderingDeviceVulkan::compute_list_begin() {
- ERR_FAIL_COND_V_MSG(draw_list != nullptr, INVALID_ID, "Only one draw list can be active at the same time.");
+RenderingDevice::ComputeListID RenderingDeviceVulkan::compute_list_begin(bool p_allow_draw_overlap) {
+ ERR_FAIL_COND_V_MSG(!p_allow_draw_overlap && draw_list != nullptr, INVALID_ID, "Only one draw list can be active at the same time.");
ERR_FAIL_COND_V_MSG(compute_list != nullptr, INVALID_ID, "Only one draw/compute list can be active at the same time.");
compute_list = memnew(ComputeList);
compute_list->command_buffer = frames[frame].draw_command_buffer;
+ compute_list->state.allow_draw_overlap = p_allow_draw_overlap;
return ID_TYPE_COMPUTE_LIST;
}
@@ -6535,6 +6903,9 @@ void RenderingDeviceVulkan::compute_list_bind_compute_pipeline(ComputeListID p_l
}
cl->state.pipeline_shader = pipeline->shader;
+ cl->state.local_group_size[0] = pipeline->local_group_size[0];
+ cl->state.local_group_size[1] = pipeline->local_group_size[1];
+ cl->state.local_group_size[2] = pipeline->local_group_size[2];
}
#ifdef DEBUG_ENABLED
@@ -6551,7 +6922,7 @@ void RenderingDeviceVulkan::compute_list_bind_uniform_set(ComputeListID p_list,
ComputeList *cl = compute_list;
#ifdef DEBUG_ENABLED
- ERR_FAIL_COND_MSG(p_index >= limits.maxBoundDescriptorSets || p_index > MAX_UNIFORM_SETS,
+ ERR_FAIL_COND_MSG(p_index >= limits.maxBoundDescriptorSets || p_index >= MAX_UNIFORM_SETS,
"Attempting to bind a descriptor set (" + itos(p_index) + ") greater than what the hardware supports (" + itos(limits.maxBoundDescriptorSets) + ").");
#endif
@@ -6572,11 +6943,24 @@ void RenderingDeviceVulkan::compute_list_bind_uniform_set(ComputeListID p_list,
cl->state.sets[p_index].uniform_set = p_uniform_set;
uint32_t textures_to_sampled_count = uniform_set->mutable_sampled_textures.size();
+ uint32_t textures_to_storage_count = uniform_set->mutable_storage_textures.size();
+
Texture **textures_to_sampled = uniform_set->mutable_sampled_textures.ptrw();
+ VkImageMemoryBarrier *texture_barriers = nullptr;
+
+ if (textures_to_sampled_count + textures_to_storage_count) {
+ texture_barriers = (VkImageMemoryBarrier *)alloca(sizeof(VkImageMemoryBarrier) * (textures_to_sampled_count + textures_to_storage_count));
+ }
+ uint32_t texture_barrier_count = 0;
+
+ uint32_t src_stage_flags = 0;
+
for (uint32_t i = 0; i < textures_to_sampled_count; i++) {
if (textures_to_sampled[i]->layout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
- VkImageMemoryBarrier image_memory_barrier;
+ src_stage_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+
+ VkImageMemoryBarrier &image_memory_barrier = texture_barriers[texture_barrier_count++];
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
@@ -6593,23 +6977,55 @@ void RenderingDeviceVulkan::compute_list_bind_uniform_set(ComputeListID p_list,
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_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
-
textures_to_sampled[i]->layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
cl->state.textures_to_sampled_layout.erase(textures_to_sampled[i]);
}
+
+ if (textures_to_sampled[i]->used_in_frame != frames_drawn) {
+ textures_to_sampled[i]->used_in_frame = frames_drawn;
+ textures_to_sampled[i]->used_in_transfer = false;
+ textures_to_sampled[i]->used_in_raster = false;
+ }
+ textures_to_sampled[i]->used_in_compute = true;
}
- uint32_t textures_to_storage_count = uniform_set->mutable_storage_textures.size();
Texture **textures_to_storage = uniform_set->mutable_storage_textures.ptrw();
for (uint32_t i = 0; i < textures_to_storage_count; i++) {
if (textures_to_storage[i]->layout != VK_IMAGE_LAYOUT_GENERAL) {
- VkImageMemoryBarrier image_memory_barrier;
+ uint32_t src_access_flags = 0;
+
+ if (textures_to_storage[i]->used_in_frame == frames_drawn) {
+ if (textures_to_storage[i]->used_in_compute) {
+ src_stage_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ src_access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ }
+ if (textures_to_storage[i]->used_in_raster) {
+ src_stage_flags |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
+ src_access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ }
+ if (textures_to_storage[i]->used_in_transfer) {
+ src_stage_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
+ src_access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT;
+ }
+
+ textures_to_storage[i]->used_in_compute = false;
+ textures_to_storage[i]->used_in_raster = false;
+ textures_to_storage[i]->used_in_compute = false;
+
+ } else {
+ src_access_flags = 0;
+ textures_to_storage[i]->used_in_compute = false;
+ textures_to_storage[i]->used_in_raster = false;
+ textures_to_storage[i]->used_in_compute = false;
+ textures_to_storage[i]->used_in_frame = frames_drawn;
+ }
+
+ VkImageMemoryBarrier &image_memory_barrier = texture_barriers[texture_barrier_count++];
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
- image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ image_memory_barrier.srcAccessMask = src_access_flags;
image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
image_memory_barrier.oldLayout = textures_to_storage[i]->layout;
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
@@ -6623,14 +7039,20 @@ void RenderingDeviceVulkan::compute_list_bind_uniform_set(ComputeListID p_list,
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);
-
textures_to_storage[i]->layout = VK_IMAGE_LAYOUT_GENERAL;
cl->state.textures_to_sampled_layout.insert(textures_to_storage[i]); //needs to go back to sampled layout afterwards
}
}
+ if (texture_barrier_count) {
+ if (src_stage_flags == 0) {
+ src_stage_flags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ }
+
+ vkCmdPipelineBarrier(cl->command_buffer, src_stage_flags, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, texture_barrier_count, texture_barriers);
+ }
+
#if 0
{ //validate that textures bound are not attached as framebuffer bindings
uint32_t attachable_count = uniform_set->attachable_textures.size();
@@ -6724,6 +7146,27 @@ void RenderingDeviceVulkan::compute_list_dispatch(ComputeListID p_list, uint32_t
vkCmdDispatch(cl->command_buffer, p_x_groups, p_y_groups, p_z_groups);
}
+void RenderingDeviceVulkan::compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads) {
+ ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST);
+ ERR_FAIL_COND(!compute_list);
+
+ ComputeList *cl = compute_list;
+
+#ifdef DEBUG_ENABLED
+
+ ERR_FAIL_COND_MSG(!cl->validation.pipeline_active, "No compute pipeline was set before attempting to draw.");
+
+ if (cl->validation.pipeline_push_constant_size > 0) {
+ //using push constants, check that they were supplied
+ ERR_FAIL_COND_MSG(!cl->validation.pipeline_push_constant_supplied,
+ "The shader in this pipeline requires a push constant to be set before drawing, but it's not present.");
+ }
+
+#endif
+
+ compute_list_dispatch(p_list, (p_x_threads - 1) / cl->state.local_group_size[0] + 1, (p_y_threads - 1) / cl->state.local_group_size[1] + 1, (p_z_threads - 1) / cl->state.local_group_size[2] + 1);
+}
+
void RenderingDeviceVulkan::compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset) {
ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST);
ERR_FAIL_COND(!compute_list);
@@ -6788,14 +7231,44 @@ void RenderingDeviceVulkan::compute_list_add_barrier(ComputeListID p_list) {
#endif
}
-void RenderingDeviceVulkan::compute_list_end() {
+void RenderingDeviceVulkan::compute_list_end(uint32_t p_post_barrier) {
ERR_FAIL_COND(!compute_list);
+
+ uint32_t barrier_flags = 0;
+ uint32_t access_flags = 0;
+ if (p_post_barrier & BARRIER_MASK_COMPUTE) {
+ barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ }
+ if (p_post_barrier & BARRIER_MASK_RASTER) {
+ barrier_flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
+ access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
+ }
+ if (p_post_barrier & BARRIER_MASK_TRANSFER) {
+ barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
+ access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT;
+ }
+
+ if (barrier_flags == 0) {
+ barrier_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+
+ VkImageMemoryBarrier *image_barriers = nullptr;
+
+ uint32_t image_barrier_count = compute_list->state.textures_to_sampled_layout.size();
+
+ if (image_barrier_count) {
+ image_barriers = (VkImageMemoryBarrier *)alloca(sizeof(VkImageMemoryBarrier) * image_barrier_count);
+ }
+
+ uint32_t barrier_idx = 0;
+
for (Set<Texture *>::Element *E = compute_list->state.textures_to_sampled_layout.front(); E; E = E->next()) {
- VkImageMemoryBarrier image_memory_barrier;
+ VkImageMemoryBarrier &image_memory_barrier = image_barriers[barrier_idx++];
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
- image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT;
+ image_memory_barrier.dstAccessMask = access_flags;
image_memory_barrier.oldLayout = E->get()->layout;
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
@@ -6808,19 +7281,75 @@ void RenderingDeviceVulkan::compute_list_end() {
image_memory_barrier.subresourceRange.baseArrayLayer = E->get()->base_layer;
image_memory_barrier.subresourceRange.layerCount = E->get()->layers;
- // TODO: Look at the usages in the compute list and determine tighter dst stage and access masks based on some "final" usage equivalent
- vkCmdPipelineBarrier(compute_list->command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
-
E->get()->layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+
+ if (E->get()->used_in_frame != frames_drawn) {
+ E->get()->used_in_transfer = false;
+ E->get()->used_in_raster = false;
+ E->get()->used_in_compute = false;
+ E->get()->used_in_frame = frames_drawn;
+ }
}
- memdelete(compute_list);
- compute_list = nullptr;
#ifdef FORCE_FULL_BARRIER
_full_barrier(true);
#else
- _memory_barrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_BIT, true);
+ VkMemoryBarrier mem_barrier;
+ mem_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+ mem_barrier.pNext = nullptr;
+ mem_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
+ mem_barrier.dstAccessMask = access_flags;
+
+ if (image_barrier_count > 0 || p_post_barrier != BARRIER_MASK_NO_BARRIER) {
+ vkCmdPipelineBarrier(compute_list->command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, barrier_flags, 0, 1, &mem_barrier, 0, nullptr, image_barrier_count, image_barriers);
+ }
+
#endif
+
+ memdelete(compute_list);
+ compute_list = nullptr;
+}
+
+void RenderingDeviceVulkan::barrier(uint32_t p_from, uint32_t p_to) {
+ uint32_t src_barrier_flags = 0;
+ uint32_t src_access_flags = 0;
+ if (p_from & BARRIER_MASK_COMPUTE) {
+ src_barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ src_access_flags |= VK_ACCESS_SHADER_WRITE_BIT;
+ }
+ if (p_from & BARRIER_MASK_RASTER) {
+ src_barrier_flags |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ src_access_flags |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ }
+ if (p_from & BARRIER_MASK_TRANSFER) {
+ src_barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
+ src_access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
+ }
+
+ if (p_from == 0) {
+ src_barrier_flags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ }
+
+ uint32_t dst_barrier_flags = 0;
+ uint32_t dst_access_flags = 0;
+ if (p_to & BARRIER_MASK_COMPUTE) {
+ dst_barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ dst_access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+ }
+ if (p_to & BARRIER_MASK_RASTER) {
+ dst_barrier_flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
+ dst_access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
+ }
+ if (p_to & BARRIER_MASK_TRANSFER) {
+ dst_barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
+ dst_access_flags |= VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT;
+ }
+
+ if (p_to == 0) {
+ dst_barrier_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+
+ _memory_barrier(src_barrier_flags, dst_barrier_flags, src_access_flags, dst_access_flags, true);
}
void RenderingDeviceVulkan::full_barrier() {
@@ -6957,6 +7486,82 @@ void RenderingDeviceVulkan::free(RID p_id) {
_free_internal(p_id);
}
+// The full list of resources that can be named is in the VkObjectType enum
+// We just expose the resources that are owned and can be accessed easily.
+void RenderingDeviceVulkan::set_resource_name(RID p_id, const String p_name) {
+ if (texture_owner.owns(p_id)) {
+ Texture *texture = texture_owner.getornull(p_id);
+ if (texture->owner.is_null()) {
+ // Don't set the source texture's name when calling on a texture view
+ context->set_object_name(VK_OBJECT_TYPE_IMAGE, uint64_t(texture->image), p_name);
+ }
+ context->set_object_name(VK_OBJECT_TYPE_IMAGE_VIEW, uint64_t(texture->view), p_name + " View");
+ } else if (framebuffer_owner.owns(p_id)) {
+ //Framebuffer *framebuffer = framebuffer_owner.getornull(p_id);
+ // Not implemented for now as the relationship between Framebuffer and RenderPass is very complex
+ } else if (sampler_owner.owns(p_id)) {
+ VkSampler *sampler = sampler_owner.getornull(p_id);
+ context->set_object_name(VK_OBJECT_TYPE_SAMPLER, uint64_t(*sampler), p_name);
+ } else if (vertex_buffer_owner.owns(p_id)) {
+ Buffer *vertex_buffer = vertex_buffer_owner.getornull(p_id);
+ context->set_object_name(VK_OBJECT_TYPE_BUFFER, uint64_t(vertex_buffer->buffer), p_name);
+ } else if (index_buffer_owner.owns(p_id)) {
+ IndexBuffer *index_buffer = index_buffer_owner.getornull(p_id);
+ context->set_object_name(VK_OBJECT_TYPE_BUFFER, uint64_t(index_buffer->buffer), p_name);
+ } else if (shader_owner.owns(p_id)) {
+ Shader *shader = shader_owner.getornull(p_id);
+ context->set_object_name(VK_OBJECT_TYPE_PIPELINE_LAYOUT, uint64_t(shader->pipeline_layout), p_name + " Pipeline Layout");
+ for (int i = 0; i < shader->sets.size(); i++) {
+ context->set_object_name(VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, uint64_t(shader->sets[i].descriptor_set_layout), p_name);
+ }
+ } else if (uniform_buffer_owner.owns(p_id)) {
+ Buffer *uniform_buffer = uniform_buffer_owner.getornull(p_id);
+ context->set_object_name(VK_OBJECT_TYPE_BUFFER, uint64_t(uniform_buffer->buffer), p_name);
+ } else if (texture_buffer_owner.owns(p_id)) {
+ TextureBuffer *texture_buffer = texture_buffer_owner.getornull(p_id);
+ context->set_object_name(VK_OBJECT_TYPE_BUFFER, uint64_t(texture_buffer->buffer.buffer), p_name);
+ context->set_object_name(VK_OBJECT_TYPE_BUFFER_VIEW, uint64_t(texture_buffer->view), p_name + " View");
+ } else if (storage_buffer_owner.owns(p_id)) {
+ Buffer *storage_buffer = storage_buffer_owner.getornull(p_id);
+ context->set_object_name(VK_OBJECT_TYPE_BUFFER, uint64_t(storage_buffer->buffer), p_name);
+ } else if (uniform_set_owner.owns(p_id)) {
+ UniformSet *uniform_set = uniform_set_owner.getornull(p_id);
+ context->set_object_name(VK_OBJECT_TYPE_DESCRIPTOR_SET, uint64_t(uniform_set->descriptor_set), p_name);
+ } else if (render_pipeline_owner.owns(p_id)) {
+ RenderPipeline *pipeline = render_pipeline_owner.getornull(p_id);
+ context->set_object_name(VK_OBJECT_TYPE_PIPELINE, uint64_t(pipeline->pipeline), p_name);
+ context->set_object_name(VK_OBJECT_TYPE_PIPELINE_LAYOUT, uint64_t(pipeline->pipeline_layout), p_name + " Layout");
+ } else if (compute_pipeline_owner.owns(p_id)) {
+ ComputePipeline *pipeline = compute_pipeline_owner.getornull(p_id);
+ context->set_object_name(VK_OBJECT_TYPE_PIPELINE, uint64_t(pipeline->pipeline), p_name);
+ context->set_object_name(VK_OBJECT_TYPE_PIPELINE_LAYOUT, uint64_t(pipeline->pipeline_layout), p_name + " Layout");
+ } else {
+ ERR_PRINT("Attempted to name invalid ID: " + itos(p_id.get_id()));
+ }
+}
+
+void RenderingDeviceVulkan::draw_command_begin_label(String p_label_name, const Color p_color) {
+ context->command_begin_label(frames[frame].draw_command_buffer, p_label_name, p_color);
+}
+
+void RenderingDeviceVulkan::draw_command_insert_label(String p_label_name, const Color p_color) {
+ context->command_insert_label(frames[frame].draw_command_buffer, p_label_name, p_color);
+}
+
+void RenderingDeviceVulkan::draw_command_end_label() {
+ context->command_end_label(frames[frame].draw_command_buffer);
+}
+
+String RenderingDeviceVulkan::get_device_vendor_name() const {
+ return context->get_device_vendor_name();
+}
+String RenderingDeviceVulkan::get_device_name() const {
+ return context->get_device_name();
+}
+String RenderingDeviceVulkan::get_device_pipeline_cache_uuid() const {
+ return context->get_device_pipeline_cache_uuid();
+}
+
void RenderingDeviceVulkan::_finalize_command_bufers() {
if (draw_list) {
ERR_PRINT("Found open draw list at the end of the frame, this should never happen (further drawing will likely not work).");
@@ -7009,6 +7614,7 @@ void RenderingDeviceVulkan::_begin_frame() {
if (frames[frame].timestamp_count) {
vkGetQueryPoolResults(device, frames[frame].timestamp_pool, 0, frames[frame].timestamp_count, sizeof(uint64_t) * max_timestamp_query_elements, frames[frame].timestamp_result_values, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT);
+ vkCmdResetQueryPool(frames[frame].setup_command_buffer, frames[frame].timestamp_pool, 0, frames[frame].timestamp_count);
SWAP(frames[frame].timestamp_names, frames[frame].timestamp_result_names);
SWAP(frames[frame].timestamp_cpu_values, frames[frame].timestamp_cpu_result_values);
}
@@ -7375,9 +7981,10 @@ void RenderingDeviceVulkan::_free_rids(T &p_owner, const char *p_type) {
}
}
-void RenderingDeviceVulkan::capture_timestamp(const String &p_name, bool p_sync_to_draw) {
+void RenderingDeviceVulkan::capture_timestamp(const String &p_name) {
ERR_FAIL_COND(frames[frame].timestamp_count >= max_timestamp_query_elements);
+ //this should be optional for profiling, else it will slow things down
{
VkMemoryBarrier memoryBarrier;
@@ -7414,9 +8021,10 @@ void RenderingDeviceVulkan::capture_timestamp(const String &p_name, bool p_sync_
VK_ACCESS_HOST_READ_BIT |
VK_ACCESS_HOST_WRITE_BIT;
- vkCmdPipelineBarrier(p_sync_to_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
+ vkCmdPipelineBarrier(frames[frame].draw_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
}
- vkCmdWriteTimestamp(p_sync_to_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, frames[frame].timestamp_pool, frames[frame].timestamp_count);
+
+ vkCmdWriteTimestamp(frames[frame].draw_command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, frames[frame].timestamp_pool, frames[frame].timestamp_count);
frames[frame].timestamp_names[frames[frame].timestamp_count] = p_name;
frames[frame].timestamp_cpu_values[frames[frame].timestamp_count] = OS::get_singleton()->get_ticks_usec();
frames[frame].timestamp_count++;
diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h
index 35fc6debdd..a2527d5c33 100644
--- a/drivers/vulkan/rendering_device_vulkan.h
+++ b/drivers/vulkan/rendering_device_vulkan.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,6 +32,7 @@
#define RENDERING_DEVICE_VULKAN_H
#include "core/os/thread_safe.h"
+#include "core/templates/local_vector.h"
#include "core/templates/oa_hash_map.h"
#include "core/templates/rid_owner.h"
#include "servers/rendering/rendering_device.h"
@@ -45,11 +46,6 @@
#include <vulkan/vulkan.h>
-//todo:
-//compute
-//push constants
-//views of texture slices
-
class VulkanContext;
class RenderingDeviceVulkan : public RenderingDevice {
@@ -145,6 +141,11 @@ class RenderingDeviceVulkan : public RenderingDevice {
VkImageLayout layout;
+ uint64_t used_in_frame = 0;
+ bool used_in_transfer = false;
+ bool used_in_raster = false;
+ bool used_in_compute = false;
+
uint32_t read_aspect_mask = 0;
uint32_t barrier_aspect_mask = 0;
bool bound = false; //bound to framebffer
@@ -232,13 +233,8 @@ class RenderingDeviceVulkan : public RenderingDevice {
// used for the render pipelines.
struct FramebufferFormatKey {
- Size2i empty_size;
Vector<AttachmentFormat> attachments;
bool operator<(const FramebufferFormatKey &p_key) const {
- if (empty_size != p_key.empty_size) {
- return empty_size < p_key.empty_size;
- }
-
int as = attachments.size();
int bs = p_key.attachments.size();
if (as != bs) {
@@ -537,6 +533,8 @@ class RenderingDeviceVulkan : public RenderingDevice {
PushConstant push_constant;
+ uint32_t compute_local_size[3] = { 0, 0, 0 };
+
bool is_compute = false;
int max_output = 0;
Vector<Set> sets;
@@ -638,7 +636,12 @@ class RenderingDeviceVulkan : public RenderingDevice {
DescriptorPoolKey pool_key;
VkDescriptorSet descriptor_set = VK_NULL_HANDLE;
//VkPipelineLayout pipeline_layout; //not owned, inherited from shader
- Vector<RID> attachable_textures; //used for validation
+ struct AttachableTexture {
+ uint32_t bind;
+ RID texture;
+ };
+
+ LocalVector<AttachableTexture> attachable_textures; //used for validation
Vector<Texture *> mutable_sampled_textures; //used for layout change
Vector<Texture *> mutable_storage_textures; //used for layout change
};
@@ -690,6 +693,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
VkPipeline pipeline = VK_NULL_HANDLE;
uint32_t push_constant_size = 0;
uint32_t push_constant_stages = 0;
+ uint32_t local_group_size[3] = { 0, 0, 0 };
};
RID_Owner<ComputePipeline, true> compute_pipeline_owner;
@@ -789,7 +793,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
Error _draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, VkFramebuffer *r_framebuffer, VkRenderPass *r_render_pass);
Error _draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents, const Vector<RID> &p_storage_textures);
_FORCE_INLINE_ DrawList *_get_draw_list_ptr(DrawListID p_id);
- Buffer *_get_buffer_from_owner(RID p_buffer, VkPipelineStageFlags &dst_stage_mask, VkAccessFlags &dst_access);
+ Buffer *_get_buffer_from_owner(RID p_buffer, VkPipelineStageFlags &dst_stage_mask, VkAccessFlags &dst_access, uint32_t p_post_barrier);
/**********************/
/**** COMPUTE LIST ****/
@@ -812,8 +816,10 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint32_t set_count = 0;
RID pipeline;
RID pipeline_shader;
+ uint32_t local_group_size[3] = { 0, 0, 0 };
VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
uint32_t pipeline_push_constant_stages = 0;
+ bool allow_draw_overlap;
} state;
#ifdef DEBUG_ENABLED
@@ -917,27 +923,27 @@ public:
virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture);
virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type = TEXTURE_SLICE_2D);
- virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, bool p_sync_with_draw = false);
+ virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL);
virtual Vector<uint8_t> texture_get_data(RID p_texture, uint32_t p_layer);
virtual bool texture_is_format_supported_for_usage(DataFormat p_format, uint32_t p_usage) const;
virtual bool texture_is_shared(RID p_texture);
virtual bool texture_is_valid(RID p_texture);
- virtual Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, bool p_sync_with_draw = false);
- virtual Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, bool p_sync_with_draw = false);
- virtual Error texture_resolve_multisample(RID p_from_texture, RID p_to_texture, bool p_sync_with_draw = false);
+ virtual Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, uint32_t p_post_barrier = BARRIER_MASK_ALL);
+ virtual Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, uint32_t p_post_barrier = BARRIER_MASK_ALL);
+ virtual Error texture_resolve_multisample(RID p_from_texture, RID p_to_texture, uint32_t p_post_barrier = BARRIER_MASK_ALL);
/*********************/
/**** FRAMEBUFFER ****/
/*********************/
virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format);
- virtual FramebufferFormatID framebuffer_format_create_empty(const Size2i &p_size);
+ virtual FramebufferFormatID framebuffer_format_create_empty(TextureSamples p_samples = TEXTURE_SAMPLES_1);
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format);
virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID);
- virtual RID framebuffer_create_empty(const Size2i &p_size, FramebufferFormatID p_format_check = INVALID_ID);
+ virtual RID framebuffer_create_empty(const Size2i &p_size, TextureSamples p_samples = TEXTURE_SAMPLES_1, FramebufferFormatID p_format_check = INVALID_ID);
virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer);
@@ -951,7 +957,7 @@ public:
/**** VERTEX ARRAY ****/
/**********************/
- virtual RID vertex_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>());
+ virtual RID vertex_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>(), bool p_use_as_storage = false);
// Internally reference counted, this ID is warranted to be unique for the same description, but needs to be freed as many times as it was allocated
virtual VertexFormatID vertex_format_create(const Vector<VertexAttribute> &p_vertex_formats);
@@ -979,7 +985,8 @@ public:
virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set);
virtual bool uniform_set_is_valid(RID p_uniform_set);
- virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, bool p_sync_with_draw = false); //works for any buffer
+ virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL); //works for any buffer
+ virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, uint32_t p_post_barrier = BARRIER_MASK_ALL);
virtual Vector<uint8_t> buffer_get_data(RID p_buffer);
/*************************/
@@ -1025,22 +1032,24 @@ public:
virtual void draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect);
virtual void draw_list_disable_scissor(DrawListID p_list);
- virtual void draw_list_end();
+ virtual void draw_list_end(uint32_t p_post_barrier = BARRIER_MASK_ALL);
/***********************/
/**** COMPUTE LISTS ****/
/***********************/
- virtual ComputeListID compute_list_begin();
+ virtual ComputeListID compute_list_begin(bool p_allow_draw_overlap = false);
virtual void compute_list_bind_compute_pipeline(ComputeListID p_list, RID p_compute_pipeline);
virtual void compute_list_bind_uniform_set(ComputeListID p_list, RID p_uniform_set, uint32_t p_index);
virtual void compute_list_set_push_constant(ComputeListID p_list, const void *p_data, uint32_t p_data_size);
virtual void compute_list_add_barrier(ComputeListID p_list);
virtual void compute_list_dispatch(ComputeListID p_list, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups);
+ virtual void compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads);
virtual void compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset);
- virtual void compute_list_end();
+ virtual void compute_list_end(uint32_t p_post_barrier = BARRIER_MASK_ALL);
+ virtual void barrier(uint32_t p_from = BARRIER_MASK_ALL, uint32_t p_to = BARRIER_MASK_ALL);
virtual void full_barrier();
/**************/
@@ -1053,7 +1062,7 @@ public:
/**** Timing ****/
/****************/
- virtual void capture_timestamp(const String &p_name, bool p_sync_to_draw);
+ virtual void capture_timestamp(const String &p_name);
virtual uint32_t get_captured_timestamps_count() const;
virtual uint64_t get_captured_timestamps_frame() const;
virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const;
@@ -1081,6 +1090,16 @@ public:
virtual uint64_t get_memory_usage() const;
+ virtual void set_resource_name(RID p_id, const String p_name);
+
+ virtual void draw_command_begin_label(String p_label_name, const Color p_color = Color(1, 1, 1, 1));
+ virtual void draw_command_insert_label(String p_label_name, const Color p_color = Color(1, 1, 1, 1));
+ virtual void draw_command_end_label();
+
+ virtual String get_device_vendor_name() const;
+ virtual String get_device_name() const;
+ virtual String get_device_pipeline_cache_uuid() const;
+
RenderingDeviceVulkan();
~RenderingDeviceVulkan();
};
diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp
index ecf9dac61b..c564cee757 100644
--- a/drivers/vulkan/vulkan_context.cpp
+++ b/drivers/vulkan/vulkan_context.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -55,10 +55,29 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::_debug_messenger_callback(
return VK_FALSE;
}
// This needs to be ignored because Validator is wrong here.
+ if (strstr(pCallbackData->pMessage, "Invalid SPIR-V binary version 1.3") != nullptr) {
+ return VK_FALSE;
+ }
+ // This needs to be ignored because Validator is wrong here.
+ if (strstr(pCallbackData->pMessage, "Shader requires flag") != nullptr) {
+ return VK_FALSE;
+ }
+
+ // This needs to be ignored because Validator is wrong here.
if (strstr(pCallbackData->pMessage, "SPIR-V module not valid: Pointer operand") != nullptr &&
strstr(pCallbackData->pMessage, "must be a memory object") != nullptr) {
return VK_FALSE;
}
+ /*
+ // This is a valid warning because its illegal in Vulkan, but in practice it should work according to VK_KHR_maintenance2
+ if (strstr(pCallbackData->pMessage, "VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 with tiling VK_IMAGE_TILING_OPTIMAL does not support usage that includes VK_IMAGE_USAGE_STORAGE_BIT") != nullptr) {
+ return VK_FALSE;
+ }
+
+ if (strstr(pCallbackData->pMessage, "VK_FORMAT_R4G4B4A4_UNORM_PACK16 with tiling VK_IMAGE_TILING_OPTIMAL does not support usage that includes VK_IMAGE_USAGE_STORAGE_BIT") != nullptr) {
+ return VK_FALSE;
+ }
+*/
// Workaround for Vulkan-Loader usability bug: https://github.com/KhronosGroup/Vulkan-Loader/issues/262.
if (strstr(pCallbackData->pMessage, "wrong ELF class: ELFCLASS32") != nullptr) {
return VK_FALSE;
@@ -216,23 +235,23 @@ Error VulkanContext::_create_validation_layers() {
}
Error VulkanContext::_initialize_extensions() {
- VkResult err;
uint32_t instance_extension_count = 0;
enabled_extension_count = 0;
enabled_layer_count = 0;
+ enabled_debug_utils = false;
/* Look for instance extensions */
VkBool32 surfaceExtFound = 0;
VkBool32 platformSurfaceExtFound = 0;
memset(extension_names, 0, sizeof(extension_names));
- err = vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, nullptr);
- ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
+ VkResult err = vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, nullptr);
+ ERR_FAIL_COND_V(err != VK_SUCCESS && err != VK_INCOMPLETE, ERR_CANT_CREATE);
if (instance_extension_count > 0) {
VkExtensionProperties *instance_extensions = (VkExtensionProperties *)malloc(sizeof(VkExtensionProperties) * instance_extension_count);
err = vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, instance_extensions);
- if (err) {
+ if (err != VK_SUCCESS && err != VK_INCOMPLETE) {
free(instance_extensions);
ERR_FAIL_V(ERR_CANT_CREATE);
}
@@ -252,9 +271,8 @@ Error VulkanContext::_initialize_extensions() {
}
}
if (!strcmp(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, instance_extensions[i].extensionName)) {
- if (use_validation_layers) {
- extension_names[enabled_extension_count++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
- }
+ extension_names[enabled_extension_count++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
+ enabled_debug_utils = true;
}
if (enabled_extension_count >= MAX_EXTENSIONS) {
free(instance_extensions);
@@ -313,7 +331,7 @@ Error VulkanContext::_create_physical_device() {
* function to register the final callback.
*/
VkDebugUtilsMessengerCreateInfoEXT dbg_messenger_create_info;
- if (use_validation_layers) {
+ if (enabled_debug_utils) {
// VK_EXT_debug_utils style
dbg_messenger_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
dbg_messenger_create_info.pNext = nullptr;
@@ -362,7 +380,8 @@ Error VulkanContext::_create_physical_device() {
ERR_FAIL_V(ERR_CANT_CREATE);
}
/* for now, just grab the first physical device */
- gpu = physical_devices[0];
+ uint32_t device_index = 0;
+ gpu = physical_devices[device_index];
free(physical_devices);
/* Look for device extensions */
@@ -371,6 +390,40 @@ Error VulkanContext::_create_physical_device() {
enabled_extension_count = 0;
memset(extension_names, 0, sizeof(extension_names));
+ /* Get identifier properties */
+ vkGetPhysicalDeviceProperties(gpu, &gpu_props);
+
+ static const struct {
+ uint32_t id;
+ const char *name;
+ } vendor_names[] = {
+ { 0x1002, "AMD" },
+ { 0x1010, "ImgTec" },
+ { 0x10DE, "NVIDIA" },
+ { 0x13B5, "ARM" },
+ { 0x5143, "Qualcomm" },
+ { 0x8086, "INTEL" },
+ { 0, nullptr },
+ };
+ device_name = gpu_props.deviceName;
+ pipeline_cache_id = String::hex_encode_buffer(gpu_props.pipelineCacheUUID, VK_UUID_SIZE);
+ pipeline_cache_id += "-driver-" + itos(gpu_props.driverVersion);
+ {
+ device_vendor = "Unknown";
+ uint32_t vendor_idx = 0;
+ while (vendor_names[vendor_idx].name != nullptr) {
+ if (gpu_props.vendorID == vendor_names[vendor_idx].id) {
+ device_vendor = vendor_names[vendor_idx].name;
+ break;
+ }
+ vendor_idx++;
+ }
+ }
+#ifdef DEBUG_ENABLED
+ print_line("Using Vulkan Device #" + itos(device_index) + ": " + device_vendor + " - " + device_name);
+#endif
+ device_api_version = gpu_props.apiVersion;
+
err = vkEnumerateDeviceExtensionProperties(gpu, nullptr, &device_extension_count, nullptr);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
@@ -437,7 +490,7 @@ Error VulkanContext::_create_physical_device() {
" extension.\n\nDo you have a compatible Vulkan installable client driver (ICD) installed?\n"
"vkCreateInstance Failure");
- if (use_validation_layers) {
+ if (enabled_debug_utils) {
// Setup VK_EXT_debug_utils function pointers always (we use them for
// debug labels and names).
CreateDebugUtilsMessengerEXT =
@@ -480,7 +533,6 @@ Error VulkanContext::_create_physical_device() {
break;
}
}
- vkGetPhysicalDeviceProperties(gpu, &gpu_props);
/* Call with NULL data to get count */
vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queue_family_count, nullptr);
@@ -494,6 +546,8 @@ Error VulkanContext::_create_physical_device() {
// features based on this query
vkGetPhysicalDeviceFeatures(gpu, &physical_device_features);
+ physical_device_features.robustBufferAccess = false; //turn off robust buffer access, which can hamper performance on some hardware
+
#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
{ \
fp##entrypoint = (PFN_vk##entrypoint)vkGetInstanceProcAddr(inst, "vk" #entrypoint); \
@@ -545,6 +599,7 @@ Error VulkanContext::_create_device() {
}
err = vkCreateDevice(gpu, &sdevice, nullptr, &device);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
+
return OK;
}
@@ -1566,6 +1621,70 @@ void VulkanContext::local_device_free(RID p_local_device) {
local_device_owner.free(p_local_device);
}
+void VulkanContext::command_begin_label(VkCommandBuffer p_command_buffer, String p_label_name, const Color p_color) {
+ if (!enabled_debug_utils) {
+ return;
+ }
+
+ CharString cs = p_label_name.utf8().get_data();
+ VkDebugUtilsLabelEXT label;
+ label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
+ label.pNext = nullptr;
+ label.pLabelName = cs.get_data();
+ label.color[0] = p_color[0];
+ label.color[1] = p_color[1];
+ label.color[2] = p_color[2];
+ label.color[3] = p_color[3];
+ CmdBeginDebugUtilsLabelEXT(p_command_buffer, &label);
+}
+
+void VulkanContext::command_insert_label(VkCommandBuffer p_command_buffer, String p_label_name, const Color p_color) {
+ if (!enabled_debug_utils) {
+ return;
+ }
+ CharString cs = p_label_name.utf8().get_data();
+ VkDebugUtilsLabelEXT label;
+ label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
+ label.pNext = nullptr;
+ label.pLabelName = cs.get_data();
+ label.color[0] = p_color[0];
+ label.color[1] = p_color[1];
+ label.color[2] = p_color[2];
+ label.color[3] = p_color[3];
+ CmdInsertDebugUtilsLabelEXT(p_command_buffer, &label);
+}
+
+void VulkanContext::command_end_label(VkCommandBuffer p_command_buffer) {
+ if (!enabled_debug_utils) {
+ return;
+ }
+ CmdEndDebugUtilsLabelEXT(p_command_buffer);
+}
+
+void VulkanContext::set_object_name(VkObjectType p_object_type, uint64_t p_object_handle, String p_object_name) {
+ if (!enabled_debug_utils) {
+ return;
+ }
+ CharString obj_data = p_object_name.utf8();
+ VkDebugUtilsObjectNameInfoEXT name_info;
+ name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+ name_info.pNext = nullptr;
+ name_info.objectType = p_object_type;
+ name_info.objectHandle = p_object_handle;
+ name_info.pObjectName = obj_data.get_data();
+ SetDebugUtilsObjectNameEXT(device, &name_info);
+}
+
+String VulkanContext::get_device_vendor_name() const {
+ return device_vendor;
+}
+String VulkanContext::get_device_name() const {
+ return device_name;
+}
+String VulkanContext::get_device_pipeline_cache_uuid() const {
+ return pipeline_cache_id;
+}
+
VulkanContext::VulkanContext() {
use_validation_layers = Engine::get_singleton()->is_validation_layers_enabled();
diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h
index 1aaad29ccd..dc6b0410bc 100644
--- a/drivers/vulkan/vulkan_context.h
+++ b/drivers/vulkan/vulkan_context.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -57,6 +57,11 @@ class VulkanContext {
bool device_initialized = false;
bool inst_initialized = false;
+ String device_vendor;
+ String device_name;
+ String pipeline_cache_id;
+ uint32_t device_api_version = 0;
+
bool buffers_prepared = false;
// Present queue.
@@ -119,6 +124,7 @@ class VulkanContext {
bool VK_GOOGLE_display_timing_enabled = true;
uint32_t enabled_extension_count = 0;
const char *extension_names[MAX_EXTENSIONS];
+ bool enabled_debug_utils = false;
uint32_t enabled_layer_count = 0;
const char *enabled_layers[MAX_LAYERS];
@@ -209,6 +215,15 @@ public:
Error swap_buffers();
Error initialize();
+ void command_begin_label(VkCommandBuffer p_command_buffer, String p_label_name, const Color p_color);
+ void command_insert_label(VkCommandBuffer p_command_buffer, String p_label_name, const Color p_color);
+ void command_end_label(VkCommandBuffer p_command_buffer);
+ void set_object_name(VkObjectType p_object_type, uint64_t p_object_handle, String p_object_name);
+
+ String get_device_vendor_name() const;
+ String get_device_name() const;
+ String get_device_pipeline_cache_uuid() const;
+
VulkanContext();
virtual ~VulkanContext();
};