You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3045482 on 2016/07/11 by Zabir.Hoque DX12 Quries need to individually track their syncpoints. Only when resolving a query on the same frame should be stall. Change 3045929 on 2016/07/12 by Simon.Tovey Removing some deprecated node types from Niagara Change 3045951 on 2016/07/12 by Ben.Woodhouse D3D11 Log detailed live device info on shutdown if the debug layer is enabled (including resource types) Change3046019on 2016/07/12 by Chris.Bunner Fixed typo in material input name. #jira UE-5575 Change 3046053 on 2016/07/12 by Rolando.Caloca DR - Fix GL4 shutdown #jira UE-32799 Change 3046055 on 2016/07/12 by Rolando.Caloca DR - vk - Fix NumInstances=0 Change 3046063 on 2016/07/12 by Rolando.Caloca DR - vk - Added flat to uint layouts per glslang - Fix bad extension on dumped shaders Change 3046067 on 2016/07/12 by Rolando.Caloca DR - vk - Fix check when not using color RT - Added queue submit & present counters Change3046088on 2016/07/12 by Ben.Woodhouse Live GPU stats A non-hierarchical realtime high level GPU profiler with support for cumulative stat recording. Stats are added with SCOPED_GPU_STAT macros, e.g. SCOPED_GPU_STAT(RHICmdList, Stat_GPU_Distortion) The bulk of the files in this change are simply instrumentation for the renderer. The core changes are in SceneUtils.cpp/h and D3D11Query.cpp (this is the XB1/DX11X implementation of timestamp RHI queries, which was missing) Note: this is currently disabled by default. Enable with the cvar r.gpustatsenabled Tested on PC, XB1, PS4 Change 3046128 on 2016/07/12 by Olaf.Piesche Max draw distance and fade range for lights, requested by JonL Change 3046183 on 2016/07/12 by Ben.Woodhouse PR #2532: Fix SSAO being applied in unlit viewmode (Contributed by nick-penwarden) Change 3046223 on 2016/07/12 by Luke.Thatcher Fix Scene Cube Captures. SceneCaptureSource flag on the ViewFamily was not set for cube components. #jira UE-32345 Change 3046228 on 2016/07/12 by Marc.Olano Add Voronoi noise to Noise material node. Four versions with differing speed/quality levels accessed through the Quality value in the material node. Tooltips give estimates of the cost of each. Also includes spiffy new Rand3DPCG16 and Rand3DPCG32 int3 to int3 hash functions, and a 20% improvement on the computed gradient noise. Change 3046269 on 2016/07/12 by Rolando.Caloca DR - Skip flush on RHIDiscardRenderTargets and only use it on platforms that need it (ie OpenGL) Change 3046294 on 2016/07/12 by Rolando.Caloca DR - Fix static analyisis warning C6326: Potential comparison of a constant with another constant. Change 3046295 on 2016/07/12 by Rolando.Caloca DR - Fix the previous fix Change 3046731 on 2016/07/12 by Marc.Olano Fix typo in shader random number constant: repeated extra digit made it too big. Change 3046796 on 2016/07/12 by Uriel.Doyon The texture streaming manager now keeps a set of all valid textures. This is used to prevent from indirecting deleted memory upon SetTexturesRemovedTimestamp. #jira UE-33048 Change 3046800 on 2016/07/12 by Rolando.Caloca DR - vk - Added create image & renderpass dump Change 3046845 on 2016/07/12 by John.Billon Forgot to apply MaxGPUSkinBones Cvar access changes in a few locations. Change 3047023 on 2016/07/12 by Olaf.Piesche Niagara: -a bit of cleanup -now store and double buffer attributes individually, eliminating unnecessary copy of unused attributes -removed FNiagaraConstantMap, replaced with an instance of FNiagaraConstants -some code simplification -removed some deprecated structs and code used only by old content Change 3047052 on 2016/07/12 by Zabir.Hoque Unshelved from pending changelist '3044062': PR #2588: Adding blend mode BLEND_AlphaComposite (4.12) (Contributed by moritz-wundke) Change 3047727 on 2016/07/13 by Luke.Thatcher Fix Scene Capture Components only updating every other frame. #jira UE-32581 Change 3047919 on 2016/07/13 by Olaf.Piesche CMask decode, use in deferred decals, for PS4 Change 3047921 on 2016/07/13 by Uriel.Doyon "Build Texture Streaming" will now remove duplicate error msg when computing texcoord scales. Also, several texture messages are packed on the same line if they relate to the same material. Change 3047952 on 2016/07/13 by Rolando.Caloca DR - vk - Initial prep pass for separating combined images & samplers Change 3048648 on 2016/07/13 by Marcus.Wassmer Fix rare GPU hang when asynctexture reallocs would overlap with EndFrame Change 3049058 on 2016/07/13 by Rolando.Caloca DR - vk - timestamps Change 3049725 on 2016/07/14 by Marcus.Wassmer Fix autosdk bug where not having a platform directory sync'd at all would break manual SDK detection Change 3049742 on 2016/07/14 by Rolando.Caloca DR - Fix warning Change 3049902 on 2016/07/14 by Rolando.Caloca DR - Fix typo Change 3050345 on 2016/07/14 by Olaf.Piesche UE-23925 Clamping noise tessellation for beams at a high but sensible value; also making sure during beam index buffer building that we never get over 2^16 indices; this is a bit hokey, but there are so many variables that can influence triangle/index count, that this is the only way to be sure (short of nuking the entire site from orbit). Change 3050409 on 2016/07/14 by Olaf.Piesche Replicating 3049049; missing break and check for active particles when resolving a source point to avoid a potential crash Change 3050809 on 2016/07/14 by Rolando.Caloca DR - vk - Remove redundant validation layers Change 3051319 on 2016/07/15 by Ben.Woodhouse Fix for world space camera position not being exposed in decal pixel shaders; also fixes decal lighting missing spec and reflection The fix was to calculate ResolvedView at the top of the shader. Previously this was not initialized #jira UE-31976 Change 3051692 on 2016/07/15 by Rolando.Caloca DR - vk - Enable RHI thread by default Change 3052103 on 2016/07/15 by Uriel.Doyon Disabled depth offset in depth only pixel shaders when using debug view shaders (to prevent Z fighting). #jira UE-32765 Change 3052140 on 2016/07/15 by Rolando.Caloca DR - vk - Fix shader snafu Change 3052495 on 2016/07/15 by Rolando.Caloca DR - Fix for Win32 compile #jira UE-33349 Change 3052536 on 2016/07/15 by Uriel.Doyon Fixed texture streaming overbudget warning when using per texture bias. [CL 3054554 by Gil Gribb in Main branch]
1563 lines
57 KiB
C++
1563 lines
57 KiB
C++
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
OpenGLDevice.cpp: OpenGL device RHI implementation.
|
|
=============================================================================*/
|
|
|
|
#include "OpenGLDrvPrivate.h"
|
|
|
|
#include "HardwareInfo.h"
|
|
#include "ShaderCache.h"
|
|
|
|
#ifndef GL_STEREO
|
|
#define GL_STEREO 0x0C33
|
|
#endif
|
|
|
|
extern GLint GMaxOpenGLColorSamples;
|
|
extern GLint GMaxOpenGLDepthSamples;
|
|
extern GLint GMaxOpenGLIntegerSamples;
|
|
extern GLint GMaxOpenGLTextureFilterAnisotropic;
|
|
extern GLint GMaxOpenGLDrawBuffers;
|
|
|
|
/** OpenGL texture format table. */
|
|
FOpenGLTextureFormat GOpenGLTextureFormats[PF_MAX];
|
|
|
|
/** Device is necessary for vertex buffers, so they can reach the global device on destruction, and tell it to reset vertex array caches */
|
|
static FOpenGLDynamicRHI* PrivateOpenGLDevicePtr = NULL;
|
|
|
|
/** true if we're not using UBOs. (ES2) */
|
|
bool GUseEmulatedUniformBuffers;
|
|
|
|
void OnQueryCreation( FOpenGLRenderQuery* Query )
|
|
{
|
|
check(PrivateOpenGLDevicePtr);
|
|
PrivateOpenGLDevicePtr->RegisterQuery( Query );
|
|
}
|
|
|
|
void OnQueryDeletion( FOpenGLRenderQuery* Query )
|
|
{
|
|
if(PrivateOpenGLDevicePtr)
|
|
{
|
|
PrivateOpenGLDevicePtr->UnregisterQuery( Query );
|
|
}
|
|
}
|
|
|
|
void OnQueryInvalidation( void )
|
|
{
|
|
if(PrivateOpenGLDevicePtr)
|
|
{
|
|
PrivateOpenGLDevicePtr->InvalidateQueries();
|
|
}
|
|
}
|
|
|
|
void OnProgramDeletion( GLint ProgramResource )
|
|
{
|
|
check(PrivateOpenGLDevicePtr);
|
|
PrivateOpenGLDevicePtr->OnProgramDeletion( ProgramResource );
|
|
}
|
|
|
|
void OnVertexBufferDeletion( GLuint VertexBufferResource )
|
|
{
|
|
check(PrivateOpenGLDevicePtr);
|
|
PrivateOpenGLDevicePtr->OnVertexBufferDeletion( VertexBufferResource );
|
|
}
|
|
|
|
void OnIndexBufferDeletion( GLuint IndexBufferResource )
|
|
{
|
|
check(PrivateOpenGLDevicePtr);
|
|
PrivateOpenGLDevicePtr->OnIndexBufferDeletion( IndexBufferResource );
|
|
}
|
|
|
|
void OnPixelBufferDeletion( GLuint PixelBufferResource )
|
|
{
|
|
check(PrivateOpenGLDevicePtr);
|
|
PrivateOpenGLDevicePtr->OnPixelBufferDeletion( PixelBufferResource );
|
|
}
|
|
|
|
void OnUniformBufferDeletion( GLuint UniformBufferResource, uint32 AllocatedSize, bool bStreamDraw, uint32 , uint8* )
|
|
{
|
|
check(PrivateOpenGLDevicePtr);
|
|
PrivateOpenGLDevicePtr->OnUniformBufferDeletion( UniformBufferResource, AllocatedSize, bStreamDraw );
|
|
}
|
|
|
|
void CachedBindArrayBuffer( GLuint Buffer )
|
|
{
|
|
check(PrivateOpenGLDevicePtr);
|
|
PrivateOpenGLDevicePtr->CachedBindArrayBuffer(PrivateOpenGLDevicePtr->GetContextStateForCurrentContext(),Buffer);
|
|
}
|
|
|
|
void CachedBindElementArrayBuffer( GLuint Buffer )
|
|
{
|
|
check(PrivateOpenGLDevicePtr);
|
|
PrivateOpenGLDevicePtr->CachedBindElementArrayBuffer(PrivateOpenGLDevicePtr->GetContextStateForCurrentContext(),Buffer);
|
|
}
|
|
|
|
void CachedBindPixelUnpackBuffer( GLuint Buffer )
|
|
{
|
|
check(PrivateOpenGLDevicePtr);
|
|
if ( FOpenGL::SupportsPixelBuffers() )
|
|
{
|
|
PrivateOpenGLDevicePtr->CachedBindPixelUnpackBuffer(PrivateOpenGLDevicePtr->GetContextStateForCurrentContext(),Buffer);
|
|
}
|
|
}
|
|
|
|
void CachedBindUniformBuffer( GLuint Buffer )
|
|
{
|
|
check(PrivateOpenGLDevicePtr);
|
|
if (FOpenGL::SupportsUniformBuffers())
|
|
{
|
|
PrivateOpenGLDevicePtr->CachedBindUniformBuffer(PrivateOpenGLDevicePtr->GetContextStateForCurrentContext(),Buffer);
|
|
}
|
|
}
|
|
|
|
bool IsUniformBufferBound( GLuint Buffer )
|
|
{
|
|
check(PrivateOpenGLDevicePtr);
|
|
return PrivateOpenGLDevicePtr->IsUniformBufferBound(PrivateOpenGLDevicePtr->GetContextStateForCurrentContext(),Buffer);
|
|
}
|
|
|
|
extern void BeginFrame_UniformBufferPoolCleanup();
|
|
extern void BeginFrame_VertexBufferCleanup();
|
|
|
|
FOpenGLContextState& FOpenGLDynamicRHI::GetContextStateForCurrentContext(bool bAssertIfInvalid)
|
|
{
|
|
int32 ContextType = (int32)PlatformOpenGLCurrentContext(PlatformDevice);
|
|
if (bAssertIfInvalid)
|
|
{
|
|
check(ContextType >= 0);
|
|
}
|
|
else if (ContextType < 0)
|
|
{
|
|
return InvalidContextState;
|
|
}
|
|
|
|
if (ContextType == CONTEXT_Rendering)
|
|
{
|
|
return RenderingContextState;
|
|
}
|
|
else
|
|
{
|
|
return SharedContextState;
|
|
}
|
|
}
|
|
|
|
void FOpenGLDynamicRHI::RHIBeginFrame()
|
|
{
|
|
RHIPrivateBeginFrame();
|
|
BeginFrame_UniformBufferPoolCleanup();
|
|
BeginFrame_VertexBufferCleanup();
|
|
GPUProfilingData.BeginFrame(this);
|
|
|
|
#if PLATFORM_ANDROID //adding #if since not sure if this is required for any other platform.
|
|
//we need to differential between 0 (backbuffer) and lastcolorRT.
|
|
FOpenGLContextState& ContextState = GetContextStateForCurrentContext();
|
|
ContextState.LastES2ColorRTResource = 0xFFFFFFFF;
|
|
PendingState.DepthStencil = 0 ;
|
|
#endif
|
|
}
|
|
|
|
void FOpenGLDynamicRHI::RHIEndFrame()
|
|
{
|
|
GPUProfilingData.EndFrame();
|
|
}
|
|
|
|
void FOpenGLDynamicRHI::RHIBeginScene()
|
|
{
|
|
// Increment the frame counter. INDEX_NONE is a special value meaning "uninitialized", so if
|
|
// we hit it just wrap around to zero.
|
|
SceneFrameCounter++;
|
|
if (SceneFrameCounter == INDEX_NONE)
|
|
{
|
|
SceneFrameCounter++;
|
|
}
|
|
|
|
static auto* ResourceTableCachingCvar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("rhi.ResourceTableCaching"));
|
|
if (ResourceTableCachingCvar == NULL || ResourceTableCachingCvar->GetValueOnAnyThread() == 1)
|
|
{
|
|
ResourceTableFrameCounter = SceneFrameCounter;
|
|
}
|
|
}
|
|
|
|
void FOpenGLDynamicRHI::RHIEndScene()
|
|
{
|
|
ResourceTableFrameCounter = INDEX_NONE;
|
|
}
|
|
|
|
|
|
|
|
bool GDisableOpenGLDebugOutput = false;
|
|
|
|
// workaround for HTML5.
|
|
#if PLATFORM_HTML5
|
|
#undef GL_ARB_debug_output
|
|
#undef GL_KHR_debug
|
|
#endif
|
|
|
|
#if defined(GL_ARB_debug_output) || defined(GL_KHR_debug)
|
|
/**
|
|
* Map GL_DEBUG_SOURCE_*_ARB to a human-readable string.
|
|
*/
|
|
static const TCHAR* GetOpenGLDebugSourceStringARB(GLenum Source)
|
|
{
|
|
static const TCHAR* SourceStrings[] =
|
|
{
|
|
TEXT("API"),
|
|
TEXT("System"),
|
|
TEXT("ShaderCompiler"),
|
|
TEXT("ThirdParty"),
|
|
TEXT("Application"),
|
|
TEXT("Other")
|
|
};
|
|
|
|
if (Source >= GL_DEBUG_SOURCE_API_ARB && Source <= GL_DEBUG_SOURCE_OTHER_ARB)
|
|
{
|
|
return SourceStrings[Source - GL_DEBUG_SOURCE_API_ARB];
|
|
}
|
|
return TEXT("Unknown");
|
|
}
|
|
|
|
/**
|
|
* Map GL_DEBUG_TYPE_*_ARB to a human-readable string.
|
|
*/
|
|
static const TCHAR* GetOpenGLDebugTypeStringARB(GLenum Type)
|
|
{
|
|
static const TCHAR* TypeStrings[] =
|
|
{
|
|
TEXT("Error"),
|
|
TEXT("Deprecated"),
|
|
TEXT("UndefinedBehavior"),
|
|
TEXT("Portability"),
|
|
TEXT("Performance"),
|
|
TEXT("Other")
|
|
};
|
|
|
|
if (Type >= GL_DEBUG_TYPE_ERROR_ARB && Type <= GL_DEBUG_TYPE_OTHER_ARB)
|
|
{
|
|
return TypeStrings[Type - GL_DEBUG_TYPE_ERROR_ARB];
|
|
}
|
|
#ifdef GL_KHR_debug
|
|
{
|
|
static const TCHAR* DebugTypeStrings[] =
|
|
{
|
|
TEXT("Marker"),
|
|
TEXT("PushGroup"),
|
|
TEXT("PopGroup"),
|
|
};
|
|
|
|
if (Type >= GL_DEBUG_TYPE_MARKER && Type <= GL_DEBUG_TYPE_POP_GROUP)
|
|
{
|
|
return DebugTypeStrings[Type - GL_DEBUG_TYPE_MARKER];
|
|
}
|
|
}
|
|
#endif
|
|
return TEXT("Unknown");
|
|
}
|
|
|
|
/**
|
|
* Map GL_DEBUG_SEVERITY_*_ARB to a human-readable string.
|
|
*/
|
|
static const TCHAR* GetOpenGLDebugSeverityStringARB(GLenum Severity)
|
|
{
|
|
static const TCHAR* SeverityStrings[] =
|
|
{
|
|
TEXT("High"),
|
|
TEXT("Medium"),
|
|
TEXT("Low")
|
|
};
|
|
|
|
if (Severity >= GL_DEBUG_SEVERITY_HIGH_ARB && Severity <= GL_DEBUG_SEVERITY_LOW_ARB)
|
|
{
|
|
return SeverityStrings[Severity - GL_DEBUG_SEVERITY_HIGH_ARB];
|
|
}
|
|
#ifdef GL_KHR_debug
|
|
if(Severity == GL_DEBUG_SEVERITY_NOTIFICATION)
|
|
return TEXT("Notification");
|
|
#endif
|
|
return TEXT("Unknown");
|
|
}
|
|
|
|
/**
|
|
* OpenGL debug message callback. Conforms to GLDEBUGPROCARB.
|
|
*/
|
|
#if (PLATFORM_ANDROID && !PLATFORM_ANDROIDGL4) || PLATFORM_HTML5
|
|
#ifndef GL_APIENTRY
|
|
#define GL_APIENTRY APIENTRY
|
|
#endif
|
|
static void GL_APIENTRY OpenGLDebugMessageCallbackARB(
|
|
#else
|
|
static void APIENTRY OpenGLDebugMessageCallbackARB(
|
|
#endif
|
|
GLenum Source,
|
|
GLenum Type,
|
|
GLuint Id,
|
|
GLenum Severity,
|
|
GLsizei Length,
|
|
const GLchar* Message,
|
|
GLvoid* UserParam)
|
|
{
|
|
if (GDisableOpenGLDebugOutput)
|
|
return;
|
|
#if !NO_LOGGING
|
|
const TCHAR* SourceStr = GetOpenGLDebugSourceStringARB(Source);
|
|
const TCHAR* TypeStr = GetOpenGLDebugTypeStringARB(Type);
|
|
const TCHAR* SeverityStr = GetOpenGLDebugSeverityStringARB(Severity);
|
|
|
|
ELogVerbosity::Type Verbosity = ELogVerbosity::Warning;
|
|
if (Type == GL_DEBUG_TYPE_ERROR_ARB && Severity == GL_DEBUG_SEVERITY_HIGH_ARB)
|
|
{
|
|
Verbosity = ELogVerbosity::Fatal;
|
|
}
|
|
|
|
if ((Verbosity & ELogVerbosity::VerbosityMask) <= FLogCategoryLogRHI::CompileTimeVerbosity)
|
|
{
|
|
if (!LogRHI.IsSuppressed(Verbosity))
|
|
{
|
|
FMsg::Logf(__FILE__, __LINE__, LogRHI.GetCategoryName(), Verbosity,
|
|
TEXT("[%s][%s][%s][%u] %s"),
|
|
SourceStr,
|
|
TypeStr,
|
|
SeverityStr,
|
|
Id,
|
|
ANSI_TO_TCHAR(Message)
|
|
);
|
|
}
|
|
|
|
// this is a debugging code to catch VIDEO->HOST copying
|
|
if (Id == 131186)
|
|
{
|
|
int A = 5;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#endif // GL_ARB_debug_output
|
|
|
|
#ifdef GL_AMD_debug_output
|
|
|
|
/**
|
|
* Map GL_DEBUG_CATEGORY_*_AMD to a human-readable string.
|
|
*/
|
|
static const TCHAR* GetOpenGLDebugCategoryStringAMD(GLenum Category)
|
|
{
|
|
static const TCHAR* CategoryStrings[] =
|
|
{
|
|
TEXT("API"),
|
|
TEXT("System"),
|
|
TEXT("Deprecation"),
|
|
TEXT("UndefinedBehavior"),
|
|
TEXT("Performance"),
|
|
TEXT("ShaderCompiler"),
|
|
TEXT("Application"),
|
|
TEXT("Other")
|
|
};
|
|
|
|
if (Category >= GL_DEBUG_CATEGORY_API_ERROR_AMD && Category <= GL_DEBUG_CATEGORY_OTHER_AMD)
|
|
{
|
|
return CategoryStrings[Category - GL_DEBUG_CATEGORY_API_ERROR_AMD];
|
|
}
|
|
return TEXT("Unknown");
|
|
}
|
|
|
|
/**
|
|
* Map GL_DEBUG_SEVERITY_*_AMD to a human-readable string.
|
|
*/
|
|
static const TCHAR* GetOpenGLDebugSeverityStringAMD(GLenum Severity)
|
|
{
|
|
static const TCHAR* SeverityStrings[] =
|
|
{
|
|
TEXT("High"),
|
|
TEXT("Medium"),
|
|
TEXT("Low")
|
|
};
|
|
|
|
if (Severity >= GL_DEBUG_SEVERITY_HIGH_AMD && Severity <= GL_DEBUG_SEVERITY_LOW_AMD)
|
|
{
|
|
return SeverityStrings[Severity - GL_DEBUG_SEVERITY_HIGH_AMD];
|
|
}
|
|
return TEXT("Unknown");
|
|
}
|
|
|
|
/**
|
|
* OpenGL debug message callback. Conforms to GLDEBUGPROCAMD.
|
|
*/
|
|
static void APIENTRY OpenGLDebugMessageCallbackAMD(
|
|
GLuint Id,
|
|
GLenum Category,
|
|
GLenum Severity,
|
|
GLsizei Length,
|
|
const GLchar* Message,
|
|
GLvoid* UserParam)
|
|
{
|
|
#if !NO_LOGGING
|
|
const TCHAR* CategoryStr = GetOpenGLDebugCategoryStringAMD(Category);
|
|
const TCHAR* SeverityStr = GetOpenGLDebugSeverityStringAMD(Severity);
|
|
|
|
ELogVerbosity::Type Verbosity = ELogVerbosity::Warning;
|
|
if (Severity == GL_DEBUG_SEVERITY_HIGH_AMD)
|
|
{
|
|
Verbosity = ELogVerbosity::Fatal;
|
|
}
|
|
|
|
if ((Verbosity & ELogVerbosity::VerbosityMask) <= FLogCategoryLogRHI::CompileTimeVerbosity)
|
|
{
|
|
if (!LogRHI.IsSuppressed(Verbosity))
|
|
{
|
|
FMsg::Logf(__FILE__, __LINE__, LogRHI.GetCategoryName(), Verbosity,
|
|
TEXT("[%s][%s][%u] %s"),
|
|
CategoryStr,
|
|
SeverityStr,
|
|
Id,
|
|
ANSI_TO_TCHAR(Message)
|
|
);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#endif // GL_AMD_debug_output
|
|
|
|
#if PLATFORM_WINDOWS
|
|
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT_ProcAddress = NULL;
|
|
#endif
|
|
|
|
|
|
static inline void SetupTextureFormat( EPixelFormat Format, const FOpenGLTextureFormat& GLFormat)
|
|
{
|
|
GOpenGLTextureFormats[Format] = GLFormat;
|
|
GPixelFormats[Format].Supported = (GLFormat.Format != GL_NONE && (GLFormat.InternalFormat[0] != GL_NONE || GLFormat.InternalFormat[1] != GL_NONE));
|
|
}
|
|
|
|
|
|
void InitDebugContext()
|
|
{
|
|
// Set the debug output callback if the driver supports it.
|
|
VERIFY_GL(__FUNCTION__);
|
|
bool bDebugOutputInitialized = false;
|
|
#if !ENABLE_VERIFY_GL
|
|
#if defined(GL_ARB_debug_output)
|
|
if (glDebugMessageCallbackARB)
|
|
{
|
|
// Synchronous output can slow things down, but we'll get better callstack if breaking in or crashing in the callback. This is debug only after all.
|
|
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
|
glDebugMessageCallbackARB(GLDEBUGPROCARB(OpenGLDebugMessageCallbackARB), /*UserParam=*/ NULL);
|
|
bDebugOutputInitialized = (glGetError() == GL_NO_ERROR);
|
|
}
|
|
#elif defined(GL_KHR_debug)
|
|
// OpenGLES names the debug functions differently, but they behave the same
|
|
if (glDebugMessageCallbackKHR)
|
|
{
|
|
glDebugMessageCallbackKHR(GLDEBUGPROCKHR(OpenGLDebugMessageCallbackARB), /*UserParam=*/ NULL);
|
|
bDebugOutputInitialized = (glGetError() == GL_NO_ERROR);
|
|
}
|
|
#endif // GL_ARB_debug_output / GL_KHR_debug
|
|
#if defined(GL_AMD_debug_output)
|
|
if (glDebugMessageCallbackAMD && !bDebugOutputInitialized)
|
|
{
|
|
glDebugMessageCallbackAMD(OpenGLDebugMessageCallbackAMD, /*UserParam=*/ NULL);
|
|
bDebugOutputInitialized = (glGetError() == GL_NO_ERROR);
|
|
}
|
|
#endif // GL_AMD_debug_output
|
|
#endif // !ENABLE_VERIFY_GL
|
|
#if !PLATFORM_MAC
|
|
if (!bDebugOutputInitialized)
|
|
{
|
|
UE_LOG(LogRHI,Warning,TEXT("OpenGL debug output extension not supported!"));
|
|
}
|
|
#endif
|
|
|
|
// this is to suppress feeding back of the debug markers and groups to the log, since those originate in the app anyways...
|
|
#if ENABLE_OPENGL_DEBUG_GROUPS && GL_ARB_debug_output && GL_KHR_debug && !OPENGL_ES31
|
|
if(glDebugMessageControlARB && bDebugOutputInitialized)
|
|
{
|
|
glDebugMessageControlARB(GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_MARKER, GL_DONT_CARE, 0, NULL, GL_FALSE);
|
|
glDebugMessageControlARB(GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PUSH_GROUP, GL_DONT_CARE, 0, NULL, GL_FALSE);
|
|
glDebugMessageControlARB(GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_POP_GROUP, GL_DONT_CARE, 0, NULL, GL_FALSE);
|
|
#ifdef GL_KHR_debug
|
|
glDebugMessageControlARB(GL_DEBUG_SOURCE_API_ARB, GL_DEBUG_TYPE_OTHER_ARB, GL_DEBUG_SEVERITY_NOTIFICATION, 0, NULL, GL_FALSE);
|
|
#endif
|
|
UE_LOG(LogRHI,Verbose,TEXT("disabling reporting back of debug groups and markers to the OpenGL debug output callback"));
|
|
}
|
|
#elif ENABLE_OPENGL_DEBUG_GROUPS && !defined(GL_ARB_debug_output) && GL_KHR_debug
|
|
if(glDebugMessageControlKHR)
|
|
{
|
|
glDebugMessageControlKHR(GL_DEBUG_SOURCE_APPLICATION_KHR, GL_DEBUG_TYPE_MARKER_KHR, GL_DONT_CARE, 0, NULL, GL_FALSE);
|
|
glDebugMessageControlKHR(GL_DEBUG_SOURCE_APPLICATION_KHR, GL_DEBUG_TYPE_PUSH_GROUP_KHR, GL_DONT_CARE, 0, NULL, GL_FALSE);
|
|
glDebugMessageControlKHR(GL_DEBUG_SOURCE_APPLICATION_KHR, GL_DEBUG_TYPE_POP_GROUP_KHR, GL_DONT_CARE, 0, NULL, GL_FALSE);
|
|
glDebugMessageControlKHR(GL_DEBUG_SOURCE_API_KHR, GL_DEBUG_TYPE_OTHER_KHR, GL_DEBUG_SEVERITY_NOTIFICATION, 0, NULL, GL_FALSE);
|
|
UE_LOG(LogRHI,Verbose,TEXT("disabling reporting back of debug groups and markers to the OpenGL debug output callback"));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
TAutoConsoleVariable<FString> CVarOpenGLStripExtensions(
|
|
TEXT("r.OpenGL.StripExtensions"),
|
|
TEXT(""),
|
|
TEXT("List of comma separated OpenGL extensions to strip from a driver reported extensions string"),
|
|
ECVF_ReadOnly);
|
|
|
|
TAutoConsoleVariable<FString> CVarOpenGLAddExtensions(
|
|
TEXT("r.OpenGL.AddExtensions"),
|
|
TEXT(""),
|
|
TEXT("List of comma separated OpenGL extensions to add to a driver reported extensions string"),
|
|
ECVF_ReadOnly);
|
|
|
|
void ApplyExtensionsOverrides(FString& ExtensionsString)
|
|
{
|
|
// Strip extensions
|
|
{
|
|
TArray<FString> ExtList;
|
|
FString ExtString = CVarOpenGLStripExtensions.GetValueOnAnyThread();
|
|
ExtString.ParseIntoArray(ExtList, TEXT(","), /*InCullEmpty=*/true);
|
|
|
|
for (FString& ExtName : ExtList)
|
|
{
|
|
ExtName = ExtName.Trim().TrimTrailing();
|
|
if (ExtensionsString.ReplaceInline(*ExtName, TEXT("")) > 0)
|
|
{
|
|
UE_LOG(LogRHI, Log, TEXT("Stripped extension: %s"), *ExtName);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add extensions
|
|
{
|
|
TArray<FString> ExtList;
|
|
FString ExtString = CVarOpenGLAddExtensions.GetValueOnAnyThread();
|
|
ExtString.ParseIntoArray(ExtList, TEXT(","), /*InCullEmpty=*/true);
|
|
|
|
for (FString& ExtName : ExtList)
|
|
{
|
|
ExtName = ExtName.Trim().TrimTrailing();
|
|
if (!ExtensionsString.Contains(ExtName))
|
|
{
|
|
ExtensionsString.Append(TEXT(" ")); // extensions delimiter
|
|
ExtensionsString.Append(ExtName);
|
|
UE_LOG(LogRHI, Log, TEXT("Added extension: %s"), *ExtName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Initialize RHI capabilities for the current OpenGL context.
|
|
*/
|
|
static void InitRHICapabilitiesForGL()
|
|
{
|
|
VERIFY_GL_SCOPE();
|
|
|
|
GTexturePoolSize = 0;
|
|
GPoolSizeVRAMPercentage = 0;
|
|
#if PLATFORM_WINDOWS || PLATFORM_LINUX
|
|
GConfig->GetInt( TEXT( "TextureStreaming" ), TEXT( "PoolSizeVRAMPercentage" ), GPoolSizeVRAMPercentage, GEngineIni );
|
|
#endif
|
|
|
|
// GL vendor and version information.
|
|
#if !defined(__GNUC__) && !defined(__clang__) && !(defined(_MSC_VER) && _MSC_VER >= 1900)
|
|
#define LOG_GL_STRING(StringEnum) UE_LOG(LogRHI, Log, TEXT(" ") ## TEXT(#StringEnum) ## TEXT(": %s"), ANSI_TO_TCHAR((const ANSICHAR*)glGetString(StringEnum)))
|
|
#else
|
|
#define LOG_GL_STRING(StringEnum) UE_LOG(LogRHI, Log, TEXT(" " #StringEnum ": %s"), ANSI_TO_TCHAR((const ANSICHAR*)glGetString(StringEnum)))
|
|
#endif
|
|
UE_LOG(LogRHI, Log, TEXT("Initializing OpenGL RHI"));
|
|
LOG_GL_STRING(GL_VENDOR);
|
|
LOG_GL_STRING(GL_RENDERER);
|
|
LOG_GL_STRING(GL_VERSION);
|
|
LOG_GL_STRING(GL_SHADING_LANGUAGE_VERSION);
|
|
#undef LOG_GL_STRING
|
|
|
|
GRHIAdapterName = FOpenGL::GetAdapterName();
|
|
|
|
// Log all supported extensions.
|
|
#if PLATFORM_WINDOWS
|
|
bool bWindowsSwapControlExtensionPresent = false;
|
|
#endif
|
|
{
|
|
extern void GetExtensionsString( FString& ExtensionsString);
|
|
FString ExtensionsString;
|
|
|
|
GetExtensionsString(ExtensionsString);
|
|
|
|
#if PLATFORM_WINDOWS
|
|
if (ExtensionsString.Contains(TEXT("WGL_EXT_swap_control")))
|
|
{
|
|
bWindowsSwapControlExtensionPresent = true;
|
|
}
|
|
#endif
|
|
|
|
// Log supported GL extensions
|
|
UE_LOG(LogRHI, Log, TEXT("OpenGL Extensions:"));
|
|
TArray<FString> GLExtensionArray;
|
|
ExtensionsString.ParseIntoArray(GLExtensionArray, TEXT(" "), true);
|
|
for (int ExtIndex = 0; ExtIndex < GLExtensionArray.Num(); ExtIndex++)
|
|
{
|
|
UE_LOG(LogRHI, Log, TEXT(" %s"), *GLExtensionArray[ExtIndex]);
|
|
}
|
|
|
|
ApplyExtensionsOverrides(ExtensionsString);
|
|
|
|
FOpenGL::ProcessExtensions(ExtensionsString);
|
|
}
|
|
|
|
#if PLATFORM_WINDOWS
|
|
#pragma warning(push)
|
|
#pragma warning(disable:4191)
|
|
if (!bWindowsSwapControlExtensionPresent)
|
|
{
|
|
// Disable warning C4191: 'type cast' : unsafe conversion from 'PROC' to 'XXX' while getting GL entry points.
|
|
PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT_ProcAddress =
|
|
(PFNWGLGETEXTENSIONSSTRINGEXTPROC) wglGetProcAddress("wglGetExtensionsStringEXT");
|
|
|
|
if (strstr(wglGetExtensionsStringEXT_ProcAddress(), "WGL_EXT_swap_control") != NULL)
|
|
{
|
|
bWindowsSwapControlExtensionPresent = true;
|
|
}
|
|
}
|
|
|
|
if (bWindowsSwapControlExtensionPresent)
|
|
{
|
|
wglSwapIntervalEXT_ProcAddress = (PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress("wglSwapIntervalEXT");
|
|
}
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
// Set debug flag if context was setup with debugging
|
|
FOpenGL::InitDebugContext();
|
|
|
|
// Log and get various limits.
|
|
#if !defined(__GNUC__) && !defined(__clang__) && !(defined(_MSC_VER) && _MSC_VER >= 1900)
|
|
#define LOG_AND_GET_GL_INT_TEMP(IntEnum,Default) GLint Value_##IntEnum = Default; if (IntEnum) {glGetIntegerv(IntEnum, &Value_##IntEnum); glGetError();} else {Value_##IntEnum = Default;} UE_LOG(LogRHI, Log, TEXT(" ") ## TEXT(#IntEnum) ## TEXT(": %d"), Value_##IntEnum)
|
|
#else
|
|
#define LOG_AND_GET_GL_INT_TEMP(IntEnum,Default) GLint Value_##IntEnum = Default; if (IntEnum) {glGetIntegerv(IntEnum, &Value_##IntEnum); glGetError();} else {Value_##IntEnum = Default;} UE_LOG(LogRHI, Log, TEXT(" " #IntEnum ": %d"), Value_##IntEnum)
|
|
#endif
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_TEXTURE_SIZE, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_CUBE_MAP_TEXTURE_SIZE, 0);
|
|
#if GL_MAX_ARRAY_TEXTURE_LAYERS
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_ARRAY_TEXTURE_LAYERS, 0);
|
|
#endif
|
|
#if GL_MAX_3D_TEXTURE_SIZE
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_3D_TEXTURE_SIZE, 0);
|
|
#endif
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_RENDERBUFFER_SIZE, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_TEXTURE_IMAGE_UNITS, 0);
|
|
if (FOpenGL::SupportsDrawBuffers())
|
|
{
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_DRAW_BUFFERS, 1);
|
|
GMaxOpenGLDrawBuffers = FMath::Min(Value_GL_MAX_DRAW_BUFFERS, (GLint)MaxSimultaneousRenderTargets);
|
|
}
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_COLOR_ATTACHMENTS, 1);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_SAMPLES, 1);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_COLOR_TEXTURE_SAMPLES, 1);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_DEPTH_TEXTURE_SAMPLES, 1);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_INTEGER_SAMPLES, 1);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_VERTEX_ATTRIBS, 0);
|
|
|
|
if (FParse::Param(FCommandLine::Get(), TEXT("quad_buffer_stereo")))
|
|
{
|
|
GLboolean Result = GL_FALSE;
|
|
glGetBooleanv(GL_STEREO, &Result);
|
|
// Skip any errors if any were generated
|
|
glGetError();
|
|
GSupportsQuadBufferStereo = (Result == GL_TRUE);
|
|
}
|
|
|
|
if( FOpenGL::SupportsTextureFilterAnisotropic())
|
|
{
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, 0);
|
|
GMaxOpenGLTextureFilterAnisotropic = Value_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT;
|
|
}
|
|
#undef LOG_AND_GET_GL_INT_TEMP
|
|
|
|
GMaxOpenGLColorSamples = Value_GL_MAX_COLOR_TEXTURE_SAMPLES;
|
|
GMaxOpenGLDepthSamples = Value_GL_MAX_DEPTH_TEXTURE_SAMPLES;
|
|
GMaxOpenGLIntegerSamples = Value_GL_MAX_INTEGER_SAMPLES;
|
|
|
|
// Verify some assumptions.
|
|
// Android seems like reports one color attachment even when it supports MRT
|
|
#if !PLATFORM_ANDROID
|
|
check(Value_GL_MAX_COLOR_ATTACHMENTS >= MaxSimultaneousRenderTargets || !FOpenGL::SupportsMultipleRenderTargets());
|
|
#endif
|
|
|
|
// We don't check for compressed formats right now because vendors have not
|
|
// done a great job reporting what is actually supported:
|
|
// OSX/NVIDIA doesn't claim to support SRGB DXT formats even though they work correctly.
|
|
// Windows/AMD sometimes claim to support no compressed formats even though they all work correctly.
|
|
#if 0
|
|
// Check compressed texture formats.
|
|
bool bSupportsCompressedTextures = true;
|
|
{
|
|
FString CompressedFormatsString = TEXT(" GL_COMPRESSED_TEXTURE_FORMATS:");
|
|
TArray<GLint> CompressedFormats;
|
|
GLint NumCompressedFormats = 0;
|
|
glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &NumCompressedFormats);
|
|
CompressedFormats.Empty(NumCompressedFormats);
|
|
CompressedFormats.AddZeroed(NumCompressedFormats);
|
|
glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, CompressedFormats.GetTypedData());
|
|
|
|
#define CHECK_COMPRESSED_FORMAT(GLName) if (CompressedFormats.Contains(GLName)) { CompressedFormatsString += TEXT(" ") TEXT(#GLName); } else { bSupportsCompressedTextures = false; }
|
|
CHECK_COMPRESSED_FORMAT(GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
|
|
CHECK_COMPRESSED_FORMAT(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT);
|
|
CHECK_COMPRESSED_FORMAT(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
|
|
CHECK_COMPRESSED_FORMAT(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT);
|
|
CHECK_COMPRESSED_FORMAT(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT);
|
|
CHECK_COMPRESSED_FORMAT(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT);
|
|
//CHECK_COMPRESSED_FORMAT(GL_COMPRESSED_RG_RGTC2);
|
|
#undef CHECK_COMPRESSED_FORMAT
|
|
|
|
// ATI does not report that it supports RGTC2, but the 3.2 core profile mandates it.
|
|
// For now assume it is supported and bring it up with ATI if it really isn't(?!)
|
|
CompressedFormatsString += TEXT(" GL_COMPRESSED_RG_RGTC2");
|
|
|
|
UE_LOG(LogRHI, Log, *CompressedFormatsString);
|
|
}
|
|
check(bSupportsCompressedTextures);
|
|
#endif
|
|
|
|
// Set capabilities.
|
|
const GLint MajorVersion = FOpenGL::GetMajorVersion();
|
|
const GLint MinorVersion = FOpenGL::GetMinorVersion();
|
|
|
|
// Shader platform & RHI feature level
|
|
GMaxRHIFeatureLevel = FOpenGL::GetFeatureLevel();
|
|
GMaxRHIShaderPlatform = FOpenGL::GetShaderPlatform();
|
|
|
|
// Emulate uniform buffers on ES2, unless we're on a desktop platform emulating ES2.
|
|
GUseEmulatedUniformBuffers = IsES2Platform(GMaxRHIShaderPlatform) && !IsPCPlatform(GMaxRHIShaderPlatform);
|
|
if (!GUseEmulatedUniformBuffers && IsPCPlatform(GMaxRHIShaderPlatform))
|
|
{
|
|
static auto* CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("OpenGL.UseEmulatedUBs"));
|
|
GUseEmulatedUniformBuffers = CVar && CVar->GetValueOnAnyThread() != 0;
|
|
}
|
|
|
|
FString FeatureLevelName;
|
|
GetFeatureLevelName(GMaxRHIFeatureLevel, FeatureLevelName);
|
|
FString ShaderPlatformName = LegacyShaderPlatformToShaderFormat(GMaxRHIShaderPlatform).ToString();
|
|
|
|
UE_LOG(LogRHI, Log, TEXT("OpenGL MajorVersion = %d, MinorVersion = %d, ShaderPlatform = %s, FeatureLevel = %s"), MajorVersion, MinorVersion, *ShaderPlatformName, *FeatureLevelName);
|
|
#if PLATFORM_ANDROIDGL4
|
|
UE_LOG(LogRHI, Log, TEXT("PLATFORM_ANDROIDGL4"));
|
|
#elif PLATFORM_ANDROIDES31
|
|
UE_LOG(LogRHI, Log, TEXT("PLATFORM_ANDROIDES31"));
|
|
#elif PLATFORM_ANDROID
|
|
UE_LOG(LogRHI, Log, TEXT("PLATFORM_ANDROID"));
|
|
#endif
|
|
|
|
GMaxTextureMipCount = FMath::CeilLogTwo(Value_GL_MAX_TEXTURE_SIZE) + 1;
|
|
GMaxTextureMipCount = FMath::Min<int32>(MAX_TEXTURE_MIP_COUNT, GMaxTextureMipCount);
|
|
GMaxTextureDimensions = Value_GL_MAX_TEXTURE_SIZE;
|
|
GMaxCubeTextureDimensions = Value_GL_MAX_CUBE_MAP_TEXTURE_SIZE;
|
|
#if GL_MAX_ARRAY_TEXTURE_LAYERS
|
|
GMaxTextureArrayLayers = Value_GL_MAX_ARRAY_TEXTURE_LAYERS;
|
|
#endif
|
|
|
|
GSupportsVolumeTextureRendering = FOpenGL::SupportsVolumeTextureRendering();
|
|
GSupportsRenderDepthTargetableShaderResources = true;
|
|
GSupportsRenderTargetFormat_PF_G8 = true;
|
|
GSupportsSeparateRenderTargetBlendState = FOpenGL::SupportsSeparateAlphaBlend();
|
|
GSupportsDepthBoundsTest = FOpenGL::SupportsDepthBoundsTest();
|
|
|
|
GSupportsRenderTargetFormat_PF_FloatRGBA = FOpenGL::SupportsColorBufferHalfFloat();
|
|
|
|
GSupportsMultipleRenderTargets = FOpenGL::SupportsMultipleRenderTargets();
|
|
GSupportsWideMRT = FOpenGL::SupportsWideMRT();
|
|
GSupportsTexture3D = FOpenGL::SupportsTexture3D();
|
|
GSupportsResourceView = FOpenGL::SupportsResourceView();
|
|
|
|
GSupportsShaderFramebufferFetch = FOpenGL::SupportsShaderFramebufferFetch();
|
|
GSupportsShaderDepthStencilFetch = FOpenGL::SupportsShaderDepthStencilFetch();
|
|
GMaxShadowDepthBufferSizeX = FMath::Min<int32>(Value_GL_MAX_RENDERBUFFER_SIZE, 4096); // Limit to the D3D11 max.
|
|
GMaxShadowDepthBufferSizeY = FMath::Min<int32>(Value_GL_MAX_RENDERBUFFER_SIZE, 4096);
|
|
GHardwareHiddenSurfaceRemoval = FOpenGL::HasHardwareHiddenSurfaceRemoval();
|
|
GRHISupportsInstancing = FOpenGL::SupportsInstancing(); // HTML5 does not support it. Android supports it with OpenGL ES3.0+
|
|
GSupportsTimestampRenderQueries = FOpenGL::SupportsTimestampQueries();
|
|
|
|
GSupportsHDR32bppEncodeModeIntrinsic = FOpenGL::SupportsHDR32bppEncodeModeIntrinsic();
|
|
|
|
GShaderPlatformForFeatureLevel[ERHIFeatureLevel::ES2] = (GMaxRHIFeatureLevel == ERHIFeatureLevel::ES2) ? GMaxRHIShaderPlatform : SP_OPENGL_PCES2;
|
|
GShaderPlatformForFeatureLevel[ERHIFeatureLevel::ES3_1] = (GMaxRHIFeatureLevel == ERHIFeatureLevel::ES3_1) ? GMaxRHIShaderPlatform : SP_OPENGL_PCES3_1;
|
|
GShaderPlatformForFeatureLevel[ERHIFeatureLevel::SM4] = PLATFORM_MAC ? SP_OPENGL_SM4_MAC : SP_OPENGL_SM4;
|
|
GShaderPlatformForFeatureLevel[ERHIFeatureLevel::SM5] = OPENGL_ES31 ? SP_OPENGL_ES31_EXT : SP_OPENGL_SM5;
|
|
|
|
// Set to same values as in DX11, as for the time being clip space adjustment are done entirely
|
|
// in HLSLCC-generated shader code and OpenGLDrv.
|
|
GMinClipZ = 0.0f;
|
|
GProjectionSignY = 1.0f;
|
|
|
|
// Disable texture streaming on ES2 unless we have the GL_APPLE_copy_texture_levels extension
|
|
if (GMaxRHIFeatureLevel == ERHIFeatureLevel::ES2 && !FOpenGL::SupportsCopyTextureLevels())
|
|
{
|
|
GRHISupportsTextureStreaming = false;
|
|
}
|
|
else
|
|
{
|
|
GRHISupportsTextureStreaming = true;
|
|
}
|
|
|
|
GVertexElementTypeSupport.SetSupported(VET_Half2, FOpenGL::SupportsVertexHalfFloat());
|
|
GVertexElementTypeSupport.SetSupported(VET_Half4, FOpenGL::SupportsVertexHalfFloat());
|
|
GVertexElementTypeSupport.SetSupported(VET_URGB10A2N, FOpenGL::SupportsRGB10A2());
|
|
|
|
for (int32 PF = 0; PF < PF_MAX; ++PF)
|
|
{
|
|
SetupTextureFormat(EPixelFormat(PF), FOpenGLTextureFormat());
|
|
}
|
|
|
|
GLenum DepthFormat = FOpenGL::GetDepthFormat();
|
|
GLenum ShadowDepthFormat = FOpenGL::GetShadowDepthFormat();
|
|
|
|
// Initialize the platform pixel format map. InternalFormat InternalFormatSRGB Format Type bCompressed bBGRA
|
|
SetupTextureFormat( PF_Unknown, FOpenGLTextureFormat( ));
|
|
SetupTextureFormat( PF_A32B32G32R32F, FOpenGLTextureFormat( GL_RGBA32F, GL_NONE, GL_RGBA, GL_FLOAT, false, false));
|
|
SetupTextureFormat( PF_UYVY, FOpenGLTextureFormat( ));
|
|
//@todo: ES2 requires GL_OES_depth_texture extension to support depth textures of any kind.
|
|
SetupTextureFormat( PF_ShadowDepth, FOpenGLTextureFormat( ShadowDepthFormat, GL_NONE, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, false, false));
|
|
SetupTextureFormat( PF_D24, FOpenGLTextureFormat( DepthFormat, GL_NONE, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, false, false));
|
|
SetupTextureFormat( PF_A16B16G16R16, FOpenGLTextureFormat( GL_RGBA16, GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, false, false));
|
|
SetupTextureFormat( PF_A1, FOpenGLTextureFormat( ));
|
|
SetupTextureFormat( PF_R16G16B16A16_UINT, FOpenGLTextureFormat( GL_RGBA16UI, GL_NONE, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, false, false));
|
|
SetupTextureFormat( PF_R16G16B16A16_SINT, FOpenGLTextureFormat( GL_RGBA16I, GL_NONE, GL_RGBA_INTEGER, GL_SHORT, false, false));
|
|
SetupTextureFormat( PF_R5G6B5_UNORM, FOpenGLTextureFormat( ));
|
|
#if PLATFORM_DESKTOP || PLATFORM_ANDROIDGL4 || PLATFORM_ANDROIDES31
|
|
CA_SUPPRESS(6286);
|
|
if (PLATFORM_DESKTOP || PLATFORM_ANDROIDGL4 || FOpenGL::GetFeatureLevel() >= ERHIFeatureLevel::SM4)
|
|
{
|
|
// Not supported for rendering:
|
|
SetupTextureFormat( PF_G16, FOpenGLTextureFormat( GL_R16, GL_R16, GL_RED, GL_UNSIGNED_SHORT, false, false));
|
|
SetupTextureFormat( PF_R32_FLOAT, FOpenGLTextureFormat( GL_R32F, GL_R32F, GL_RED, GL_FLOAT, false, false));
|
|
SetupTextureFormat( PF_G16R16F, FOpenGLTextureFormat( GL_RG16F, GL_RG16F, GL_RG, GL_HALF_FLOAT, false, false));
|
|
SetupTextureFormat( PF_G16R16F_FILTER, FOpenGLTextureFormat( GL_RG16F, GL_RG16F, GL_RG, GL_HALF_FLOAT, false, false));
|
|
SetupTextureFormat( PF_G32R32F, FOpenGLTextureFormat( GL_RG32F, GL_RG32F, GL_RG, GL_FLOAT, false, false));
|
|
SetupTextureFormat( PF_A2B10G10R10, FOpenGLTextureFormat( GL_RGB10_A2, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, false, false));
|
|
SetupTextureFormat( PF_R16F, FOpenGLTextureFormat( GL_R16F, GL_R16F, GL_RED, GL_HALF_FLOAT, false, false));
|
|
SetupTextureFormat( PF_R16F_FILTER, FOpenGLTextureFormat( GL_R16F, GL_R16F, GL_RED, GL_HALF_FLOAT, false, false));
|
|
if (FOpenGL::SupportsR11G11B10F())
|
|
{
|
|
// Note: Also needs to include support for compute shaders to be defined here (e.g. glBindImageTexture)
|
|
SetupTextureFormat(PF_FloatRGB, FOpenGLTextureFormat(GL_R11F_G11F_B10F, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, false, false));
|
|
SetupTextureFormat(PF_FloatR11G11B10, FOpenGLTextureFormat(GL_RGBA16F, GL_RGBA16F, GL_RGB, GL_HALF_FLOAT, false, false));
|
|
}
|
|
else
|
|
{
|
|
SetupTextureFormat(PF_FloatRGB, FOpenGLTextureFormat(GL_RGBA16F, GL_RGBA16F, GL_RGB, GL_HALF_FLOAT, false, false));
|
|
SetupTextureFormat(PF_FloatR11G11B10, FOpenGLTextureFormat(GL_R11F_G11F_B10F, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, false, false));
|
|
}
|
|
SetupTextureFormat(PF_V8U8, FOpenGLTextureFormat(GL_RG8_SNORM, GL_NONE, GL_RG, GL_BYTE, false, false));
|
|
SetupTextureFormat( PF_R8G8, FOpenGLTextureFormat( GL_RG8, GL_NONE, GL_RG, GL_UNSIGNED_BYTE, false, false));
|
|
SetupTextureFormat( PF_BC5, FOpenGLTextureFormat( GL_COMPRESSED_RG_RGTC2, GL_COMPRESSED_RG_RGTC2, GL_RG, GL_UNSIGNED_BYTE, true, false));
|
|
SetupTextureFormat( PF_BC4, FOpenGLTextureFormat( GL_COMPRESSED_RED_RGTC1, GL_COMPRESSED_RED_RGTC1,GL_RED, GL_UNSIGNED_BYTE, true, false));
|
|
SetupTextureFormat( PF_A8, FOpenGLTextureFormat( GL_R8, GL_NONE, GL_RED, GL_UNSIGNED_BYTE, false, false));
|
|
SetupTextureFormat( PF_R32_UINT, FOpenGLTextureFormat( GL_R32UI, GL_NONE, GL_RED_INTEGER, GL_UNSIGNED_INT, false, false));
|
|
SetupTextureFormat( PF_R32_SINT, FOpenGLTextureFormat( GL_R32I, GL_NONE, GL_RED_INTEGER, GL_INT, false, false));
|
|
SetupTextureFormat( PF_R16_UINT, FOpenGLTextureFormat( GL_R16UI, GL_NONE, GL_RED_INTEGER, GL_UNSIGNED_SHORT, false, false));
|
|
SetupTextureFormat( PF_R16_SINT, FOpenGLTextureFormat( GL_R16I, GL_NONE, GL_RED_INTEGER, GL_SHORT, false, false));
|
|
SetupTextureFormat( PF_R8_UINT, FOpenGLTextureFormat( GL_R8UI, GL_NONE, GL_RED_INTEGER, GL_UNSIGNED_BYTE, false, false));
|
|
SetupTextureFormat( PF_FloatRGBA, FOpenGLTextureFormat( GL_RGBA16F, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, false, false));
|
|
if (FOpenGL::GetShaderPlatform() == EShaderPlatform::SP_OPENGL_ES31_EXT)
|
|
{
|
|
SetupTextureFormat(PF_G8, FOpenGLTextureFormat(GL_R8, GL_R8, GL_RED, GL_UNSIGNED_BYTE, false, false));
|
|
SetupTextureFormat(PF_B8G8R8A8, FOpenGLTextureFormat(GL_RGBA8, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, false, true));
|
|
SetupTextureFormat(PF_R8G8B8A8, FOpenGLTextureFormat(GL_RGBA8, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, false, false));
|
|
if (FOpenGL::SupportsRG16UI())
|
|
{
|
|
// The user should check for support for PF_G16R16 and implement a fallback if it's not supported!
|
|
SetupTextureFormat(PF_G16R16, FOpenGLTextureFormat(GL_RG16, GL_RG16, GL_RG, GL_UNSIGNED_SHORT, false, false));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetupTextureFormat(PF_G8, FOpenGLTextureFormat(GL_R8, GL_SRGB8, GL_RED, GL_UNSIGNED_BYTE, false, false));
|
|
SetupTextureFormat(PF_B8G8R8A8, FOpenGLTextureFormat(GL_RGBA8, GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, false, false));
|
|
SetupTextureFormat(PF_R8G8B8A8, FOpenGLTextureFormat(GL_RGBA8, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false, false));
|
|
SetupTextureFormat(PF_G16R16, FOpenGLTextureFormat(GL_RG16, GL_RG16, GL_RG, GL_UNSIGNED_SHORT, false, false));
|
|
}
|
|
if (FOpenGL::SupportsPackedDepthStencil())
|
|
{
|
|
SetupTextureFormat(PF_DepthStencil, FOpenGLTextureFormat(GL_DEPTH24_STENCIL8, GL_NONE, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, false, false));
|
|
}
|
|
else
|
|
{
|
|
// @todo android: This is cheating by not setting a stencil anywhere, need that! And Shield is still rendering black scene
|
|
SetupTextureFormat(PF_DepthStencil, FOpenGLTextureFormat(DepthFormat, GL_NONE, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, false, false));
|
|
}
|
|
}
|
|
else
|
|
#endif // PLATFORM_DESKTOP || PLATFORM_ANDROIDGL4 || PLATFORM_ANDROIDES31
|
|
{
|
|
#if !PLATFORM_DESKTOP && !PLATFORM_ANDROIDGL4
|
|
// ES2-based cases
|
|
GLuint BGRA8888 = FOpenGL::SupportsBGRA8888() ? GL_BGRA_EXT : GL_RGBA;
|
|
GLuint RGBA8 = FOpenGL::SupportsRGBA8() ? GL_RGBA8_OES : GL_RGBA;
|
|
|
|
#if PLATFORM_ANDROID
|
|
SetupTextureFormat(PF_B8G8R8A8, FOpenGLTextureFormat(BGRA8888, FOpenGL::SupportsSRGB() ? GL_SRGB_ALPHA_EXT : BGRA8888, BGRA8888, GL_UNSIGNED_BYTE, false, false));
|
|
#else
|
|
SetupTextureFormat(PF_B8G8R8A8, FOpenGLTextureFormat(GL_RGBA, FOpenGL::SupportsSRGB() ? GL_SRGB_ALPHA_EXT : GL_RGBA, GL_BGRA8_EXT, FOpenGL::SupportsSRGB() ? GL_SRGB8_ALPHA8_EXT : GL_BGRA8_EXT, BGRA8888, GL_UNSIGNED_BYTE, false, false));
|
|
#endif
|
|
SetupTextureFormat(PF_R8G8B8A8, FOpenGLTextureFormat(RGBA8, FOpenGL::SupportsSRGB() ? GL_SRGB_ALPHA_EXT : RGBA8, GL_RGBA8, FOpenGL::SupportsSRGB() ? GL_SRGB8_ALPHA8_EXT : GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false, false));
|
|
#if PLATFORM_IOS
|
|
SetupTextureFormat(PF_G8, FOpenGLTextureFormat(GL_LUMINANCE, GL_LUMINANCE, GL_LUMINANCE8_EXT, GL_LUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE, false, false));
|
|
SetupTextureFormat(PF_A8, FOpenGLTextureFormat(GL_ALPHA, GL_ALPHA, GL_ALPHA8_EXT, GL_ALPHA8_EXT, GL_ALPHA, GL_UNSIGNED_BYTE, false, false));
|
|
#else
|
|
SetupTextureFormat(PF_G8, FOpenGLTextureFormat(GL_LUMINANCE, GL_LUMINANCE, GL_LUMINANCE, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, false, false));
|
|
SetupTextureFormat(PF_A8, FOpenGLTextureFormat(GL_ALPHA, GL_ALPHA, GL_ALPHA, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, false, false));
|
|
#endif
|
|
|
|
if (FOpenGL::SupportsColorBufferHalfFloat() && FOpenGL::SupportsTextureHalfFloat())
|
|
{
|
|
#if PLATFORM_ANDROID
|
|
SetupTextureFormat(PF_FloatRGBA, FOpenGLTextureFormat(GL_RGBA, GL_RGBA, GL_RGBA16F_EXT, GL_RGBA16F_EXT, GL_RGBA, GL_HALF_FLOAT_OES, false, false));
|
|
#else
|
|
SetupTextureFormat(PF_FloatRGBA, FOpenGLTextureFormat(GL_RGBA, GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES, false, false));
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
SetupTextureFormat( PF_FloatRGBA, FOpenGLTextureFormat(GL_RGBA, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, false, false));
|
|
}
|
|
|
|
if (FOpenGL::SupportsColorBufferFloat())
|
|
{
|
|
SetupTextureFormat( PF_G16, FOpenGLTextureFormat( GL_R16, GL_R16, GL_RED, GL_UNSIGNED_SHORT, false, false));
|
|
SetupTextureFormat( PF_R32_FLOAT, FOpenGLTextureFormat( GL_R32F, GL_R32F, GL_RED, GL_FLOAT, false, false));
|
|
#ifdef GL_RG_EXT
|
|
SetupTextureFormat( PF_G16R16F, FOpenGLTextureFormat( GL_RG16F, GL_RG16F, GL_RG_EXT, GL_HALF_FLOAT, false, false));
|
|
SetupTextureFormat( PF_G16R16F_FILTER, FOpenGLTextureFormat( GL_RG16F, GL_RG16F, GL_RG_EXT, GL_HALF_FLOAT, false, false));
|
|
SetupTextureFormat( PF_G32R32F, FOpenGLTextureFormat( GL_RG32F, GL_RG32F, GL_RG_EXT, GL_FLOAT, false, false));
|
|
#endif
|
|
#ifdef GL_UNSIGNED_INT_2_10_10_10_REV
|
|
SetupTextureFormat( PF_A2B10G10R10, FOpenGLTextureFormat( GL_RGB10_A2, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, false, false));
|
|
#endif
|
|
SetupTextureFormat( PF_R16F, FOpenGLTextureFormat( GL_R16F, GL_R16F, GL_RED, GL_HALF_FLOAT, false, false));
|
|
SetupTextureFormat( PF_R16F_FILTER, FOpenGLTextureFormat( GL_R16F, GL_R16F, GL_RED, GL_HALF_FLOAT, false, false));
|
|
}
|
|
|
|
if (FOpenGL::SupportsPackedDepthStencil())
|
|
{
|
|
SetupTextureFormat(PF_DepthStencil, FOpenGLTextureFormat(GL_DEPTH_STENCIL_OES, GL_NONE, GL_DEPTH_STENCIL_OES, GL_UNSIGNED_INT_24_8_OES, false, false));
|
|
}
|
|
else
|
|
{
|
|
// @todo android: This is cheating by not setting a stencil anywhere, need that! And Shield is still rendering black scene
|
|
SetupTextureFormat(PF_DepthStencil, FOpenGLTextureFormat(GL_DEPTH_COMPONENT, GL_NONE, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, false, false));
|
|
}
|
|
#endif // !PLATFORM_DESKTOP
|
|
}
|
|
|
|
if (FOpenGL::SupportsDXT())
|
|
{
|
|
if ( FOpenGL::SupportsSRGB() )
|
|
{
|
|
SetupTextureFormat( PF_DXT1, FOpenGLTextureFormat(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true, false));
|
|
SetupTextureFormat( PF_DXT3, FOpenGLTextureFormat(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true, false));
|
|
SetupTextureFormat( PF_DXT5, FOpenGLTextureFormat(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true, false));
|
|
}
|
|
else
|
|
{
|
|
// WebGL does not support SRGB versions of DXTn texture formats! Run with SRGB formats disabled. Will need to make sure
|
|
// sRGB is always emulated if it's needed.
|
|
SetupTextureFormat( PF_DXT1, FOpenGLTextureFormat(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true, false));
|
|
SetupTextureFormat( PF_DXT3, FOpenGLTextureFormat(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true, false));
|
|
SetupTextureFormat( PF_DXT5, FOpenGLTextureFormat(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true, false));
|
|
}
|
|
}
|
|
if ( FOpenGL::SupportsPVRTC() )
|
|
{
|
|
SetupTextureFormat( PF_PVRTC2, FOpenGLTextureFormat(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, GL_RGBA, GL_UNSIGNED_BYTE, true, false));
|
|
SetupTextureFormat( PF_PVRTC4, FOpenGLTextureFormat(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, GL_RGBA, GL_UNSIGNED_BYTE, true, false));
|
|
}
|
|
if ( FOpenGL::SupportsATITC() )
|
|
{
|
|
SetupTextureFormat( PF_ATC_RGB, FOpenGLTextureFormat(GL_ATC_RGB_AMD, GL_ATC_RGB_AMD, GL_RGBA, GL_UNSIGNED_BYTE, true, false));
|
|
SetupTextureFormat( PF_ATC_RGBA_E, FOpenGLTextureFormat(GL_ATC_RGBA_EXPLICIT_ALPHA_AMD, GL_ATC_RGBA_EXPLICIT_ALPHA_AMD, GL_RGBA, GL_UNSIGNED_BYTE, true, false));
|
|
SetupTextureFormat( PF_ATC_RGBA_I, FOpenGLTextureFormat(GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD, GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD, GL_RGBA, GL_UNSIGNED_BYTE, true, false));
|
|
}
|
|
if ( FOpenGL::SupportsETC1() )
|
|
{
|
|
SetupTextureFormat( PF_ETC1, FOpenGLTextureFormat(GL_ETC1_RGB8_OES, GL_ETC1_RGB8_OES, GL_RGBA, GL_UNSIGNED_BYTE, true, false));
|
|
}
|
|
#if PLATFORM_ANDROID
|
|
if ( FOpenGL::SupportsETC2() )
|
|
{
|
|
SetupTextureFormat( PF_ETC2_RGB, FOpenGLTextureFormat(GL_COMPRESSED_RGB8_ETC2, FOpenGL::SupportsSRGB() ? GL_COMPRESSED_SRGB8_ETC2 : GL_COMPRESSED_RGB8_ETC2, GL_RGBA, GL_UNSIGNED_BYTE, true, false));
|
|
SetupTextureFormat( PF_ETC2_RGBA, FOpenGLTextureFormat(GL_COMPRESSED_RGBA8_ETC2_EAC, FOpenGL::SupportsSRGB() ? GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : GL_COMPRESSED_RGBA8_ETC2_EAC, GL_RGBA, GL_UNSIGNED_BYTE, true, false));
|
|
}
|
|
#endif
|
|
if (FOpenGL::SupportsASTC())
|
|
{
|
|
SetupTextureFormat( PF_ASTC_4x4, FOpenGLTextureFormat(GL_COMPRESSED_RGBA_ASTC_4x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, GL_RGBA, GL_UNSIGNED_BYTE, true, false) );
|
|
SetupTextureFormat( PF_ASTC_6x6, FOpenGLTextureFormat(GL_COMPRESSED_RGBA_ASTC_6x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, GL_RGBA, GL_UNSIGNED_BYTE, true, false) );
|
|
SetupTextureFormat( PF_ASTC_8x8, FOpenGLTextureFormat(GL_COMPRESSED_RGBA_ASTC_8x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, GL_RGBA, GL_UNSIGNED_BYTE, true, false) );
|
|
SetupTextureFormat( PF_ASTC_10x10, FOpenGLTextureFormat(GL_COMPRESSED_RGBA_ASTC_10x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, GL_RGBA, GL_UNSIGNED_BYTE, true, false) );
|
|
SetupTextureFormat( PF_ASTC_12x12, FOpenGLTextureFormat(GL_COMPRESSED_RGBA_ASTC_12x12_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, GL_RGBA, GL_UNSIGNED_BYTE, true, false) );
|
|
}
|
|
|
|
// Some formats need to know how large a block is.
|
|
GPixelFormats[ PF_DepthStencil ].BlockBytes = 4;
|
|
GPixelFormats[ PF_FloatRGB ].BlockBytes = 4;
|
|
GPixelFormats[ PF_FloatRGBA ].BlockBytes = 8;
|
|
}
|
|
|
|
FOpenGLDynamicRHI::FOpenGLDynamicRHI()
|
|
: SceneFrameCounter(0)
|
|
, ResourceTableFrameCounter(INDEX_NONE)
|
|
, bRevertToSharedContextAfterDrawingViewport(false)
|
|
, bIsRenderingContextAcquired(false)
|
|
, PlatformDevice(NULL)
|
|
, GPUProfilingData(this)
|
|
{
|
|
// This should be called once at the start
|
|
check( IsInGameThread() );
|
|
check( !GIsThreadedRendering );
|
|
|
|
PlatformInitOpenGL();
|
|
PlatformDevice = PlatformCreateOpenGLDevice();
|
|
VERIFY_GL_SCOPE();
|
|
InitRHICapabilitiesForGL();
|
|
|
|
check(PlatformOpenGLCurrentContext(PlatformDevice) == CONTEXT_Shared);
|
|
|
|
PrivateOpenGLDevicePtr = this;
|
|
}
|
|
|
|
extern void DestroyShadersAndPrograms();
|
|
|
|
#if PLATFORM_ANDROID
|
|
// only used to test for shader compatibility issues
|
|
static bool VerifyCompiledShader(GLuint Shader, const ANSICHAR* GlslCode, bool IsFatal )
|
|
{
|
|
SCOPE_CYCLE_COUNTER(STAT_OpenGLShaderCompileVerifyTime);
|
|
|
|
GLint CompileStatus;
|
|
glGetShaderiv(Shader, GL_COMPILE_STATUS, &CompileStatus);
|
|
if (CompileStatus != GL_TRUE)
|
|
{
|
|
GLint LogLength;
|
|
ANSICHAR DefaultLog[] = "No log";
|
|
ANSICHAR *CompileLog = DefaultLog;
|
|
glGetShaderiv(Shader, GL_INFO_LOG_LENGTH, &LogLength);
|
|
#if PLATFORM_ANDROID
|
|
if ( LogLength == 0 )
|
|
{
|
|
// make it big anyway
|
|
// there was a bug in android 2.2 where glGetShaderiv would return 0 even though there was a error message
|
|
// https://code.google.com/p/android/issues/detail?id=9953
|
|
LogLength = 4096;
|
|
}
|
|
#endif
|
|
if (LogLength > 1)
|
|
{
|
|
CompileLog = (ANSICHAR *)FMemory::Malloc(LogLength);
|
|
glGetShaderInfoLog(Shader, LogLength, NULL, CompileLog);
|
|
}
|
|
|
|
#if DEBUG_GL_SHADERS
|
|
if (GlslCode)
|
|
{
|
|
UE_LOG(LogRHI,Warning,TEXT("Shader:\n%s"),ANSI_TO_TCHAR(GlslCode));
|
|
|
|
|
|
const ANSICHAR *Temp = GlslCode;
|
|
|
|
for ( int i = 0; i < 30 && (*Temp != '\0'); ++i )
|
|
{
|
|
FString Converted = ANSI_TO_TCHAR( Temp );
|
|
Converted.LeftChop( 256 );
|
|
|
|
UE_LOG(LogRHI,Display,TEXT("%s"), *Converted );
|
|
Temp += Converted.Len();
|
|
}
|
|
|
|
}
|
|
#endif
|
|
UE_LOG(LogRHI,Warning,TEXT("Failed to compile shader. Compile log:\n%s"), ANSI_TO_TCHAR(CompileLog));
|
|
|
|
if (LogLength > 1)
|
|
{
|
|
FMemory::Free(CompileLog);
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
static void CheckVaryingLimit()
|
|
{
|
|
#if PLATFORM_ANDROID
|
|
FOpenGL::bRequiresGLFragCoordVaryingLimitHack = false;
|
|
if (IsES2Platform(GMaxRHIShaderPlatform))
|
|
{
|
|
// Some mobile GPUs require an available varying vector to support gl_FragCoord.
|
|
// If there are only 8 supported, it is possible to run out of varyings on these
|
|
// GPUs so test to see if need to fake gl_FragCoord with the assumption it is
|
|
// used for mobile HDR mosaic.
|
|
|
|
// Do not need to do this check if more than 8 varyings supported
|
|
if (FOpenGL::GetMaxVaryingVectors() > 8)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Make sure MobileHDR is on and device needs mosaic
|
|
static auto* MobileHDRCvar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.MobileHDR"));
|
|
static auto* MobileHDR32bppModeCvar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.MobileHDR32bppMode"));
|
|
|
|
const bool bMobileHDR32bpp = (MobileHDRCvar && MobileHDRCvar->GetValueOnAnyThread() == 1)
|
|
&& (FAndroidMisc::SupportsFloatingPointRenderTargets() == false || (MobileHDR32bppModeCvar && MobileHDR32bppModeCvar->GetValueOnAnyThread() != 0));
|
|
const bool bRequiresMosaic = bMobileHDR32bpp && (!FAndroidMisc::SupportsShaderFramebufferFetch() || (MobileHDR32bppModeCvar && MobileHDR32bppModeCvar->GetValueOnAnyThread() == 1));
|
|
|
|
if (!bRequiresMosaic)
|
|
{
|
|
return;
|
|
}
|
|
|
|
UE_LOG(LogRHI, Display, TEXT("Testing for gl_FragCoord requiring a varying since mosaic is enabled"));
|
|
FOpenGL::bIsCheckingShaderCompilerHacks = true;
|
|
|
|
static const ANSICHAR TestVertexProgram[] = "\n"
|
|
"#version 100\n"
|
|
"attribute vec4 in_ATTRIBUTE0;\n"
|
|
"attribute vec4 in_ATTRIBUTE1;\n"
|
|
"varying highp vec4 TexCoord0;\n"
|
|
"varying highp vec4 TexCoord1;\n"
|
|
"varying highp vec4 TexCoord2;\n"
|
|
"varying highp vec4 TexCoord3;\n"
|
|
"varying highp vec4 TexCoord4;\n"
|
|
"varying highp vec4 TexCoord5;\n"
|
|
"varying highp vec4 TexCoord6;\n"
|
|
"varying highp vec4 TexCoord7;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" TexCoord0 = in_ATTRIBUTE1 * vec4(0.1,0.2,0.3,0.4);\n"
|
|
" TexCoord1 = in_ATTRIBUTE1 * vec4(0.5,0.6,0.7,0.8);\n"
|
|
" TexCoord2 = in_ATTRIBUTE1 * vec4(0.12,0.22,0.32,0.42);\n"
|
|
" TexCoord3 = in_ATTRIBUTE1 * vec4(0.52,0.62,0.72,0.82);\n"
|
|
" TexCoord4 = in_ATTRIBUTE1 * vec4(0.14,0.24,0.34,0.44);\n"
|
|
" TexCoord5 = in_ATTRIBUTE1 * vec4(0.54,0.64,0.74,0.84);\n"
|
|
" TexCoord6 = in_ATTRIBUTE1 * vec4(0.16,0.26,0.36,0.46);\n"
|
|
" TexCoord7 = in_ATTRIBUTE1 * vec4(0.56,0.66,0.76,0.86);\n"
|
|
" gl_Position.xyzw = in_ATTRIBUTE0;\n"
|
|
"}\n";
|
|
static const ANSICHAR TestFragmentProgram[] = "\n"
|
|
"#version 100\n"
|
|
"varying highp vec4 TexCoord0;\n"
|
|
"varying highp vec4 TexCoord1;\n"
|
|
"varying highp vec4 TexCoord2;\n"
|
|
"varying highp vec4 TexCoord3;\n"
|
|
"varying highp vec4 TexCoord4;\n"
|
|
"varying highp vec4 TexCoord5;\n"
|
|
"varying highp vec4 TexCoord6;\n"
|
|
"varying highp vec4 TexCoord7;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_FragColor = TexCoord0 * TexCoord1 * TexCoord2 * TexCoord3 * TexCoord4 * TexCoord5 * TexCoord6 * TexCoord7 * gl_FragCoord.xyxy;"
|
|
"}\n";
|
|
|
|
FShaderCode VertexShaderCode;
|
|
{
|
|
FOpenGLCodeHeader Header;
|
|
Header.FrequencyMarker = 0x5653;
|
|
Header.GlslMarker = 0x474c534c;
|
|
|
|
FMemoryWriter Writer(VertexShaderCode.GetWriteAccess(), true);
|
|
Writer << Header;
|
|
Writer.Serialize((void*)TestVertexProgram, sizeof(TestVertexProgram));
|
|
Writer.Close();
|
|
}
|
|
|
|
FShaderCode FragmentShaderCode;
|
|
{
|
|
FOpenGLCodeHeader Header;
|
|
Header.FrequencyMarker = 0x5053;
|
|
Header.GlslMarker = 0x474c534c;
|
|
|
|
FMemoryWriter Writer(FragmentShaderCode.GetWriteAccess(), true);
|
|
Writer << Header;
|
|
Writer.Serialize((void*)(TestFragmentProgram), sizeof(TestFragmentProgram));
|
|
Writer.Close();
|
|
}
|
|
|
|
// Try to compile test shaders
|
|
TRefCountPtr<FOpenGLVertexShader> VertexShader = (FOpenGLVertexShader*)(RHICreateVertexShader(VertexShaderCode.GetReadAccess()).GetReference());
|
|
if (!VerifyCompiledShader(VertexShader->Resource, TestVertexProgram, false))
|
|
{
|
|
UE_LOG(LogRHI, Warning, TEXT("Vertex shader for varying test failed to compile. Try running anyway."));
|
|
FOpenGL::bIsCheckingShaderCompilerHacks = false;
|
|
return;
|
|
}
|
|
TRefCountPtr<FOpenGLPixelShader> PixelShader = (FOpenGLPixelShader*)(RHICreatePixelShader(FragmentShaderCode.GetReadAccess()).GetReference());
|
|
if (!VerifyCompiledShader(PixelShader->Resource, TestFragmentProgram, false))
|
|
{
|
|
UE_LOG(LogRHI, Warning, TEXT("Fragment shader for varying test failed to compile. Try running anyway."));
|
|
FOpenGL::bIsCheckingShaderCompilerHacks = false;
|
|
return;
|
|
}
|
|
|
|
FOpenGL::bIsCheckingShaderCompilerHacks = false;
|
|
|
|
// Now try linking them.. this is where gl_FragCoord may cause a failure
|
|
GLuint Program = glCreateProgram();
|
|
glAttachShader(Program, VertexShader->Resource);
|
|
glAttachShader(Program, PixelShader->Resource);
|
|
glLinkProgram(Program);
|
|
GLint LinkStatus = 0;
|
|
glGetProgramiv(Program, GL_LINK_STATUS, &LinkStatus);
|
|
if (LinkStatus != GL_TRUE)
|
|
{
|
|
FOpenGL::bRequiresGLFragCoordVaryingLimitHack = true;
|
|
UE_LOG(LogRHI, Warning, TEXT("gl_FragCoord uses a varying... enabled hack"));
|
|
return;
|
|
}
|
|
|
|
UE_LOG(LogRHI, Warning, TEXT("gl_FragCoord does not need a varying"));
|
|
}
|
|
#elif PLATFORM_IOS
|
|
if (IsES2Platform(GMaxRHIShaderPlatform))
|
|
{
|
|
FOpenGL::bIsLimitingShaderCompileCount = FPlatformMisc::GetIOSDeviceType() == FPlatformMisc::IOS_IPad4;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void CheckTextureCubeLodSupport()
|
|
{
|
|
#if PLATFORM_ANDROID
|
|
if (IsES2Platform(GMaxRHIShaderPlatform))
|
|
{
|
|
UE_LOG(LogRHI, Display, TEXT("Testing for shader compiler compatibility"));
|
|
FOpenGL::bIsCheckingShaderCompilerHacks = true;
|
|
|
|
// This code creates a sample program and finds out which hacks are required to compile it
|
|
static const ANSICHAR TestFragmentProgram[] = "\n"
|
|
"#version 100\n"
|
|
"#ifndef DONTEMITEXTENSIONSHADERTEXTURELODENABLE\n"
|
|
"#extension GL_EXT_shader_texture_lod : enable\n"
|
|
"#endif\n"
|
|
"precision mediump float;\n"
|
|
"precision mediump int;\n"
|
|
"#ifndef DONTEMITSAMPLERDEFAULTPRECISION\n"
|
|
"precision mediump sampler2D;\n"
|
|
"precision mediump samplerCube;\n"
|
|
"#endif\n"
|
|
"varying vec3 TexCoord;\n"
|
|
"uniform samplerCube Texture;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_FragColor = textureCubeLodEXT(Texture,TexCoord, 4.0);\n"
|
|
"}\n";
|
|
|
|
FOpenGL::bRequiresDontEmitPrecisionForTextureSamplers = false;
|
|
FOpenGL::bRequiresTextureCubeLodEXTToTextureCubeLodDefine = false;
|
|
|
|
FShaderCode ShaderCode;
|
|
{
|
|
FOpenGLCodeHeader Header;
|
|
Header.FrequencyMarker = 0x5053;
|
|
Header.GlslMarker = 0x474c534c;
|
|
|
|
FMemoryWriter Writer(ShaderCode.GetWriteAccess(), true);
|
|
Writer << Header;
|
|
Writer.Serialize((void*)TestFragmentProgram, sizeof(TestFragmentProgram));
|
|
Writer.Close();
|
|
}
|
|
const TArray<uint8>& Code = ShaderCode.GetReadAccess();
|
|
|
|
// try to compile without any hacks
|
|
TRefCountPtr<FOpenGLPixelShader> PixelShader = (FOpenGLPixelShader*)(RHICreatePixelShader(Code).GetReference());
|
|
|
|
if (VerifyCompiledShader(PixelShader->Resource, TestFragmentProgram, false))
|
|
{
|
|
UE_LOG(LogRHI, Display, TEXT("Shaders compile fine no need to enable hacks"));
|
|
// we are done
|
|
FOpenGL::bIsCheckingShaderCompilerHacks = false;
|
|
return;
|
|
}
|
|
|
|
FOpenGL::bRequiresDontEmitPrecisionForTextureSamplers = true;
|
|
FOpenGL::bRequiresTextureCubeLodEXTToTextureCubeLodDefine = false;
|
|
|
|
// second most number of devices fall into this hack category
|
|
// try to compile without using precision for texture samplers
|
|
// Samsung Galaxy Express Samsung Galaxy S3 Samsung Galaxy S3 mini Samsung Galaxy Tab GT-P1000 Samsung Galaxy Tab 2
|
|
PixelShader = (FOpenGLPixelShader*)(RHICreatePixelShader(Code).GetReference());
|
|
|
|
if (VerifyCompiledShader(PixelShader->Resource, TestFragmentProgram, false))
|
|
{
|
|
UE_LOG(LogRHI, Warning, TEXT("Enabling shader compiler hack to remove precision modifiers for texture samplers"));
|
|
|
|
// we are done
|
|
FOpenGL::bIsCheckingShaderCompilerHacks = false;
|
|
return;
|
|
}
|
|
|
|
FOpenGL::bRequiresDontEmitPrecisionForTextureSamplers = false;
|
|
FOpenGL::bRequiresTextureCubeLodEXTToTextureCubeLodDefine = true;
|
|
|
|
// third most likely Samsung Galaxy Tab GT-P1000
|
|
PixelShader = (FOpenGLPixelShader*)(RHICreatePixelShader(Code).GetReference());
|
|
|
|
if (VerifyCompiledShader(PixelShader->Resource, TestFragmentProgram, false))
|
|
{
|
|
UE_LOG(LogRHI, Warning, TEXT("Enabling shader compiler hack to redefine textureCubeLodEXT to textureCubeLod"));
|
|
// we are done
|
|
FOpenGL::bIsCheckingShaderCompilerHacks = false;
|
|
return;
|
|
}
|
|
|
|
FOpenGL::bRequiresDontEmitPrecisionForTextureSamplers = true;
|
|
FOpenGL::bRequiresTextureCubeLodEXTToTextureCubeLodDefine = true;
|
|
|
|
// try both hacks
|
|
PixelShader = (FOpenGLPixelShader*)(RHICreatePixelShader(Code).GetReference());
|
|
|
|
if (VerifyCompiledShader(PixelShader->Resource, TestFragmentProgram, false))
|
|
{
|
|
UE_LOG(LogRHI, Warning, TEXT("Enabling shader compiler hack to redefine textureCubeLodEXT to textureCubeLod and remove precision modifiers"));
|
|
// we are done
|
|
FOpenGL::bIsCheckingShaderCompilerHacks = false;
|
|
return;
|
|
}
|
|
|
|
UE_LOG(LogRHI, Warning, TEXT("Unable to find a test shader that compiles try running anyway"));
|
|
FOpenGL::bIsCheckingShaderCompilerHacks = false;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void FOpenGLDynamicRHI::Init()
|
|
{
|
|
check(!GIsRHIInitialized);
|
|
VERIFY_GL_SCOPE();
|
|
|
|
FOpenGLProgramBinaryCache::Initialize();
|
|
#if PLATFORM_DESKTOP
|
|
FShaderCache::InitShaderCache(SCO_Default, FOpenGL::GetMaxTextureImageUnits());
|
|
#endif
|
|
|
|
InitializeStateResources();
|
|
|
|
// Create a default point sampler state for internal use.
|
|
FSamplerStateInitializerRHI PointSamplerStateParams(SF_Point,AM_Clamp,AM_Clamp,AM_Clamp);
|
|
PointSamplerState = this->RHICreateSamplerState(PointSamplerStateParams);
|
|
|
|
// Allocate vertex and index buffers for DrawPrimitiveUP calls.
|
|
DynamicVertexBuffers.Init(CalcDynamicBufferSize(1));
|
|
DynamicIndexBuffers.Init(CalcDynamicBufferSize(1));
|
|
|
|
// Notify all initialized FRenderResources that there's a valid RHI device to create their RHI resources for now.
|
|
for(TLinkedList<FRenderResource*>::TIterator ResourceIt(FRenderResource::GetResourceList());ResourceIt;ResourceIt.Next())
|
|
{
|
|
ResourceIt->InitRHI();
|
|
}
|
|
// Dynamic resources can have dependencies on static resources (with uniform buffers) and must initialized last!
|
|
for(TLinkedList<FRenderResource*>::TIterator ResourceIt(FRenderResource::GetResourceList());ResourceIt;ResourceIt.Next())
|
|
{
|
|
ResourceIt->InitDynamicRHI();
|
|
}
|
|
|
|
#if PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX
|
|
|
|
extern int64 GOpenGLDedicatedVideoMemory;
|
|
extern int64 GOpenGLTotalGraphicsMemory;
|
|
|
|
GOpenGLDedicatedVideoMemory = FOpenGL::GetVideoMemorySize();
|
|
|
|
if ( GOpenGLDedicatedVideoMemory != 0)
|
|
{
|
|
GOpenGLTotalGraphicsMemory = GOpenGLDedicatedVideoMemory;
|
|
|
|
if ( GPoolSizeVRAMPercentage > 0 )
|
|
{
|
|
float PoolSize = float(GPoolSizeVRAMPercentage) * 0.01f * float(GOpenGLTotalGraphicsMemory);
|
|
|
|
// Truncate GTexturePoolSize to MB (but still counted in bytes)
|
|
GTexturePoolSize = int64(FGenericPlatformMath::TruncToInt(PoolSize / 1024.0f / 1024.0f)) * 1024 * 1024;
|
|
|
|
UE_LOG(LogRHI, Log, TEXT("Texture pool is %llu MB (%d%% of %llu MB)"),
|
|
GTexturePoolSize / 1024 / 1024,
|
|
GPoolSizeVRAMPercentage,
|
|
GOpenGLTotalGraphicsMemory / 1024 / 1024);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
// Flush here since we might be switching to a different context/thread for rendering
|
|
FOpenGL::Flush();
|
|
|
|
FHardwareInfo::RegisterHardwareInfo( NAME_RHI, TEXT( "OpenGL" ) );
|
|
|
|
// Set the RHI initialized flag.
|
|
GIsRHIInitialized = true;
|
|
|
|
CheckTextureCubeLodSupport();
|
|
CheckVaryingLimit();
|
|
|
|
#if PLATFORM_DESKTOP
|
|
FShaderCache::LoadBinaryCache();
|
|
#endif
|
|
}
|
|
|
|
void FOpenGLDynamicRHI::Shutdown()
|
|
{
|
|
check(IsInGameThread() && IsInRenderingThread()); // require that the render thread has been shut down
|
|
|
|
Cleanup();
|
|
|
|
DestroyShadersAndPrograms();
|
|
PlatformDestroyOpenGLDevice(PlatformDevice);
|
|
|
|
PrivateOpenGLDevicePtr = NULL;
|
|
}
|
|
|
|
void FOpenGLDynamicRHI::Cleanup()
|
|
{
|
|
if(GIsRHIInitialized)
|
|
{
|
|
#if PLATFORM_DESKTOP
|
|
FShaderCache::ShutdownShaderCache();
|
|
#endif
|
|
FOpenGLProgramBinaryCache::Shutdown();
|
|
|
|
// Reset the RHI initialized flag.
|
|
GIsRHIInitialized = false;
|
|
|
|
GPUProfilingData.Cleanup();
|
|
|
|
// Ask all initialized FRenderResources to release their RHI resources.
|
|
for(TLinkedList<FRenderResource*>::TIterator ResourceIt(FRenderResource::GetResourceList());ResourceIt;ResourceIt.Next())
|
|
{
|
|
ResourceIt->ReleaseRHI();
|
|
}
|
|
for(TLinkedList<FRenderResource*>::TIterator ResourceIt(FRenderResource::GetResourceList());ResourceIt;ResourceIt.Next())
|
|
{
|
|
ResourceIt->ReleaseDynamicRHI();
|
|
}
|
|
}
|
|
|
|
// Release dynamic vertex and index buffers.
|
|
DynamicVertexBuffers.Cleanup();
|
|
DynamicIndexBuffers.Cleanup();
|
|
|
|
FreeZeroStrideBuffers();
|
|
|
|
// Release the point sampler state.
|
|
PointSamplerState.SafeRelease();
|
|
|
|
extern void EmptyGLSamplerStateCache();
|
|
EmptyGLSamplerStateCache();
|
|
|
|
// Release zero-filled dummy uniform buffer, if it exists.
|
|
if (PendingState.ZeroFilledDummyUniformBuffer)
|
|
{
|
|
FOpenGL::DeleteBuffers(1, &PendingState.ZeroFilledDummyUniformBuffer);
|
|
PendingState.ZeroFilledDummyUniformBuffer = 0;
|
|
DecrementBufferMemory(GL_UNIFORM_BUFFER, false, ZERO_FILLED_DUMMY_UNIFORM_BUFFER_SIZE);
|
|
}
|
|
|
|
// Release pending shader
|
|
PendingState.BoundShaderState.SafeRelease();
|
|
check(!IsValidRef(PendingState.BoundShaderState));
|
|
|
|
PendingState.CleanupResources();
|
|
SharedContextState.CleanupResources();
|
|
RenderingContextState.CleanupResources();
|
|
}
|
|
|
|
void FOpenGLDynamicRHI::RHIFlushResources()
|
|
{
|
|
PlatformFlushIfNeeded();
|
|
}
|
|
|
|
void FOpenGLDynamicRHI::RHIAcquireThreadOwnership()
|
|
{
|
|
check(!bRevertToSharedContextAfterDrawingViewport); // if this is true, then main thread is rendering using our context right now.
|
|
PlatformRenderingContextSetup(PlatformDevice);
|
|
PlatformRebindResources(PlatformDevice);
|
|
bIsRenderingContextAcquired = true;
|
|
VERIFY_GL(RHIAcquireThreadOwnership);
|
|
{
|
|
FScopeLock lock(&CustomPresentSection);
|
|
if (CustomPresent)
|
|
{
|
|
CustomPresent->OnAcquireThreadOwnership();
|
|
}
|
|
}
|
|
}
|
|
|
|
void FOpenGLDynamicRHI::RHIReleaseThreadOwnership()
|
|
{
|
|
{
|
|
FScopeLock lock(&CustomPresentSection);
|
|
if (CustomPresent)
|
|
{
|
|
CustomPresent->OnReleaseThreadOwnership();
|
|
}
|
|
}
|
|
VERIFY_GL(RHIReleaseThreadOwnership);
|
|
bIsRenderingContextAcquired = false;
|
|
PlatformNULLContextSetup();
|
|
}
|
|
|
|
void FOpenGLDynamicRHI::RegisterQuery( FOpenGLRenderQuery* Query )
|
|
{
|
|
FScopeLock Lock(&QueriesListCriticalSection);
|
|
Queries.Add(Query);
|
|
}
|
|
|
|
void FOpenGLDynamicRHI::UnregisterQuery( FOpenGLRenderQuery* Query )
|
|
{
|
|
FScopeLock Lock(&QueriesListCriticalSection);
|
|
Queries.RemoveSingleSwap(Query);
|
|
}
|
|
|
|
void FOpenGLDynamicRHI::RHIAutomaticCacheFlushAfterComputeShader(bool bEnable)
|
|
{
|
|
// Nothing to do here...
|
|
}
|
|
|
|
void FOpenGLDynamicRHI::RHIFlushComputeShaderCache()
|
|
{
|
|
// Nothing to do here...
|
|
}
|
|
|
|
|
|
|
|
void* FOpenGLDynamicRHI::RHIGetNativeDevice()
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
void FOpenGLDynamicRHI::InvalidateQueries( void )
|
|
{
|
|
{
|
|
FScopeLock Lock(&QueriesListCriticalSection);
|
|
PendingState.RunningOcclusionQuery = 0;
|
|
for( int32 Index = 0; Index < Queries.Num(); ++Index )
|
|
{
|
|
Queries[Index]->bInvalidResource = true;
|
|
}
|
|
}
|
|
|
|
{
|
|
FScopeLock Lock(&TimerQueriesListCriticalSection);
|
|
|
|
for( int32 Index = 0; Index < TimerQueries.Num(); ++Index )
|
|
{
|
|
TimerQueries[Index]->bInvalidResource = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void FOpenGLDynamicRHI::SetCustomPresent(FRHICustomPresent* InCustomPresent)
|
|
{
|
|
FScopeLock lock(&CustomPresentSection);
|
|
CustomPresent = InCustomPresent;
|
|
}
|
|
|
|
bool FOpenGLDynamicRHIModule::IsSupported()
|
|
{
|
|
return PlatformInitOpenGL();
|
|
}
|