diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 6 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.h | 26 | ||||
-rw-r--r-- | drivers/gles3/shaders/scene.glsl | 8 | ||||
-rw-r--r-- | drivers/unix/os_unix.cpp | 4 | ||||
-rw-r--r-- | drivers/vulkan/SCsub | 3 | ||||
-rw-r--r-- | drivers/vulkan/rendering_device_vulkan.cpp | 322 | ||||
-rw-r--r-- | drivers/vulkan/rendering_device_vulkan.h | 4 | ||||
-rw-r--r-- | drivers/vulkan/vulkan_context.cpp | 232 | ||||
-rw-r--r-- | drivers/vulkan/vulkan_context.h | 5 | ||||
-rw-r--r-- | drivers/vulkan/vulkan_hooks.h | 48 |
10 files changed, 444 insertions, 214 deletions
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index abbba13ee6..dce515a96d 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -2255,9 +2255,6 @@ void RasterizerStorageGLES3::light_set_param(RID p_light, RS::LightParam p_param void RasterizerStorageGLES3::light_set_shadow(RID p_light, bool p_enabled) { } -void RasterizerStorageGLES3::light_set_shadow_color(RID p_light, const Color &p_color) { -} - void RasterizerStorageGLES3::light_set_projector(RID p_light, RID p_texture) { } @@ -2267,6 +2264,9 @@ void RasterizerStorageGLES3::light_set_negative(RID p_light, bool p_enable) { void RasterizerStorageGLES3::light_set_cull_mask(RID p_light, uint32_t p_mask) { } +void RasterizerStorageGLES3::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) { +} + void RasterizerStorageGLES3::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) { } diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index b6a5c0e73e..de984fa8df 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -898,10 +898,10 @@ public: void light_set_color(RID p_light, const Color &p_color) override; void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override; void light_set_shadow(RID p_light, bool p_enabled) override; - void light_set_shadow_color(RID p_light, const Color &p_color) override; void light_set_projector(RID p_light, RID p_texture) override; void light_set_negative(RID p_light, bool p_enable) override; void light_set_cull_mask(RID p_light, uint32_t p_mask) override; + void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override; void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override; void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override; void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override; @@ -1168,27 +1168,21 @@ public: int height = 0; GLuint color = 0; - - Effect() { - } }; Effect copy_screen_effect; struct MipMaps { struct Size { - GLuint fbo; - GLuint color; - int width; - int height; + GLuint fbo = 0; + GLuint color = 0; + int width = 0; + int height = 0; }; Vector<Size> sizes; GLuint color = 0; int levels = 0; - - MipMaps() { - } }; MipMaps mip_maps[2]; @@ -1198,14 +1192,14 @@ public: GLuint color = 0; GLuint depth = 0; RID texture; - - External() { - } } external; - int x = 0, y = 0, width = 0, height = 0; + int x = 0; + int y = 0; + int width = 0; + int height = 0; - bool flags[RENDER_TARGET_FLAG_MAX]; + bool flags[RENDER_TARGET_FLAG_MAX] = {}; // instead of allocating sized render targets immediately, // defer this for faster startup diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 98c92a1d99..2d504cd052 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -1107,7 +1107,7 @@ void light_compute( float rim, float rim_tint, float clearcoat, - float clearcoat_gloss, + float clearcoat_roughness, float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light, @@ -1298,7 +1298,7 @@ LIGHT_SHADER_CODE #if !defined(SPECULAR_SCHLICK_GGX) float cLdotH5 = SchlickFresnel(cLdotH); #endif - float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss)); + float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_roughness)); float Fr = mix(.04, 1.0, cLdotH5); //float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); float Gr = V_GGX(cNdotL, cNdotV, 0.25); @@ -1427,7 +1427,7 @@ void main() { float rim = 0.0; float rim_tint = 0.0; float clearcoat = 0.0; - float clearcoat_gloss = 0.0; + float clearcoat_roughness = 0.0; float anisotropy = 0.0; vec2 anisotropy_flow = vec2(1.0, 0.0); float sss_strength = 0.0; //unused @@ -2028,7 +2028,7 @@ FRAGMENT_SHADER_CODE rim, rim_tint, clearcoat, - clearcoat_gloss, + clearcoat_roughness, anisotropy, diffuse_light, specular_light, diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 088525647c..3b5e1bf91d 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -439,12 +439,12 @@ Error OS_Unix::open_dynamic_library(const String p_path, void *&p_library_handle } if (!FileAccess::exists(path)) { - //this code exists so gdnative can load .so files from within the executable path + // This code exists so GDExtension can load .so files from within the executable path. path = get_executable_path().get_base_dir().plus_file(p_path.get_file()); } if (!FileAccess::exists(path)) { - //this code exists so gdnative can load .so files from a standard unix location + // This code exists so GDExtension can load .so files from a standard unix location. path = get_executable_path().get_base_dir().plus_file("../lib").plus_file(p_path.get_file()); } diff --git a/drivers/vulkan/SCsub b/drivers/vulkan/SCsub index 8fe75367a8..b6ceb1cdea 100644 --- a/drivers/vulkan/SCsub +++ b/drivers/vulkan/SCsub @@ -40,6 +40,9 @@ elif env["platform"] == "android": # Our current NDK version only provides old Vulkan headers, # so we have to limit VMA. env_thirdparty_vma.AppendUnique(CPPDEFINES=["VMA_VULKAN_VERSION=1000000"]) +elif env["platform"] == "osx" or env["platform"] == "iphone": + # MoltenVK supports only Vulkan 1.1 API, limit VMA to the same version. + env_thirdparty_vma.AppendUnique(CPPDEFINES=["VMA_VULKAN_VERSION=1001000"]) env_thirdparty_vma.add_source_files(thirdparty_obj, thirdparty_sources_vma) diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index ddeac220ec..b86b5f1579 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -1335,8 +1335,13 @@ Error RenderingDeviceVulkan::_buffer_allocate(Buffer *p_buffer, uint32_t p_size, allocInfo.requiredFlags = 0; allocInfo.preferredFlags = 0; allocInfo.memoryTypeBits = 0; - allocInfo.pool = p_size <= SMALL_ALLOCATION_MAX_SIZE ? small_allocs_pool : nullptr; + allocInfo.pool = nullptr; allocInfo.pUserData = nullptr; + if (p_size <= SMALL_ALLOCATION_MAX_SIZE) { + uint32_t mem_type_index = 0; + vmaFindMemoryTypeIndexForBufferInfo(allocator, &bufferInfo, &allocInfo, &mem_type_index); + allocInfo.pool = _find_or_create_small_allocs_pool(mem_type_index); + } VkResult err = vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &p_buffer->buffer, &p_buffer->allocation, nullptr); ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE, "Can't create buffer of size: " + itos(p_size) + ", error " + itos(err) + "."); @@ -1843,12 +1848,17 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T VmaAllocationCreateInfo allocInfo; allocInfo.flags = 0; - allocInfo.pool = image_size <= SMALL_ALLOCATION_MAX_SIZE ? small_allocs_pool : nullptr; + allocInfo.pool = nullptr; allocInfo.usage = p_format.usage_bits & TEXTURE_USAGE_CPU_READ_BIT ? VMA_MEMORY_USAGE_CPU_ONLY : VMA_MEMORY_USAGE_GPU_ONLY; allocInfo.requiredFlags = 0; allocInfo.preferredFlags = 0; allocInfo.memoryTypeBits = 0; allocInfo.pUserData = nullptr; + if (image_size <= SMALL_ALLOCATION_MAX_SIZE) { + uint32_t mem_type_index = 0; + vmaFindMemoryTypeIndexForImageInfo(allocator, &image_create_info, &allocInfo, &mem_type_index); + allocInfo.pool = _find_or_create_small_allocs_pool(mem_type_index); + } Texture texture; @@ -2118,6 +2128,124 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID return id; } +RID RenderingDeviceVulkan::texture_create_from_extension(TextureType p_type, DataFormat p_format, TextureSamples p_samples, uint64_t p_flags, uint64_t p_image, uint64_t p_width, uint64_t p_height, uint64_t p_depth, uint64_t p_layers) { + _THREAD_SAFE_METHOD_ + // This method creates a texture object using a VkImage created by an extension, module or other external source (OpenXR uses this). + VkImage image = (VkImage)p_image; + + Texture texture; + texture.image = image; + // if we leave texture.allocation as a nullptr, would that be enough to detect we don't "own" the image? + // also leave texture.allocation_info alone + // we'll set texture.view later on + texture.type = p_type; + texture.format = p_format; + texture.samples = p_samples; + texture.width = p_width; + texture.height = p_height; + texture.depth = p_depth; + texture.layers = p_layers; + texture.mipmaps = 0; // maybe make this settable too? + texture.usage_flags = p_flags; + texture.base_mipmap = 0; + texture.base_layer = 0; + texture.allowed_shared_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_UNORM); + texture.allowed_shared_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_SRGB); + + // Do we need to do something with texture.layout ? + + if (texture.usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + texture.read_aspect_mask = VK_IMAGE_ASPECT_DEPTH_BIT; + texture.barrier_aspect_mask = VK_IMAGE_ASPECT_DEPTH_BIT; + + // if (format_has_stencil(p_format.format)) { + // texture.barrier_aspect_mask |= VK_IMAGE_ASPECT_STENCIL_BIT; + // } + } else { + texture.read_aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT; + texture.barrier_aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT; + } + + // Create a view for us to use + + VkImageViewCreateInfo image_view_create_info; + image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + image_view_create_info.pNext = nullptr; + image_view_create_info.flags = 0; + image_view_create_info.image = texture.image; + + static const VkImageViewType view_types[TEXTURE_TYPE_MAX] = { + VK_IMAGE_VIEW_TYPE_1D, + VK_IMAGE_VIEW_TYPE_2D, + VK_IMAGE_VIEW_TYPE_3D, + VK_IMAGE_VIEW_TYPE_CUBE, + VK_IMAGE_VIEW_TYPE_1D_ARRAY, + VK_IMAGE_VIEW_TYPE_2D_ARRAY, + VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, + }; + + image_view_create_info.viewType = view_types[texture.type]; + image_view_create_info.format = vulkan_formats[texture.format]; + + static const VkComponentSwizzle component_swizzles[TEXTURE_SWIZZLE_MAX] = { + VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_ZERO, + VK_COMPONENT_SWIZZLE_ONE, + VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, + VK_COMPONENT_SWIZZLE_A + }; + + // hardcode for now, maybe make this settable from outside.. + image_view_create_info.components.r = component_swizzles[TEXTURE_SWIZZLE_R]; + image_view_create_info.components.g = component_swizzles[TEXTURE_SWIZZLE_G]; + image_view_create_info.components.b = component_swizzles[TEXTURE_SWIZZLE_B]; + image_view_create_info.components.a = component_swizzles[TEXTURE_SWIZZLE_A]; + + image_view_create_info.subresourceRange.baseMipLevel = 0; + image_view_create_info.subresourceRange.levelCount = texture.mipmaps; + image_view_create_info.subresourceRange.baseArrayLayer = 0; + image_view_create_info.subresourceRange.layerCount = texture.layers; + if (texture.usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + } else { + image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + } + + VkResult err = vkCreateImageView(device, &image_view_create_info, nullptr, &texture.view); + + if (err) { + // vmaDestroyImage(allocator, texture.image, texture.allocation); + ERR_FAIL_V_MSG(RID(), "vkCreateImageView failed with error " + itos(err) + "."); + } + + //barrier to set layout + { + VkImageMemoryBarrier image_memory_barrier; + image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + image_memory_barrier.pNext = nullptr; + image_memory_barrier.srcAccessMask = 0; + image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + image_memory_barrier.newLayout = texture.layout; + image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.image = texture.image; + image_memory_barrier.subresourceRange.aspectMask = texture.barrier_aspect_mask; + image_memory_barrier.subresourceRange.baseMipLevel = 0; + image_memory_barrier.subresourceRange.levelCount = texture.mipmaps; + image_memory_barrier.subresourceRange.baseArrayLayer = 0; + image_memory_barrier.subresourceRange.layerCount = texture.layers; + + vkCmdPipelineBarrier(frames[frame].setup_command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_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); + } + + RID id = texture_owner.make_rid(texture); + + return id; +} + RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps, TextureSliceType p_slice_type) { _THREAD_SAFE_METHOD_ @@ -4635,19 +4763,22 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve for (uint32_t j = 0; j < sc_count; j++) { int32_t existing = -1; RenderingDeviceVulkanShaderBinarySpecializationConstant sconst; - sconst.constant_id = spec_constants[j]->constant_id; - switch (spec_constants[j]->constant_type) { + SpvReflectSpecializationConstant *spc = spec_constants[j]; + + sconst.constant_id = spc->constant_id; + sconst.int_value = 0.0; // clear previous value JIC + switch (spc->constant_type) { case SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL: { sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; - sconst.bool_value = spec_constants[j]->default_value.int_bool_value != 0; + sconst.bool_value = spc->default_value.int_bool_value != 0; } break; case SPV_REFLECT_SPECIALIZATION_CONSTANT_INT: { sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT; - sconst.int_value = spec_constants[j]->default_value.int_bool_value; + sconst.int_value = spc->default_value.int_bool_value; } break; case SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT: { sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT; - sconst.float_value = spec_constants[j]->default_value.float_value; + sconst.float_value = spc->default_value.float_value; } break; } sconst.stage_flags = 1 << p_spirv[i].shader_stage; @@ -5501,18 +5632,18 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, switch (uniform.uniform_type) { case UNIFORM_TYPE_SAMPLER: { - if (uniform.ids.size() != set_uniform.length) { + if (uniform.get_id_count() != (uint32_t)set_uniform.length) { if (set_uniform.length > 1) { - ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler elements, so it should be provided equal number of sampler IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler elements, so it should be provided equal number of sampler IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ")."); } else { - ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") should provide one ID referencing a sampler (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") should provide one ID referencing a sampler (IDs provided: " + itos(uniform.get_id_count()) + ")."); } } Vector<VkDescriptorImageInfo> image_info; - for (int j = 0; j < uniform.ids.size(); j++) { - VkSampler *sampler = sampler_owner.get_or_null(uniform.ids[j]); + for (uint32_t j = 0; j < uniform.get_id_count(); j++) { + VkSampler *sampler = sampler_owner.get_or_null(uniform.get_id(j)); ERR_FAIL_COND_V_MSG(!sampler, RID(), "Sampler (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid sampler."); VkDescriptorImageInfo img_info; @@ -5524,31 +5655,31 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } write.dstArrayElement = 0; - write.descriptorCount = uniform.ids.size(); + write.descriptorCount = uniform.get_id_count(); write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; write.pImageInfo = image_infos.push_back(image_info)->get().ptr(); write.pBufferInfo = nullptr; write.pTexelBufferView = nullptr; - type_size = uniform.ids.size(); + type_size = uniform.get_id_count(); } break; case UNIFORM_TYPE_SAMPLER_WITH_TEXTURE: { - if (uniform.ids.size() != set_uniform.length * 2) { + if (uniform.get_id_count() != (uint32_t)set_uniform.length * 2) { if (set_uniform.length > 1) { - ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler&texture elements, so it should provided twice the amount of IDs (sampler,texture pairs) to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler&texture elements, so it should provided twice the amount of IDs (sampler,texture pairs) to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ")."); } else { - ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture (IDs provided: " + itos(uniform.get_id_count()) + ")."); } } Vector<VkDescriptorImageInfo> image_info; - for (int j = 0; j < uniform.ids.size(); j += 2) { - VkSampler *sampler = sampler_owner.get_or_null(uniform.ids[j + 0]); + for (uint32_t j = 0; j < uniform.get_id_count(); j += 2) { + VkSampler *sampler = sampler_owner.get_or_null(uniform.get_id(j + 0)); ERR_FAIL_COND_V_MSG(!sampler, RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ", index " + itos(j + 1) + ") is not a valid sampler."); - Texture *texture = texture_owner.get_or_null(uniform.ids[j + 1]); + Texture *texture = texture_owner.get_or_null(uniform.get_id(j + 1)); ERR_FAIL_COND_V_MSG(!texture, RID(), "Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture."); ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT), RID(), @@ -5561,7 +5692,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, if (texture->usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)) { UniformSet::AttachableTexture attachable_texture; attachable_texture.bind = set_uniform.binding; - attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.ids[j + 1]; + attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.get_id(j + 1); attachable_textures.push_back(attachable_texture); } @@ -5580,28 +5711,28 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } write.dstArrayElement = 0; - write.descriptorCount = uniform.ids.size() / 2; + write.descriptorCount = uniform.get_id_count() / 2; write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; write.pImageInfo = image_infos.push_back(image_info)->get().ptr(); write.pBufferInfo = nullptr; write.pTexelBufferView = nullptr; - type_size = uniform.ids.size() / 2; + type_size = uniform.get_id_count() / 2; } break; case UNIFORM_TYPE_TEXTURE: { - if (uniform.ids.size() != set_uniform.length) { + if (uniform.get_id_count() != (uint32_t)set_uniform.length) { if (set_uniform.length > 1) { - ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ")."); } else { - ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.get_id_count()) + ")."); } } Vector<VkDescriptorImageInfo> image_info; - for (int j = 0; j < uniform.ids.size(); j++) { - Texture *texture = texture_owner.get_or_null(uniform.ids[j]); + for (uint32_t j = 0; j < uniform.get_id_count(); j++) { + Texture *texture = texture_owner.get_or_null(uniform.get_id(j)); ERR_FAIL_COND_V_MSG(!texture, RID(), "Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture."); ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT), RID(), @@ -5614,7 +5745,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, if (texture->usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)) { UniformSet::AttachableTexture attachable_texture; attachable_texture.bind = set_uniform.binding; - attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.ids[j]; + attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.get_id(j); attachable_textures.push_back(attachable_texture); } @@ -5634,27 +5765,27 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } write.dstArrayElement = 0; - write.descriptorCount = uniform.ids.size(); + write.descriptorCount = uniform.get_id_count(); write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; write.pImageInfo = image_infos.push_back(image_info)->get().ptr(); write.pBufferInfo = nullptr; write.pTexelBufferView = nullptr; - type_size = uniform.ids.size(); + type_size = uniform.get_id_count(); } break; case UNIFORM_TYPE_IMAGE: { - if (uniform.ids.size() != set_uniform.length) { + if (uniform.get_id_count() != (uint32_t)set_uniform.length) { if (set_uniform.length > 1) { - ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ")."); } else { - ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.get_id_count()) + ")."); } } Vector<VkDescriptorImageInfo> image_info; - for (int j = 0; j < uniform.ids.size(); j++) { - Texture *texture = texture_owner.get_or_null(uniform.ids[j]); + for (uint32_t j = 0; j < uniform.get_id_count(); j++) { + Texture *texture = texture_owner.get_or_null(uniform.get_id(j)); ERR_FAIL_COND_V_MSG(!texture, RID(), "Image (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture."); @@ -5682,29 +5813,29 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } write.dstArrayElement = 0; - write.descriptorCount = uniform.ids.size(); + write.descriptorCount = uniform.get_id_count(); write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; write.pImageInfo = image_infos.push_back(image_info)->get().ptr(); write.pBufferInfo = nullptr; write.pTexelBufferView = nullptr; - type_size = uniform.ids.size(); + type_size = uniform.get_id_count(); } break; case UNIFORM_TYPE_TEXTURE_BUFFER: { - if (uniform.ids.size() != set_uniform.length) { + if (uniform.get_id_count() != (uint32_t)set_uniform.length) { if (set_uniform.length > 1) { - ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") texture buffer elements, so it should be provided equal number of texture buffer IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") texture buffer elements, so it should be provided equal number of texture buffer IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ")."); } else { - ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture buffer (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture buffer (IDs provided: " + itos(uniform.get_id_count()) + ")."); } } Vector<VkDescriptorBufferInfo> buffer_info; Vector<VkBufferView> buffer_view; - for (int j = 0; j < uniform.ids.size(); j++) { - TextureBuffer *buffer = texture_buffer_owner.get_or_null(uniform.ids[j]); + for (uint32_t j = 0; j < uniform.get_id_count(); j++) { + TextureBuffer *buffer = texture_buffer_owner.get_or_null(uniform.get_id(j)); ERR_FAIL_COND_V_MSG(!buffer, RID(), "Texture Buffer (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture buffer."); buffer_info.push_back(buffer->buffer.buffer_info); @@ -5712,21 +5843,21 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } write.dstArrayElement = 0; - write.descriptorCount = uniform.ids.size(); + write.descriptorCount = uniform.get_id_count(); write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; write.pImageInfo = nullptr; write.pBufferInfo = buffer_infos.push_back(buffer_info)->get().ptr(); write.pTexelBufferView = buffer_views.push_back(buffer_view)->get().ptr(); - type_size = uniform.ids.size(); + type_size = uniform.get_id_count(); } break; case UNIFORM_TYPE_SAMPLER_WITH_TEXTURE_BUFFER: { - if (uniform.ids.size() != set_uniform.length * 2) { + if (uniform.get_id_count() != (uint32_t)set_uniform.length * 2) { if (set_uniform.length > 1) { - ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler buffer elements, so it should provided twice the amount of IDs (sampler,buffer pairs) to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler buffer elements, so it should provided twice the amount of IDs (sampler,buffer pairs) to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ")."); } else { - ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture buffer (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture buffer (IDs provided: " + itos(uniform.get_id_count()) + ")."); } } @@ -5734,11 +5865,11 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, Vector<VkDescriptorBufferInfo> buffer_info; Vector<VkBufferView> buffer_view; - for (int j = 0; j < uniform.ids.size(); j += 2) { - VkSampler *sampler = sampler_owner.get_or_null(uniform.ids[j + 0]); + for (uint32_t j = 0; j < uniform.get_id_count(); j += 2) { + VkSampler *sampler = sampler_owner.get_or_null(uniform.get_id(j + 0)); ERR_FAIL_COND_V_MSG(!sampler, RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ", index " + itos(j + 1) + ") is not a valid sampler."); - TextureBuffer *buffer = texture_buffer_owner.get_or_null(uniform.ids[j + 1]); + TextureBuffer *buffer = texture_buffer_owner.get_or_null(uniform.get_id(j + 1)); VkDescriptorImageInfo img_info; img_info.sampler = *sampler; @@ -5754,23 +5885,23 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } write.dstArrayElement = 0; - write.descriptorCount = uniform.ids.size() / 2; + write.descriptorCount = uniform.get_id_count() / 2; write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; write.pImageInfo = image_infos.push_back(image_info)->get().ptr(); write.pBufferInfo = buffer_infos.push_back(buffer_info)->get().ptr(); write.pTexelBufferView = buffer_views.push_back(buffer_view)->get().ptr(); - type_size = uniform.ids.size() / 2; + type_size = uniform.get_id_count() / 2; } break; case UNIFORM_TYPE_IMAGE_BUFFER: { //todo } break; case UNIFORM_TYPE_UNIFORM_BUFFER: { - ERR_FAIL_COND_V_MSG(uniform.ids.size() != 1, RID(), - "Uniform buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.ids.size()) + " provided)."); + ERR_FAIL_COND_V_MSG(uniform.get_id_count() != 1, RID(), + "Uniform buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.get_id_count()) + " provided)."); - Buffer *buffer = uniform_buffer_owner.get_or_null(uniform.ids[0]); + Buffer *buffer = uniform_buffer_owner.get_or_null(uniform.get_id(0)); ERR_FAIL_COND_V_MSG(!buffer, RID(), "Uniform buffer supplied (binding: " + itos(uniform.binding) + ") is invalid."); ERR_FAIL_COND_V_MSG(buffer->size != (uint32_t)set_uniform.length, RID(), @@ -5785,15 +5916,15 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } break; case UNIFORM_TYPE_STORAGE_BUFFER: { - 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)."); + ERR_FAIL_COND_V_MSG(uniform.get_id_count() != 1, RID(), + "Storage buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.get_id_count()) + " provided)."); Buffer *buffer = nullptr; - if (storage_buffer_owner.owns(uniform.ids[0])) { - buffer = storage_buffer_owner.get_or_null(uniform.ids[0]); - } else if (vertex_buffer_owner.owns(uniform.ids[0])) { - buffer = vertex_buffer_owner.get_or_null(uniform.ids[0]); + if (storage_buffer_owner.owns(uniform.get_id(0))) { + buffer = storage_buffer_owner.get_or_null(uniform.get_id(0)); + } else if (vertex_buffer_owner.owns(uniform.get_id(0))) { + buffer = vertex_buffer_owner.get_or_null(uniform.get_id(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."); } @@ -5813,18 +5944,18 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, case UNIFORM_TYPE_INPUT_ATTACHMENT: { ERR_FAIL_COND_V_MSG(shader->is_compute, RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") supplied for compute shader (this is not allowed)."); - if (uniform.ids.size() != set_uniform.length) { + if (uniform.get_id_count() != (uint32_t)set_uniform.length) { if (set_uniform.length > 1) { - ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ")."); } else { - ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.ids.size()) + ")."); + ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.get_id_count()) + ")."); } } Vector<VkDescriptorImageInfo> image_info; - for (int j = 0; j < uniform.ids.size(); j++) { - Texture *texture = texture_owner.get_or_null(uniform.ids[j]); + for (uint32_t j = 0; j < uniform.get_id_count(); j++) { + Texture *texture = texture_owner.get_or_null(uniform.get_id(j)); ERR_FAIL_COND_V_MSG(!texture, RID(), "InputAttachment (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture."); @@ -5847,13 +5978,13 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } write.dstArrayElement = 0; - write.descriptorCount = uniform.ids.size(); + write.descriptorCount = uniform.get_id_count(); write.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; write.pImageInfo = image_infos.push_back(image_info)->get().ptr(); write.pBufferInfo = nullptr; write.pTexelBufferView = nullptr; - type_size = uniform.ids.size(); + type_size = uniform.get_id_count(); } break; default: { } @@ -5903,10 +6034,9 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, _add_dependency(id, p_shader); for (uint32_t i = 0; i < uniform_count; i++) { const Uniform &uniform = uniforms[i]; - int id_count = uniform.ids.size(); - const RID *ids = uniform.ids.ptr(); + int id_count = uniform.get_id_count(); for (int j = 0; j < id_count; j++) { - _add_dependency(id, ids[j]); + _add_dependency(id, uniform.get_id(j)); } } @@ -8596,6 +8726,30 @@ void RenderingDeviceVulkan::sync() { local_device_processing = false; } +VmaPool RenderingDeviceVulkan::_find_or_create_small_allocs_pool(uint32_t p_mem_type_index) { + if (small_allocs_pools.has(p_mem_type_index)) { + return small_allocs_pools[p_mem_type_index]; + } + + print_verbose("Creating VMA small objects pool for memory type index " + itos(p_mem_type_index)); + + VmaPoolCreateInfo pci; + pci.memoryTypeIndex = p_mem_type_index; + pci.flags = 0; + pci.blockSize = 0; + pci.minBlockCount = 0; + pci.maxBlockCount = SIZE_MAX; + pci.priority = 0.5f; + pci.minAllocationAlignment = 0; + pci.pMemoryAllocateNext = nullptr; + VmaPool pool = VK_NULL_HANDLE; + VkResult res = vmaCreatePool(allocator, &pci, &pool); + small_allocs_pools[p_mem_type_index] = pool; // Don't try to create it again if failed the first time + ERR_FAIL_COND_V_MSG(res, pool, "vmaCreatePool failed with error " + itos(res) + "."); + + return pool; +} + void RenderingDeviceVulkan::_free_pending_resources(int p_frame) { //free in dependency usage order, so nothing weird happens //pipelines @@ -8716,9 +8870,9 @@ uint64_t RenderingDeviceVulkan::get_memory_usage(MemoryType p_type) const { } else if (p_type == MEMORY_TEXTURES) { return image_memory; } else { - VmaStats stats; - vmaCalculateStats(allocator, &stats); - return stats.total.usedBytes; + VmaTotalStatistics stats; + vmaCalculateStatistics(allocator, &stats); + return stats.total.statistics.allocationBytes; } } @@ -8817,18 +8971,6 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de vmaCreateAllocator(&allocatorInfo, &allocator); } - { //create pool for small objects - VmaPoolCreateInfo pci; - pci.flags = VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT; - pci.blockSize = 0; - pci.minBlockCount = 0; - pci.maxBlockCount = SIZE_MAX; - pci.priority = 0.5f; - pci.minAllocationAlignment = 0; - pci.pMemoryAllocateNext = nullptr; - vmaCreatePool(allocator, &pci, &small_allocs_pool); - } - frames = memnew_arr(Frame, frame_count); frame = 0; //create setup and frame buffers @@ -9297,7 +9439,11 @@ 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); } - vmaDestroyPool(allocator, small_allocs_pool); + while (small_allocs_pools.size()) { + Map<uint32_t, VmaPool>::Element *E = small_allocs_pools.front(); + vmaDestroyPool(allocator, E->get()); + small_allocs_pools.erase(E); + } vmaDestroyAllocator(allocator); while (vertex_formats.size()) { diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index 6510893196..126f6f8ad0 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -1016,7 +1016,8 @@ class RenderingDeviceVulkan : public RenderingDevice { void _free_pending_resources(int p_frame); VmaAllocator allocator = nullptr; - VmaPool small_allocs_pool = nullptr; + Map<uint32_t, VmaPool> small_allocs_pools; + VmaPool _find_or_create_small_allocs_pool(uint32_t p_mem_type_index); VulkanContext *context = nullptr; @@ -1037,6 +1038,7 @@ class RenderingDeviceVulkan : public RenderingDevice { public: virtual RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector<Vector<uint8_t>> &p_data = Vector<Vector<uint8_t>>()); virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture); + virtual RID texture_create_from_extension(TextureType p_type, DataFormat p_format, TextureSamples p_samples, uint64_t p_flags, uint64_t p_image, uint64_t p_width, uint64_t p_height, uint64_t p_depth, uint64_t p_layers); virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D); 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); diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index db3517ac97..3551b5d6c4 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -46,6 +46,8 @@ #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #define APP_SHORT_NAME "GodotEngine" +VulkanHooks *VulkanContext::vulkan_hooks = nullptr; + VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::_debug_messenger_callback( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, @@ -695,19 +697,27 @@ Error VulkanContext::_create_instance() { inst_info.pNext = &dbg_report_callback_create_info; } - VkResult err = vkCreateInstance(&inst_info, nullptr, &inst); - ERR_FAIL_COND_V_MSG(err == VK_ERROR_INCOMPATIBLE_DRIVER, ERR_CANT_CREATE, - "Cannot find a compatible Vulkan installable client driver (ICD).\n\n" - "vkCreateInstance Failure"); - ERR_FAIL_COND_V_MSG(err == VK_ERROR_EXTENSION_NOT_PRESENT, ERR_CANT_CREATE, - "Cannot find a specified extension library.\n" - "Make sure your layers path is set appropriately.\n" - "vkCreateInstance Failure"); - ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE, - "vkCreateInstance failed.\n\n" - "Do you have a compatible Vulkan installable client driver (ICD) installed?\n" - "Please look at the Getting Started guide for additional information.\n" - "vkCreateInstance Failure"); + VkResult err; + + if (vulkan_hooks) { + if (!vulkan_hooks->create_vulkan_instance(&inst_info, &inst)) { + return ERR_CANT_CREATE; + } + } else { + err = vkCreateInstance(&inst_info, nullptr, &inst); + ERR_FAIL_COND_V_MSG(err == VK_ERROR_INCOMPATIBLE_DRIVER, ERR_CANT_CREATE, + "Cannot find a compatible Vulkan installable client driver (ICD).\n\n" + "vkCreateInstance Failure"); + ERR_FAIL_COND_V_MSG(err == VK_ERROR_EXTENSION_NOT_PRESENT, ERR_CANT_CREATE, + "Cannot find a specified extension library.\n" + "Make sure your layers path is set appropriately.\n" + "vkCreateInstance Failure"); + ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE, + "vkCreateInstance failed.\n\n" + "Do you have a compatible Vulkan installable client driver (ICD) installed?\n" + "Please look at the Getting Started guide for additional information.\n" + "vkCreateInstance Failure"); + } inst_initialized = true; @@ -820,107 +830,122 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) { { 0, nullptr }, }; - // TODO: At least on Linux Laptops integrated GPUs fail with Vulkan in many instances. - // The device should really be a preference, but for now choosing a discrete GPU over the - // integrated one is better than the default. - int32_t device_index = -1; - int type_selected = -1; - print_verbose("Vulkan devices:"); - for (uint32_t i = 0; i < gpu_count; ++i) { - VkPhysicalDeviceProperties props; - vkGetPhysicalDeviceProperties(physical_devices[i], &props); - - bool present_supported = false; - - uint32_t device_queue_family_count = 0; - vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &device_queue_family_count, nullptr); - VkQueueFamilyProperties *device_queue_props = (VkQueueFamilyProperties *)malloc(device_queue_family_count * sizeof(VkQueueFamilyProperties)); - vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &device_queue_family_count, device_queue_props); - for (uint32_t j = 0; j < device_queue_family_count; j++) { - VkBool32 supports; - vkGetPhysicalDeviceSurfaceSupportKHR(physical_devices[i], j, p_surface, &supports); - if (supports && ((device_queue_props[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)) { - present_supported = true; - } else { - continue; - } - } - String name = props.deviceName; - String vendor = "Unknown"; - String dev_type; - switch (props.deviceType) { - case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: { - dev_type = "Discrete"; - } break; - case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: { - dev_type = "Integrated"; - } break; - case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: { - dev_type = "Virtual"; - } break; - case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_CPU: { - dev_type = "CPU"; - } break; - default: { - dev_type = "Other"; - } break; + if (vulkan_hooks) { + if (!vulkan_hooks->get_physical_device(&gpu)) { + return ERR_CANT_CREATE; } - uint32_t vendor_idx = 0; - while (vendor_names[vendor_idx].name != nullptr) { - if (props.vendorID == vendor_names[vendor_idx].id) { - vendor = vendor_names[vendor_idx].name; + + // not really needed but nice to print the correct entry + for (uint32_t i = 0; i < gpu_count; ++i) { + if (physical_devices[i] == gpu) { + device_index = i; break; } - vendor_idx++; } - free(device_queue_props); - print_verbose(" #" + itos(i) + ": " + vendor + " " + name + " - " + (present_supported ? "Supported" : "Unsupported") + ", " + dev_type); - - if (present_supported) { // Select first supported device of preferred type: Discrete > Integrated > Virtual > CPU > Other. + } else { + // TODO: At least on Linux Laptops integrated GPUs fail with Vulkan in many instances. + // The device should really be a preference, but for now choosing a discrete GPU over the + // integrated one is better than the default. + + int type_selected = -1; + print_verbose("Vulkan devices:"); + for (uint32_t i = 0; i < gpu_count; ++i) { + VkPhysicalDeviceProperties props; + vkGetPhysicalDeviceProperties(physical_devices[i], &props); + + bool present_supported = false; + + uint32_t device_queue_family_count = 0; + vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &device_queue_family_count, nullptr); + VkQueueFamilyProperties *device_queue_props = (VkQueueFamilyProperties *)malloc(device_queue_family_count * sizeof(VkQueueFamilyProperties)); + vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &device_queue_family_count, device_queue_props); + for (uint32_t j = 0; j < device_queue_family_count; j++) { + VkBool32 supports; + vkGetPhysicalDeviceSurfaceSupportKHR(physical_devices[i], j, p_surface, &supports); + if (supports && ((device_queue_props[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)) { + present_supported = true; + } else { + continue; + } + } + String name = props.deviceName; + String vendor = "Unknown"; + String dev_type; switch (props.deviceType) { case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: { - if (type_selected < 4) { - type_selected = 4; - device_index = i; - } + dev_type = "Discrete"; } break; case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: { - if (type_selected < 3) { - type_selected = 3; - device_index = i; - } + dev_type = "Integrated"; } break; case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: { - if (type_selected < 2) { - type_selected = 2; - device_index = i; - } + dev_type = "Virtual"; } break; case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_CPU: { - if (type_selected < 1) { - type_selected = 1; - device_index = i; - } + dev_type = "CPU"; } break; default: { - if (type_selected < 0) { - type_selected = 0; - device_index = i; - } + dev_type = "Other"; } break; } + uint32_t vendor_idx = 0; + while (vendor_names[vendor_idx].name != nullptr) { + if (props.vendorID == vendor_names[vendor_idx].id) { + vendor = vendor_names[vendor_idx].name; + break; + } + vendor_idx++; + } + free(device_queue_props); + print_verbose(" #" + itos(i) + ": " + vendor + " " + name + " - " + (present_supported ? "Supported" : "Unsupported") + ", " + dev_type); + + if (present_supported) { // Select first supported device of preffered type: Discrete > Integrated > Virtual > CPU > Other. + switch (props.deviceType) { + case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: { + if (type_selected < 4) { + type_selected = 4; + device_index = i; + } + } break; + case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: { + if (type_selected < 3) { + type_selected = 3; + device_index = i; + } + } break; + case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: { + if (type_selected < 2) { + type_selected = 2; + device_index = i; + } + } break; + case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_CPU: { + if (type_selected < 1) { + type_selected = 1; + device_index = i; + } + } break; + default: { + if (type_selected < 0) { + type_selected = 0; + device_index = i; + } + } break; + } + } } - } - int32_t user_device_index = Engine::get_singleton()->get_gpu_index(); // Force user selected GPU. - if (user_device_index >= 0 && user_device_index < (int32_t)gpu_count) { - device_index = user_device_index; - } + int32_t user_device_index = Engine::get_singleton()->get_gpu_index(); // Force user selected GPU. + if (user_device_index >= 0 && user_device_index < (int32_t)gpu_count) { + device_index = user_device_index; + } - ERR_FAIL_COND_V_MSG(device_index == -1, ERR_CANT_CREATE, "None of Vulkan devices supports both graphics and present queues."); + ERR_FAIL_COND_V_MSG(device_index == -1, ERR_CANT_CREATE, "None of Vulkan devices supports both graphics and present queues."); + + gpu = physical_devices[device_index]; + } - gpu = physical_devices[device_index]; free(physical_devices); /* Look for device extensions */ @@ -1148,8 +1173,14 @@ Error VulkanContext::_create_device() { sdevice.queueCreateInfoCount = 2; } - err = vkCreateDevice(gpu, &sdevice, nullptr, &device); - ERR_FAIL_COND_V(err, ERR_CANT_CREATE); + if (vulkan_hooks) { + if (!vulkan_hooks->create_vulkan_device(&sdevice, &device)) { + return ERR_CANT_CREATE; + } + } else { + err = vkCreateDevice(gpu, &sdevice, nullptr, &device); + ERR_FAIL_COND_V(err, ERR_CANT_CREATE); + } return OK; } @@ -1978,24 +2009,25 @@ Error VulkanContext::swap_buffers() { } VkSemaphore *semaphores_to_acquire = (VkSemaphore *)alloca(windows.size() * sizeof(VkSemaphore)); + VkPipelineStageFlags *pipe_stage_flags = (VkPipelineStageFlags *)alloca(windows.size() * sizeof(VkPipelineStageFlags)); uint32_t semaphores_to_acquire_count = 0; for (KeyValue<int, Window> &E : windows) { Window *w = &E.value; if (w->semaphore_acquired) { - semaphores_to_acquire[semaphores_to_acquire_count++] = w->image_acquired_semaphores[frame_index]; + semaphores_to_acquire[semaphores_to_acquire_count] = w->image_acquired_semaphores[frame_index]; + pipe_stage_flags[semaphores_to_acquire_count] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + semaphores_to_acquire_count++; } } - VkPipelineStageFlags pipe_stage_flags; VkSubmitInfo submit_info; submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submit_info.pNext = nullptr; - submit_info.pWaitDstStageMask = &pipe_stage_flags; - pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; submit_info.waitSemaphoreCount = semaphores_to_acquire_count; submit_info.pWaitSemaphores = semaphores_to_acquire; + submit_info.pWaitDstStageMask = pipe_stage_flags; submit_info.commandBufferCount = commands_to_submit; submit_info.pCommandBuffers = commands_ptr; submit_info.signalSemaphoreCount = 1; @@ -2011,7 +2043,7 @@ Error VulkanContext::swap_buffers() { // present queue before presenting, waiting for the draw complete // semaphore and signalling the ownership released semaphore when finished VkFence nullFence = VK_NULL_HANDLE; - pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + pipe_stage_flags[0] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; submit_info.waitSemaphoreCount = 1; submit_info.pWaitSemaphores = &draw_complete_semaphores[frame_index]; submit_info.commandBufferCount = 0; diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h index d4052666e3..8c0111714c 100644 --- a/drivers/vulkan/vulkan_context.h +++ b/drivers/vulkan/vulkan_context.h @@ -45,6 +45,8 @@ #include <vulkan/vulkan.h> #endif +#include "vulkan_hooks.h" + class VulkanContext { public: struct SubgroupCapabilities { @@ -86,6 +88,7 @@ private: FRAME_LAG = 2 }; + static VulkanHooks *vulkan_hooks; VkInstance inst = VK_NULL_HANDLE; VkPhysicalDevice gpu = VK_NULL_HANDLE; VkPhysicalDeviceProperties gpu_props; @@ -267,6 +270,8 @@ public: VkQueue get_graphics_queue() const; uint32_t get_graphics_queue_family_index() const; + static void set_vulkan_hooks(VulkanHooks *p_vulkan_hooks) { vulkan_hooks = p_vulkan_hooks; }; + void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height); int window_get_width(DisplayServer::WindowID p_window = 0); int window_get_height(DisplayServer::WindowID p_window = 0); diff --git a/drivers/vulkan/vulkan_hooks.h b/drivers/vulkan/vulkan_hooks.h new file mode 100644 index 0000000000..3f244b4d45 --- /dev/null +++ b/drivers/vulkan/vulkan_hooks.h @@ -0,0 +1,48 @@ +/*************************************************************************/ +/* vulkan_hooks.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef VULKAN_HOOKS_H +#define VULKAN_HOOKS_H + +#ifdef USE_VOLK +#include <volk.h> +#else +#include <vulkan/vulkan.h> +#endif + +class VulkanHooks { +public: + virtual bool create_vulkan_instance(const VkInstanceCreateInfo *p_vulkan_create_info, VkInstance *r_instance) { return false; }; + virtual bool get_physical_device(VkPhysicalDevice *r_device) { return false; }; + virtual bool create_vulkan_device(const VkDeviceCreateInfo *p_device_create_info, VkDevice *r_device) { return false; }; + virtual ~VulkanHooks(){}; +}; + +#endif |