Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

igl | shell | vulkan | Support screen rotate on android #168

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
tools:targetApi="33">
<activity
android:name=".SampleActivity"
android:configChanges="orientation|screenSize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
2 changes: 1 addition & 1 deletion shell/android/jni/Jni.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ JNIEXPORT void JNICALL Java_com_facebook_igl_shell_SampleLib_init(JNIEnv* env,
: nullptr,
activeBackendTypeID);
} else if (activeBackendTypeID == BackendTypeID::Vulkan) {
renderers[activeBackendTypeID]->recreateSwapchain(ANativeWindow_fromSurface(env, surface));
renderers[activeBackendTypeID]->recreateSwapchain(ANativeWindow_fromSurface(env, surface), true);
}
}

Expand Down
63 changes: 61 additions & 2 deletions shell/android/jni/TinyRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ void TinyRenderer::init(AAssetManager* mgr,
ANativeWindow* nativeWindow,
BackendTypeID backendTypeID) {
backendTypeID_ = backendTypeID;
nativeWindow_ = nativeWindow;
Result result;
const igl::HWDeviceQueryDesc queryDesc(HWDeviceType::IntegratedGpu);
std::unique_ptr<IDevice> d;
Expand All @@ -61,6 +62,7 @@ void TinyRenderer::init(AAssetManager* mgr,

#if IGL_BACKEND_VULKAN
case BackendTypeID::Vulkan: {
isSurfaceCreated_ = true;
IGL_ASSERT(nativeWindow != nullptr);
vulkan::VulkanContextConfig config;
config.terminateOnValidationError = true;
Expand Down Expand Up @@ -106,6 +108,11 @@ void TinyRenderer::init(AAssetManager* mgr,
if (d) {
platform_ = std::make_shared<igl::shell::PlatformAndroid>(std::move(d));
IGL_ASSERT(platform_ != nullptr);

#if IGL_BACKEND_VULKAN
updateSurfaceTransformRotate(platform_->getDevice());
#endif

static_cast<igl::shell::ImageLoaderAndroid&>(platform_->getImageLoader()).setAssetManager(mgr);
static_cast<igl::shell::FileLoaderAndroid&>(platform_->getFileLoader()).setAssetManager(mgr);
session_ = igl::shell::createDefaultRenderSession(platform_);
Expand All @@ -115,8 +122,9 @@ void TinyRenderer::init(AAssetManager* mgr,
}
}

void TinyRenderer::recreateSwapchain(ANativeWindow* nativeWindow) {
void TinyRenderer::recreateSwapchain(ANativeWindow* nativeWindow, bool createSurface) {
#if IGL_BACKEND_VULKAN
nativeWindow_ = nativeWindow;
width_ = static_cast<uint32_t>(ANativeWindow_getWidth(nativeWindow));
height_ = static_cast<uint32_t>(ANativeWindow_getHeight(nativeWindow));

Expand All @@ -127,7 +135,9 @@ void TinyRenderer::recreateSwapchain(ANativeWindow* nativeWindow) {
auto& vulkan_device = static_cast<igl::vulkan::Device&>(platform_->getDevice());
auto& vk_context = vulkan_device.getVulkanContext();

vk_context.createSurface(nativeWindow, nullptr);
if (createSurface) {
vk_context.createSurface(nativeWindow, nullptr);
}
vk_context.initSwapchain(width_, height_);

// need release frame buffer when recreate swap chain
Expand Down Expand Up @@ -195,6 +205,55 @@ void TinyRenderer::onSurfacesChanged(ANativeWindow* /*surface*/, int width, int
IGL_REPORT_ERROR(result.isOk());
}
#endif

#if IGL_BACKEND_VULKAN
if (backendTypeID_ == BackendTypeID::Vulkan){
if (isSurfaceCreated_){
isSurfaceCreated_ = false;
return;
}

recreateSwapchain(nativeWindow_, false);

updateSurfaceTransformRotate(platform_->getDevice());
}
#endif
}

void TinyRenderer::updateSurfaceTransformRotate(igl::IDevice& device) {
#if IGL_BACKEND_VULKAN
if (backendTypeID_ != BackendTypeID::Vulkan){
return;
}
igl::vulkan::Device& vulkan_device = static_cast<igl::vulkan::Device&>(device);
igl::vulkan::VulkanContext& vk_context = vulkan_device.getVulkanContext();
const VkSurfaceCapabilitiesKHR& surface_capabilities = vk_context.getSurfaceCapabilities();

SurfaceTransformRotate surfaceTransformRotate = kSurfaceTransformRotate0;

switch (surface_capabilities.currentTransform) {
case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
surfaceTransformRotate = kSurfaceTransformRotate0;
break;

case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
surfaceTransformRotate = kSurfaceTransformRotate90;
break;

case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
surfaceTransformRotate = kSurfaceTransformRotate180;
break;

case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
surfaceTransformRotate = kSurfaceTransformRotate270;
break;

default:
break;
}

platform_->updateSurfaceTransformRotate(surfaceTransformRotate);
#endif
}

void TinyRenderer::touchEvent(bool isDown, float x, float y, float dx, float dy) {
Expand Down
7 changes: 6 additions & 1 deletion shell/android/jni/TinyRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,15 @@ enum class BackendTypeID { GLES3, GLES2, Vulkan };
class TinyRenderer final {
public:
void init(AAssetManager* mgr, ANativeWindow* nativeWindow, BackendTypeID backendTypeID);
void recreateSwapchain(ANativeWindow* nativeWindow); // only for Vulkan
void recreateSwapchain(ANativeWindow* nativeWindow, bool createSurface); // only for Vulkan
void render(float displayScale);
void onSurfacesChanged(ANativeWindow* nativeWindow, int width, int height);
void touchEvent(bool isDown, float x, float y, float dx, float dy);
void setClearColorValue(float r, float g, float b, float a);

private:
void updateSurfaceTransformRotate(igl::IDevice& device);

private:
BackendTypeID backendTypeID_;
std::shared_ptr<igl::shell::PlatformAndroid> platform_;
Expand All @@ -38,6 +41,8 @@ class TinyRenderer final {
shell::ShellParams shellParams_;
uint32_t width_ = 0;
uint32_t height_ = 0;
bool isSurfaceCreated_ = true;
ANativeWindow* nativeWindow_ = NULL;
};

} // namespace igl::samples
17 changes: 14 additions & 3 deletions shell/renderSessions/ColorSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ static std::string getMetalShaderSource() {
return R"(
using namespace metal;

typedef struct { float3 color; } UniformBlock;
typedef struct {
vinsentli marked this conversation as resolved.
Show resolved Hide resolved
float4x4 mvp;
float3 color;
} UniformBlock;

typedef struct {
float3 position [[attribute(0)]];
Expand Down Expand Up @@ -112,11 +115,12 @@ static std::string getVulkanVertexShaderSource() {
layout(location = 1) out vec3 color;

layout (set = 1, binding = 0, std140) uniform UniformsPerObject {
mat4 mvp;
vec3 color;
} perObject;

void main() {
gl_Position = vec4(position, 1.0);
gl_Position = perObject.mvp * vec4(position, 1.0);
uv = uv_in;
color = perObject.color;
}
Expand Down Expand Up @@ -241,7 +245,9 @@ void ColorSession::initialize() noexcept {
renderPass_.depthAttachment.clearDepth = 1.0;

// init uniforms
fragmentParameters_ = FragmentFormat{{1.0f, 1.0f, 1.0f}};
glm::mat4x4 mvp(1.0f);
memcpy(&fragmentParameters_.mvp, &mvp, sizeof(mvp));
fragmentParameters_.color = {1.0f, 1.0f, 1.0f};

BufferDesc fpDesc;
fpDesc.type = BufferDesc::BufferTypeBits::Uniform;
Expand Down Expand Up @@ -322,6 +328,11 @@ void ColorSession::update(igl::SurfaceTextures surfaceTextures) noexcept {
fragmentUniformDescriptors_.back().offset = offsetof(FragmentFormat, color);
}

glm::mat4x4 mvp(1.0f);
getPlatform().preRotateMVPMatrix(mvp);
memcpy(&fragmentParameters_.mvp, &mvp, sizeof(mvp));
vinsentli marked this conversation as resolved.
Show resolved Hide resolved
fragmentParamBuffer_->upload(&fragmentParameters_, {sizeof(fragmentParameters_)});

// Submit commands
const std::shared_ptr<igl::IRenderCommandEncoder> commands =
buffer->createRenderCommandEncoder(renderPass_, framebuffer_);
Expand Down
1 change: 1 addition & 0 deletions shell/renderSessions/ColorSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace igl::shell {

class ColorSession : public RenderSession {
struct FragmentFormat {
iglu::simdtypes::float4x4 mvp;
iglu::simdtypes::float3 color;
};

Expand Down
10 changes: 10 additions & 0 deletions shell/shared/platform/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ namespace igl {
class IDevice;
}

enum SurfaceTransformRotate {
kSurfaceTransformRotate0,
kSurfaceTransformRotate90,
kSurfaceTransformRotate180,
kSurfaceTransformRotate270,
kSurfaceTransformRotateNum,
};

namespace igl::shell {

class Extension;
Expand Down Expand Up @@ -43,6 +51,8 @@ class Platform {
return displayContext_;
}

virtual void preRotateMVPMatrix(glm::mat4x4 & mvp) {}

std::shared_ptr<ITexture> loadTexture(
const char* filename,
bool calculateMipmapLevels = true,
Expand Down
15 changes: 15 additions & 0 deletions shell/shared/platform/android/PlatformAndroid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <shell/shared/imageWriter/ImageWriter.h>
#include <shell/shared/imageWriter/android/ImageWriterAndroid.h>

#include <glm/gtc/matrix_transform.hpp>

namespace igl::shell {

PlatformAndroid::PlatformAndroid(std::shared_ptr<igl::IDevice> device, bool useFakeLoader) :
Expand All @@ -23,6 +25,13 @@ PlatformAndroid::PlatformAndroid(std::shared_ptr<igl::IDevice> device, bool useF
imageLoader_ = std::make_unique<igl::shell::ImageLoaderAndroid>(*fileLoader_);
imageWriter_ = std::make_unique<igl::shell::ImageWriterAndroid>();
}

float rotate_angle[kSurfaceTransformRotateNum] = {0, -90, -180, -270};
for (int i = 0; i != kSurfaceTransformRotateNum; ++i) {
glm::mat4x4 pre_rotate_mat = glm::mat4x4(1.0f);
glm::vec3 rotation_axis = glm::vec3(0.0f, 0.0f, 1.0f);
surfaceTransformRotateMatrix_[i] = glm::rotate(pre_rotate_mat, glm::radians(rotate_angle[i]), rotation_axis);
}
}

igl::IDevice& PlatformAndroid::getDevice() noexcept {
Expand All @@ -45,4 +54,10 @@ FileLoader& PlatformAndroid::getFileLoader() const noexcept {
return *fileLoader_;
}

void PlatformAndroid::preRotateMVPMatrix(glm::mat4x4 & mvp){
if (kSurfaceTransformRotate0 != surfaceTransformRotate_) {
mvp = surfaceTransformRotateMatrix_[surfaceTransformRotate_] * mvp;
}
}

} // namespace igl::shell
5 changes: 5 additions & 0 deletions shell/shared/platform/android/PlatformAndroid.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,17 @@ class PlatformAndroid : public Platform {
ImageLoader& getImageLoader() noexcept override;
[[nodiscard]] const ImageWriter& getImageWriter() const noexcept override;
[[nodiscard]] FileLoader& getFileLoader() const noexcept override;
void preRotateMVPMatrix(glm::mat4x4 & mvp) override;
void updateSurfaceTransformRotate(SurfaceTransformRotate rotate) { surfaceTransformRotate_ = rotate;}

private:
std::shared_ptr<igl::IDevice> device_;
std::shared_ptr<FileLoader> fileLoader_;
std::shared_ptr<ImageWriter> imageWriter_;
std::shared_ptr<ImageLoader> imageLoader_;

SurfaceTransformRotate surfaceTransformRotate_ = kSurfaceTransformRotate0;
glm::mat4x4 surfaceTransformRotateMatrix_[kSurfaceTransformRotateNum];
};

} // namespace igl::shell
2 changes: 2 additions & 0 deletions src/igl/vulkan/VulkanContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ class VulkanContext final {

const VulkanFeatures& features() const noexcept;

const VkSurfaceCapabilitiesKHR & getSurfaceCapabilities() { return deviceSurfaceCaps_; }

#if defined(IGL_WITH_TRACY_GPU)
TracyVkCtx tracyCtx_ = nullptr;
std::unique_ptr<VulkanCommandPool> profilingCommandPool_;
Expand Down
9 changes: 5 additions & 4 deletions src/igl/vulkan/VulkanSwapchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& mode
VkImageUsageFlags chooseUsageFlags(const VulkanFunctionTable& vf,
VkPhysicalDevice pd,
VkSurfaceKHR surface,
VkFormat format) {
VkFormat format,
VkSurfaceCapabilitiesKHR &caps) {
VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
VkSurfaceCapabilitiesKHR caps = {};
VK_ASSERT(vf.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(pd, surface, &caps));

const bool isStorageSupported = (caps.supportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) > 0;
Expand All @@ -119,7 +119,7 @@ VkImageUsageFlags chooseUsageFlags(const VulkanFunctionTable& vf,

namespace igl::vulkan {

VulkanSwapchain::VulkanSwapchain(const VulkanContext& ctx, uint32_t width, uint32_t height) :
VulkanSwapchain::VulkanSwapchain(VulkanContext& ctx, uint32_t width, uint32_t height) :
ctx_(ctx),
device_(ctx.device_->getVkDevice()),
graphicsQueue_(ctx.deviceQueues_.graphicsQueue),
Expand Down Expand Up @@ -154,7 +154,7 @@ VulkanSwapchain::VulkanSwapchain(const VulkanContext& ctx, uint32_t width, uint3
#endif

const VkImageUsageFlags usageFlags =
chooseUsageFlags(ctx.vf_, ctx.getVkPhysicalDevice(), ctx.vkSurface_, surfaceFormat_.format);
chooseUsageFlags(ctx.vf_, ctx.getVkPhysicalDevice(), ctx.vkSurface_, surfaceFormat_.format, ctx.deviceSurfaceCaps_);

{
const uint32_t requestedSwapchainImageCount = chooseSwapImageCount(ctx.deviceSurfaceCaps_);
Expand Down Expand Up @@ -315,6 +315,7 @@ Result VulkanSwapchain::present(VkSemaphore waitSemaphore) {
IGL_PROFILER_FUNCTION();

IGL_PROFILER_ZONE("vkQueuePresent()", IGL_PROFILER_COLOR_PRESENT);

const auto presentResult =
ivkQueuePresent(&ctx_.vf_, graphicsQueue_, waitSemaphore, swapchain_, currentImageIndex_);
if (presentResult == VK_SUBOPTIMAL_KHR) {
Expand Down
4 changes: 2 additions & 2 deletions src/igl/vulkan/VulkanSwapchain.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class VulktanTexture;

class VulkanSwapchain final {
public:
VulkanSwapchain(const VulkanContext& ctx, uint32_t width, uint32_t height);
VulkanSwapchain(VulkanContext& ctx, uint32_t width, uint32_t height);
~VulkanSwapchain();

Result acquireNextImage();
Expand Down Expand Up @@ -104,7 +104,7 @@ class VulkanSwapchain final {
std::vector<VulkanFence> acquireFences_;

private:
const VulkanContext& ctx_;
VulkanContext& ctx_;
VkDevice device_;
VkQueue graphicsQueue_;
uint32_t width_ = 0;
Expand Down