diff --git a/renderdoc/CMakeLists.txt b/renderdoc/CMakeLists.txt index 887895e56..830183fa4 100644 --- a/renderdoc/CMakeLists.txt +++ b/renderdoc/CMakeLists.txt @@ -564,6 +564,12 @@ if(ENABLE_GL OR ENABLE_GLES) list(APPEND renderdoc_objects $) endif() +# pull in the NVIDIA folder +if(NOT ANDROID AND NOT APPLE AND (ENABLE_GL OR ENABLE_GLES)) + add_subdirectory(driver/ihv/nv) + list(APPEND renderdoc_objects $) +endif() + add_library(rdoc OBJECT ${sources}) target_compile_definitions(rdoc ${RDOC_DEFINITIONS}) target_include_directories(rdoc ${RDOC_INCLUDES}) diff --git a/renderdoc/driver/ihv/nv/CMakeLists.txt b/renderdoc/driver/ihv/nv/CMakeLists.txt new file mode 100644 index 000000000..0867fae6c --- /dev/null +++ b/renderdoc/driver/ihv/nv/CMakeLists.txt @@ -0,0 +1,14 @@ +set(sources + nv_counter_enumerator.cpp + nv_counter_enumerator.h + nv_vk_counters.cpp + nv_vk_counters.h) + +set(include_dirs + ${RDOC_INCLUDES} + "${CMAKE_CURRENT_SOURCE_DIR}/official/PerfSDK/redist/include" + "${CMAKE_CURRENT_SOURCE_DIR}/official/PerfSDK/redist/NvPerfUtility/include") + +add_library(rdoc_nv OBJECT ${sources}) +target_compile_definitions(rdoc_nv ${RDOC_DEFINITIONS}) +target_include_directories(rdoc_nv ${include_dirs}) diff --git a/renderdoc/driver/ihv/nv/NV.vcxproj b/renderdoc/driver/ihv/nv/NV.vcxproj index c58bf008b..eccc8f216 100644 --- a/renderdoc/driver/ihv/nv/NV.vcxproj +++ b/renderdoc/driver/ihv/nv/NV.vcxproj @@ -102,6 +102,7 @@ + @@ -109,6 +110,7 @@ + diff --git a/renderdoc/driver/ihv/nv/nv_vk_counters.cpp b/renderdoc/driver/ihv/nv/nv_vk_counters.cpp new file mode 100644 index 000000000..178d8ac19 --- /dev/null +++ b/renderdoc/driver/ihv/nv/nv_vk_counters.cpp @@ -0,0 +1,383 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2022 Baldur Karlsson + * + * 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. + ******************************************************************************/ + +#include "nv_vk_counters.h" + +#include "nv_counter_enumerator.h" + +#include "driver/vulkan/vk_core.h" +#include "driver/vulkan/vk_replay.h" + +#define NV_PERF_UTILITY_HIDE_VULKAN_SYMBOLS +#include "NvPerfRangeProfilerVulkan.h" +#include "NvPerfScopeExitGuard.h" +#include "NvPerfVulkan.h" + +struct NVVulkanCounters::Impl +{ + NVCounterEnumerator *CounterEnumerator; + bool LibraryNotFound = false; + + Impl() : CounterEnumerator(NULL) {} + ~Impl() + { + delete CounterEnumerator; + CounterEnumerator = NULL; + } + + bool TryInitializePerfSDK(WrappedVulkan *driver) + { + if(!NVCounterEnumerator::InitializeNvPerf()) + { + RDCERR("NvPerf library failed to initialize"); + LibraryNotFound = true; + + // NOTE: Return success here so that we can later show a message + // directing the user to download the Nsight Perf SDK library. + return true; + } + + if(!nv::perf::VulkanLoadDriver(Unwrap(driver->GetInstance()))) + { + RDCERR("NvPerf failed to load Vulkan driver"); + return false; + } + + if(!nv::perf::profiler::VulkanIsGpuSupported( + Unwrap(driver->GetInstance()), Unwrap(driver->GetPhysDev()), Unwrap(driver->GetDev()), + ObjDisp(driver->GetInstance())->GetInstanceProcAddr, + ObjDisp(driver->GetDev())->GetDeviceProcAddr)) + { + RDCERR("NvPerf does not support profiling on this GPU"); + return false; + } + + nv::perf::DeviceIdentifiers deviceIdentifiers = nv::perf::VulkanGetDeviceIdentifiers( + Unwrap(driver->GetInstance()), Unwrap(driver->GetPhysDev()), Unwrap(driver->GetDev()), + ObjDisp(driver->GetInstance())->GetInstanceProcAddr, + ObjDisp(driver->GetDev())->GetDeviceProcAddr); + if(!deviceIdentifiers.pChipName) + { + RDCERR("NvPerf could not determine chip name"); + return false; + } + + const size_t scratchBufferSize = + nv::perf::VulkanCalculateMetricsEvaluatorScratchBufferSize(deviceIdentifiers.pChipName); + if(!scratchBufferSize) + { + RDCERR("NvPerf could not determine scratch buffer size for metrics evaluation"); + return false; + } + + std::vector scratchBuffer; + scratchBuffer.resize(scratchBufferSize); + NVPW_MetricsEvaluator *pMetricsEvaluator = nv::perf::VulkanCreateMetricsEvaluator( + scratchBuffer.data(), scratchBuffer.size(), deviceIdentifiers.pChipName); + if(!pMetricsEvaluator) + { + RDCERR("NvPerf could not initialize metrics evaluator"); + return false; + } + + nv::perf::MetricsEvaluator metricsEvaluator(pMetricsEvaluator, std::move(scratchBuffer)); + + CounterEnumerator = new NVCounterEnumerator; + if(!CounterEnumerator->Init(std::move(metricsEvaluator))) + { + RDCERR("NvPerf could not initialize metrics evaluator"); + delete CounterEnumerator; + return false; + } + return true; + } + + static bool CanProfileEvent(const ActionDescription &actionnode) + { + if(!actionnode.children.empty()) + return false; // Only profile events for leaf nodes + + if(actionnode.events.empty()) + return false; // Skip nodes with no events + + if(!(actionnode.flags & (ActionFlags::Clear | ActionFlags::Drawcall | ActionFlags::Dispatch | + ActionFlags::Present | ActionFlags::Copy | ActionFlags::Resolve))) + return false; // Filter out events we cannot profile + + return true; + } + + static void RecurseDiscoverEvents(uint32_t &numEvents, const ActionDescription &actionnode) + { + for(size_t i = 0; i < actionnode.children.size(); i++) + { + RecurseDiscoverEvents(numEvents, actionnode.children[i]); + } + + if(!Impl::CanProfileEvent(actionnode)) + return; + + numEvents++; + } +}; + +NVVulkanCounters::NVVulkanCounters() : m_Impl(NULL) +{ +} + +NVVulkanCounters::~NVVulkanCounters() +{ + delete m_Impl; + m_Impl = NULL; +} + +bool NVVulkanCounters::Init(WrappedVulkan *driver) +{ + m_Impl = new Impl; + if(!m_Impl) + return false; + + const bool initSuccess = m_Impl->TryInitializePerfSDK(driver); + if(!initSuccess) + { + delete m_Impl; + m_Impl = NULL; + return false; + } + + return true; +} + +rdcarray NVVulkanCounters::EnumerateCounters() const +{ + if(m_Impl->LibraryNotFound) + { + return {GPUCounter::FirstNvidia}; + } + return m_Impl->CounterEnumerator->GetPublicCounterIds(); +} + +bool NVVulkanCounters::HasCounter(GPUCounter counterID) const +{ + if(m_Impl->LibraryNotFound) + { + return counterID == GPUCounter::FirstNvidia; + } + return m_Impl->CounterEnumerator->HasCounter(counterID); +} + +CounterDescription NVVulkanCounters::DescribeCounter(GPUCounter counterID) const +{ + if(m_Impl->LibraryNotFound) + { + RDCASSERT(counterID == GPUCounter::FirstNvidia); + // Dummy counter shows message directing user to download the Nsight Perf SDK library + return NVCounterEnumerator::LibraryNotFoundMessage(); + } + return m_Impl->CounterEnumerator->GetCounterDescription(counterID); +} + +struct VulkanNvidiaActionCallback final : public VulkanActionCallback +{ + VulkanNvidiaActionCallback(WrappedVulkan *driver) : m_driver(driver) + { + m_driver->SetActionCB(this); + } + ~VulkanNvidiaActionCallback() { m_driver->SetActionCB(NULL); } + void PreDraw(uint32_t eid, VkCommandBuffer cmd) final + { + rdcstr eidName = StringFormat::Fmt("%d", eid); + nv::perf::profiler::VulkanPushRange(Unwrap(cmd), eidName.c_str()); + } + + bool PostDraw(uint32_t eid, VkCommandBuffer cmd) final + { + nv::perf::profiler::VulkanPopRange(Unwrap(cmd)); + return false; + } + + void PostRedraw(uint32_t eid, VkCommandBuffer cmd) final {} + void PreDispatch(uint32_t eid, VkCommandBuffer cmd) final { PreDraw(eid, cmd); } + bool PostDispatch(uint32_t eid, VkCommandBuffer cmd) final { return PostDraw(eid, cmd); } + void PostRedispatch(uint32_t eid, VkCommandBuffer cmd) final {} + void PreMisc(uint32_t eid, ActionFlags flags, VkCommandBuffer cmd) final + { + if(flags & ActionFlags::PassBoundary) + return; + PreDraw(eid, cmd); + } + + bool PostMisc(uint32_t eid, ActionFlags flags, VkCommandBuffer cmd) final + { + if(flags & ActionFlags::PassBoundary) + return false; + return PostDraw(eid, cmd); + } + + void PostRemisc(uint32_t eid, ActionFlags flags, VkCommandBuffer cmd) final {} + void PreEndCommandBuffer(VkCommandBuffer cmd) final {} + void AliasEvent(uint32_t primary, uint32_t alias) final {} + bool SplitSecondary() final { return false; } + bool ForceLoadRPs() final { return false; } + void PreCmdExecute(uint32_t baseEid, uint32_t secondaryFirst, uint32_t secondaryLast, + VkCommandBuffer cmd) final + { + } + void PostCmdExecute(uint32_t baseEid, uint32_t secondaryFirst, uint32_t secondaryLast, + VkCommandBuffer cmd) final + { + } + WrappedVulkan *m_driver; +}; + +rdcarray NVVulkanCounters::FetchCounters(const rdcarray &counters, + WrappedVulkan *driver) +{ + if(m_Impl->LibraryNotFound) + { + return {}; + } + + uint32_t maxEID = driver->GetMaxEID(); + + uint32_t maxNumRanges = 0; + { + // replay the events to determine how many profile-able events there are + FrameRecord frameRecord = driver->GetReplay()->GetFrameRecord(); + for(size_t i = 0; i < frameRecord.actionList.size(); i++) + { + Impl::RecurseDiscoverEvents(maxNumRanges, frameRecord.actionList[i]); + } + } + + nv::perf::profiler::SessionOptions sessionOptions = {}; + sessionOptions.maxNumRanges = maxNumRanges; + sessionOptions.avgRangeNameLength = 16; + sessionOptions.numTraceBuffers = 1; + + nv::perf::profiler::RangeProfilerVulkan rangeProfiler; + + rdcarray results; + // TODO: For each Vulkan queue + { + if(!rangeProfiler.BeginSession(Unwrap(driver->GetInstance()), Unwrap(driver->GetPhysDev()), + Unwrap(driver->GetDev()), Unwrap(driver->GetQ()), + driver->GetQueueFamilyIndex(), sessionOptions, + ObjDisp(driver->GetInstance())->GetInstanceProcAddr, + ObjDisp(driver->GetDev())->GetDeviceProcAddr)) + { + RDCERR("NvPerf failed to start profiling session"); + return {}; // Failure + } + auto sessionGuard = nv::perf::ScopeExitGuard([&rangeProfiler]() { rangeProfiler.EndSession(); }); + + // Create counter configuration, and set it. + { + nv::perf::DeviceIdentifiers deviceIdentifiers = nv::perf::VulkanGetDeviceIdentifiers( + Unwrap(driver->GetInstance()), Unwrap(driver->GetPhysDev()), Unwrap(driver->GetDev()), + ObjDisp(driver->GetInstance())->GetInstanceProcAddr, + ObjDisp(driver->GetDev())->GetDeviceProcAddr); + NVPA_RawMetricsConfig *pRawMetricsConfig = + nv::perf::profiler::VulkanCreateRawMetricsConfig(deviceIdentifiers.pChipName); + if(!m_Impl->CounterEnumerator->CreateConfig(deviceIdentifiers.pChipName, pRawMetricsConfig, + counters)) + return {}; // Failure + } + + nv::perf::profiler::SetConfigParams setConfigParams; + setConfigParams.numNestingLevels = 1; + setConfigParams.numStatisticalSamples = 1; + m_Impl->CounterEnumerator->GetConfig( + setConfigParams.pConfigImage, setConfigParams.configImageSize, + setConfigParams.pCounterDataPrefix, setConfigParams.counterDataPrefixSize); + + size_t maxNumReplayPasses = + m_Impl->CounterEnumerator->GetMaxNumReplayPasses(setConfigParams.numNestingLevels); + RDCASSERT(maxNumReplayPasses > 0u); + + if(!rangeProfiler.EnqueueCounterCollection(setConfigParams)) + { + RDCERR("NvPerf failed to schedule counter collection"); + return {}; // Failure + } + + VulkanNvidiaActionCallback actionCallback(driver); + + std::vector counterDataImage; + for(size_t replayPass = 0;; ++replayPass) + { + if(!rangeProfiler.BeginPass()) + { + RDCERR("NvPerf failed to start counter collection pass"); + break; + } + + // replay the events to perform all the queries + uint32_t eventStartID = 0; + driver->ReplayLog(eventStartID, maxEID, eReplay_Full); + + if(!rangeProfiler.EndPass()) + { + RDCERR("NvPerf failed to end counter collection pass!"); + break; + } + + ObjDisp(driver->GetQ())->QueueWaitIdle(Unwrap(driver->GetQ())); + + nv::perf::profiler::DecodeResult decodeResult; + if(!rangeProfiler.DecodeCounters(decodeResult)) + { + RDCERR("NvPerf failed to decode counters in collection pass"); + break; + } + + if(decodeResult.allPassesDecoded) + { + counterDataImage = std::move(decodeResult.counterDataImage); + break; // success! + } + + if(replayPass >= maxNumReplayPasses - 1) + { + RDCERR("NvPerf exceeded the maximum expected number of replay passes"); + break; // Failure + } + } + + if(counterDataImage.empty()) + { + RDCERR("No data found in NvPerf counter data image"); + return {}; + } + + if(!m_Impl->CounterEnumerator->EvaluateMetrics(counterDataImage.data(), counterDataImage.size(), + results)) + { + RDCERR("NvPerf failed to evaluate metrics from counter data"); + return {}; + } + } + + return results; +} diff --git a/renderdoc/driver/ihv/nv/nv_vk_counters.h b/renderdoc/driver/ihv/nv/nv_vk_counters.h new file mode 100644 index 000000000..cee5f3af7 --- /dev/null +++ b/renderdoc/driver/ihv/nv/nv_vk_counters.h @@ -0,0 +1,49 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2022 Baldur Karlsson + * + * 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. + ******************************************************************************/ + +#pragma once + +#include "api/replay/data_types.h" +#include "api/replay/rdcarray.h" +#include "api/replay/replay_enums.h" + +class WrappedVulkan; + +class NVVulkanCounters final +{ +public: + NVVulkanCounters(); + ~NVVulkanCounters(); + + bool Init(WrappedVulkan *driver); + + rdcarray EnumerateCounters() const; + bool HasCounter(GPUCounter counterID) const; + CounterDescription DescribeCounter(GPUCounter counterID) const; + rdcarray FetchCounters(const rdcarray &counters, WrappedVulkan *driver); + +private: + struct Impl; + Impl *m_Impl; +}; diff --git a/renderdoc/driver/vulkan/vk_counters.cpp b/renderdoc/driver/vulkan/vk_counters.cpp index 134c75844..b21ac8025 100644 --- a/renderdoc/driver/vulkan/vk_counters.cpp +++ b/renderdoc/driver/vulkan/vk_counters.cpp @@ -34,6 +34,8 @@ #include "driver/ihv/amd/official/GPUPerfAPI/Include/gpu_perf_api_vk.h" #include "strings/string_utils.h" +#include "driver/ihv/nv/nv_vk_counters.h" + static uint32_t FromKHRCounter(GPUCounter counterID) { return (uint32_t)counterID - (uint32_t)GPUCounter::FirstVulkanExtended; @@ -169,6 +171,13 @@ rdcarray VulkanReplay::EnumerateCounters() ret.append(m_pAMDCounters->GetPublicCounterIds()); } +#if DISABLED(RDOC_ANDROID) && DISABLED(RDOC_ANDROID) + if(m_pNVCounters) + { + ret.append(m_pNVCounters->EnumerateCounters()); + } +#endif + return ret; } @@ -188,6 +197,15 @@ CounterDescription VulkanReplay::DescribeCounter(GPUCounter counterID) } } +#if DISABLED(RDOC_ANDROID) && DISABLED(RDOC_ANDROID) + /////NVIDIA////// + if(m_pNVCounters && m_pNVCounters->HasCounter(counterID)) + { + desc = m_pNVCounters->DescribeCounter(counterID); + return desc; + } +#endif + if(IsVulkanExtendedCounter(counterID)) { const VkPerformanceCounterKHR &khrCounter = m_KHRCounters[FromKHRCounter(counterID)]; @@ -852,6 +870,21 @@ rdcarray VulkanReplay::FetchCounters(const rdcarray & } } +#if DISABLED(RDOC_ANDROID) && DISABLED(RDOC_ANDROID) + if(m_pNVCounters) + { + // Filter out the NVIDIA counters + rdcarray nvCounters; + std::copy_if(counters.begin(), counters.end(), std::back_inserter(nvCounters), + [=](const GPUCounter &c) { return m_pNVCounters->HasCounter(c); }); + if(!nvCounters.empty()) + { + rdcarray results = m_pNVCounters->FetchCounters(nvCounters, m_pDriver); + ret.append(results); + } + } +#endif + rdcarray vkKHRCounters; std::copy_if(counters.begin(), counters.end(), std::back_inserter(vkKHRCounters), [](const GPUCounter &c) { return IsVulkanExtendedCounter(c); }); diff --git a/renderdoc/driver/vulkan/vk_debug.cpp b/renderdoc/driver/vulkan/vk_debug.cpp index 781a471f1..74244dbb1 100644 --- a/renderdoc/driver/vulkan/vk_debug.cpp +++ b/renderdoc/driver/vulkan/vk_debug.cpp @@ -30,6 +30,7 @@ #include "data/glsl_shaders.h" #include "driver/ihv/amd/amd_counters.h" #include "driver/ihv/amd/official/GPUPerfAPI/Include/gpu_perf_api_vk.h" +#include "driver/ihv/nv/nv_vk_counters.h" #include "driver/shaders/spirv/spirv_compile.h" #include "maths/camera.h" #include "maths/formatpacking.h" @@ -3026,29 +3027,44 @@ void VulkanReplay::CreateResources() if(!m_pDriver->GetReplay()->IsRemoteProxy() && Vulkan_HardwareCounters()) { - AMDCounters *counters = NULL; - GPUVendor vendor = m_pDriver->GetDriverInfo().Vendor(); if(vendor == GPUVendor::AMD || vendor == GPUVendor::Samsung) { RDCLOG("AMD GPU detected - trying to initialise AMD counters"); - counters = new AMDCounters(); + AMDCounters *counters = new AMDCounters(); + if(counters && counters->Init(AMDCounters::ApiType::Vk, (void *)&context)) + { + m_pAMDCounters = counters; + } + else + { + delete counters; + m_pAMDCounters = NULL; + } } +#if DISABLED(RDOC_ANDROID) && DISABLED(RDOC_ANDROID) + else if(vendor == GPUVendor::nVidia) + { + RDCLOG("NVIDIA GPU detected - trying to initialise NVIDIA counters"); + NVVulkanCounters *countersNV = new NVVulkanCounters(); + bool initSuccess = false; + if(countersNV && countersNV->Init(m_pDriver)) + { + m_pNVCounters = countersNV; + initSuccess = true; + } + else + { + delete countersNV; + } + RDCLOG("NVIDIA Vulkan counter initialisation: %s", initSuccess ? "SUCCEEDED" : "FAILED"); + } +#endif else { RDCLOG("%s GPU detected - no counters available", ToStr(vendor).c_str()); } - - if(counters && counters->Init(AMDCounters::ApiType::Vk, (void *)&context)) - { - m_pAMDCounters = counters; - } - else - { - delete counters; - m_pAMDCounters = NULL; - } } } @@ -3067,6 +3083,10 @@ void VulkanReplay::DestroyResources() m_PostVS.Destroy(m_pDriver); SAFE_DELETE(m_pAMDCounters); + +#if DISABLED(RDOC_ANDROID) && DISABLED(RDOC_ANDROID) + SAFE_DELETE(m_pNVCounters); +#endif } void VulkanReplay::GeneralMisc::Init(WrappedVulkan *driver, VkDescriptorPool descriptorPool) diff --git a/renderdoc/driver/vulkan/vk_replay.h b/renderdoc/driver/vulkan/vk_replay.h index aebf330e8..483f6b819 100644 --- a/renderdoc/driver/vulkan/vk_replay.h +++ b/renderdoc/driver/vulkan/vk_replay.h @@ -152,6 +152,8 @@ class VulkanResourceManager; struct VulkanStatePipeline; struct VulkanAMDActionCallback; +class NVVulkanCounters; + struct VulkanPostVSData { struct InstData @@ -792,6 +794,10 @@ private: VulkanAMDActionCallback *m_pAMDActionCallback = NULL; +#if DISABLED(RDOC_ANDROID) && DISABLED(RDOC_ANDROID) + NVVulkanCounters *m_pNVCounters = NULL; +#endif + rdcarray FetchCountersKHR(const rdcarray &counters); rdcarray m_KHRCounters; diff --git a/renderdoc/driver/vulkan/vk_resources.h b/renderdoc/driver/vulkan/vk_resources.h index 2beee755d..a278c6ce2 100644 --- a/renderdoc/driver/vulkan/vk_resources.h +++ b/renderdoc/driver/vulkan/vk_resources.h @@ -2161,7 +2161,7 @@ struct VkResourceRecord : public ResourceRecord public: enum { - NullResource = VK_NULL_HANDLE + NullResource = 0u }; static byte markerValue[32]; diff --git a/renderdoc/driver/vulkan/vk_win32.cpp b/renderdoc/driver/vulkan/vk_win32.cpp index d3776fb88..ec8811c77 100644 --- a/renderdoc/driver/vulkan/vk_win32.cpp +++ b/renderdoc/driver/vulkan/vk_win32.cpp @@ -127,6 +127,21 @@ void WrappedVulkan::AddRequiredExtensions(bool instance, rdcarray &exten if(!extensionList.contains(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) extensionList.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); } + if((supportedExtensions.find(VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME) == + supportedExtensions.end()) || + (supportedExtensions.find(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME) == + supportedExtensions.end())) + { + RDCWARN("Unsupported required instance extension for NVIDIA performance counters '%s'", + VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME); + } + else + { + if(!extensionList.contains(VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME)) + extensionList.push_back(VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME); + if(!extensionList.contains(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME)) + extensionList.push_back(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME); + } } }