Commit 98de826c by Jamie Madill Committed by Commit Bot

Platform: Fix initialization order in tests.

Because of the platform refactor in abf38572 we broke the way the tests override the D3D workarounds for the tiny depth/stencil bug. This change passes a pointer to the platform directly in the EGL init logic, which solves this issue. It also removes all decltype code in the platform header which might fix the UBSAN problem we were seeing previously. Also change a present mode selection error into a warning in the Vk back-end, since this was being triggered on AMD, but is safe. BUG=angleproject:2042 Change-Id: Ibbd0c69ce11a840cf4b33c616f56020001e553aa Reviewed-on: https://chromium-review.googlesource.com/513519Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 20805650
......@@ -38,12 +38,15 @@ using EGLDisplayType = void *;
struct PlatformMethods;
// Use a C-like API to not trigger undefined calling behaviour.
// Avoid using decltype here to work around sanitizer limitations.
// TODO(jmadill): Use decltype here if/when UBSAN is fixed.
// System --------------------------------------------------------------
// Wall clock time in seconds since the epoch.
// TODO(jmadill): investigate using an ANGLE internal time library
inline double ANGLE_currentTime(PlatformMethods *platform)
using CurrentTimeFunc = double (*)(PlatformMethods *platform);
inline double DefaultCurrentTime(PlatformMethods *platform)
{
return 0.0;
}
......@@ -51,7 +54,8 @@ inline double ANGLE_currentTime(PlatformMethods *platform)
// Monotonically increasing time in seconds from an arbitrary fixed point in the past.
// This function is expected to return at least millisecond-precision values. For this reason,
// it is recommended that the fixed point be no further in the past than the epoch.
inline double ANGLE_monotonicallyIncreasingTime(PlatformMethods *platform)
using MonotonicallyIncreasingTimeFunc = double (*)(PlatformMethods *platform);
inline double DefaultMonotonicallyIncreasingTime(PlatformMethods *platform)
{
return 0.0;
}
......@@ -59,17 +63,20 @@ inline double ANGLE_monotonicallyIncreasingTime(PlatformMethods *platform)
// Logging ------------------------------------------------------------
// Log an error message within the platform implementation.
inline void ANGLE_logError(PlatformMethods *platform, const char *errorMessage)
using LogErrorFunc = void (*)(PlatformMethods *platform, const char *errorMessage);
inline void DefaultLogError(PlatformMethods *platform, const char *errorMessage)
{
}
// Log a warning message within the platform implementation.
inline void ANGLE_logWarning(PlatformMethods *platform, const char *warningMessage)
using LogWarningFunc = void (*)(PlatformMethods *platform, const char *warningMessage);
inline void DefaultLogWarning(PlatformMethods *platform, const char *warningMessage)
{
}
// Log an info message within the platform implementation.
inline void ANGLE_logInfo(PlatformMethods *platform, const char *infoMessage)
using LogInfoFunc = void (*)(PlatformMethods *platform, const char *infoMessage);
inline void DefaultLogInfo(PlatformMethods *platform, const char *infoMessage)
{
}
......@@ -82,8 +89,10 @@ inline void ANGLE_logInfo(PlatformMethods *platform, const char *infoMessage)
// expects the returned pointer to be held permanently in a local static. If
// the unsigned char is non-zero, tracing is enabled. If tracing is enabled,
// addTraceEvent is expected to be called by the trace event macros.
inline const unsigned char *ANGLE_getTraceCategoryEnabledFlag(PlatformMethods *platform,
const char *categoryName)
using GetTraceCategoryEnabledFlagFunc = const unsigned char *(*)(PlatformMethods *platform,
const char *categoryName);
inline const unsigned char *DefaultGetTraceCategoryEnabledFlag(PlatformMethods *platform,
const char *categoryName)
{
return nullptr;
}
......@@ -135,80 +144,109 @@ inline const unsigned char *ANGLE_getTraceCategoryEnabledFlag(PlatformMethods *p
// matching with other events of the same name.
// - MANGLE_ID (0x4): specify this flag if the id parameter is the value
// of a pointer.
inline angle::TraceEventHandle ANGLE_addTraceEvent(PlatformMethods *platform,
char phase,
const unsigned char *categoryEnabledFlag,
const char *name,
unsigned long long id,
double timestamp,
int numArgs,
const char **argNames,
const unsigned char *argTypes,
const unsigned long long *argValues,
unsigned char flags)
using AddTraceEventFunc = angle::TraceEventHandle (*)(PlatformMethods *platform,
char phase,
const unsigned char *categoryEnabledFlag,
const char *name,
unsigned long long id,
double timestamp,
int numArgs,
const char **argNames,
const unsigned char *argTypes,
const unsigned long long *argValues,
unsigned char flags);
inline angle::TraceEventHandle DefaultAddTraceEvent(PlatformMethods *platform,
char phase,
const unsigned char *categoryEnabledFlag,
const char *name,
unsigned long long id,
double timestamp,
int numArgs,
const char **argNames,
const unsigned char *argTypes,
const unsigned long long *argValues,
unsigned char flags)
{
return 0;
}
// Set the duration field of a COMPLETE trace event.
inline void ANGLE_updateTraceEventDuration(PlatformMethods *platform,
const unsigned char *categoryEnabledFlag,
const char *name,
angle::TraceEventHandle eventHandle)
using UpdateTraceEventDurationFunc = void (*)(PlatformMethods *platform,
const unsigned char *categoryEnabledFlag,
const char *name,
angle::TraceEventHandle eventHandle);
inline void DefaultUpdateTraceEventDuration(PlatformMethods *platform,
const unsigned char *categoryEnabledFlag,
const char *name,
angle::TraceEventHandle eventHandle)
{
}
// Callbacks for reporting histogram data.
// CustomCounts histogram has exponential bucket sizes, so that min=1, max=1000000, bucketCount=50
// would do.
inline void ANGLE_histogramCustomCounts(PlatformMethods *platform,
const char *name,
int sample,
int min,
int max,
int bucketCount)
using HistogramCustomCountsFunc = void (*)(PlatformMethods *platform,
const char *name,
int sample,
int min,
int max,
int bucketCount);
inline void DefaultHistogramCustomCounts(PlatformMethods *platform,
const char *name,
int sample,
int min,
int max,
int bucketCount)
{
}
// Enumeration histogram buckets are linear, boundaryValue should be larger than any possible sample
// value.
inline void ANGLE_histogramEnumeration(PlatformMethods *platform,
const char *name,
int sample,
int boundaryValue)
using HistogramEnumerationFunc = void (*)(PlatformMethods *platform,
const char *name,
int sample,
int boundaryValue);
inline void DefaultHistogramEnumeration(PlatformMethods *platform,
const char *name,
int sample,
int boundaryValue)
{
}
// Unlike enumeration histograms, sparse histograms only allocate memory for non-empty buckets.
inline void ANGLE_histogramSparse(PlatformMethods *platform, const char *name, int sample)
using HistogramSparseFunc = void (*)(PlatformMethods *platform, const char *name, int sample);
inline void DefaultHistogramSparse(PlatformMethods *platform, const char *name, int sample)
{
}
// Boolean histograms track two-state variables.
inline void ANGLE_histogramBoolean(PlatformMethods *platform, const char *name, bool sample)
using HistogramBooleanFunc = void (*)(PlatformMethods *platform, const char *name, bool sample);
inline void DefaultHistogramBoolean(PlatformMethods *platform, const char *name, bool sample)
{
}
// Allows us to programatically override ANGLE's default workarounds for testing purposes.
inline void ANGLE_overrideWorkaroundsD3D(PlatformMethods *platform,
angle::WorkaroundsD3D *workaroundsD3D)
using OverrideWorkaroundsD3DFunc = void (*)(PlatformMethods *platform,
angle::WorkaroundsD3D *workaroundsD3D);
inline void DefaultOverrideWorkaroundsD3D(PlatformMethods *platform,
angle::WorkaroundsD3D *workaroundsD3D)
{
}
// Platform methods are enumerated here once.
#define ANGLE_PLATFORM_OP(OP) \
OP(currentTime) \
OP(monotonicallyIncreasingTime) \
OP(logError) \
OP(logWarning) \
OP(logInfo) \
OP(getTraceCategoryEnabledFlag) \
OP(addTraceEvent) \
OP(updateTraceEventDuration) \
OP(histogramCustomCounts) \
OP(histogramEnumeration) \
OP(histogramSparse) \
OP(histogramBoolean) \
OP(overrideWorkaroundsD3D)
#define ANGLE_PLATFORM_METHOD_DEF(Name) decltype(&ANGLE_##Name) Name = ANGLE_##Name;
#define ANGLE_PLATFORM_OP(OP) \
OP(currentTime, CurrentTime) \
OP(monotonicallyIncreasingTime, MonotonicallyIncreasingTime) \
OP(logError, LogError) \
OP(logWarning, LogWarning) \
OP(logInfo, LogInfo) \
OP(getTraceCategoryEnabledFlag, GetTraceCategoryEnabledFlag) \
OP(addTraceEvent, AddTraceEvent) \
OP(updateTraceEventDuration, UpdateTraceEventDuration) \
OP(histogramCustomCounts, HistogramCustomCounts) \
OP(histogramEnumeration, HistogramEnumeration) \
OP(histogramSparse, HistogramSparse) \
OP(histogramBoolean, HistogramBoolean) \
OP(overrideWorkaroundsD3D, OverrideWorkaroundsD3D)
#define ANGLE_PLATFORM_METHOD_DEF(Name, CapsName) CapsName##Func Name = Default##CapsName;
struct PlatformMethods
{
......@@ -224,7 +262,7 @@ struct PlatformMethods
constexpr unsigned int g_NumPlatformMethods = (sizeof(PlatformMethods) / sizeof(uintptr_t)) - 1;
#define ANGLE_PLATFORM_METHOD_STRING(Name) #Name
#define ANGLE_PLATFORM_METHOD_STRING2(Name) ANGLE_PLATFORM_METHOD_STRING(Name),
#define ANGLE_PLATFORM_METHOD_STRING2(Name, CapsName) ANGLE_PLATFORM_METHOD_STRING(Name),
constexpr const char *const g_PlatformMethodNames[g_NumPlatformMethods] = {
ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_STRING2)};
......@@ -240,9 +278,6 @@ extern "C" {
// match the compiled signature for this ANGLE, false is returned. On success true is returned.
// The application should set any platform methods it cares about on the returned pointer.
// If display is not valid, behaviour is undefined.
//
// Use a void * here to silence a sanitizer limitation with decltype.
// TODO(jmadill): Use angle::PlatformMethods ** if UBSAN is fixed to handle decltype.
ANGLE_PLATFORM_EXPORT bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display,
const char *const methodNames[],
......@@ -258,8 +293,6 @@ ANGLE_PLATFORM_EXPORT void ANGLE_APIENTRY ANGLEResetDisplayPlatform(angle::EGLDi
namespace angle
{
// Use typedefs here instead of decltype to work around sanitizer limitations.
// TODO(jmadill): Use decltype here if UBSAN is fixed.
typedef bool(ANGLE_APIENTRY *GetDisplayPlatformFunc)(angle::EGLDisplayType,
const char *const *,
unsigned int,
......
......@@ -183,6 +183,9 @@ std::string ToString(const T &value)
// Hidden enum for the NULL D3D device type.
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE 0x6AC0
// TODO(jmadill): Clean this up at some point.
#define EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX 0x9999
#define ANGLE_TRY_CHECKED_MATH(result) \
if (!result.IsValid()) \
{ \
......
......@@ -254,7 +254,7 @@ void Display_logInfo(angle::PlatformMethods *platform, const char *infoMessage)
void ANGLESetDefaultDisplayPlatform(angle::EGLDisplayType display)
{
angle::PlatformMethods *platformMethods = ANGLEPlatformCurrent();
if (platformMethods->logError != angle::ANGLE_logError)
if (platformMethods->logError != angle::DefaultLogError)
{
// Don't reset pre-set Platform to Default
return;
......@@ -419,7 +419,17 @@ void Display::setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap
Error Display::initialize()
{
// TODO(jmadill): Store Platform in Display and init here.
ANGLESetDefaultDisplayPlatform(this);
const angle::PlatformMethods *platformMethods =
reinterpret_cast<const angle::PlatformMethods *>(
mAttributeMap.get(EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX, 0));
if (platformMethods != nullptr)
{
*ANGLEPlatformCurrent() = *platformMethods;
}
else
{
ANGLESetDefaultDisplayPlatform(this);
}
gl::InitializeDebugAnnotations(&mAnnotator);
......
......@@ -47,7 +47,8 @@ VkPresentModeKHR GetDesiredPresentMode(const std::vector<VkPresentModeKHR> &pres
}
}
ERR() << "Desired present mode not available. Falling back to " << presentModes[0];
WARN() << "Present mode " << bestChoice << " not available. Falling back to "
<< presentModes[0];
return presentModes[0];
}
......
......@@ -10,7 +10,6 @@
#include "ANGLETest.h"
#include "EGLWindow.h"
#include "OSWindow.h"
#include "platform/Platform.h"
namespace angle
{
......@@ -254,6 +253,13 @@ void ANGLETest::SetUp()
needSwap = true;
}
mPlatformMethods.overrideWorkaroundsD3D = angle::TestPlatform_overrideWorkaroundsD3D;
mPlatformMethods.logError = angle::TestPlatform_logError;
mPlatformMethods.logWarning = angle::TestPlatform_logWarning;
mPlatformMethods.logInfo = angle::TestPlatform_logInfo;
mPlatformMethods.context = &mPlatformContext;
mEGLWindow->setPlatformMethods(&mPlatformMethods);
if (!mEGLWindow->initializeDisplayAndSurface(mOSWindow))
{
FAIL() << "egl display or surface init failed.";
......@@ -264,22 +270,6 @@ void ANGLETest::SetUp()
FAIL() << "GL Context init failed.";
}
if (mGLESLibrary)
{
auto initFunc = reinterpret_cast<angle::GetDisplayPlatformFunc>(
mGLESLibrary->getSymbol("ANGLEGetDisplayPlatform"));
if (initFunc)
{
angle::PlatformMethods *platformMethods = nullptr;
initFunc(mEGLWindow->getDisplay(), angle::g_PlatformMethodNames,
angle::g_NumPlatformMethods, &mPlatformContext, &platformMethods);
platformMethods->overrideWorkaroundsD3D = angle::TestPlatform_overrideWorkaroundsD3D;
platformMethods->logError = angle::TestPlatform_logError;
platformMethods->logWarning = angle::TestPlatform_logWarning;
platformMethods->logInfo = angle::TestPlatform_logInfo;
}
}
if (needSwap)
{
// Swap the buffers so that the default framebuffer picks up the resize
......@@ -299,6 +289,8 @@ void ANGLETest::SetUp()
void ANGLETest::TearDown()
{
mEGLWindow->setPlatformMethods(nullptr);
mPlatformContext.currentTest = nullptr;
checkD3D11SDKLayersMessages();
......
......@@ -18,6 +18,7 @@
#include "angle_test_configs.h"
#include "common/angleutils.h"
#include "common/vector_utils.h"
#include "platform/Platform.h"
#include "shader_utils.h"
#include "system_utils.h"
......@@ -305,6 +306,7 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters>
// Used for indexed quad rendering
GLuint mQuadVertexBuffer;
angle::PlatformMethods mPlatformMethods;
TestPlatformContext mPlatformContext;
bool mDeferContextInit;
......
......@@ -12,6 +12,9 @@
#include "OSWindow.h"
#include "common/debug.h"
// TODO(jmadill): Clean this up at some point.
#define EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX 0x9999
EGLPlatformParameters::EGLPlatformParameters()
: renderer(EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE),
majorVersion(EGL_DONT_CARE),
......@@ -118,7 +121,8 @@ EGLWindow::EGLWindow(EGLint glesMajorVersion,
mClientArraysEnabled(true),
mRobustResourceInit(false),
mSwapInterval(-1),
mSamples(-1)
mSamples(-1),
mPlatformMethods(nullptr)
{
}
......@@ -196,6 +200,13 @@ bool EGLWindow::initializeDisplayAndSurface(OSWindow *osWindow)
displayAttributes.push_back(mVulkanLayersEnabled.value() ? EGL_TRUE : EGL_FALSE);
}
if (mPlatformMethods)
{
static_assert(sizeof(EGLAttrib) == sizeof(mPlatformMethods), "Unexpected pointer size");
displayAttributes.push_back(EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX);
displayAttributes.push_back(reinterpret_cast<EGLAttrib>(mPlatformMethods));
}
displayAttributes.push_back(EGL_NONE);
mDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
......
......@@ -30,6 +30,11 @@ class OSWindow;
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE 0x6AC0
#endif
namespace angle
{
struct PlatformMethods;
}
struct ANGLE_EXPORT EGLPlatformParameters
{
EGLint renderer;
......@@ -83,6 +88,10 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
void setClientArraysEnabled(bool enabled) { mClientArraysEnabled = enabled; }
void setRobustResourceInit(bool enabled) { mRobustResourceInit = enabled; }
void setSwapInterval(EGLint swapInterval) { mSwapInterval = swapInterval; }
void setPlatformMethods(angle::PlatformMethods *platformMethods)
{
mPlatformMethods = platformMethods;
}
static EGLBoolean FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config);
......@@ -104,6 +113,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
bool isMultisample() const { return mMultisample; }
bool isDebugEnabled() const { return mDebug; }
EGLint getSwapInterval() const { return mSwapInterval; }
const angle::PlatformMethods *getPlatformMethods() const { return mPlatformMethods; }
// Internally initializes the Display, Surface and Context.
bool initializeGL(OSWindow *osWindow);
......@@ -145,6 +155,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
EGLint mSwapInterval;
EGLint mSamples;
Optional<bool> mVulkanLayersEnabled;
angle::PlatformMethods *mPlatformMethods;
};
#endif // UTIL_EGLWINDOW_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment