Add runtime RenderDoc support for Windows dx12/vulkan via --enableRenderDoc option
- RenderDoc is disabled when building the monolithic build - The installation path is inferred on Windows, but may be overridden on Windows/Linux via the ATOM_RENDERDOC_PATH environment variable - Linux support may work, but I have no means to test it - Android support shouldn't be difficult to add, but requires a renderdoc_android.cmake file that understands how the RenderDoc package is distributed as part of the Android toolchain Signed-off-by: Jeremy Ong <jcong@amazon.com>
This commit is contained in:
@@ -10,6 +10,23 @@ ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${P
|
||||
|
||||
include(${pal_dir}/AtomRHITests_traits_${PAL_PLATFORM_NAME_LOWERCASE}.cmake)
|
||||
|
||||
set(RENDERDOC_CMAKE ${CMAKE_CURRENT_SOURCE_DIR}/${pal_dir}/renderdoc_${PAL_PLATFORM_NAME_LOWERCASE}.cmake)
|
||||
if(EXISTS ${RENDERDOC_CMAKE})
|
||||
include(${RENDERDOC_CMAKE})
|
||||
endif()
|
||||
|
||||
if(TARGET "3rdParty::renderdoc")
|
||||
message(STATUS "Renderdoc found")
|
||||
set(USE_RENDERDOC_DEFINE "USE_RENDERDOC")
|
||||
set(RENDERDOC_BUILD_DEPENDENCY "3rdParty::renderdoc")
|
||||
set(RENDERDOC_API_DEPENDENCY "3rdParty::renderdoc_api")
|
||||
else()
|
||||
message(STATUS "Renderdoc missing")
|
||||
set(USE_RENDERDOC_DEFINE "")
|
||||
set(RENDERDOC_BUILD_DEPENDENCY "")
|
||||
set(RENDERDOC_API_DEPENDENCY "")
|
||||
endif()
|
||||
|
||||
ly_add_target(
|
||||
NAME Atom_RHI.Reflect STATIC
|
||||
NAMESPACE Gem
|
||||
@@ -43,6 +60,12 @@ ly_add_target(
|
||||
AZ::AzCore
|
||||
AZ::AzFramework
|
||||
Gem::Atom_RHI.Reflect
|
||||
${RENDERDOC_BUILD_DEPENDENCY}
|
||||
PUBLIC
|
||||
${RENDERDOC_API_DEPENDENCY}
|
||||
COMPILE_DEFINITIONS
|
||||
PUBLIC
|
||||
${USE_RENDERDOC_DEFINE}
|
||||
)
|
||||
|
||||
ly_add_target(
|
||||
|
||||
@@ -11,6 +11,11 @@
|
||||
#include <Atom/RHI/PhysicalDevice.h>
|
||||
#include <AzCore/Name/Name.h>
|
||||
|
||||
#if defined(USE_RENDERDOC)
|
||||
#include <renderdoc_app.h>
|
||||
#include <AzCore/AzCore_Traits_Platform.h>
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
@@ -66,7 +71,7 @@ namespace AZ
|
||||
public:
|
||||
AZ_TYPE_INFO(Factory, "{2C0231FD-DD11-4154-A4F5-177181E26D8E}");
|
||||
|
||||
Factory() = default;
|
||||
Factory();
|
||||
virtual ~Factory() = default;
|
||||
|
||||
// Note that you have to delete these for safety reasons, you will trip a static_assert if you do not
|
||||
@@ -93,6 +98,25 @@ namespace AZ
|
||||
/// Access the global factory instance.
|
||||
static Factory& Get();
|
||||
|
||||
#if defined(USE_RENDERDOC)
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
static const char* RENDERDOC_MODULE = "renderdoc.dll";
|
||||
#elif defined(AZ_PLATFORM_LINUX)
|
||||
static const char* RENDERDOC_MODULE = "librenderdoc.so";
|
||||
#elif defined(AZ_PLATFORM_ANDROID)
|
||||
static const char* RENDERDOC_MODULE = "libVkLayer_GLES_RenderDoc.so"
|
||||
#else
|
||||
static const char* RENDERDOC_MODULE = nullptr;
|
||||
#endif
|
||||
|
||||
/// Access the RenderDoc API pointer if available.
|
||||
/// The availability of the render doc API at runtime depends on the following:
|
||||
/// - You must not be building a packaged game/product (LY_MONOLITHIC_GAME not enabled in CMake)
|
||||
/// - A valid renderdoc installation was found, either by auto-discovery, or by supplying ATOM_RENDERDOC_PATH as an environment variable
|
||||
/// - The module loaded successfully at runtime, and the API function pointer was retrieved successfully
|
||||
static RENDERDOC_API_1_1_2* GetRenderDocAPI();
|
||||
#endif
|
||||
|
||||
/// Returns the name of the Factory.
|
||||
virtual Name GetName() = 0;
|
||||
|
||||
|
||||
@@ -37,6 +37,9 @@ namespace AZ
|
||||
//! If multiple values exist it will return the last one
|
||||
AZStd::string GetCommandLineValue(const AZStd::string& commandLineOption);
|
||||
|
||||
//! Returns true if the command line option is set
|
||||
bool QueryCommandLineOption(const AZStd::string& commandLineOption);
|
||||
|
||||
//! Returns if the current bakcend is a null renderer
|
||||
bool IsNullRenderer();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
# Prevent bundling the renderdoc dll with a packaged title
|
||||
if(NOT LY_MONOLITHIC_GAME)
|
||||
if(DEFINED ENV{"ATOM_RENDERDOC_PATH"})
|
||||
set(RENDERDOC_PATH ENV{"ATOM_RENDERDOC_PATH"})
|
||||
endif()
|
||||
|
||||
if(RENDERDOC_PATH)
|
||||
# Normalize file path
|
||||
file(TO_CMAKE_PATH "${RENDERDOC_PATH}" RENDERDOC_PATH)
|
||||
|
||||
if(EXISTS "${RENDERDOC_PATH}/librenderdoc.so")
|
||||
ly_add_external_target(
|
||||
NAME renderdoc
|
||||
VERSION
|
||||
3RDPARTY_ROOT_DIRECTORY ${RENDERDOC_PATH}
|
||||
INCLUDE_DIRECTORIES "."
|
||||
RUNTIME_DEPENDENCIES "${RENDERDOC_PATH}/librenderdoc.so"
|
||||
)
|
||||
|
||||
ly_add_external_target(
|
||||
NAME renderdoc_api
|
||||
VERSION
|
||||
3RDPARTY_ROOT_DIRECTORY ${RENDERDOC_PATH}
|
||||
INCLUDE_DIRECTORIES "."
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,38 @@
|
||||
#
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
# Prevent bundling the renderdoc dll with a packaged title
|
||||
if(NOT LY_MONOLITHIC_GAME)
|
||||
# Common installation path for renderdoc path
|
||||
set(RENDERDOC_PATH "C:/Program Files/RenderDoc")
|
||||
if(DEFINED ENV{"ATOM_RENDERDOC_PATH"})
|
||||
set(RENDERDOC_PATH ENV{"ATOM_RENDERDOC_PATH"})
|
||||
endif()
|
||||
|
||||
if(RENDERDOC_PATH)
|
||||
# Normalize file path
|
||||
file(TO_CMAKE_PATH "${RENDERDOC_PATH}" RENDERDOC_PATH)
|
||||
|
||||
if(EXISTS "${RENDERDOC_PATH}/renderdoc.dll")
|
||||
ly_add_external_target(
|
||||
NAME renderdoc
|
||||
VERSION
|
||||
3RDPARTY_ROOT_DIRECTORY ${RENDERDOC_PATH}
|
||||
INCLUDE_DIRECTORIES "."
|
||||
RUNTIME_DEPENDENCIES "${RENDERDOC_PATH}/renderdoc.dll"
|
||||
)
|
||||
|
||||
ly_add_external_target(
|
||||
NAME renderdoc_api
|
||||
VERSION
|
||||
3RDPARTY_ROOT_DIRECTORY ${RENDERDOC_PATH}
|
||||
INCLUDE_DIRECTORIES "."
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@@ -11,6 +11,15 @@
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
|
||||
#if defined(USE_RENDERDOC)
|
||||
#include <AzCore/Module/DynamicModuleHandle.h>
|
||||
#include <Atom/RHI/RHIUtils.h>
|
||||
|
||||
static AZStd::unique_ptr<AZ::DynamicModuleHandle> s_renderDocModule;
|
||||
static RENDERDOC_API_1_1_2* s_renderDocApi = nullptr;
|
||||
#endif
|
||||
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
@@ -30,6 +39,48 @@ namespace AZ
|
||||
return AZ_CRC("RHIPlatformService", 0xfff2cea4);
|
||||
}
|
||||
|
||||
Factory::Factory()
|
||||
{
|
||||
#if defined(USE_RENDERDOC)
|
||||
// If RenderDoc is requested, we need to load the library as early as possible (before device queries/factories are made)
|
||||
bool enableRenderDoc = RHI::QueryCommandLineOption("enableRenderDoc");
|
||||
|
||||
if (enableRenderDoc && RENDERDOC_MODULE && !s_renderDocModule)
|
||||
{
|
||||
s_renderDocModule = DynamicModuleHandle::Create(RENDERDOC_MODULE);
|
||||
if (s_renderDocModule)
|
||||
{
|
||||
if (s_renderDocModule->Load(false))
|
||||
{
|
||||
pRENDERDOC_GetAPI renderDocGetAPI = s_renderDocModule->GetFunction<pRENDERDOC_GetAPI>("RENDERDOC_GetAPI");
|
||||
if (renderDocGetAPI)
|
||||
{
|
||||
if (!renderDocGetAPI(eRENDERDOC_API_Version_1_1_2, reinterpret_cast<void**>(&s_renderDocApi)))
|
||||
{
|
||||
s_renderDocApi = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_renderDocApi)
|
||||
{
|
||||
// Prevent RenderDoc from handling any exceptions that may interfere with the O3DE exception handler
|
||||
s_renderDocApi->UnloadCrashHandler();
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Printf("RHISystem", "RenderDoc module loaded but failed to retrieve API function pointer.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Printf("RHISystem", "RenderDoc module requested but module failed to load.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // defined(USE_RENDERDOC)
|
||||
|
||||
}
|
||||
|
||||
void Factory::Register(Factory* instance)
|
||||
{
|
||||
Interface<Factory>::Register(instance);
|
||||
@@ -58,6 +109,13 @@ namespace AZ
|
||||
ResourceInvalidateBus::ClearQueuedEvents();
|
||||
|
||||
Interface<Factory>::Unregister(instance);
|
||||
|
||||
#if defined(USE_RENDERDOC)
|
||||
if (s_renderDocModule)
|
||||
{
|
||||
s_renderDocModule->Unload();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Factory::IsReady()
|
||||
@@ -71,5 +129,12 @@ namespace AZ
|
||||
AZ_Assert(factory, "RHI::Factory is not connected to a platform. Call IsReady() to get the status of the platform. A null de-reference is imminent.");
|
||||
return *factory;
|
||||
}
|
||||
|
||||
#if defined(USE_RENDERDOC)
|
||||
RENDERDOC_API_1_1_2* Factory::GetRenderDocAPI()
|
||||
{
|
||||
return s_renderDocApi;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,5 +122,17 @@ namespace AZ
|
||||
}
|
||||
return commandLineValue;
|
||||
}
|
||||
|
||||
bool QueryCommandLineOption(const AZStd::string& commandLineOption)
|
||||
{
|
||||
const AzFramework::CommandLine* commandLine = nullptr;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(commandLine, &AzFramework::ApplicationRequests::GetApplicationCommandLine);
|
||||
|
||||
if (commandLine)
|
||||
{
|
||||
return commandLine->HasSwitch(commandLineOption);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user