Commit b0db7cca by Shahbaz Youssefi Committed by Commit Bot

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: 's avatarIan Elliott <ianelliott@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 04294e68
...@@ -456,6 +456,21 @@ struct FeaturesVk : FeatureSetBase ...@@ -456,6 +456,21 @@ struct FeaturesVk : FeatureSetBase
"On some hardware, clear using a draw call instead of vkCmdClearAttachments in the middle " "On some hardware, clear using a draw call instead of vkCmdClearAttachments in the middle "
"of render pass due to bugs", "of render pass due to bugs",
&members, "https://issuetracker.google.com/166809097"}; &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; inline FeaturesVk::FeaturesVk() = default;
......
...@@ -72,9 +72,12 @@ std::shared_ptr<WaitableCompileEvent> ShaderVk::compile(const gl::Context *conte ...@@ -72,9 +72,12 @@ std::shared_ptr<WaitableCompileEvent> ShaderVk::compile(const gl::Context *conte
// context state does not allow it // context state does not allow it
compileOptions |= SH_EARLY_FRAGMENT_TESTS_OPTIMIZATION; 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; compileOptions |= SH_ADD_PRE_ROTATION;
} }
......
...@@ -475,6 +475,7 @@ WindowSurfaceVk::WindowSurfaceVk(const egl::SurfaceState &surfaceState, EGLNativ ...@@ -475,6 +475,7 @@ WindowSurfaceVk::WindowSurfaceVk(const egl::SurfaceState &surfaceState, EGLNativ
mDesiredSwapchainPresentMode(VK_PRESENT_MODE_FIFO_KHR), mDesiredSwapchainPresentMode(VK_PRESENT_MODE_FIFO_KHR),
mMinImageCount(0), mMinImageCount(0),
mPreTransform(VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR), mPreTransform(VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR),
mEmulatedPreTransform(VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR),
mCompositeAlpha(VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR), mCompositeAlpha(VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR),
mCurrentSwapHistoryIndex(0), mCurrentSwapHistoryIndex(0),
mCurrentSwapchainImageIndex(0), mCurrentSwapchainImageIndex(0),
...@@ -610,12 +611,37 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk) ...@@ -610,12 +611,37 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk)
{ {
// Default to identity transform. // Default to identity transform.
mPreTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; mPreTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
if ((mSurfaceCaps.supportedTransforms & mPreTransform) == 0) if ((mSurfaceCaps.supportedTransforms & mPreTransform) == 0)
{ {
mPreTransform = mSurfaceCaps.currentTransform; 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; uint32_t presentModeCount = 0;
ANGLE_VK_TRY(displayVk, vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, mSurface, ANGLE_VK_TRY(displayVk, vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, mSurface,
&presentModeCount, nullptr)); &presentModeCount, nullptr));
...@@ -779,7 +805,16 @@ angle::Result WindowSurfaceVk::recreateSwapchain(ContextVk *contextVk, const gl: ...@@ -779,7 +805,16 @@ angle::Result WindowSurfaceVk::recreateSwapchain(ContextVk *contextVk, const gl:
releaseSwapchainImages(contextVk); 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. // Notify the parent classes of the surface's new state.
onStateChange(angle::SubjectMessage::SurfaceChanged); onStateChange(angle::SubjectMessage::SurfaceChanged);
...@@ -882,7 +917,7 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context, ...@@ -882,7 +917,7 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context,
VkFormat nativeFormat = format.vkImageFormat; VkFormat nativeFormat = format.vkImageFormat;
gl::Extents rotatedExtents = extents; 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 // 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 // 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, ...@@ -1300,7 +1335,7 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk,
rect.extent.width = gl::clamp(*eglRects++, 0, width - rect.offset.x); rect.extent.width = gl::clamp(*eglRects++, 0, width - rect.offset.x);
rect.extent.height = gl::clamp(*eglRects++, 0, height - rect.offset.y); rect.extent.height = gl::clamp(*eglRects++, 0, height - rect.offset.y);
rect.layer = 0; rect.layer = 0;
if (Is90DegreeRotation(mPreTransform)) if (Is90DegreeRotation(getPreTransform()))
{ {
std::swap(rect.offset.x, rect.offset.y); std::swap(rect.offset.x, rect.offset.y);
std::swap(rect.extent.width, rect.extent.height); std::swap(rect.extent.width, rect.extent.height);
...@@ -1702,7 +1737,7 @@ angle::Result WindowSurfaceVk::getCurrentFramebuffer(ContextVk *contextVk, ...@@ -1702,7 +1737,7 @@ angle::Result WindowSurfaceVk::getCurrentFramebuffer(ContextVk *contextVk,
framebufferInfo.pAttachments = imageViews.data(); framebufferInfo.pAttachments = imageViews.data();
framebufferInfo.width = static_cast<uint32_t>(extents.width); framebufferInfo.width = static_cast<uint32_t>(extents.width);
framebufferInfo.height = static_cast<uint32_t>(extents.height); framebufferInfo.height = static_cast<uint32_t>(extents.height);
if (Is90DegreeRotation(mPreTransform)) if (Is90DegreeRotation(getPreTransform()))
{ {
std::swap(framebufferInfo.width, framebufferInfo.height); std::swap(framebufferInfo.width, framebufferInfo.height);
} }
......
...@@ -243,7 +243,14 @@ class WindowSurfaceVk : public SurfaceVk ...@@ -243,7 +243,14 @@ class WindowSurfaceVk : public SurfaceVk
vk::Semaphore getAcquireImageSemaphore(); vk::Semaphore getAcquireImageSemaphore();
VkSurfaceTransformFlagBitsKHR getPreTransform() { return mPreTransform; } VkSurfaceTransformFlagBitsKHR getPreTransform()
{
if (mEmulatedPreTransform != VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
{
return mEmulatedPreTransform;
}
return mPreTransform;
}
protected: protected:
angle::Result swapImpl(const gl::Context *context, angle::Result swapImpl(const gl::Context *context,
...@@ -302,6 +309,7 @@ class WindowSurfaceVk : public SurfaceVk ...@@ -302,6 +309,7 @@ class WindowSurfaceVk : public SurfaceVk
VkPresentModeKHR mDesiredSwapchainPresentMode; // Desired mode set through setSwapInterval() VkPresentModeKHR mDesiredSwapchainPresentMode; // Desired mode set through setSwapInterval()
uint32_t mMinImageCount; uint32_t mMinImageCount;
VkSurfaceTransformFlagBitsKHR mPreTransform; VkSurfaceTransformFlagBitsKHR mPreTransform;
VkSurfaceTransformFlagBitsKHR mEmulatedPreTransform;
VkCompositeAlphaFlagBitsKHR mCompositeAlpha; VkCompositeAlphaFlagBitsKHR mCompositeAlpha;
// A circular buffer that stores the submission fence of the context on every swap. The CPU is // 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 ...@@ -14,7 +14,7 @@ class BlitFramebufferANGLETest : public ANGLETest
protected: protected:
BlitFramebufferANGLETest() BlitFramebufferANGLETest()
{ {
setWindowWidth(32); setWindowWidth(64);
setWindowHeight(32); setWindowHeight(32);
setConfigRedBits(8); setConfigRedBits(8);
setConfigGreenBits(8); setConfigGreenBits(8);
...@@ -2447,6 +2447,9 @@ ANGLE_INSTANTIATE_TEST(BlitFramebufferANGLETest, ...@@ -2447,6 +2447,9 @@ ANGLE_INSTANTIATE_TEST(BlitFramebufferANGLETest,
ES3_OPENGL(), ES3_OPENGL(),
ES2_VULKAN(), ES2_VULKAN(),
ES3_VULKAN(), ES3_VULKAN(),
WithEmulatedPrerotation(ES3_VULKAN(), 90),
WithEmulatedPrerotation(ES3_VULKAN(), 180),
WithEmulatedPrerotation(ES3_VULKAN(), 270),
ES2_METAL(), ES2_METAL(),
WithNoShaderStencilOutput(ES2_METAL())); WithNoShaderStencilOutput(ES2_METAL()));
......
...@@ -538,9 +538,27 @@ void ANGLETestBase::ANGLETestSetUp() ...@@ -538,9 +538,27 @@ void ANGLETestBase::ANGLETestSetUp()
// Resize the window before creating the context so that the first make current // Resize the window before creating the context so that the first make current
// sets the viewport and scissor box to the right size. // sets the viewport and scissor box to the right size.
bool needSwap = false; 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)
{
std::swap(osWindowWidth, osWindowHeight);
}
if (osWindowWidth != mWidth || osWindowHeight != mHeight)
{
int newWindowWidth = mWidth;
int newWindowHeight = mHeight;
if (isRotated)
{ {
if (!mFixture->osWindow->resize(mWidth, mHeight)) std::swap(newWindowWidth, newWindowHeight);
}
if (!mFixture->osWindow->resize(newWindowWidth, newWindowHeight))
{ {
FAIL() << "Failed to resize ANGLE test window."; FAIL() << "Failed to resize ANGLE test window.";
} }
...@@ -1229,9 +1247,9 @@ int ANGLETestBase::getWindowHeight() const ...@@ -1229,9 +1247,9 @@ int ANGLETestBase::getWindowHeight() const
return mHeight; 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) void ANGLETestBase::setWindowVisible(OSWindow *osWindow, bool isVisible)
......
...@@ -462,7 +462,7 @@ class ANGLETestBase ...@@ -462,7 +462,7 @@ class ANGLETestBase
EGLWindow *getEGLWindow() const; EGLWindow *getEGLWindow() const;
int getWindowWidth() const; int getWindowWidth() const;
int getWindowHeight() const; int getWindowHeight() const;
bool isMultisampleEnabled() const; bool isEmulatedPrerotation() const;
EGLint getPlatformRenderer() const; EGLint getPlatformRenderer() const;
......
...@@ -219,6 +219,19 @@ std::ostream &operator<<(std::ostream &stream, const PlatformParameters &pp) ...@@ -219,6 +219,19 @@ std::ostream &operator<<(std::ostream &stream, const PlatformParameters &pp)
stream << "_NoGenMultipleMipsPerPass"; 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; return stream;
} }
......
...@@ -247,6 +247,13 @@ inline PlatformParameters WithRobustness(const PlatformParameters &params) ...@@ -247,6 +247,13 @@ inline PlatformParameters WithRobustness(const PlatformParameters &params)
withRobustness.eglParameters.robustness = EGL_TRUE; withRobustness.eglParameters.robustness = EGL_TRUE;
return withRobustness; return withRobustness;
} }
inline PlatformParameters WithEmulatedPrerotation(const PlatformParameters &params, EGLint rotation)
{
PlatformParameters prerotation = params;
prerotation.eglParameters.emulatedPrerotation = rotation;
return prerotation;
}
} // namespace angle } // namespace angle
#endif // ANGLE_TEST_CONFIGS_H_ #endif // ANGLE_TEST_CONFIGS_H_
...@@ -62,7 +62,7 @@ struct EGLPlatformParameters ...@@ -62,7 +62,7 @@ struct EGLPlatformParameters
debugLayersEnabled, contextVirtualization, transformFeedbackFeature, debugLayersEnabled, contextVirtualization, transformFeedbackFeature,
allocateNonZeroMemoryFeature, emulateCopyTexImage2DFromRenderbuffers, allocateNonZeroMemoryFeature, emulateCopyTexImage2DFromRenderbuffers,
shaderStencilOutputFeature, genMultipleMipsPerPassFeature, platformMethods, shaderStencilOutputFeature, genMultipleMipsPerPassFeature, platformMethods,
robustness); robustness, emulatedPrerotation);
} }
EGLint renderer = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE; EGLint renderer = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
...@@ -78,6 +78,7 @@ struct EGLPlatformParameters ...@@ -78,6 +78,7 @@ struct EGLPlatformParameters
EGLint emulateCopyTexImage2DFromRenderbuffers = EGL_DONT_CARE; EGLint emulateCopyTexImage2DFromRenderbuffers = EGL_DONT_CARE;
EGLint shaderStencilOutputFeature = EGL_DONT_CARE; EGLint shaderStencilOutputFeature = EGL_DONT_CARE;
EGLint genMultipleMipsPerPassFeature = EGL_DONT_CARE; EGLint genMultipleMipsPerPassFeature = EGL_DONT_CARE;
uint32_t emulatedPrerotation = 0; // Can be 0, 90, 180 or 270
angle::PlatformMethods *platformMethods = nullptr; angle::PlatformMethods *platformMethods = nullptr;
}; };
......
...@@ -206,6 +206,19 @@ bool EGLWindow::initializeDisplay(OSWindow *osWindow, ...@@ -206,6 +206,19 @@ bool EGLWindow::initializeDisplay(OSWindow *osWindow,
disabledFeatureOverrides.push_back("gen_multiple_mips_per_pass"); 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 (!disabledFeatureOverrides.empty())
{ {
if (strstr(extensionString, "EGL_ANGLE_feature_control") == nullptr) if (strstr(extensionString, "EGL_ANGLE_feature_control") == nullptr)
......
...@@ -438,7 +438,7 @@ bool X11Window::resize(int width, int height) ...@@ -438,7 +438,7 @@ bool X11Window::resize(int width, int height)
Timer timer; Timer timer;
timer.start(); 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. // can assume the window has been resized.
const double kResizeWaitDelay = 0.2; const double kResizeWaitDelay = 0.2;
while ((mHeight != height || mWidth != width) && timer.getElapsedTime() < kResizeWaitDelay) while ((mHeight != height || mWidth != width) && timer.getElapsedTime() < kResizeWaitDelay)
......
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