Implement Android surface pre-rotation for Vulkan (#2955)
This commit is contained in:
@@ -51,6 +51,9 @@ static_assert(sizeof(GlobalPaintParamsUBO) == 3 * 16);
|
||||
|
||||
enum {
|
||||
idGlobalPaintParamsUBO,
|
||||
#if MLN_RENDER_BACKEND_VULKAN
|
||||
PlatformParamsUBO,
|
||||
#endif
|
||||
globalUBOCount
|
||||
};
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ layout(set = DRAWABLE_UBO_SET_INDEX, binding = 0) uniform BackgroundDrawableUBO
|
||||
|
||||
void main() {
|
||||
gl_Position = drawable.matrix * vec4(in_position, 0.0, 1.0);
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
}
|
||||
)";
|
||||
|
||||
@@ -101,7 +101,7 @@ void main() {
|
||||
in_position);
|
||||
|
||||
gl_Position = drawable.matrix * vec4(in_position, 0.0, 1.0);
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
}
|
||||
)";
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ void main() {
|
||||
gl_Position.xy += scaled_extrude * (radius + stroke_width) * factor;
|
||||
}
|
||||
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
// This is a minimum blur distance that serves as a faux-antialiasing for
|
||||
// the circle. since blur is a ratio of the circle's size and the intent is
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
struct ClipUBO {
|
||||
matf4 matrix;
|
||||
mat4 matrix;
|
||||
std::uint32_t stencil_ref;
|
||||
};
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ void main() {
|
||||
|
||||
gl_Position = drawable.matrix * vec4(in_position, 0.0, 1.0);
|
||||
gl_Position.xy += (in_extrude + in_shift) * drawable.extrude_scale * gl_Position.w * collision_perspective_ratio;
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
frag_placed = in_placed.x;
|
||||
frag_notUsed = in_placed.y;
|
||||
@@ -128,7 +128,7 @@ void main() {
|
||||
float padding_factor = 1.2; // Pad the vertices slightly to make room for anti-alias blur
|
||||
gl_Position = drawable.matrix * vec4(in_position, 0.0, 1.0);
|
||||
gl_Position.xy += in_extrude * drawable.extrude_scale * padding_factor * gl_Position.w * collision_perspective_ratio;
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
frag_placed = in_placed.x;
|
||||
frag_notUsed = in_placed.y;
|
||||
|
||||
@@ -84,6 +84,20 @@ layout(set = GLOBAL_SET_INDEX, binding = 0) uniform GlobalPaintParamsUBO {
|
||||
float pad1;
|
||||
} global;
|
||||
|
||||
#ifdef USE_SURFACE_TRANSFORM
|
||||
layout(set = GLOBAL_SET_INDEX, binding = 1) uniform PlatformParamsUBO {
|
||||
mat2 rotation;
|
||||
} platform;
|
||||
#endif
|
||||
|
||||
void applySurfaceTransform() {
|
||||
#ifdef USE_SURFACE_TRANSFORM
|
||||
gl_Position.xy = platform.rotation * gl_Position.xy;
|
||||
#endif
|
||||
|
||||
gl_Position.y *= -1.0;
|
||||
}
|
||||
|
||||
)";
|
||||
|
||||
static constexpr auto fragment = R"(
|
||||
@@ -130,7 +144,7 @@ layout(set = DRAWABLE_UBO_SET_INDEX, binding = 0) uniform CommonUBO {
|
||||
|
||||
void main() {
|
||||
gl_Position = ubo.matrix * vec4(in_position, 0, 1);
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
}
|
||||
)";
|
||||
|
||||
@@ -170,7 +184,7 @@ layout(location = 0) out vec2 frag_uv;
|
||||
|
||||
void main() {
|
||||
gl_Position = ubo.matrix * vec4(in_position, 0, 1);
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
frag_uv = in_texcoord;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ layout(location = 0) out vec2 frag_uv;
|
||||
void main() {
|
||||
|
||||
gl_Position = debug.matrix * vec4(in_position * debug.overlay_scale, 0, 1);
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
// This vertex shader expects a EXTENT x EXTENT quad,
|
||||
// The UV co-ordinates for the overlay texture can be calculated using that knowledge
|
||||
|
||||
@@ -55,7 +55,7 @@ void main() {
|
||||
#endif
|
||||
|
||||
gl_Position = drawable.matrix * vec4(in_position, 0.0, 1.0);
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
}
|
||||
)";
|
||||
|
||||
@@ -150,7 +150,7 @@ void main() {
|
||||
#endif
|
||||
|
||||
gl_Position = drawable.matrix * vec4(in_position, 0.0, 1.0);
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
frag_position = (gl_Position.xy / gl_Position.w + 1.0) / 2.0 * global.world_size;
|
||||
}
|
||||
@@ -309,7 +309,7 @@ void main() {
|
||||
frag_pos_b = get_pattern_pos(drawable.pixel_coord_upper, drawable.pixel_coord_lower, toScale * display_size_b, tileZoomRatio, in_position),
|
||||
|
||||
gl_Position = drawable.matrix * vec4(in_position, 0.0, 1.0);
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
}
|
||||
)";
|
||||
|
||||
@@ -502,14 +502,12 @@ void main() {
|
||||
const vec2 display_size_b = vec2((pattern_br_b.x - pattern_tl_b.x) / pixelRatio, (pattern_br_b.y - pattern_tl_b.y) / pixelRatio);
|
||||
|
||||
const vec2 position2 = in_position.xy;
|
||||
vec4 position = drawable.matrix * vec4(in_position, 0.0, 1.0);
|
||||
position.y *= -1.0;
|
||||
gl_Position = drawable.matrix * vec4(in_position, 0.0, 1.0);
|
||||
applySurfaceTransform();
|
||||
|
||||
frag_pos_a = get_pattern_pos(drawable.pixel_coord_upper, drawable.pixel_coord_lower, fromScale * display_size_a, tileZoomRatio, position2),
|
||||
frag_pos_b = get_pattern_pos(drawable.pixel_coord_upper, drawable.pixel_coord_lower, toScale * display_size_b, tileZoomRatio, position2),
|
||||
frag_pos = (position.xy / position.w + 1.0) / 2.0 * global.world_size;
|
||||
|
||||
gl_Position = position;
|
||||
frag_pos = (gl_Position.xy / gl_Position.w + 1.0) / 2.0 * global.world_size;
|
||||
}
|
||||
)";
|
||||
|
||||
@@ -655,7 +653,7 @@ void main() {
|
||||
|
||||
vec4 projected_extrude = drawable.matrix * vec4(dist / drawable.ratio, 0.0, 0.0);
|
||||
gl_Position = drawable.matrix * vec4(pos, 0.0, 1.0) + projected_extrude;
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
// calculate how much the perspective view squishes or stretches the extrude
|
||||
float extrude_length_without_perspective = length(dist);
|
||||
@@ -788,7 +786,7 @@ void main() {
|
||||
const float z = t != 0.0 ? height : base;
|
||||
|
||||
gl_Position = drawable.matrix * vec4(in_position, z, 1.0);
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
#if defined(OVERDRAW_INSPECTOR)
|
||||
frag_color = vec4(1.0);
|
||||
@@ -944,7 +942,7 @@ void main() {
|
||||
const float z = t != 0.0 ? height : base;
|
||||
|
||||
gl_Position = drawable.matrix * vec4(in_position, z, 1.0);
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
#if defined(OVERDRAW_INSPECTOR)
|
||||
frag_color = vec4(1.0);
|
||||
|
||||
@@ -98,7 +98,7 @@ void main() {
|
||||
// multiply a_pos by 0.5, since we had it * 2 in order to sneak
|
||||
// in extrusion data
|
||||
gl_Position = drawable.matrix * vec4(floor(in_position * 0.5) + scaled_extrude, 0, 1);
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
frag_weight = weight;
|
||||
frag_extrude = extrude;
|
||||
@@ -162,7 +162,7 @@ layout(location = 0) out vec2 frag_position;
|
||||
void main() {
|
||||
|
||||
gl_Position = props.matrix * vec4(in_position * global.world_size, 0, 1);
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
frag_position = in_position;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ layout(location = 0) out vec2 frag_position;
|
||||
void main() {
|
||||
|
||||
gl_Position = drawable.matrix * vec4(in_position, 0.0, 1.0);
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
const vec2 epsilon = vec2(1.0) / drawable.dimension;
|
||||
const float scale = (drawable.dimension.x - 2.0) / drawable.dimension.x;
|
||||
@@ -149,7 +149,7 @@ layout(location = 0) out vec2 frag_position;
|
||||
void main() {
|
||||
|
||||
gl_Position = drawable.matrix * vec4(in_position, 0.0, 1.0);
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
frag_position = vec2(in_texture_position) / 8192.0;
|
||||
frag_position.y = 1.0 - frag_position.y; // TODO check this. prepare should ignore the flip
|
||||
|
||||
@@ -155,7 +155,7 @@ void main() {
|
||||
|
||||
vec4 projected_extrude = drawable.matrix * vec4(dist / drawable.ratio, 0.0, 0.0);
|
||||
gl_Position = drawable.matrix * vec4(pos + offset2 / drawable.ratio, 0.0, 1.0) + projected_extrude;
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
// calculate how much the perspective view squishes or stretches the extrude
|
||||
float extrude_length_without_perspective = length(dist);
|
||||
@@ -376,7 +376,7 @@ void main() {
|
||||
|
||||
vec4 projected_extrude = drawable.matrix * vec4(dist / drawable.ratio, 0.0, 0.0);
|
||||
gl_Position = drawable.matrix * vec4(pos + offset2 / drawable.ratio, 0.0, 1.0) + projected_extrude;
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
// calculate how much the perspective view squishes or stretches the extrude
|
||||
float extrude_length_without_perspective = length(dist);
|
||||
@@ -626,7 +626,7 @@ void main() {
|
||||
|
||||
vec4 projected_extrude = drawable.matrix * vec4(dist / drawable.ratio, 0.0, 0.0);
|
||||
gl_Position = drawable.matrix * vec4(pos + offset2 / drawable.ratio, 0.0, 1.0) + projected_extrude;
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
// calculate how much the perspective view squishes or stretches the extrude
|
||||
float extrude_length_without_perspective = length(dist);
|
||||
@@ -941,7 +941,7 @@ void main() {
|
||||
|
||||
vec4 projected_extrude = drawable.matrix * vec4(dist / drawable.ratio, 0.0, 0.0);
|
||||
gl_Position = drawable.matrix * vec4(pos + offset2 / drawable.ratio, 0.0, 1.0) + projected_extrude;
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
// calculate how much the perspective view squishes or stretches the extrude
|
||||
float extrude_length_without_perspective = length(dist);
|
||||
|
||||
@@ -44,7 +44,7 @@ layout(location = 1) out vec2 frag_position1;
|
||||
void main() {
|
||||
|
||||
gl_Position = drawable.matrix * vec4(in_position, 0, 1);
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
// We are using Int16 for texture position coordinates to give us enough precision for
|
||||
// fractional coordinates. We use 8192 to scale the texture coordinates in the buffer
|
||||
|
||||
@@ -117,7 +117,7 @@ void main() {
|
||||
const vec2 pos0 = projected_pos.xy / projected_pos.w;
|
||||
const vec2 posOffset = a_offset * max(a_minFontScale, fontScale) / 32.0 + a_pxoffset / 16.0;
|
||||
gl_Position = drawable.coord_matrix * vec4(pos0 + rotation_matrix * posOffset, 0.0, 1.0);
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
const vec2 raw_fade_opacity = unpack_opacity(in_fade_opacity);
|
||||
const float fade_change = raw_fade_opacity[1] > 0.5 ? global.symbol_fade_change : -global.symbol_fade_change;
|
||||
@@ -339,8 +339,8 @@ void main() {
|
||||
const vec2 pos_rot = a_offset / 32.0 * fontScale + a_pxoffset;
|
||||
const vec2 pos0 = projected_pos.xy / projected_pos.w + rotation_matrix * pos_rot;
|
||||
gl_Position = drawable.coord_matrix * vec4(pos0, 0.0, 1.0);
|
||||
gl_Position.y *= -1.0;
|
||||
|
||||
applySurfaceTransform();
|
||||
|
||||
const vec2 raw_fade_opacity = unpack_opacity(in_fade_opacity);
|
||||
const float fade_change = raw_fade_opacity[1] > 0.5 ? global.symbol_fade_change : -global.symbol_fade_change;
|
||||
|
||||
@@ -640,7 +640,7 @@ void main() {
|
||||
const vec2 pos_rot = a_offset / 32.0 * fontScale;
|
||||
const vec2 pos0 = projected_pos.xy / projected_pos.w + rotation_matrix * pos_rot;
|
||||
gl_Position = drawable.coord_matrix * vec4(pos0, 0.0, 1.0);
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
const vec2 raw_fade_opacity = unpack_opacity(in_fade_opacity);
|
||||
const float fade_change = raw_fade_opacity[1] > 0.5 ? global.symbol_fade_change : -global.symbol_fade_change;
|
||||
@@ -862,7 +862,7 @@ void main() {
|
||||
}
|
||||
|
||||
gl_Position = position;
|
||||
gl_Position.y *= -1.0;
|
||||
applySurfaceTransform();
|
||||
|
||||
frag_tex = in_tex;
|
||||
}
|
||||
|
||||
@@ -197,6 +197,7 @@ private:
|
||||
uint8_t frameResourceIndex = 0;
|
||||
std::vector<FrameResources> frameResources;
|
||||
bool surfaceUpdateRequested{false};
|
||||
int32_t currentFrameCount{0};
|
||||
|
||||
struct {
|
||||
gfx::ShaderProgramBasePtr shader;
|
||||
|
||||
@@ -58,12 +58,22 @@ public:
|
||||
void setAcquiredImageIndex(uint32_t index) { acquiredImageIndex = index; };
|
||||
const vk::Image getAcquiredImage() const;
|
||||
|
||||
bool hasSurfaceTransformSupport() const;
|
||||
bool didSurfaceTransformUpdate() const;
|
||||
|
||||
// rotation needed to align framebuffer contents with device surface
|
||||
float getRotation();
|
||||
|
||||
void setSurfaceTransformPollingInterval(int32_t value) { surfaceTransformPollingInterval = value; }
|
||||
int32_t getSurfaceTransformPollingInterval() const { return surfaceTransformPollingInterval; }
|
||||
|
||||
void init(uint32_t w, uint32_t h);
|
||||
void recreateSwapchain();
|
||||
|
||||
protected:
|
||||
vk::UniqueSurfaceKHR surface;
|
||||
vk::UniqueSwapchainKHR swapchain;
|
||||
vk::SurfaceCapabilitiesKHR capabilities;
|
||||
|
||||
uint32_t acquiredImageIndex{0};
|
||||
|
||||
@@ -77,6 +87,18 @@ protected:
|
||||
|
||||
UniqueImageAllocation depthAllocation;
|
||||
vk::Format depthFormat{vk::Format::eUndefined};
|
||||
|
||||
int32_t surfaceTransformPollingInterval{-1};
|
||||
};
|
||||
|
||||
class Renderable : public gfx::Renderable {
|
||||
protected:
|
||||
Renderable(const Size size_, std::unique_ptr<gfx::RenderableResource> resource_)
|
||||
: gfx::Renderable(size_, std::move(resource_)) {}
|
||||
virtual ~Renderable() override = default;
|
||||
|
||||
public:
|
||||
void setSize(const Size& size_) { size = size_; }
|
||||
};
|
||||
|
||||
} // namespace vulkan
|
||||
|
||||
@@ -25,6 +25,11 @@ public:
|
||||
auto& backendImpl = static_cast<AndroidVulkanRendererBackend&>(backend);
|
||||
const vk::AndroidSurfaceCreateInfoKHR createInfo({}, backendImpl.getWindow());
|
||||
surface = backendImpl.getInstance()->createAndroidSurfaceKHRUnique(createInfo);
|
||||
|
||||
const int apiLevel = android_get_device_api_level();
|
||||
if (apiLevel < __ANDROID_API_Q__) {
|
||||
setSurfaceTransformPollingInterval(30);
|
||||
}
|
||||
}
|
||||
|
||||
void bind() override {}
|
||||
@@ -42,7 +47,7 @@ private:
|
||||
|
||||
AndroidVulkanRendererBackend::AndroidVulkanRendererBackend(ANativeWindow* window_)
|
||||
: vulkan::RendererBackend(gfx::ContextMode::Unique),
|
||||
mbgl::gfx::Renderable({64, 64}, std::make_unique<AndroidVulkanRenderableResource>(*this)),
|
||||
vulkan::Renderable({64, 64}, std::make_unique<AndroidVulkanRenderableResource>(*this)),
|
||||
window(window_) {
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/renderable.hpp>
|
||||
#include <mbgl/vulkan/renderable_resource.hpp>
|
||||
#include <mbgl/vulkan/renderer_backend.hpp>
|
||||
#include "android_renderer_backend.hpp"
|
||||
#include <android/native_window.h>
|
||||
@@ -10,7 +10,7 @@ namespace android {
|
||||
|
||||
class AndroidVulkanRendererBackend : public AndroidRendererBackend,
|
||||
public vulkan::RendererBackend,
|
||||
public mbgl::gfx::Renderable {
|
||||
public vulkan::Renderable {
|
||||
public:
|
||||
AndroidVulkanRendererBackend(ANativeWindow*);
|
||||
~AndroidVulkanRendererBackend() override;
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
|
||||
GLFWVulkanBackend::GLFWVulkanBackend(GLFWwindow* window_, const bool)
|
||||
: mbgl::vulkan::RendererBackend(mbgl::gfx::ContextMode::Unique),
|
||||
mbgl::gfx::Renderable(
|
||||
mbgl::vulkan::Renderable(
|
||||
[window_] {
|
||||
int fbWidth;
|
||||
int fbHeight;
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
|
||||
#include "glfw_backend.hpp"
|
||||
|
||||
#include <mbgl/gfx/renderable.hpp>
|
||||
#include <mbgl/vulkan/renderable_resource.hpp>
|
||||
#include <mbgl/vulkan/renderer_backend.hpp>
|
||||
|
||||
struct GLFWwindow;
|
||||
|
||||
class GLFWVulkanBackend final : public GLFWBackend, public mbgl::vulkan::RendererBackend, public mbgl::gfx::Renderable {
|
||||
class GLFWVulkanBackend final : public GLFWBackend,
|
||||
public mbgl::vulkan::RendererBackend,
|
||||
public mbgl::vulkan::Renderable {
|
||||
public:
|
||||
GLFWVulkanBackend(GLFWwindow*, bool capFrameRate);
|
||||
~GLFWVulkanBackend() override;
|
||||
|
||||
@@ -229,7 +229,7 @@ void PaintParameters::renderTileClippingMasks(const RenderTiles& renderTiles) {
|
||||
tileUBOs.reserve(count);
|
||||
}
|
||||
|
||||
tileUBOs.emplace_back(shaders::ClipUBO{util::cast<float>(matrixForTile(tileID)), stencilID});
|
||||
tileUBOs.emplace_back(shaders::ClipUBO{matrixForTile(tileID), stencilID});
|
||||
}
|
||||
|
||||
if (!tileUBOs.empty()) {
|
||||
|
||||
@@ -41,6 +41,12 @@ ShaderProgram::ShaderProgram(shaders::BuiltIn shaderID,
|
||||
for (const auto& define : additionalDefines) {
|
||||
defineStr += "#define " + define.first + " " + define.second + "\n";
|
||||
}
|
||||
|
||||
const auto& renderableResource = backend.getDefaultRenderable().getResource<SurfaceRenderableResource>();
|
||||
if (renderableResource.hasSurfaceTransformSupport()) {
|
||||
defineStr += "#define USE_SURFACE_TRANSFORM";
|
||||
}
|
||||
|
||||
observer.onPreCompileShader(shaderID, gfx::Backend::Type::Metal, defineStr);
|
||||
|
||||
constexpr auto targetClientVersion = glslang::EShTargetVulkan_1_0;
|
||||
|
||||
@@ -189,6 +189,20 @@ void Context::beginFrame() {
|
||||
auto& renderableResource = backend.getDefaultRenderable().getResource<SurfaceRenderableResource>();
|
||||
const auto& platformSurface = renderableResource.getPlatformSurface();
|
||||
|
||||
// poll for surface transform updates if enabled
|
||||
const int32_t surfaceTransformPollingInterval = renderableResource.getSurfaceTransformPollingInterval();
|
||||
if (surfaceTransformPollingInterval >= 0 && !surfaceUpdateRequested) {
|
||||
if (currentFrameCount > surfaceTransformPollingInterval) {
|
||||
if (renderableResource.didSurfaceTransformUpdate()) {
|
||||
requestSurfaceUpdate();
|
||||
}
|
||||
|
||||
currentFrameCount = 0;
|
||||
} else {
|
||||
++currentFrameCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (platformSurface && surfaceUpdateRequested) {
|
||||
renderableResource.recreateSwapchain();
|
||||
|
||||
@@ -201,6 +215,14 @@ void Context::beginFrame() {
|
||||
// sync resources with swapchain
|
||||
frameResourceIndex = 0;
|
||||
surfaceUpdateRequested = false;
|
||||
|
||||
// update renderable size
|
||||
if (renderableResource.hasSurfaceTransformSupport()) {
|
||||
const auto& extent = renderableResource.getExtent();
|
||||
|
||||
auto& renderable = static_cast<Renderable&>(backend.getDefaultRenderable());
|
||||
renderable.setSize({extent.width, extent.height});
|
||||
}
|
||||
}
|
||||
|
||||
backend.startFrameCapture();
|
||||
@@ -221,13 +243,9 @@ void Context::beginFrame() {
|
||||
if (acquireImageResult.result == vk::Result::eSuccess) {
|
||||
renderableResource.setAcquiredImageIndex(acquireImageResult.value);
|
||||
} else if (acquireImageResult.result == vk::Result::eSuboptimalKHR) {
|
||||
renderableResource.setAcquiredImageIndex(acquireImageResult.value);
|
||||
// TODO implement pre-rotation transform for surface orientation
|
||||
#if defined(__APPLE__)
|
||||
requestSurfaceUpdate();
|
||||
beginFrame();
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
} catch (const vk::OutOfDateKHRError& e) {
|
||||
@@ -289,10 +307,7 @@ void Context::submitFrame() {
|
||||
const auto& presentQueue = backend.getPresentQueue();
|
||||
const vk::Result presentResult = presentQueue.presentKHR(presentInfo);
|
||||
if (presentResult == vk::Result::eSuboptimalKHR) {
|
||||
// TODO implement pre-rotation transform for surface orientation
|
||||
#if defined(__APPLE__)
|
||||
requestSurfaceUpdate();
|
||||
#endif
|
||||
}
|
||||
} catch (const vk::OutOfDateKHRError& e) {
|
||||
requestSurfaceUpdate();
|
||||
@@ -409,7 +424,22 @@ void Context::clearStencilBuffer(int32_t) {
|
||||
|
||||
void Context::bindGlobalUniformBuffers(gfx::RenderPass& renderPass) const noexcept {
|
||||
auto& renderPassImpl = static_cast<RenderPass&>(renderPass);
|
||||
const_cast<Context*>(this)->globalUniformBuffers.bindDescriptorSets(renderPassImpl.getEncoder());
|
||||
auto& context = const_cast<Context&>(*this);
|
||||
|
||||
auto& renderableResource = renderPassImpl.getDescriptor().renderable.getResource<SurfaceRenderableResource>();
|
||||
if (renderableResource.hasSurfaceTransformSupport()) {
|
||||
float surfaceRotation = renderableResource.getRotation();
|
||||
|
||||
struct alignas(16) {
|
||||
alignas(16) std::array<float, 2> rotation0;
|
||||
alignas(16) std::array<float, 2> rotation1;
|
||||
} data;
|
||||
|
||||
data = {{cosf(surfaceRotation), -sinf(surfaceRotation)}, {sinf(surfaceRotation), cosf(surfaceRotation)}};
|
||||
context.globalUniformBuffers.createOrUpdate(shaders::PlatformParamsUBO, &data, sizeof(data), context);
|
||||
}
|
||||
|
||||
context.globalUniformBuffers.bindDescriptorSets(renderPassImpl.getEncoder());
|
||||
}
|
||||
|
||||
bool Context::renderTileClippingMasks(gfx::RenderPass& renderPass,
|
||||
@@ -489,15 +519,23 @@ bool Context::renderTileClippingMasks(gfx::RenderPass& renderPass,
|
||||
commandBuffer->bindVertexBuffers(0, vertexBuffers, offset);
|
||||
commandBuffer->bindIndexBuffer(clipping.indexBuffer->getVulkanBuffer(), 0, vk::IndexType::eUint16);
|
||||
|
||||
auto& renderableResource = renderPassImpl.getDescriptor().renderable.getResource<SurfaceRenderableResource>();
|
||||
const float rad = renderableResource.getRotation();
|
||||
const mat4 rotationMat = {cos(rad), -sin(rad), 0, 0, sin(rad), cos(rad), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
|
||||
|
||||
for (const auto& tileInfo : tileUBOs) {
|
||||
commandBuffer->setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack, tileInfo.stencil_ref);
|
||||
|
||||
mat4 matrix;
|
||||
matrix::multiply(matrix, rotationMat, tileInfo.matrix);
|
||||
const auto& matrixf = util::cast<float>(matrix);
|
||||
|
||||
commandBuffer->pushConstants(
|
||||
getPushConstantPipelineLayout().get(),
|
||||
vk::ShaderStageFlags() | vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment,
|
||||
0,
|
||||
sizeof(tileInfo.matrix),
|
||||
&tileInfo.matrix);
|
||||
sizeof(matrixf),
|
||||
&matrixf);
|
||||
commandBuffer->drawIndexed(clipping.indexCount, 1, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <mbgl/vulkan/renderable_resource.hpp>
|
||||
#include <mbgl/vulkan/context.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
#include <mbgl/util/constants.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace vulkan {
|
||||
@@ -95,7 +96,7 @@ void SurfaceRenderableResource::initSwapchain(uint32_t w, uint32_t h, vk::Presen
|
||||
}
|
||||
|
||||
// pick surface size
|
||||
const vk::SurfaceCapabilitiesKHR& capabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface.get());
|
||||
capabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface.get());
|
||||
|
||||
if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) {
|
||||
extent = capabilities.currentExtent;
|
||||
@@ -105,6 +106,13 @@ void SurfaceRenderableResource::initSwapchain(uint32_t w, uint32_t h, vk::Presen
|
||||
extent.height = std::min(std::max(h, capabilities.minImageExtent.height), capabilities.maxImageExtent.height);
|
||||
}
|
||||
|
||||
if (hasSurfaceTransformSupport()) {
|
||||
if (capabilities.currentTransform & vk::SurfaceTransformFlagBitsKHR::eRotate90 ||
|
||||
capabilities.currentTransform & vk::SurfaceTransformFlagBitsKHR::eRotate270) {
|
||||
std::swap(extent.width, extent.height);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t swapchainImageCount = capabilities.minImageCount + 1;
|
||||
// check surface limits (0 is unlimited)
|
||||
if (capabilities.maxImageCount > 0) swapchainImageCount = std::min(swapchainImageCount, capabilities.maxImageCount);
|
||||
@@ -133,7 +141,8 @@ void SurfaceRenderableResource::initSwapchain(uint32_t w, uint32_t h, vk::Presen
|
||||
swapchainCreateInfo.setImageSharingMode(vk::SharingMode::eExclusive);
|
||||
}
|
||||
|
||||
swapchainCreateInfo.setPreTransform(vk::SurfaceTransformFlagBitsKHR::eIdentity);
|
||||
swapchainCreateInfo.setPreTransform(hasSurfaceTransformSupport() ? capabilities.currentTransform
|
||||
: vk::SurfaceTransformFlagBitsKHR::eIdentity);
|
||||
swapchainCreateInfo.setClipped(VK_TRUE);
|
||||
|
||||
if (capabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::eInherit) {
|
||||
@@ -143,7 +152,7 @@ void SurfaceRenderableResource::initSwapchain(uint32_t w, uint32_t h, vk::Presen
|
||||
}
|
||||
|
||||
// update this when recreating
|
||||
swapchainCreateInfo.setOldSwapchain(vk::SwapchainKHR(swapchain.get()));
|
||||
swapchainCreateInfo.setOldSwapchain(swapchain.get());
|
||||
|
||||
swapchain = device->createSwapchainKHRUnique(swapchainCreateInfo);
|
||||
swapchainImages = device->getSwapchainImagesKHR(swapchain.get());
|
||||
@@ -231,6 +240,41 @@ const vk::Image SurfaceRenderableResource::getAcquiredImage() const {
|
||||
return colorAllocations[acquiredImageIndex]->image;
|
||||
}
|
||||
|
||||
bool SurfaceRenderableResource::hasSurfaceTransformSupport() const {
|
||||
#ifdef __ANDROID__
|
||||
return surface && capabilities.supportedTransforms != vk::SurfaceTransformFlagBitsKHR::eIdentity;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SurfaceRenderableResource::didSurfaceTransformUpdate() const {
|
||||
const auto& physicalDevice = backend.getPhysicalDevice();
|
||||
const auto& updatedCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface.get());
|
||||
|
||||
return capabilities.currentTransform != updatedCapabilities.currentTransform;
|
||||
}
|
||||
|
||||
float SurfaceRenderableResource::getRotation() {
|
||||
switch (capabilities.currentTransform) {
|
||||
default:
|
||||
case vk::SurfaceTransformFlagBitsKHR::eIdentity:
|
||||
return 0.0f * M_PI / 180.0f;
|
||||
|
||||
case vk::SurfaceTransformFlagBitsKHR::eRotate90:
|
||||
case vk::SurfaceTransformFlagBitsKHR::eHorizontalMirrorRotate90:
|
||||
return 90.0f * M_PI / 180.0f;
|
||||
|
||||
case vk::SurfaceTransformFlagBitsKHR::eRotate180:
|
||||
case vk::SurfaceTransformFlagBitsKHR::eHorizontalMirrorRotate180:
|
||||
return 180.0f * M_PI / 180.0f;
|
||||
|
||||
case vk::SurfaceTransformFlagBitsKHR::eRotate270:
|
||||
case vk::SurfaceTransformFlagBitsKHR::eHorizontalMirrorRotate270:
|
||||
return 270.0f * M_PI / 180.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceRenderableResource::init(uint32_t w, uint32_t h) {
|
||||
if (surface) {
|
||||
initSwapchain(w, h);
|
||||
|
||||
@@ -557,7 +557,7 @@ void RendererBackend::initDevice() {
|
||||
}
|
||||
|
||||
void RendererBackend::initSwapchain() {
|
||||
const auto& renderable = getDefaultRenderable();
|
||||
auto& renderable = getDefaultRenderable();
|
||||
auto& renderableResource = renderable.getResource<SurfaceRenderableResource>();
|
||||
const auto& size = renderable.getSize();
|
||||
|
||||
@@ -566,6 +566,13 @@ void RendererBackend::initSwapchain() {
|
||||
maxFrames = renderableResource.getPlatformSurface() ? 3 : 1;
|
||||
|
||||
renderableResource.init(size.width, size.height);
|
||||
|
||||
if (renderableResource.hasSurfaceTransformSupport()) {
|
||||
auto& renderableImpl = static_cast<Renderable&>(renderable);
|
||||
const auto& extent = renderableResource.getExtent();
|
||||
|
||||
renderableImpl.setSize({extent.width, extent.height});
|
||||
}
|
||||
}
|
||||
|
||||
void RendererBackend::initCommandPool() {
|
||||
|
||||
Reference in New Issue
Block a user