VkGrUpscaler.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Gr/Vulkan/VkGrUpscaler.h>
  6. #include <AnKi/Gr/Vulkan/VkGrManager.h>
  7. #include <AnKi/Gr/Vulkan/VkFence.h>
  8. #include <AnKi/Gr/Vulkan/VkCommandBuffer.h>
  9. // Ngx specific
  10. #if ANKI_DLSS
  11. # include <ThirdParty/DlssSdk/sdk/include/nvsdk_ngx.h>
  12. # include <ThirdParty/DlssSdk/sdk/include/nvsdk_ngx_helpers.h>
  13. # include <ThirdParty/DlssSdk/sdk/include/nvsdk_ngx_vk.h>
  14. # include <ThirdParty/DlssSdk/sdk/include/nvsdk_ngx_helpers_vk.h>
  15. #endif
  16. namespace anki {
  17. GrUpscaler* GrUpscaler::newInstance(const GrUpscalerInitInfo& initInfo)
  18. {
  19. GrUpscalerImpl* impl = anki::newInstance<GrUpscalerImpl>(GrMemoryPool::getSingleton(), initInfo.getName());
  20. const Error err = impl->initInternal(initInfo);
  21. if(err)
  22. {
  23. deleteInstance(GrMemoryPool::getSingleton(), impl);
  24. impl = nullptr;
  25. }
  26. return impl;
  27. }
  28. GrUpscalerImpl::~GrUpscalerImpl()
  29. {
  30. #if ANKI_DLSS
  31. if(m_upscalerType == GrUpscalerType::kDlss2)
  32. {
  33. destroyDlss();
  34. }
  35. #endif
  36. }
  37. Error GrUpscalerImpl::initInternal(const GrUpscalerInitInfo& initInfo)
  38. {
  39. m_upscalerType = initInfo.m_upscalerType;
  40. #if ANKI_DLSS
  41. ANKI_ASSERT(initInfo.m_upscalerType == GrUpscalerType::kDlss2);
  42. ANKI_CHECK(initDlss(initInfo));
  43. #else
  44. ANKI_ASSERT(!"Not supported");
  45. #endif
  46. return Error::kNone;
  47. }
  48. // ==== DLSS ====
  49. #if ANKI_DLSS
  50. # define ANKI_NGX_CHECK(x_) \
  51. do \
  52. { \
  53. const NVSDK_NGX_Result result = x_; \
  54. if(NVSDK_NGX_FAILED(result)) \
  55. { \
  56. ANKI_VK_LOGE("DLSS failed to initialize %ls", GetNGXResultAsString(result)); \
  57. return Error::kFunctionFailed; \
  58. } \
  59. } while(0)
  60. static NVSDK_NGX_PerfQuality_Value getDlssQualityModeToNVQualityMode(GrUpscalerQualityMode mode)
  61. {
  62. static Array<NVSDK_NGX_PerfQuality_Value, U32(GrUpscalerQualityMode::kCount)> nvQualityModes = {
  63. NVSDK_NGX_PerfQuality_Value_MaxPerf, NVSDK_NGX_PerfQuality_Value_Balanced, NVSDK_NGX_PerfQuality_Value_MaxQuality};
  64. return nvQualityModes[mode];
  65. }
  66. Error GrUpscalerImpl::initDlss(const GrUpscalerInitInfo& initInfo)
  67. {
  68. const VkDevice vkdevice = getGrManagerImpl().getDevice();
  69. const VkPhysicalDevice vkphysicaldevice = getGrManagerImpl().getPhysicalDevice();
  70. const VkInstance vkinstance = getGrManagerImpl().getInstance();
  71. const U32 ngxAppId = 231313132; // Something random
  72. const WChar* appLogs = L"./";
  73. ANKI_NGX_CHECK(NVSDK_NGX_VULKAN_Init(ngxAppId, appLogs, vkinstance, vkphysicaldevice, vkdevice));
  74. m_ngxInitialized = true;
  75. ANKI_NGX_CHECK(NVSDK_NGX_VULKAN_GetCapabilityParameters(&m_ngxParameters));
  76. ANKI_ASSERT(m_ngxParameters);
  77. // Currently, the SDK and this sample are not in sync. The sample is a bit forward looking, in this case. This will
  78. // likely be resolved very shortly, and therefore, the code below should be thought of as needed for a smooth user
  79. // experience.
  80. # if defined(NVSDK_NGX_Parameter_SuperSampling_NeedsUpdatedDriver) && defined(NVSDK_NGX_Parameter_SuperSampling_MinDriverVersionMajor) \
  81. && defined(NVSDK_NGX_Parameter_SuperSampling_MinDriverVersionMinor)
  82. // If NGX Successfully initialized then it should set those flags in return
  83. I32 needsUpdatedDriver = 0;
  84. ANKI_NGX_CHECK(m_ngxParameters->Get(NVSDK_NGX_Parameter_SuperSampling_NeedsUpdatedDriver, &needsUpdatedDriver));
  85. if(needsUpdatedDriver)
  86. {
  87. ANKI_VK_LOGE("DLSS cannot be loaded due to outdated driver");
  88. return Error::kFunctionFailed;
  89. }
  90. # endif
  91. I32 dlssAvailable = 0;
  92. ANKI_NGX_CHECK(m_ngxParameters->Get(NVSDK_NGX_Parameter_SuperSampling_Available, &dlssAvailable));
  93. if(!dlssAvailable)
  94. {
  95. ANKI_VK_LOGE("NVIDIA DLSS not available on this hardware/platform");
  96. return Error::kFunctionFailed;
  97. }
  98. // Create the feature
  99. ANKI_CHECK(createDlssFeature(initInfo.m_sourceTextureResolution, initInfo.m_targetTextureResolution, initInfo.m_qualityMode));
  100. return Error::kNone;
  101. }
  102. Error GrUpscalerImpl::createDlssFeature(const UVec2& srcRes, const UVec2& dstRes, const GrUpscalerQualityMode quality)
  103. {
  104. NVSDK_NGX_PerfQuality_Value nvQuality = getDlssQualityModeToNVQualityMode(quality);
  105. F32 sharpness; // Deprecared in newer DLSS
  106. ANKI_NGX_CHECK(NGX_DLSS_GET_OPTIMAL_SETTINGS(
  107. m_ngxParameters, dstRes.x, dstRes.y, nvQuality, &m_recommendedSettings.m_optimalRenderSize.x, &m_recommendedSettings.m_optimalRenderSize.y,
  108. &m_recommendedSettings.m_dynamicMaximumRenderSize.x, &m_recommendedSettings.m_dynamicMaximumRenderSize.y,
  109. &m_recommendedSettings.m_dynamicMinimumRenderSize.x, &m_recommendedSettings.m_dynamicMinimumRenderSize.y, &sharpness));
  110. // Next create features (See NVSDK_NGX_DLSS_Feature_Flags in nvsdk_ngx_defs.h)
  111. const I32 dlssCreateFeatureFlags = NVSDK_NGX_DLSS_Feature_Flags_MVLowRes | NVSDK_NGX_DLSS_Feature_Flags_IsHDR; // TODO
  112. NVSDK_NGX_DLSS_Create_Params dlssCreateParams;
  113. memset(&dlssCreateParams, 0, sizeof(dlssCreateParams));
  114. dlssCreateParams.Feature.InWidth = srcRes.x;
  115. dlssCreateParams.Feature.InHeight = srcRes.y;
  116. dlssCreateParams.Feature.InTargetWidth = dstRes.x;
  117. dlssCreateParams.Feature.InTargetHeight = dstRes.y;
  118. dlssCreateParams.Feature.InPerfQualityValue = nvQuality;
  119. dlssCreateParams.InFeatureCreateFlags = dlssCreateFeatureFlags;
  120. // Create the feature with a tmp CmdBuffer
  121. CommandBufferInitInfo cmdbinit;
  122. cmdbinit.m_flags = CommandBufferFlag::kGeneralWork | CommandBufferFlag::kSmallBatch;
  123. CommandBufferPtr cmdb = getGrManagerImpl().newCommandBuffer(cmdbinit);
  124. CommandBufferImpl& cmdbImpl = static_cast<CommandBufferImpl&>(*cmdb);
  125. cmdbImpl.beginRecordingExt();
  126. const U32 creationNodeMask = 1;
  127. const U32 visibilityNodeMask = 1;
  128. ANKI_NGX_CHECK(
  129. NGX_VULKAN_CREATE_DLSS_EXT(cmdbImpl.getHandle(), creationNodeMask, visibilityNodeMask, &m_dlssFeature, m_ngxParameters, &dlssCreateParams));
  130. FencePtr fence;
  131. cmdb->endRecording();
  132. GrManager::getSingleton().submit(cmdb.get(), {}, &fence);
  133. fence->clientWait(60.0_sec);
  134. return Error::kNone;
  135. }
  136. void GrUpscalerImpl::destroyDlss()
  137. {
  138. if(m_dlssFeature)
  139. {
  140. NVSDK_NGX_VULKAN_ReleaseFeature(m_dlssFeature);
  141. m_dlssFeature = nullptr;
  142. }
  143. if(m_ngxParameters)
  144. {
  145. NVSDK_NGX_VULKAN_DestroyParameters(m_ngxParameters);
  146. m_ngxParameters = nullptr;
  147. }
  148. if(m_ngxInitialized)
  149. {
  150. NVSDK_NGX_VULKAN_Shutdown();
  151. m_ngxInitialized = false;
  152. }
  153. }
  154. #endif // ANKI_DLSS
  155. } // end namespace anki