Files
UnrealEngine/Engine/Source/Runtime/OpenGLDrv/Public/OpenGLUtil.h
2025-05-18 13:04:45 +08:00

143 lines
5.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
OpenGLUtil.h: OpenGL RHI utility definitions.
=============================================================================*/
#pragma once
#include "RHICommandList.h"
#include "OpenGLThirdParty.h"
#include "OpenGLShaderResources.h"
class FOpenGLTexture;
/** Set to 1 to enable the VERIFY_GL macros which call glGetError */
#define ENABLE_VERIFY_GL (0 & DO_CHECK)
#define ENABLE_VERIFY_GL_TRACE 0
// Include GL debug output functionality on everything but shipping configs.
// to enable the debug output specify '-OpenGLDebugLevel=[1-5]' via the command line.
#define ENABLE_DEBUG_OUTPUT (!UE_BUILD_SHIPPING)
#if !ENABLE_DEBUG_OUTPUT
inline bool IsOGLDebugOutputEnabled() { return false; }
inline int32 GetOGLDebugOutputLevel() { return 0; }
#else
bool IsOGLDebugOutputEnabled();
int32 GetOGLDebugOutputLevel();
#endif
// Additional check that our GL calls are occurring on the expected thread
#define ENABLE_VERIFY_GL_THREAD (!(UE_BUILD_TEST || UE_BUILD_SHIPPING))
/** Set to 1 to verify that the the engine side uniform buffer layout matches the driver side of the GLSL shader*/
#define ENABLE_UNIFORM_BUFFER_LAYOUT_VERIFICATION ( 0 & UE_BUILD_DEBUG & (!PLATFORM_ANDROID))
/** Set to 1 to additinally dump uniform buffer layout at shader link time, this assumes ENABLE_UNIFORM_BUFFER_LAYOUT_VERIFICATION == 1 */
#define ENABLE_UNIFORM_BUFFER_LAYOUT_DUMP 0
/** Set to 1 to enable calls to place event markers into the OpenGL stream
this is purposefully not considered for OPENGL_PERFORMANCE_DATA_INVALID,
since there is an additional cvar OpenGLConsoleVariables::bEnableARBDebug*/
#define ENABLE_OPENGL_DEBUG_GROUPS 1
#define OPENGL_PERFORMANCE_DATA_INVALID (ENABLE_VERIFY_GL | ENABLE_UNIFORM_BUFFER_LAYOUT_VERIFICATION | DEBUG_GL_SHADERS)
void SetOpenGLResourceName(FOpenGLTexture* Texture, const ANSICHAR* Name);
void SetOpenGLResourceName(FOpenGLTexture* Texture, const TCHAR* Name);
/**
* Convert from ECubeFace to GLenum type
* @param Face - ECubeFace type to convert
* @return OpenGL cube face enum value
*/
GLenum GetOpenGLCubeFace(ECubeFace Face);
extern bool PlatformOpenGLThreadHasRenderingContext();
#if ENABLE_VERIFY_GL_THREAD
#define CHECK_EXPECTED_GL_THREAD() \
if (!PlatformOpenGLThreadHasRenderingContext()) \
{ \
UE_LOG(LogRHI, Fatal, TEXT("Potential use of GL context from incorrect thread. [IsInGameThread() = %d, IsInRenderingThread() = %d, IsInRHIThread() = %d, IsRunningRHIInSeparateThread() = %d]"), IsInGameThread(), IsInRenderingThread(), IsInRHIThread(), IsRunningRHIInSeparateThread()); \
}
#else
#define CHECK_EXPECTED_GL_THREAD()
#endif
#if ENABLE_VERIFY_GL
extern int32 PlatformGlGetError();
void VerifyOpenGLResult(GLenum ErrorCode, const TCHAR* Msg1, const TCHAR* Msg2, const TCHAR* Filename, uint32 Line);
#define VERIFY_GL(msg) { CHECK_EXPECTED_GL_THREAD(); GLenum ErrorCode = PlatformGlGetError(); if (ErrorCode != GL_NO_ERROR) { VerifyOpenGLResult(ErrorCode,TEXT(#msg),TEXT(""),TEXT(__FILE__),__LINE__); } }
struct FOpenGLErrorScope
{
const char* FunctionName;
const TCHAR* Filename;
const uint32 Line;
FOpenGLErrorScope(
const char* InFunctionName,
const TCHAR* InFilename,
const uint32 InLine)
: FunctionName(InFunctionName)
, Filename(InFilename)
, Line(InLine)
{
#if ENABLE_VERIFY_GL_TRACE
UE_LOG(LogRHI, Log, TEXT("log before %s(%d): %s"), InFilename, InLine, ANSI_TO_TCHAR(InFunctionName));
#endif
CheckForErrors(0);
}
~FOpenGLErrorScope()
{
#if ENABLE_VERIFY_GL_TRACE
UE_LOG(LogRHI, Log, TEXT("log after %s(%d): %s"), Filename, Line, ANSI_TO_TCHAR(FunctionName));
#endif
CheckForErrors(1);
}
void CheckForErrors(int32 BeforeOrAfter)
{
check(PlatformOpenGLThreadHasRenderingContext());
GLenum ErrorCode = PlatformGlGetError();
if (ErrorCode != GL_NO_ERROR)
{
const TCHAR* PrefixStrings[] = { TEXT("Before "), TEXT("During ") };
VerifyOpenGLResult(ErrorCode,PrefixStrings[BeforeOrAfter], ANSI_TO_TCHAR(FunctionName),Filename,Line);
}
}
};
#define MACRO_TOKENIZER(IdentifierName, Msg, FileName, LineNumber) FOpenGLErrorScope IdentifierName_ ## LineNumber (Msg, FileName, LineNumber)
#define MACRO_TOKENIZER2(IdentifierName, Msg, FileName, LineNumber) MACRO_TOKENIZER(IdentiferName, Msg, FileName, LineNumber)
#define VERIFY_GL_SCOPE_WITH_MSG_STR(MsgStr) CHECK_EXPECTED_GL_THREAD(); MACRO_TOKENIZER2(ErrorScope_, MsgStr, TEXT(__FILE__), __LINE__)
#define VERIFY_GL_SCOPE() VERIFY_GL_SCOPE_WITH_MSG_STR(__FUNCTION__)
#define VERIFY_GL_FUNC(Func, ...) { VERIFY_GL_SCOPE_WITH_MSG_STR((#Func)); Func(__VA_ARGS__); }
/**
* Some important GL calls are trapped individually.
*/
#define glBlitFramebuffer(...) VERIFY_GL_FUNC(glBlitFramebuffer, __VA_ARGS__)
#define glTexImage2D(...) VERIFY_GL_FUNC(glTexImage2D, __VA_ARGS__)
#define glTexSubImage2D(...) VERIFY_GL_FUNC(glTexSubImage2D, __VA_ARGS__)
#define glCompressedTexImage2D(...) VERIFY_GL_FUNC(glCompressedTexImage2D, __VA_ARGS__)
#else
#define VERIFY_GL(...) CHECK_EXPECTED_GL_THREAD()
#define VERIFY_GL_SCOPE(...) CHECK_EXPECTED_GL_THREAD()
#endif
struct FRHICommandGLCommandString
{
static const TCHAR* TStr() { return TEXT("FRHICommandGLCommand"); }
};
#define GL_CAPTURE_CALLSTACK 0 // Capture the callstack at the point of enqueuing the command.