Vulkan: Initial emulated prerotation support

This is currently only supported for end2end tests (those which use
ANGLETestBase, excluding those that use WithNoFixture) and Vulkan.  Use
WithEmulatedPreoration(*_VULKAN(), degree) where degree is either 90,
180 or 270.

With emulated prerotation, the window dimensions are physically swapped
if 90 and 270 degrees, while the width and height is still reported as
requested by the test.  In the Vulkan backend, the width and height are
swapped after getting queried from the surface, and prerotation is
assumed.

Bug: angleproject:4901
Change-Id: I294436be4c7015d2a63463c4d61de7b67f38c95d
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2495544
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Ian Elliott <ianelliott@google.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Shahbaz Youssefi 2020-10-23 17:37:41 -04:00 коммит произвёл Commit Bot
Родитель 04294e6876
Коммит b0db7cca32
12 изменённых файлов: 131 добавлений и 15 удалений

Просмотреть файл

@ -456,6 +456,21 @@ struct FeaturesVk : FeatureSetBase
"On some hardware, clear using a draw call instead of vkCmdClearAttachments in the middle "
"of render pass due to bugs",
&members, "https://issuetracker.google.com/166809097"};
// Whether prerotation is being emulated for testing. 90 degree rotation.
Feature emulatedPrerotation90 = {"emulated_prerotation_90", FeatureCategory::VulkanFeatures,
"Emulate 90-degree prerotation.", &members,
"http://anglebug.com/4901"};
// Whether prerotation is being emulated for testing. 180 degree rotation.
Feature emulatedPrerotation180 = {"emulated_prerotation_180", FeatureCategory::VulkanFeatures,
"Emulate 180-degree prerotation.", &members,
"http://anglebug.com/4901"};
// Whether prerotation is being emulated for testing. 270 degree rotation.
Feature emulatedPrerotation270 = {"emulated_prerotation_270", FeatureCategory::VulkanFeatures,
"Emulate 270-degree prerotation.", &members,
"http://anglebug.com/4901"};
};
inline FeaturesVk::FeaturesVk() = default;

Просмотреть файл

@ -72,9 +72,12 @@ std::shared_ptr<WaitableCompileEvent> ShaderVk::compile(const gl::Context *conte
// context state does not allow it
compileOptions |= SH_EARLY_FRAGMENT_TESTS_OPTIMIZATION;
if (contextVk->getFeatures().enablePreRotateSurfaces.enabled)
if (contextVk->getFeatures().enablePreRotateSurfaces.enabled ||
contextVk->getFeatures().emulatedPrerotation90.enabled ||
contextVk->getFeatures().emulatedPrerotation180.enabled ||
contextVk->getFeatures().emulatedPrerotation270.enabled)
{
// Let compiler inserts pre-rotation code.
// Let compiler insert pre-rotation code.
compileOptions |= SH_ADD_PRE_ROTATION;
}

Просмотреть файл

@ -475,6 +475,7 @@ WindowSurfaceVk::WindowSurfaceVk(const egl::SurfaceState &surfaceState, EGLNativ
mDesiredSwapchainPresentMode(VK_PRESENT_MODE_FIFO_KHR),
mMinImageCount(0),
mPreTransform(VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR),
mEmulatedPreTransform(VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR),
mCompositeAlpha(VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR),
mCurrentSwapHistoryIndex(0),
mCurrentSwapchainImageIndex(0),
@ -610,12 +611,37 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk)
{
// Default to identity transform.
mPreTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
if ((mSurfaceCaps.supportedTransforms & mPreTransform) == 0)
{
mPreTransform = mSurfaceCaps.currentTransform;
}
}
// Set emulated pre-transform if any emulated prerotation features are set.
if (renderer->getFeatures().emulatedPrerotation90.enabled)
{
mEmulatedPreTransform = VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR;
}
else if (renderer->getFeatures().emulatedPrerotation180.enabled)
{
mEmulatedPreTransform = VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR;
}
else if (renderer->getFeatures().emulatedPrerotation270.enabled)
{
mEmulatedPreTransform = VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR;
}
// If prerotation is emulated, the window is physically rotated. With real prerotation, the
// surface reports the rotated sizes. With emulated prerotation however, the surface reports
// the actual window sizes. Adjust the window extents to match what real prerotation would have
// reported.
if (Is90DegreeRotation(mEmulatedPreTransform))
{
ASSERT(mPreTransform == VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR);
std::swap(extents.width, extents.height);
}
uint32_t presentModeCount = 0;
ANGLE_VK_TRY(displayVk, vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, mSurface,
&presentModeCount, nullptr));
@ -779,7 +805,16 @@ angle::Result WindowSurfaceVk::recreateSwapchain(ContextVk *contextVk, const gl:
releaseSwapchainImages(contextVk);
angle::Result result = createSwapChain(contextVk, extents, lastSwapchain);
// If prerotation is emulated, adjust the window extents to match what real prerotation would
// have reported.
gl::Extents swapchainExtents = extents;
if (Is90DegreeRotation(mEmulatedPreTransform))
{
ASSERT(mPreTransform == VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR);
std::swap(swapchainExtents.width, swapchainExtents.height);
}
angle::Result result = createSwapChain(contextVk, swapchainExtents, lastSwapchain);
// Notify the parent classes of the surface's new state.
onStateChange(angle::SubjectMessage::SurfaceChanged);
@ -882,7 +917,7 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context,
VkFormat nativeFormat = format.vkImageFormat;
gl::Extents rotatedExtents = extents;
if (Is90DegreeRotation(mPreTransform))
if (Is90DegreeRotation(getPreTransform()))
{
// The Surface is oriented such that its aspect ratio no longer matches that of the
// device. In this case, the width and height of the swapchain images must be swapped to
@ -1300,7 +1335,7 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk,
rect.extent.width = gl::clamp(*eglRects++, 0, width - rect.offset.x);
rect.extent.height = gl::clamp(*eglRects++, 0, height - rect.offset.y);
rect.layer = 0;
if (Is90DegreeRotation(mPreTransform))
if (Is90DegreeRotation(getPreTransform()))
{
std::swap(rect.offset.x, rect.offset.y);
std::swap(rect.extent.width, rect.extent.height);
@ -1702,7 +1737,7 @@ angle::Result WindowSurfaceVk::getCurrentFramebuffer(ContextVk *contextVk,
framebufferInfo.pAttachments = imageViews.data();
framebufferInfo.width = static_cast<uint32_t>(extents.width);
framebufferInfo.height = static_cast<uint32_t>(extents.height);
if (Is90DegreeRotation(mPreTransform))
if (Is90DegreeRotation(getPreTransform()))
{
std::swap(framebufferInfo.width, framebufferInfo.height);
}

Просмотреть файл

@ -243,7 +243,14 @@ class WindowSurfaceVk : public SurfaceVk
vk::Semaphore getAcquireImageSemaphore();
VkSurfaceTransformFlagBitsKHR getPreTransform() { return mPreTransform; }
VkSurfaceTransformFlagBitsKHR getPreTransform()
{
if (mEmulatedPreTransform != VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
{
return mEmulatedPreTransform;
}
return mPreTransform;
}
protected:
angle::Result swapImpl(const gl::Context *context,
@ -302,6 +309,7 @@ class WindowSurfaceVk : public SurfaceVk
VkPresentModeKHR mDesiredSwapchainPresentMode; // Desired mode set through setSwapInterval()
uint32_t mMinImageCount;
VkSurfaceTransformFlagBitsKHR mPreTransform;
VkSurfaceTransformFlagBitsKHR mEmulatedPreTransform;
VkCompositeAlphaFlagBitsKHR mCompositeAlpha;
// A circular buffer that stores the submission fence of the context on every swap. The CPU is

Просмотреть файл

@ -14,7 +14,7 @@ class BlitFramebufferANGLETest : public ANGLETest
protected:
BlitFramebufferANGLETest()
{
setWindowWidth(32);
setWindowWidth(64);
setWindowHeight(32);
setConfigRedBits(8);
setConfigGreenBits(8);
@ -2447,6 +2447,9 @@ ANGLE_INSTANTIATE_TEST(BlitFramebufferANGLETest,
ES3_OPENGL(),
ES2_VULKAN(),
ES3_VULKAN(),
WithEmulatedPrerotation(ES3_VULKAN(), 90),
WithEmulatedPrerotation(ES3_VULKAN(), 180),
WithEmulatedPrerotation(ES3_VULKAN(), 270),
ES2_METAL(),
WithNoShaderStencilOutput(ES2_METAL()));

Просмотреть файл

@ -538,9 +538,27 @@ void ANGLETestBase::ANGLETestSetUp()
// Resize the window before creating the context so that the first make current
// sets the viewport and scissor box to the right size.
bool needSwap = false;
if (mFixture->osWindow->getWidth() != mWidth || mFixture->osWindow->getHeight() != mHeight)
int osWindowWidth = mFixture->osWindow->getWidth();
int osWindowHeight = mFixture->osWindow->getHeight();
const bool isRotated = mCurrentParams->eglParameters.emulatedPrerotation == 90 ||
mCurrentParams->eglParameters.emulatedPrerotation == 270;
if (isRotated)
{
if (!mFixture->osWindow->resize(mWidth, mHeight))
std::swap(osWindowWidth, osWindowHeight);
}
if (osWindowWidth != mWidth || osWindowHeight != mHeight)
{
int newWindowWidth = mWidth;
int newWindowHeight = mHeight;
if (isRotated)
{
std::swap(newWindowWidth, newWindowHeight);
}
if (!mFixture->osWindow->resize(newWindowWidth, newWindowHeight))
{
FAIL() << "Failed to resize ANGLE test window.";
}
@ -1229,9 +1247,9 @@ int ANGLETestBase::getWindowHeight() const
return mHeight;
}
bool ANGLETestBase::isMultisampleEnabled() const
bool ANGLETestBase::isEmulatedPrerotation() const
{
return mFixture->eglWindow->isMultisample();
return mCurrentParams->eglParameters.emulatedPrerotation != 0;
}
void ANGLETestBase::setWindowVisible(OSWindow *osWindow, bool isVisible)

Просмотреть файл

@ -462,7 +462,7 @@ class ANGLETestBase
EGLWindow *getEGLWindow() const;
int getWindowWidth() const;
int getWindowHeight() const;
bool isMultisampleEnabled() const;
bool isEmulatedPrerotation() const;
EGLint getPlatformRenderer() const;

Просмотреть файл

@ -219,6 +219,19 @@ std::ostream &operator<<(std::ostream &stream, const PlatformParameters &pp)
stream << "_NoGenMultipleMipsPerPass";
}
if (pp.eglParameters.emulatedPrerotation == 90)
{
stream << "_PreRotation90";
}
else if (pp.eglParameters.emulatedPrerotation == 180)
{
stream << "_PreRotation180";
}
else if (pp.eglParameters.emulatedPrerotation == 270)
{
stream << "_PreRotation270";
}
return stream;
}

Просмотреть файл

@ -247,6 +247,13 @@ inline PlatformParameters WithRobustness(const PlatformParameters &params)
withRobustness.eglParameters.robustness = EGL_TRUE;
return withRobustness;
}
inline PlatformParameters WithEmulatedPrerotation(const PlatformParameters &params, EGLint rotation)
{
PlatformParameters prerotation = params;
prerotation.eglParameters.emulatedPrerotation = rotation;
return prerotation;
}
} // namespace angle
#endif // ANGLE_TEST_CONFIGS_H_

Просмотреть файл

@ -62,7 +62,7 @@ struct EGLPlatformParameters
debugLayersEnabled, contextVirtualization, transformFeedbackFeature,
allocateNonZeroMemoryFeature, emulateCopyTexImage2DFromRenderbuffers,
shaderStencilOutputFeature, genMultipleMipsPerPassFeature, platformMethods,
robustness);
robustness, emulatedPrerotation);
}
EGLint renderer = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
@ -78,6 +78,7 @@ struct EGLPlatformParameters
EGLint emulateCopyTexImage2DFromRenderbuffers = EGL_DONT_CARE;
EGLint shaderStencilOutputFeature = EGL_DONT_CARE;
EGLint genMultipleMipsPerPassFeature = EGL_DONT_CARE;
uint32_t emulatedPrerotation = 0; // Can be 0, 90, 180 or 270
angle::PlatformMethods *platformMethods = nullptr;
};

Просмотреть файл

@ -206,6 +206,19 @@ bool EGLWindow::initializeDisplay(OSWindow *osWindow,
disabledFeatureOverrides.push_back("gen_multiple_mips_per_pass");
}
if (params.emulatedPrerotation == 90)
{
enabledFeatureOverrides.push_back("emulated_prerotation_90");
}
else if (params.emulatedPrerotation == 180)
{
enabledFeatureOverrides.push_back("emulated_prerotation_180");
}
else if (params.emulatedPrerotation == 270)
{
enabledFeatureOverrides.push_back("emulated_prerotation_270");
}
if (!disabledFeatureOverrides.empty())
{
if (strstr(extensionString, "EGL_ANGLE_feature_control") == nullptr)

Просмотреть файл

@ -438,7 +438,7 @@ bool X11Window::resize(int width, int height)
Timer timer;
timer.start();
// Wait until the window as actually been resized so that the code calling resize
// Wait until the window has actually been resized so that the code calling resize
// can assume the window has been resized.
const double kResizeWaitDelay = 0.2;
while ((mHeight != height || mWidth != width) && timer.getElapsedTime() < kResizeWaitDelay)