Skip to content

Commit 2cdafe9

Browse files
committed
handle recreate swap chain, but not stable :(
1 parent 48c1566 commit 2cdafe9

File tree

6 files changed

+178
-27
lines changed

6 files changed

+178
-27
lines changed

app/src/main/cpp/vulkan_triangle.cpp

Lines changed: 69 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,17 @@ void HelloTriangleApplication::run(ANativeWindow *window) {
208208
cleanUp();
209209
}
210210

211+
void HelloTriangleApplication::pause() {
212+
state = STATE_PAUSED;
213+
vkDeviceWaitIdle(device);
214+
}
215+
216+
void HelloTriangleApplication::surfaceChanged() {
217+
state = STATE_PAUSED;
218+
recreateSwapchain();
219+
state = STATE_RUNNING;
220+
}
221+
211222
void HelloTriangleApplication::initVulkan() {
212223
if (!InitVulkan()) {
213224
throw std::runtime_error("InitVulkan fail!");
@@ -231,8 +242,10 @@ void HelloTriangleApplication::initVulkan() {
231242
void HelloTriangleApplication::mainLoop() {
232243
LOGI("mainLoop start");
233244

234-
while (running) {
235-
drawFrame();
245+
while (state != STATE_EXIT) {
246+
if (state == STATE_RUNNING) {
247+
drawFrame();
248+
}
236249
}
237250

238251
vkDeviceWaitIdle(device);
@@ -241,32 +254,19 @@ void HelloTriangleApplication::mainLoop() {
241254
}
242255

243256
void HelloTriangleApplication::cleanUp() {
257+
cleanupSwapchain();
258+
244259
vkDestroySemaphore(device, renderFinishedSemaphore, nullptr);
245260
vkDestroySemaphore(device, imageAvailableSemaphore, nullptr);
246261

247262
vkDestroyCommandPool(device, commandPool, nullptr);
248263

249-
for (size_t i = 0; i < swapchainFramebuffers.size(); i++) {
250-
vkDestroyFramebuffer(device, swapchainFramebuffers[i], nullptr);
251-
}
252-
253-
vkDestroyPipeline(device, graphicsPipeline, nullptr);
254-
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
255-
vkDestroyRenderPass(device, renderPass, nullptr);
256-
257-
for (const auto &imageView : swapchainImageViews) {
258-
vkDestroyImageView(device, imageView, nullptr);
259-
}
260-
261-
vkDestroySwapchainKHR(device, swapchain, nullptr);
262264
vkDestroyDevice(device, nullptr);
263-
264265
DestroyDebugReportCallbackEXT(instance, callback, nullptr);
265-
266266
vkDestroySurfaceKHR(instance, surface, nullptr);
267-
ANativeWindow_release(window);
268-
269267
vkDestroyInstance(instance, nullptr);
268+
269+
ANativeWindow_release(window);
270270
}
271271

272272
void HelloTriangleApplication::createInstance() {
@@ -709,8 +709,15 @@ void HelloTriangleApplication::createSemaphores() {
709709

710710
void HelloTriangleApplication::drawFrame() {
711711
uint32_t imageIndex = 0;
712-
vkAcquireNextImageKHR(device, swapchain, std::numeric_limits<uint64_t>::max(),
713-
imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
712+
VkResult result = vkAcquireNextImageKHR(device, swapchain, std::numeric_limits<uint64_t>::max(),
713+
imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
714+
715+
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
716+
recreateSwapchain();
717+
return;
718+
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
719+
throw std::runtime_error("failed to acquire swap chain image!");
720+
}
714721

715722
VkSubmitInfo submitInfo = {};
716723
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
@@ -743,11 +750,51 @@ void HelloTriangleApplication::drawFrame() {
743750

744751
presentInfo.pImageIndices = &imageIndex;
745752

746-
vkQueuePresentKHR(presentQueue, &presentInfo);
753+
result = vkQueuePresentKHR(presentQueue, &presentInfo);
754+
755+
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
756+
recreateSwapchain();
757+
} else if (result != VK_SUCCESS) {
758+
throw std::runtime_error("failed to present swap chain image!");
759+
}
747760

748761
vkQueueWaitIdle(presentQueue);
749762
}
750763

764+
void HelloTriangleApplication::recreateSwapchain() {
765+
LOGI("recreateSwapchain");
766+
767+
vkDeviceWaitIdle(device);
768+
769+
cleanupSwapchain();
770+
771+
createSwapchain();
772+
createImageViews();
773+
createRenderPass();
774+
createGraphicsPipeline();
775+
createFramebuffers();
776+
createCommandBuffers();
777+
}
778+
779+
void HelloTriangleApplication::cleanupSwapchain() {
780+
for (size_t i = 0; i < swapchainFramebuffers.size(); i++) {
781+
vkDestroyFramebuffer(device, swapchainFramebuffers[i], nullptr);
782+
}
783+
784+
vkFreeCommandBuffers(device, commandPool, static_cast<uint32_t>(commandBuffers.size()),
785+
commandBuffers.data());
786+
787+
vkDestroyPipeline(device, graphicsPipeline, nullptr);
788+
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
789+
vkDestroyRenderPass(device, renderPass, nullptr);
790+
791+
for (size_t i = 0; i < swapchainImageViews.size(); i++) {
792+
vkDestroyImageView(device, swapchainImageViews[i], nullptr);
793+
}
794+
795+
vkDestroySwapchainKHR(device, swapchain, nullptr);
796+
}
797+
751798
std::vector<char> HelloTriangleApplication::readAsset(std::string name) {
752799
AAsset *file = AAssetManager_open(assetManager, name.c_str(), AASSET_MODE_BUFFER);
753800
size_t len = AAsset_getLength(file);

app/src/main/cpp/vulkan_triangle.h

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, APP_NAME, __VA_ARGS__))
1818
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, APP_NAME, __VA_ARGS__))
1919

20+
#define STATE_RUNNING 1
21+
#define STATE_PAUSED 2
22+
#define STATE_EXIT 3
23+
2024
struct QueueFamilyIndices {
2125
int graphicsFamily = -1;
2226
int presentFamily = -1;
@@ -41,13 +45,21 @@ class HelloTriangleApplication {
4145
assetManager(assetManager),
4246
vertexShader(std::string(vertexShader)),
4347
fragmentShader(std::string(fragmentShader)),
44-
running(true) {
48+
state(STATE_RUNNING) {
4549
}
4650

4751
void run(ANativeWindow *window);
4852

53+
void pause();
54+
55+
inline void resume() {
56+
state = STATE_RUNNING;
57+
}
58+
59+
void surfaceChanged();
60+
4961
inline void stop() {
50-
running = false;
62+
state = STATE_EXIT;
5163
}
5264

5365
private:
@@ -89,6 +101,10 @@ class HelloTriangleApplication {
89101

90102
void drawFrame();
91103

104+
void recreateSwapchain();
105+
106+
void cleanupSwapchain();
107+
92108
std::vector<char> readAsset(std::string name);
93109

94110
VkShaderModule createShaderModule(const std::vector<char> &code);
@@ -104,7 +120,7 @@ class HelloTriangleApplication {
104120
AAssetManager *assetManager;
105121
std::string vertexShader;
106122
std::string fragmentShader;
107-
bool running;
123+
int state;
108124

109125
VkInstance instance;
110126
VkDebugReportCallbackEXT callback;

app/src/main/cpp/vulkan_triangle_jni.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,28 @@ Java_com_github_piasy_vulkantutorial_HelloTriangleApplication_run(
4747
}
4848

4949
JNIEXPORT void JNICALL
50-
Java_com_github_piasy_vulkantutorial_HelloTriangleApplication_stop__J(JNIEnv *env, jclass type,
50+
Java_com_github_piasy_vulkantutorial_HelloTriangleApplication_pause(JNIEnv *env, jclass type,
51+
jlong nativeHandle) {
52+
HelloTriangleApplication *app = reinterpret_cast<HelloTriangleApplication *>(nativeHandle);
53+
app->pause();
54+
}
55+
56+
JNIEXPORT void JNICALL
57+
Java_com_github_piasy_vulkantutorial_HelloTriangleApplication_resume(JNIEnv *env, jclass type,
58+
jlong nativeHandle) {
59+
HelloTriangleApplication *app = reinterpret_cast<HelloTriangleApplication *>(nativeHandle);
60+
app->resume();
61+
}
62+
63+
JNIEXPORT void JNICALL
64+
Java_com_github_piasy_vulkantutorial_HelloTriangleApplication_surfaceChanged(
65+
JNIEnv *env, jclass type, jlong nativeHandle) {
66+
HelloTriangleApplication *app = reinterpret_cast<HelloTriangleApplication *>(nativeHandle);
67+
app->surfaceChanged();
68+
}
69+
70+
JNIEXPORT void JNICALL
71+
Java_com_github_piasy_vulkantutorial_HelloTriangleApplication_stop(JNIEnv *env, jclass type,
5172
jlong nativeHandle) {
5273
HelloTriangleApplication *app = reinterpret_cast<HelloTriangleApplication *>(nativeHandle);
5374
app->stop();

app/src/main/java/com/github/piasy/vulkantutorial/HelloTriangleApplication.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ private static native long create(AssetManager assetManager, String vertexShader
2626

2727
private static native void run(long nativeHandle, Surface surface);
2828

29+
private static native void pause(long nativeHandle);
30+
31+
private static native void resume(long nativeHandle);
32+
33+
private static native void surfaceChanged(long nativeHandle);
34+
2935
private static native void stop(long nativeHandle);
3036

3137
public void run(final Surface surface) {
@@ -37,6 +43,18 @@ public void run() {
3743
}).start();
3844
}
3945

46+
public void pause() {
47+
pause(mNativeHandle);
48+
}
49+
50+
public void resume() {
51+
resume(mNativeHandle);
52+
}
53+
54+
public void surfaceChanged() {
55+
surfaceChanged(mNativeHandle);
56+
}
57+
4058
public void stop() {
4159
stop(mNativeHandle);
4260
}

app/src/main/java/com/github/piasy/vulkantutorial/MainActivity.java

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import android.support.v7.app.AppCompatActivity;
66
import android.view.SurfaceHolder;
77
import android.view.SurfaceView;
8+
import android.view.View;
9+
import android.view.ViewGroup;
810

911
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
1012

@@ -13,6 +15,8 @@ public class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal
1315

1416
private HelloTriangleApplication mTriangleApplication;
1517
private AssetManager mAssetManager;
18+
private boolean mFirstSurfaceChange;
19+
private boolean mFullscreen = true;
1620

1721
@Override
1822
protected void onCreate(Bundle savedInstanceState) {
@@ -24,8 +28,41 @@ protected void onCreate(Bundle savedInstanceState) {
2428
mTriangleApplication = new HelloTriangleApplication(mAssetManager, VERTEX_SHADER,
2529
FRAGMENT_SHADER);
2630

27-
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surface);
31+
final SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surface);
2832
surfaceView.getHolder().addCallback(this);
33+
34+
findViewById(R.id.mBtnResize).setOnClickListener(new View.OnClickListener() {
35+
@Override
36+
public void onClick(final View v) {
37+
mFullscreen = !mFullscreen;
38+
39+
ViewGroup.LayoutParams params = surfaceView.getLayoutParams();
40+
41+
if (mFullscreen) {
42+
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
43+
params.height = ViewGroup.LayoutParams.MATCH_PARENT;
44+
} else {
45+
params.width = 180;
46+
params.height = 320;
47+
}
48+
49+
surfaceView.setLayoutParams(params);
50+
}
51+
});
52+
}
53+
54+
@Override
55+
protected void onResume() {
56+
super.onResume();
57+
58+
mTriangleApplication.resume();
59+
}
60+
61+
@Override
62+
protected void onPause() {
63+
super.onPause();
64+
65+
mTriangleApplication.pause();
2966
}
3067

3168
@Override
@@ -38,11 +75,16 @@ protected void onDestroy() {
3875
@Override
3976
public void surfaceCreated(final SurfaceHolder holder) {
4077
mTriangleApplication.run(holder.getSurface());
78+
mFirstSurfaceChange = true;
4179
}
4280

4381
@Override
4482
public void surfaceChanged(final SurfaceHolder holder, final int format, final int width,
4583
final int height) {
84+
if (!mFirstSurfaceChange) {
85+
mTriangleApplication.surfaceChanged();
86+
}
87+
mFirstSurfaceChange = false;
4688
}
4789

4890
@Override

app/src/main/res/layout/activity_main.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,11 @@
1313
android:layout_height="match_parent"
1414
/>
1515

16+
<Button
17+
android:id="@+id/mBtnResize"
18+
android:layout_width="wrap_content"
19+
android:layout_height="wrap_content"
20+
android:text="resize"
21+
/>
22+
1623
</FrameLayout>

0 commit comments

Comments
 (0)