summaryrefslogtreecommitdiff
path: root/drivers/vulkan/rendering_device_vulkan.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vulkan/rendering_device_vulkan.cpp')
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp148
1 files changed, 110 insertions, 38 deletions
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 69957d9939..31068b5064 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "rendering_device_vulkan.h"
+
#include "core/hashfuncs.h"
#include "core/os/file_access.h"
#include "core/os/os.h"
@@ -1265,7 +1266,7 @@ Error RenderingDeviceVulkan::_buffer_free(Buffer *p_buffer) {
ERR_FAIL_COND_V(p_buffer->size == 0, ERR_INVALID_PARAMETER);
vmaDestroyBuffer(allocator, p_buffer->buffer, p_buffer->allocation);
- p_buffer->buffer = nullptr;
+ p_buffer->buffer = VK_NULL_HANDLE;
p_buffer->allocation = nullptr;
p_buffer->size = 0;
@@ -1564,11 +1565,21 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
image_create_info.pNext = nullptr;
image_create_info.flags = 0;
- VkImageFormatListCreateInfoKHR format_list_create_info;
- Vector<VkFormat> allowed_formats;
+#ifndef _MSC_VER
+#warning TODO check for support via RenderingDevice to enable on mobile when possible
+#endif
+
+#ifndef ANDROID_ENABLED
+ // vkCreateImage fails with format list on Android (VK_ERROR_OUT_OF_HOST_MEMORY)
+ VkImageFormatListCreateInfoKHR format_list_create_info; //keep out of the if, needed for creation
+ Vector<VkFormat> allowed_formats; //keep out of the if, needed for creation
+#endif
if (p_format.shareable_formats.size()) {
image_create_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
+
+#ifndef ANDROID_ENABLED
+
for (int i = 0; i < p_format.shareable_formats.size(); i++) {
allowed_formats.push_back(vulkan_formats[p_format.shareable_formats[i]]);
}
@@ -1583,7 +1594,9 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
"If supplied a list of shareable formats, the current format must be present in the list");
ERR_FAIL_COND_V_MSG(p_view.format_override != DATA_FORMAT_MAX && p_format.shareable_formats.find(p_view.format_override) == -1, RID(),
"If supplied a list of shareable formats, the current view format override must be present in the list");
+#endif
}
+
if (p_format.type == TEXTURE_TYPE_CUBE || p_format.type == TEXTURE_TYPE_CUBE_ARRAY) {
image_create_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
}
@@ -1759,6 +1772,8 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
texture.depth = image_create_info.extent.depth;
texture.layers = image_create_info.arrayLayers;
texture.mipmaps = image_create_info.mipLevels;
+ texture.base_mipmap = 0;
+ texture.base_layer = 0;
texture.usage_flags = p_format.usage_bits;
texture.samples = p_format.samples;
texture.allowed_shared_formats = p_format.shareable_formats;
@@ -1999,6 +2014,8 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
get_image_format_required_size(texture.format, texture.width, texture.height, texture.depth, p_mipmap + 1, &texture.width, &texture.height);
texture.mipmaps = 1;
texture.layers = p_slice_type == TEXTURE_SLICE_CUBEMAP ? 6 : 1;
+ texture.base_mipmap = p_mipmap;
+ texture.base_layer = p_layer;
VkImageViewCreateInfo image_view_create_info;
image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
@@ -2681,8 +2698,8 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
src_layer_count *= 6;
}
- ERR_FAIL_COND_V(p_base_mipmap + p_mipmaps > src_tex->mipmaps, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V(p_base_layer + p_layers > src_layer_count, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(src_tex->base_mipmap + p_base_mipmap + p_mipmaps > src_tex->mipmaps, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(src_tex->base_layer + p_base_layer + p_layers > src_layer_count, ERR_INVALID_PARAMETER);
VkCommandBuffer command_buffer = p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer;
@@ -2701,9 +2718,9 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = src_tex->image;
image_memory_barrier.subresourceRange.aspectMask = src_tex->read_aspect_mask;
- image_memory_barrier.subresourceRange.baseMipLevel = p_base_mipmap;
+ image_memory_barrier.subresourceRange.baseMipLevel = src_tex->base_mipmap + p_base_mipmap;
image_memory_barrier.subresourceRange.levelCount = p_mipmaps;
- image_memory_barrier.subresourceRange.baseArrayLayer = p_base_layer;
+ image_memory_barrier.subresourceRange.baseArrayLayer = src_tex->base_layer + p_base_layer;
image_memory_barrier.subresourceRange.layerCount = p_layers;
layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
@@ -2739,9 +2756,9 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = src_tex->image;
image_memory_barrier.subresourceRange.aspectMask = src_tex->read_aspect_mask;
- image_memory_barrier.subresourceRange.baseMipLevel = p_base_mipmap;
+ image_memory_barrier.subresourceRange.baseMipLevel = src_tex->base_mipmap + p_base_mipmap;
image_memory_barrier.subresourceRange.levelCount = p_mipmaps;
- image_memory_barrier.subresourceRange.baseArrayLayer = p_base_layer;
+ image_memory_barrier.subresourceRange.baseArrayLayer = src_tex->base_layer + p_base_layer;
image_memory_barrier.subresourceRange.layerCount = p_layers;
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
@@ -2839,6 +2856,21 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
}
} break;
+ case INITIAL_ACTION_DROP: {
+ if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ } else if (p_format[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ } else {
+ description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
+ }
+ } break;
case INITIAL_ACTION_CONTINUE: {
if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
@@ -4250,7 +4282,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
VkWriteDescriptorSet write; //common header
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write.pNext = nullptr;
- write.dstSet = nullptr; //will assign afterwards when everything is valid
+ write.dstSet = VK_NULL_HANDLE; //will assign afterwards when everything is valid
write.dstBinding = set_uniform.binding;
uint32_t type_size = 1;
@@ -4318,6 +4350,10 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
attachable_textures.push_back(texture->owner.is_valid() ? texture->owner : uniform.ids[j + 1]);
}
+ if (texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT) {
+ //can also be used as storage, add to mutable sampled
+ mutable_sampled_textures.push_back(texture);
+ }
if (texture->owner.is_valid()) {
texture = texture_owner.getornull(texture->owner);
ERR_FAIL_COND_V(!texture, RID()); //bug, should never happen
@@ -4326,11 +4362,6 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
image_info.push_back(img_info);
-
- if (texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT) {
- //can also be used as storage, add to mutable sampled
- mutable_sampled_textures.push_back(texture);
- }
}
write.dstArrayElement = 0;
@@ -4363,13 +4394,18 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
"Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") needs the TEXTURE_USAGE_SAMPLING_BIT usage flag set in order to be used as uniform.");
VkDescriptorImageInfo img_info;
- img_info.sampler = nullptr;
+ img_info.sampler = VK_NULL_HANDLE;
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]);
}
+ if (texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT) {
+ //can also be used as storage, add to mutable sampled
+ mutable_sampled_textures.push_back(texture);
+ }
+
if (texture->owner.is_valid()) {
texture = texture_owner.getornull(texture->owner);
ERR_FAIL_COND_V(!texture, RID()); //bug, should never happen
@@ -4378,11 +4414,6 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
image_info.push_back(img_info);
-
- if (texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT) {
- //can also be used as storage, add to mutable sampled
- mutable_sampled_textures.push_back(texture);
- }
}
write.dstArrayElement = 0;
@@ -4416,9 +4447,14 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
"Image (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") needs the TEXTURE_USAGE_STORAGE_BIT usage flag set in order to be used as uniform.");
VkDescriptorImageInfo img_info;
- img_info.sampler = nullptr;
+ img_info.sampler = VK_NULL_HANDLE;
img_info.imageView = texture->view;
+ if (texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT) {
+ //can also be used as storage, add to mutable sampled
+ mutable_storage_textures.push_back(texture);
+ }
+
if (texture->owner.is_valid()) {
texture = texture_owner.getornull(texture->owner);
ERR_FAIL_COND_V(!texture, RID()); //bug, should never happen
@@ -4427,11 +4463,6 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
img_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
image_info.push_back(img_info);
-
- if (texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT) {
- //can also be used as storage, add to mutable sampled
- mutable_storage_textures.push_back(texture);
- }
}
write.dstArrayElement = 0;
@@ -5048,11 +5079,11 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
graphics_pipeline_create_info.renderPass = fb_format.render_pass;
graphics_pipeline_create_info.subpass = 0;
- graphics_pipeline_create_info.basePipelineHandle = nullptr;
+ graphics_pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE;
graphics_pipeline_create_info.basePipelineIndex = 0;
RenderPipeline pipeline;
- VkResult err = vkCreateGraphicsPipelines(device, nullptr, 1, &graphics_pipeline_create_info, nullptr, &pipeline.pipeline);
+ VkResult err = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &graphics_pipeline_create_info, nullptr, &pipeline.pipeline);
ERR_FAIL_COND_V_MSG(err, RID(), "vkCreateGraphicsPipelines failed with error " + itos(err) + ".");
pipeline.set_formats = shader->set_formats;
@@ -5121,11 +5152,11 @@ RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader) {
compute_pipeline_create_info.stage = shader->pipeline_stages[0];
compute_pipeline_create_info.layout = shader->pipeline_layout;
- compute_pipeline_create_info.basePipelineHandle = nullptr;
+ compute_pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE;
compute_pipeline_create_info.basePipelineIndex = 0;
ComputePipeline pipeline;
- VkResult err = vkCreateComputePipelines(device, nullptr, 1, &compute_pipeline_create_info, nullptr, &pipeline.pipeline);
+ VkResult err = vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &compute_pipeline_create_info, nullptr, &pipeline.pipeline);
ERR_FAIL_COND_V_MSG(err, RID(), "vkCreateComputePipelines failed with error " + itos(err) + ".");
pipeline.set_formats = shader->set_formats;
@@ -6199,9 +6230,9 @@ void RenderingDeviceVulkan::compute_list_bind_uniform_set(ComputeListID p_list,
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = textures_to_sampled[i]->image;
image_memory_barrier.subresourceRange.aspectMask = textures_to_sampled[i]->read_aspect_mask;
- image_memory_barrier.subresourceRange.baseMipLevel = 0;
+ image_memory_barrier.subresourceRange.baseMipLevel = textures_to_sampled[i]->base_mipmap;
image_memory_barrier.subresourceRange.levelCount = textures_to_sampled[i]->mipmaps;
- image_memory_barrier.subresourceRange.baseArrayLayer = 0;
+ image_memory_barrier.subresourceRange.baseArrayLayer = textures_to_sampled[i]->base_layer;
image_memory_barrier.subresourceRange.layerCount = textures_to_sampled[i]->layers;
vkCmdPipelineBarrier(cl->command_buffer, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
@@ -6230,9 +6261,9 @@ void RenderingDeviceVulkan::compute_list_bind_uniform_set(ComputeListID p_list,
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = textures_to_storage[i]->image;
image_memory_barrier.subresourceRange.aspectMask = textures_to_storage[i]->read_aspect_mask;
- image_memory_barrier.subresourceRange.baseMipLevel = 0;
+ image_memory_barrier.subresourceRange.baseMipLevel = textures_to_storage[i]->base_mipmap;
image_memory_barrier.subresourceRange.levelCount = textures_to_storage[i]->mipmaps;
- image_memory_barrier.subresourceRange.baseArrayLayer = 0;
+ image_memory_barrier.subresourceRange.baseArrayLayer = textures_to_storage[i]->base_layer;
image_memory_barrier.subresourceRange.layerCount = textures_to_storage[i]->layers;
vkCmdPipelineBarrier(cl->command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
@@ -6362,9 +6393,9 @@ void RenderingDeviceVulkan::compute_list_end() {
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = E->get()->image;
image_memory_barrier.subresourceRange.aspectMask = E->get()->read_aspect_mask;
- image_memory_barrier.subresourceRange.baseMipLevel = 0;
+ image_memory_barrier.subresourceRange.baseMipLevel = E->get()->base_mipmap;
image_memory_barrier.subresourceRange.levelCount = E->get()->mipmaps;
- image_memory_barrier.subresourceRange.baseArrayLayer = 0;
+ image_memory_barrier.subresourceRange.baseArrayLayer = E->get()->base_layer;
image_memory_barrier.subresourceRange.layerCount = E->get()->layers;
vkCmdPipelineBarrier(compute_list->command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
@@ -6928,9 +6959,42 @@ uint64_t RenderingDeviceVulkan::get_captured_timestamps_frame() const {
return frames[frame].index;
}
+static void mult64to128(uint64_t u, uint64_t v, uint64_t &h, uint64_t &l) {
+ uint64_t u1 = (u & 0xffffffff);
+ uint64_t v1 = (v & 0xffffffff);
+ uint64_t t = (u1 * v1);
+ uint64_t w3 = (t & 0xffffffff);
+ uint64_t k = (t >> 32);
+
+ u >>= 32;
+ t = (u * v1) + k;
+ k = (t & 0xffffffff);
+ uint64_t w1 = (t >> 32);
+
+ v >>= 32;
+ t = (u1 * v) + k;
+ k = (t >> 32);
+
+ h = (u * v) + w1 + k;
+ l = (t << 32) + w3;
+}
+
uint64_t RenderingDeviceVulkan::get_captured_timestamp_gpu_time(uint32_t p_index) const {
ERR_FAIL_UNSIGNED_INDEX_V(p_index, frames[frame].timestamp_result_count, 0);
- return frames[frame].timestamp_result_values[p_index] * limits.timestampPeriod;
+
+ // this sucks because timestampPeriod multiplier is a float, while the timestamp is 64 bits nanosecs.
+ // so, in cases like nvidia which give you enormous numbers and 1 as multiplier, multiplying is next to impossible
+ // need to do 128 bits fixed point multiplication to get the rigth value
+
+ uint64_t shift_bits = 16;
+
+ uint64_t h, l;
+
+ mult64to128(frames[frame].timestamp_result_values[p_index], uint64_t(double(limits.timestampPeriod) * double(1 << shift_bits)), h, l);
+ l >>= shift_bits;
+ l |= h << (64 - shift_bits);
+
+ return l;
}
uint64_t RenderingDeviceVulkan::get_captured_timestamp_cpu_time(uint32_t p_index) const {
ERR_FAIL_UNSIGNED_INDEX_V(p_index, frames[frame].timestamp_result_count, 0);
@@ -7048,6 +7112,14 @@ void RenderingDeviceVulkan::finalize() {
for (int i = 0; i < staging_buffer_blocks.size(); i++) {
vmaDestroyBuffer(allocator, staging_buffer_blocks[i].buffer, staging_buffer_blocks[i].allocation);
}
+ vmaDestroyAllocator(allocator);
+
+ while (vertex_formats.size()) {
+ Map<VertexFormatID, VertexDescriptionCache>::Element *temp = vertex_formats.front();
+ memdelete_arr(temp->get().bindings);
+ memdelete_arr(temp->get().attributes);
+ vertex_formats.erase(temp);
+ }
//all these should be clear at this point
ERR_FAIL_COND(descriptor_pools.size());