Update to the latest Vulkan SDK 1.4.350

Update Vulkan API to `1.2` on Windows
Update Vulkan API to `1.1` on Android
This commit is contained in:
2026-06-01 14:19:09 +02:00
parent d181f8d726
commit f55ac81fe4
18 changed files with 222 additions and 117 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ description: Downloads and installs Vulkan SDK.
inputs:
vulkan-version:
description: 'Vulkan SDK release version (e.g. 1.2.198.1).'
default: '1.3.290.0'
default: '1.4.350.0'
required: false
runs:
using: "composite"
@@ -433,6 +433,7 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass
options.GenerateDebugData = data.Cache.Settings.Global.ShadersGenerateDebugData;
options.TreatWarningsAsErrors = false;
options.Output = &cacheStream;
options.Platform = data.Data.Tools->GetPlatform();
Array<String> includes;
#define COMPILE_PROFILE(profile, cacheChunk) \
@@ -535,7 +536,6 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass
#if PLATFORM_TOOLS_XBOX_SCARLETT
case BuildPlatform::XboxScarlett:
{
options.Platform = PlatformType::XboxScarlett;
const char* platformDefineName = "PLATFORM_XBOX_SCARLETT";
COMPILE_PROFILE(DirectX_SM6, SHADER_FILE_CHUNK_INTERNAL_D3D_SM6_CACHE);
break;
@@ -264,10 +264,13 @@ bool ShaderAssetBase::LoadShaderCache(ShaderCacheResult& result)
auto& platformDefine = options.Macros.AddOne();
#if PLATFORM_WINDOWS
platformDefine.Name = "PLATFORM_WINDOWS";
options.Platform = PlatformType::Windows;
#elif PLATFORM_LINUX
platformDefine.Name = "PLATFORM_LINUX";
options.Platform = PlatformType::Linux;
#elif PLATFORM_MAC
platformDefine.Name = "PLATFORM_MAC";
options.Platform = PlatformType::Mac;
#else
#error "Unknown platform."
#endif
@@ -188,6 +188,7 @@ bool ShaderCacheManagerService::Init()
int32 ShaderCacheVersion = -1;
int32 MaterialGraphVersion = -1;
int32 ParticleGraphVersion = -1;
int32 Platform = -1;
union
{
struct
@@ -210,6 +211,7 @@ bool ShaderCacheManagerService::Init()
ShaderCacheVersion = GPU_SHADER_CACHE_VERSION;
MaterialGraphVersion = MATERIAL_GRAPH_VERSION;
ParticleGraphVersion = PARTICLE_GPU_GRAPH_VERSION;
Platform = (int32)PLATFORM_TYPE;
Flags = 0;
#if USE_EDITOR
ShaderDebug = CommandLine::Options.ShaderDebug.IsTrue();
@@ -235,6 +237,7 @@ bool ShaderCacheManagerService::Init()
|| cacheVersion.ShaderCacheVersion != cacheVersionDefault.ShaderCacheVersion
|| cacheVersion.MaterialGraphVersion != cacheVersionDefault.MaterialGraphVersion
|| cacheVersion.ParticleGraphVersion != cacheVersionDefault.ParticleGraphVersion
|| cacheVersion.Platform != cacheVersionDefault.Platform
|| cacheVersion.Flags != cacheVersionDefault.Flags
)
{
@@ -12,7 +12,7 @@ void AndroidVulkanPlatform::GetInstanceExtensions(Array<const char*>& extensions
extensions.Add(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
}
void AndroidVulkanPlatform::GetDeviceExtensions(Array<const char*>& extensions, Array<const char*>& layers)
void AndroidVulkanPlatform::GetDeviceExtensions(Array<const char*>& extensions)
{
extensions.Add(VK_KHR_SURFACE_EXTENSION_NAME);
extensions.Add(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
@@ -6,6 +6,9 @@
#if GRAPHICS_API_VULKAN && PLATFORM_ANDROID
// Android has 99.4% of Vulkan 1.1 and API level 29 (Android 10.0)
#define VULKAN_API_VERSION VK_API_VERSION_1_1
// Support more backbuffers in case driver decides to use more
#define VULKAN_BACK_BUFFERS_COUNT_MAX 8
@@ -16,7 +19,7 @@ class AndroidVulkanPlatform : public VulkanPlatformBase
{
public:
static void GetInstanceExtensions(Array<const char*>& extensions, Array<const char*>& layers);
static void GetDeviceExtensions(Array<const char*>& extensions, Array<const char*>& layers);
static void GetDeviceExtensions(Array<const char*>& extensions);
static void CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* surface);
};
@@ -210,7 +210,11 @@ void GPUContextVulkan::AddImageBarrier(GPUTextureViewVulkan* handle, VkImageLayo
range.baseMipLevel = 0;
range.levelCount = mipLevels;
range.baseArrayLayer = 0;
#if VK_KHR_maintenance1
range.layerCount = VK_REMAINING_ARRAY_LAYERS; // maintenance9 could be enabled for per-layer masking
#else
range.layerCount = handle->Owner->ArraySlices;
#endif
AddImageBarrier(handle->Image, srcLayout, dstLayout, range, handle);
state.SetResourceState(dstLayout);
}
@@ -229,6 +233,10 @@ void GPUContextVulkan::AddImageBarrier(GPUTextureViewVulkan* handle, VkImageLayo
range.levelCount = 1;
range.baseArrayLayer = i / mipLevels;
range.layerCount = 1;
#if VK_KHR_maintenance1
if (handle->Owner->ArraySlices == 1)
range.layerCount = VK_REMAINING_ARRAY_LAYERS; // maintenance9 could be enabled for per-layer masking
#endif
AddImageBarrier(handle->Image, srcLayout, dstLayout, range, handle);
state.SetSubresourceState(i, dstLayout);
}
@@ -264,6 +272,10 @@ void GPUContextVulkan::AddImageBarrier(GPUTextureVulkan* texture, int32 mipSlice
range.levelCount = 1;
range.baseArrayLayer = arraySlice;
range.layerCount = 1;
#if VK_KHR_maintenance1
if (texture->IsVolume())
range.layerCount = VK_REMAINING_ARRAY_LAYERS; // maintenance9 could be enabled for per-layer masking
#endif
AddImageBarrier(texture->GetHandle(), srcLayout, dstLayout, range, nullptr);
state.SetSubresourceState(subresourceIndex, dstLayout);
}
@@ -285,6 +297,10 @@ void GPUContextVulkan::AddImageBarrier(GPUTextureVulkan* texture, VkImageLayout
range.levelCount = texture->MipLevels();
range.baseArrayLayer = 0;
range.layerCount = texture->ArraySize();
#if VK_KHR_maintenance1
if (texture->IsVolume())
range.layerCount = VK_REMAINING_ARRAY_LAYERS; // maintenance9 could be enabled for per-layer masking
#endif
AddImageBarrier(texture->GetHandle(), srcLayout, dstLayout, range, nullptr);
state.SetResourceState(dstLayout);
}
@@ -431,7 +447,7 @@ void GPUContextVulkan::BeginRenderPass()
PendingClear clear;
for (int32 i = 0; i < GPU_MAX_RT_BINDED; i++)
{
auto handle = _rtHandles[i];
auto handle = _rtTargets[i];
if (handle)
{
layout.RTVsFormats[i] = handle->GetFormat();
@@ -490,7 +506,7 @@ void GPUContextVulkan::BeginRenderPass()
}
else
{
handle = _rtHandles[0];
handle = _rtTargets[0];
#if !BUILD_RELEASE
if (!handle)
{
@@ -507,9 +523,8 @@ void GPUContextVulkan::BeginRenderPass()
layout.Layers = handle->Layers;
// Clear textures that are not bind to the render pass
for (auto& e : _pendingClears)
ManualClear(e);
_pendingClears.Clear();
if (_pendingClears.HasItems())
FlushManualClears();
// Get or create objects
auto renderPass = _device->GetOrCreateRenderPass(layout);
@@ -569,6 +584,17 @@ void GPUContextVulkan::ManualClear(const PendingClear& clear)
}
}
void GPUContextVulkan::FlushManualClears()
{
// Batch barriers
for (auto& clear : _pendingClears)
AddImageBarrier(clear.View, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
for (auto& clear : _pendingClears)
ManualClear(clear);
_pendingClears.Clear();
}
void GPUContextVulkan::UpdateDescriptorSets(const SpirvShaderDescriptorInfo& descriptorInfo, DescriptorSetWriterVulkan& dsWriter, bool& needsWrite)
{
for (uint32 i = 0; i < descriptorInfo.DescriptorTypesCount; i++)
@@ -736,6 +762,27 @@ void GPUContextVulkan::OnDrawCall()
ASSERT(pipelineState && pipelineState->IsValid());
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
// Flush pending image clears before binding descriptors but skip ones that are going to be used as render targets
// (they will be cleared in the render pass with proper loadOp and without extra barriers)
if (_pendingClears.HasItems())
{
auto rtHandles = ToSpan(_rtHandles, ARRAY_COUNT(_rtHandles));
for (auto& clear : _pendingClears)
{
if (!SpanContains(rtHandles, clear.View))
AddImageBarrier(clear.View, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
}
for (int32 i = 0; i < _pendingClears.Count(); i++)
{
auto& clear = _pendingClears.Get()[i];
if (!SpanContains(rtHandles, clear.View))
{
ManualClear(clear);
_pendingClears.RemoveAtKeepOrder(i--);
}
}
}
// End previous render pass if render targets layout was modified
if (_rtDirtyFlag && cmdBuffer->IsInsideRenderPass())
EndRenderPass();
@@ -837,7 +884,6 @@ void GPUContextVulkan::FrameBegin()
_currentState = nullptr;
_currentCompute = nullptr;
_vertexLayout = nullptr;
_rtDepth = nullptr;
Platform::MemoryClear(_rtHandles, sizeof(_rtHandles));
Platform::MemoryClear(_cbHandles, sizeof(_cbHandles));
Platform::MemoryClear(_srHandles, sizeof(_srHandles));
@@ -918,6 +964,17 @@ bool GPUContextVulkan::IsDepthBufferBinded()
void GPUContextVulkan::Clear(GPUTextureView* rt, const Color& color)
{
for (auto& e : _pendingClears)
{
if (e.View == rt)
{
// Use existing slot
Platform::MemoryCopy(e.Value.color.float32, color.Raw, sizeof(color.Raw));
return;
}
}
// Add a new entry
auto& clear = _pendingClears.AddOne();
clear.View = (GPUTextureViewVulkan*)rt;
Platform::MemoryCopy(clear.Value.color.float32, color.Raw, sizeof(color.Raw));
@@ -925,6 +982,18 @@ void GPUContextVulkan::Clear(GPUTextureView* rt, const Color& color)
void GPUContextVulkan::ClearDepth(GPUTextureView* depthBuffer, float depthValue, uint8 stencilValue)
{
for (auto& e : _pendingClears)
{
if (e.View == depthBuffer)
{
// Use existing slot
e.Value.depthStencil.depth = depthValue;
e.Value.depthStencil.stencil = stencilValue;
return;
}
}
// Add a new entry
auto& clear = _pendingClears.AddOne();
clear.View = (GPUTextureViewVulkan*)depthBuffer;
clear.Value.depthStencil.depth = depthValue;
@@ -1001,7 +1070,6 @@ void GPUContextVulkan::ResetRenderTarget()
_rtDirtyFlag = true;
_psDirtyFlag = true;
_rtCount = 0;
_rtDepth = nullptr;
Platform::MemoryClear(_rtHandles, sizeof(_rtHandles));
const auto cmdBuffer = _cmdBufferManager->GetActiveCmdBuffer();
@@ -1014,13 +1082,13 @@ void GPUContextVulkan::SetRenderTarget(GPUTextureView* rt)
{
const auto rtVulkan = static_cast<GPUTextureViewVulkan*>(rt);
if (_rtDepth != nullptr || _rtCount != 1 || _rtHandles[0] != rtVulkan)
if (_rtDepth != nullptr || _rtCount != 1 || _rtTargets[0] != rtVulkan)
{
_rtDirtyFlag = true;
_psDirtyFlag = true;
_rtCount = 1;
_rtDepth = nullptr;
_rtHandles[0] = rtVulkan;
_rtTargets[0] = rtVulkan;
}
}
@@ -1030,13 +1098,13 @@ void GPUContextVulkan::SetRenderTarget(GPUTextureView* depthBuffer, GPUTextureVi
const auto depthBufferVulkan = static_cast<GPUTextureViewVulkan*>(depthBuffer);
const auto rtCount = rtVulkan ? 1 : 0;
if (_rtDepth != depthBufferVulkan || _rtCount != rtCount || _rtHandles[0] != rtVulkan)
if (_rtDepth != depthBufferVulkan || _rtCount != rtCount || _rtTargets[0] != rtVulkan)
{
_rtDirtyFlag = true;
_psDirtyFlag = true;
_rtCount = rtCount;
_rtDepth = depthBufferVulkan;
_rtHandles[0] = rtVulkan;
_rtTargets[0] = rtVulkan;
}
}
@@ -1053,13 +1121,13 @@ void GPUContextVulkan::SetRenderTarget(GPUTextureView* depthBuffer, const Span<G
}
const int32 rtvsSize = sizeof(GPUTextureViewVulkan*) * rts.Length();
if (_rtDepth != depthBufferVulkan || _rtCount != rts.Length() || Platform::MemoryCompare(_rtHandles, rtvs, rtvsSize) != 0)
if (_rtDepth != depthBufferVulkan || _rtCount != rts.Length() || Platform::MemoryCompare(_rtTargets, rtvs, rtvsSize) != 0)
{
_rtDirtyFlag = true;
_psDirtyFlag = true;
_rtCount = rts.Length();
_rtDepth = depthBufferVulkan;
Platform::MemoryCopy(_rtHandles, rtvs, rtvsSize);
Platform::MemoryCopy(_rtTargets, rtvs, rtvsSize);
}
}
@@ -1486,11 +1554,7 @@ void GPUContextVulkan::FlushState()
if (cmdBuffer->IsInsideRenderPass())
EndRenderPass();
// Flush pending clears
for (auto& clear : _pendingClears)
ManualClear(clear);
_pendingClears.Clear();
FlushManualClears();
FlushBarriers();
}
@@ -2012,7 +2076,7 @@ void GPUContextVulkan::BeginDrawPass(GPUDrawPass& pass)
_drawPassCanClear = true;
_rtCount = pass.RenderTargetsCount;
_rtDepth = (GPUTextureViewVulkan*)pass.DepthBuffer;
Platform::MemoryCopy(_rtHandles, pass.RenderTargets, pass.RenderTargetsCount * sizeof(void*));
Platform::MemoryCopy(_rtTargets, pass.RenderTargets, pass.RenderTargetsCount * sizeof(void*));
}
void GPUContextVulkan::EndDrawPass()
@@ -96,8 +96,15 @@ private:
GPUPipelineStateVulkan* _currentState;
GPUShaderProgramCSVulkan* _currentCompute;
GPUVertexLayoutVulkan* _vertexLayout;
GPUTextureViewVulkan* _rtDepth;
GPUTextureViewVulkan* _rtHandles[GPU_MAX_RT_BINDED];
union
{
struct
{
GPUTextureViewVulkan* _rtDepth;
GPUTextureViewVulkan* _rtTargets[GPU_MAX_RT_BINDED];
};
GPUTextureViewVulkan* _rtHandles[GPU_MAX_RT_BINDED + 1];
};
DescriptorOwnerResourceVulkan* _cbHandles[GPU_MAX_CB_BINDED];
DescriptorOwnerResourceVulkan* _srHandles[GPU_MAX_SR_BINDED];
DescriptorOwnerResourceVulkan* _uaHandles[GPU_MAX_UA_BINDED];
@@ -157,6 +164,7 @@ public:
private:
bool FindClear(const GPUTextureViewVulkan* view, PendingClear& clear);
void ManualClear(const PendingClear& clear);
void FlushManualClears();
void UpdateDescriptorSets(const struct SpirvShaderDescriptorInfo& descriptorInfo, class DescriptorSetWriterVulkan& dsWriter, bool& needsWrite);
void UpdateDescriptorSets(ComputePipelineStateVulkan* pipelineState);
void OnDrawCall();
@@ -434,7 +434,7 @@ void GPUDeviceVulkan::GetInstanceLayersAndExtensions(Array<const char*>& outInst
}
}
void GPUDeviceVulkan::GetDeviceExtensionsAndLayers(VkPhysicalDevice gpu, Array<const char*>& outDeviceExtensions, Array<const char*>& outDeviceLayers)
void GPUDeviceVulkan::GetDeviceExtensions(VkPhysicalDevice gpu, Array<const char*>& outDeviceExtensions)
{
Array<LayerExtension> deviceLayerExtensions;
deviceLayerExtensions.AddDefault(1);
@@ -495,70 +495,19 @@ void GPUDeviceVulkan::GetDeviceExtensionsAndLayers(VkPhysicalDevice gpu, Array<c
{
IsDebugToolAttached = true;
}
#if VULKAN_USE_DEBUG_LAYER
bool hasKhronosStandardValidationLayer = false, hasLunargStandardValidationLayer = false;
#if VULKAN_USE_KHRONOS_STANDARD_VALIDATION
const char* vkLayerKhronosValidation = "VK_LAYER_KHRONOS_validation";
hasKhronosStandardValidationLayer = ContainsLayer(deviceLayerExtensions, vkLayerKhronosValidation);
if (hasKhronosStandardValidationLayer && _debugLayer)
{
outDeviceLayers.Add(vkLayerKhronosValidation);
}
#endif
#if VULKAN_USE_LUNARG_STANDARD_VALIDATION
if (!hasKhronosStandardValidationLayer && _debugLayer)
{
const char* vkLayerLunargStandardValidation = "VK_LAYER_LUNARG_standard_validation";
hasLunargStandardValidationLayer = ContainsLayer(deviceLayerExtensions, vkLayerLunargStandardValidation);
if (hasLunargStandardValidationLayer)
{
outDeviceLayers.Add(vkLayerLunargStandardValidation);
}
}
#endif
if (!hasKhronosStandardValidationLayer && !hasLunargStandardValidationLayer && _debugLayer)
{
for (uint32 i = 0; GValidationLayers[i] != nullptr; i++)
{
const char* validationLayer = GValidationLayers[i];
if (ContainsLayer(deviceLayerExtensions, validationLayer))
{
outDeviceLayers.Add(validationLayer);
}
}
}
#endif
// Find all extensions
Array<const char*> availableExtensions;
availableExtensions.Resize(deviceLayerExtensions[0].Extensions.Count());
for (int32 i = 0; i < deviceLayerExtensions[0].Extensions.Count(); i++)
{
for (int32 i = 0; i < deviceLayerExtensions[0].Extensions.Count(); i++)
{
availableExtensions.Add(deviceLayerExtensions[0].Extensions[i].extensionName);
}
for (int32 layerIndex = 0; layerIndex < outDeviceLayers.Count(); layerIndex++)
{
int32 findLayerIndex;
for (findLayerIndex = 1; findLayerIndex < deviceLayerExtensions.Count(); findLayerIndex++)
{
if (!StringUtils::Compare(deviceLayerExtensions[findLayerIndex].Layer.layerName, outDeviceLayers[layerIndex]))
{
break;
}
}
if (findLayerIndex < deviceLayerExtensions.Count())
{
deviceLayerExtensions[findLayerIndex].GetExtensions(availableExtensions);
}
}
availableExtensions[i] = deviceLayerExtensions[0].Extensions[i].extensionName;
}
TrimDuplicates(availableExtensions);
// Pick extensions to use
Array<const char*> platformExtensions;
VulkanPlatform::GetDeviceExtensions(platformExtensions, outDeviceLayers);
VulkanPlatform::GetDeviceExtensions(platformExtensions);
for (const char* extension : platformExtensions)
{
if (ListContains(availableExtensions, extension))
@@ -583,15 +532,6 @@ void GPUDeviceVulkan::GetDeviceExtensionsAndLayers(VkPhysicalDevice gpu, Array<c
LOG(Info, "- {0}", String(extension));
}
}
if (outDeviceLayers.HasItems())
{
LOG(Info, "Using device layers:");
for (const char* layer : outDeviceLayers)
{
LOG(Info, "- {0}", String(layer));
}
}
}
void GPUDeviceVulkan::ParseOptionalDeviceExtensions(const Array<const char*>& deviceExtensions)
@@ -130,6 +130,11 @@ static VKAPI_ATTR VkBool32 VKAPI_PTR DebugReportFunction(VkDebugReportFlagsEXT m
#if VK_EXT_debug_utils
#if GPU_ENABLE_DEBUG_LAYER
#include "Engine/Threading/ThreadLocal.h"
extern ThreadLocal<const GPUShaderProgramInitializer*> CurrentVulkanShaderLoading;
#endif
static VKAPI_ATTR VkBool32 VKAPI_PTR DebugUtilsCallback(VkDebugUtilsMessageSeverityFlagBitsEXT msgSeverity, VkDebugUtilsMessageTypeFlagsEXT msgType, const VkDebugUtilsMessengerCallbackDataEXT* callbackData, void* userData)
{
// Ignore some errors
@@ -149,6 +154,7 @@ static VKAPI_ATTR VkBool32 VKAPI_PTR DebugUtilsCallback(VkDebugUtilsMessageSever
case -1539028524: // SortedIndices is null so Vulkan backend sets it to default R32_SFLOAT format which is not good for UINT format of the buffer
case -1810835948: // SortedIndices is null so Vulkan backend sets it to default R32_SFLOAT format which is not good for UINT format of the buffer
case -1621360350: // VkFramebufferCreateInfo attachment #0 has a layer count (1) smaller than the corresponding framebuffer layer count (64). The Vulkan spec states: If flags does not include VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each element of pAttachments that is used as an input, color, resolve, or depth/stencil attachment by renderPass must have been created with a VkImageViewCreateInfo::subresourceRange.layerCount greater than or equal to layers
case -1744492148: // pCreateInfos[0] Inside [VK_SHADER_STAGE_FRAGMENT_BIT], it writes to [Output variable, Location 3], but there is no VkSubpassDescription::pColorAttachments[3] and this write is unused.
return VK_FALSE;
}
break;
@@ -158,6 +164,7 @@ static VKAPI_ATTR VkBool32 VKAPI_PTR DebugUtilsCallback(VkDebugUtilsMessageSever
case 0: // Vertex shader writes to output location 0.0 which is not consumed by fragment shader
case 558591440: // preTransform doesn't match the currentTransform returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR, the presentation engine will transform the image content as part of the presentation operation. TODO: implement preTransform for Android to improve swapchain presentation performance
case 101294395: // Vertex shader writes to output location 0.0 which is not consumed by fragment shader
case -937765618: // pCreateInfos[0] (SPIR-V Interface) [VK_SHADER_STAGE_VERTEX_BIT] has an Output value declared at Location 1 Component 0, but there is no corresponding Input declared in [VK_SHADER_STAGE_FRAGMENT_BIT].
return VK_FALSE;
}
break;
@@ -240,10 +247,14 @@ static VKAPI_ATTR VkBool32 VKAPI_PTR DebugUtilsCallback(VkDebugUtilsMessageSever
LOG(Info, "[Vulkan] {0} {1}:{2} {3}", type, severity, callbackData->messageIdNumber, message);
}
#if !BUILD_RELEASE
#if GPU_ENABLE_DEBUG_LAYER
if (GPUDevice::Instance)
{
if (auto* context = (GPUContextVulkan*)GPUDevice::Instance->GetMainContext())
if (auto* shaderInitializer = CurrentVulkanShaderLoading.Get())
{
LOG(Warning, "[Vulkan] Error during loading shader '{}' from '{}'", String(shaderInitializer->Name), String(shaderInitializer->Owner->GetName()));
}
else if (auto* context = (GPUContextVulkan*)GPUDevice::Instance->GetMainContext())
{
if (auto* state = (GPUPipelineStateVulkan*)context->GetState())
{
@@ -999,13 +1010,13 @@ GPUDeviceVulkan::GPUDeviceVulkan(ShaderProfile shaderProfile, GPUAdapterVulkan*
GPUDevice* GPUDeviceVulkan::Create()
{
#if !USE_EDITOR && (PLATFORM_WINDOWS || PLATFORM_LINUX)
auto settings = PlatformSettings::Get();
if (!settings->SupportVulkan)
{
// Skip if there is no support
LOG(Warning, "Cannot use Vulkan (support disabled).");
return nullptr;
}
auto settings = PlatformSettings::Get();
if (!settings->SupportVulkan)
{
// Skip if there is no support
LOG(Warning, "Cannot use Vulkan (support disabled).");
return nullptr;
}
#endif
VkResult result;
@@ -1225,10 +1236,19 @@ GPUDevice* GPUDeviceVulkan::Create()
}
}
}
ASSERT(adapters[selectedAdapterIndex].IsValid());
GPUAdapterVulkan& selectedAdapter = adapters[selectedAdapterIndex];
ASSERT(selectedAdapter.IsValid());
if (VK_VERSION_MAJOR(selectedAdapter.GpuProps.apiVersion) < VK_VERSION_MAJOR(VULKAN_API_VERSION) || VK_VERSION_MINOR(selectedAdapter.GpuProps.apiVersion) < VK_VERSION_MINOR(VULKAN_API_VERSION))
{
#if PLATFORM_DESKTOP
LOG(Fatal, "Failed to use GPU '{}' with Vulkan API {}.{} which is lower than required {}.{}.\nCheck your video driver version for update to the latest one.", selectedAdapter.Description, VK_VERSION_MAJOR(selectedAdapter.GpuProps.apiVersion), VK_VERSION_MINOR(selectedAdapter.GpuProps.apiVersion), VK_VERSION_MAJOR(VULKAN_API_VERSION), VK_VERSION_MINOR(VULKAN_API_VERSION));
#else
LOG(Fatal, "Failed to use GPU '{}' with Vulkan API {}.{} which is lower than required {}.{}.\nCheck your system for updates.", selectedAdapter.Description, VK_VERSION_MAJOR(selectedAdapter.GpuProps.apiVersion), VK_VERSION_MINOR(selectedAdapter.GpuProps.apiVersion), VK_VERSION_MAJOR(VULKAN_API_VERSION), VK_VERSION_MINOR(VULKAN_API_VERSION));
#endif
}
// Create device
auto device = New<GPUDeviceVulkan>(ShaderProfile::Vulkan_SM5, New<GPUAdapterVulkan>(adapters[selectedAdapterIndex]));
auto device = New<GPUDeviceVulkan>(ShaderProfile::Vulkan_SM5, New<GPUAdapterVulkan>(selectedAdapter));
if (device->Init())
{
LOG(Warning, "Graphics Device init failed");
@@ -1616,8 +1636,7 @@ bool GPUDeviceVulkan::Init()
// Get extensions and layers
Array<const char*> deviceExtensions;
Array<const char*> validationLayers;
GetDeviceExtensionsAndLayers(gpu, deviceExtensions, validationLayers);
GetDeviceExtensions(gpu, deviceExtensions);
ParseOptionalDeviceExtensions(deviceExtensions);
// Setup device info
@@ -1625,8 +1644,6 @@ bool GPUDeviceVulkan::Init()
RenderToolsVulkan::ZeroStruct(deviceInfo, VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO);
deviceInfo.enabledExtensionCount = deviceExtensions.Count();
deviceInfo.ppEnabledExtensionNames = deviceExtensions.Get();
deviceInfo.enabledLayerCount = validationLayers.Count();
deviceInfo.ppEnabledLayerNames = deviceInfo.enabledLayerCount > 0 ? validationLayers.Get() : nullptr;
// Setup queues info
Array<VkDeviceQueueCreateInfo> queueFamilyInfos;
@@ -1769,7 +1786,7 @@ bool GPUDeviceVulkan::Init()
limits.HasInstancing = true;
limits.HasVolumeTextureRendering = true;
limits.HasDrawIndirect = PhysicalDeviceLimits.maxDrawIndirectCount >= 1;
limits.HasAppendConsumeBuffers = false; // TODO: add Append Consume buffers support for Vulkan
limits.HasAppendConsumeBuffers = false;
limits.HasDepthClip = PhysicalDeviceFeatures.depthClamp;
limits.HasDepthBounds = PhysicalDeviceFeatures.depthBounds;
limits.HasDepthAsSRV = true;
@@ -1877,7 +1894,9 @@ bool GPUDeviceVulkan::Init()
// Initialize memory allocator
{
VmaVulkanFunctions vulkanFunctions;
Platform::MemoryClear(&vulkanFunctions, sizeof(vulkanFunctions));
#define INIT_FUNC(name) vulkanFunctions.name = name
#define INIT_FUNC_EXTENSION(name, extension) vulkanFunctions.name = name; if (!vulkanFunctions.name) vulkanFunctions.name = extension
INIT_FUNC(vkGetPhysicalDeviceProperties);
INIT_FUNC(vkGetPhysicalDeviceMemoryProperties);
INIT_FUNC(vkAllocateMemory);
@@ -1895,16 +1914,28 @@ bool GPUDeviceVulkan::Init()
INIT_FUNC(vkCreateImage);
INIT_FUNC(vkDestroyImage);
INIT_FUNC(vkCmdCopyBuffer);
#if VMA_DEDICATED_ALLOCATION
#if PLATFORM_SWITCH
vulkanFunctions.vkGetBufferMemoryRequirements2KHR = vkGetBufferMemoryRequirements2;
vulkanFunctions.vkGetImageMemoryRequirements2KHR = vkGetImageMemoryRequirements2;
#else
INIT_FUNC(vkGetBufferMemoryRequirements2KHR);
INIT_FUNC(vkGetImageMemoryRequirements2KHR);
#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
INIT_FUNC_EXTENSION(vkGetBufferMemoryRequirements2KHR, vkGetBufferMemoryRequirements2);
INIT_FUNC_EXTENSION(vkGetImageMemoryRequirements2KHR, vkGetImageMemoryRequirements2);
#endif
#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000
INIT_FUNC_EXTENSION(vkBindBufferMemory2KHR, vkBindBufferMemory2);
INIT_FUNC_EXTENSION(vkBindImageMemory2KHR, vkBindImageMemory2);
#endif
#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000
INIT_FUNC_EXTENSION(vkGetPhysicalDeviceMemoryProperties2KHR, vkGetPhysicalDeviceMemoryProperties2);
#endif
#if VMA_KHR_MAINTENANCE4 || VMA_VULKAN_VERSION >= 1003000
INIT_FUNC_EXTENSION(vkGetDeviceBufferMemoryRequirements, vkGetDeviceBufferMemoryRequirementsKHR);
INIT_FUNC_EXTENSION(vkGetDeviceImageMemoryRequirements, vkGetDeviceImageMemoryRequirementsKHR);
#endif
#endif
#undef INIT_FUNC
#undef INIT_FUNC_EXTENSION
VmaAllocatorCreateInfo allocatorInfo = {};
allocatorInfo.vulkanApiVersion = VULKAN_API_VERSION;
allocatorInfo.physicalDevice = gpu;
@@ -396,7 +396,7 @@ public:
private:
static void GetInstanceLayersAndExtensions(Array<const char*>& outInstanceExtensions, Array<const char*>& outInstanceLayers, bool& outDebugUtils, bool useDebugLayer = false);
void GetDeviceExtensionsAndLayers(VkPhysicalDevice gpu, Array<const char*>& outDeviceExtensions, Array<const char*>& outDeviceLayers);
void GetDeviceExtensions(VkPhysicalDevice gpu, Array<const char*>& outDeviceExtensions);
static void ParseOptionalDeviceExtensions(const Array<const char*>& deviceExtensions);
public:
@@ -101,6 +101,11 @@ void UniformBufferUploaderVulkan::OnReleaseGPU()
}
}
#if GPU_ENABLE_DEBUG_LAYER
#include "Engine/Threading/ThreadLocal.h"
ThreadLocal<const GPUShaderProgramInitializer*> CurrentVulkanShaderLoading;
#endif
GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, Span<byte> bytecode, MemoryReadStream& stream)
{
// Extract the SPIR-V shader header from the cache
@@ -146,8 +151,14 @@ GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, cons
validationInfo.validationCache = _device->ValidationCache;
createInfo.pNext = &validationInfo;
}
#endif
#if GPU_ENABLE_DEBUG_LAYER
CurrentVulkanShaderLoading = &initializer;
#endif
VALIDATE_VULKAN_RESULT(vkCreateShaderModule(_device->Device, &createInfo, nullptr, &shaderModule));
#if GPU_ENABLE_DEBUG_LAYER
CurrentVulkanShaderLoading = nullptr;
#endif
#if GPU_ENABLE_RESOURCE_NAMING
VK_SET_DEBUG_NAME(_device, shaderModule, VK_OBJECT_TYPE_SHADER_MODULE, initializer.Name.GetText());
#endif
@@ -94,6 +94,11 @@ void GPUTextureViewVulkan::Init(GPUDeviceVulkan* device, ResourceOwnerVulkan* ow
}
VALIDATE_VULKAN_RESULT(vkCreateImageView(device->Device, &Info, nullptr, &View));
#if VK_KHR_maintenance1
if (arraySize == 1 && extent.depth > 1)
range.layerCount = VK_REMAINING_ARRAY_LAYERS; // without maintenance9 for per-layer masking all layers need to be enabled with a special value
#endif
}
VkImageView GPUTextureViewVulkan::GetFramebufferView()
@@ -119,6 +124,7 @@ VkImageView GPUTextureViewVulkan::GetFramebufferView()
// Use an additional view for that case with modified level count to 1.
VkImageViewCreateInfo createInfo = Info;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.layerCount = 1;
VALIDATE_VULKAN_RESULT(vkCreateImageView(Device->Device, &createInfo, nullptr, &ViewFramebuffer));
}
else
@@ -29,7 +29,7 @@ public:
{
}
static void GetDeviceExtensions(Array<const char*>& extensions, Array<const char*>& layers)
static void GetDeviceExtensions(Array<const char*>& extensions)
{
}
@@ -6,6 +6,7 @@
#if GRAPHICS_API_VULKAN && PLATFORM_WIN32
#define VULKAN_API_VERSION VK_API_VERSION_1_2
#define VULKAN_USE_PLATFORM_WIN32_KHR 1
#define VULKAN_USE_PLATFORM_WIN32_KHX 1
#define VULKAN_USE_CREATE_WIN32_SURFACE 1
+1 -4
View File
@@ -189,12 +189,9 @@ void GBufferPass::Fill(RenderContext& renderContext, GPUTexture* lightBuffer)
context->Clear(renderContext.Buffers->GBuffer3->View(), Color::Transparent);
}
// Ensure to have valid data
// Skip when resources are not loaded yet
if (checkIfSkipPass())
{
// Resources are missing. Do not perform rendering.
return;
}
#if USE_EDITOR
// Special debug drawing
@@ -945,13 +945,45 @@ bool ShaderCompilerVulkan::OnCompileBegin()
void ShaderCompilerVulkan::InitParsing(ShaderCompilationContext* context, glslang::TShader& shader)
{
// Pick Vulkan version based on target platform
// Based on: https://docs.vulkan.org/guide/latest/versions.html#_spir_v
glslang::EShTargetClientVersion targetVulkan;
glslang::EShTargetLanguageVersion targetLang;
switch (context->Options->Platform)
{
case PlatformType::Windows:
// TODO: update glslang and try Vulkan 1.2 with SPIR-V 1.5
targetVulkan = glslang::EShTargetVulkan_1_1;
targetLang = glslang::EShTargetSpv_1_2;
break;
case PlatformType::Android:
targetVulkan = glslang::EShTargetVulkan_1_1;
targetLang = glslang::EShTargetSpv_1_2;
break;
case PlatformType::Switch:
// TODO: update glslang and try Vulkan 1.3 with SPIR-V 1.6
targetVulkan = glslang::EShTargetVulkan_1_1;
targetLang = glslang::EShTargetSpv_1_2;
break;
case PlatformType::Mac:
case PlatformType::iOS:
// TODO: update glslang and try Vulkan 1.4 with SPIR-V 1.6
targetVulkan = glslang::EShTargetVulkan_1_1;
targetLang = glslang::EShTargetSpv_1_2;
break;
default:
targetVulkan = glslang::EShTargetVulkan_1_0;
targetLang = glslang::EShTargetSpv_1_0;
break;
}
shader.setInvertY(true);
//shader.setAutoMapLocations(true);
//shader.setAutoMapBindings(true);
//shader.setShiftBinding(glslang::TResourceType::EResUav, 500);
shader.setHlslIoMapping(true);
shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0);
shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0);
shader.setEnvClient(glslang::EShClientVulkan, targetVulkan);
shader.setEnvTarget(glslang::EShTargetSpv, targetLang);
}
void ShaderCompilerVulkan::InitCodegen(ShaderCompilationContext* context, glslang::SpvOptions& spvOptions)
+6
View File
@@ -54,6 +54,12 @@ public:
GetBucket().Value = value;
}
FORCE_INLINE ThreadLocal& operator=(const T& value)
{
GetBucket().Value = value;
return *this;
}
int32 Count() const
{
int32 result = 0;