зеркало из https://github.com/AvaloniaUI/angle.git
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:
Родитель
04294e6876
Коммит
b0db7cca32
|
@ -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 ¶ms)
|
|||
withRobustness.eglParameters.robustness = EGL_TRUE;
|
||||
return withRobustness;
|
||||
}
|
||||
|
||||
inline PlatformParameters WithEmulatedPrerotation(const PlatformParameters ¶ms, 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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче