Skip to content

Commit 611799c

Browse files
committed
create graphics pipeline
1 parent af84c97 commit 611799c

File tree

9 files changed

+324
-43
lines changed

9 files changed

+324
-43
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
# VulkanTutorial-Android
2+
23
Step by step tutorial of Vulkan on Android, follow https://vulkan-tutorial.com.
4+
5+
+ We need [`vulkan_wrappe`](https://developer.android.com/ndk/guides/graphics/getting-started.html#using) on Android, which could be [download from GitHub](https://github.com/LunarG/VulkanSamples/tree/master/common).
6+
+ In Android Studio, just put shader code under `src/main/shaders` folder, they will be compiled into `.spv` files, and packaged as assets.

app/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ add_library( # Sets the name of the library.
2323

2424
# Provides a relative path to your source file(s).
2525
${VK_WRAPPER_DIR}/vulkan_wrapper.cpp
26-
${SRC_DIR}/vulkan_triangle.cpp )
26+
${SRC_DIR}/vulkan_triangle.cpp
27+
${SRC_DIR}/vulkan_triangle_jni.cpp
28+
)
2729

2830
include_directories(${VK_WRAPPER_DIR} ${VK_VAL_LAYER_SRC_DIR}/include)
2931

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ android {
2727

2828
sourceSets {
2929
debug {
30+
ndkDir = 'src/main/cpp'
3031
jniLibs {
3132
// Must have ndk-r12 or better which including layer binaries
3233
srcDirs = ["${valLayerBinDir}"]

app/src/main/cpp/vulkan_triangle.cpp

Lines changed: 194 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
// Created by Piasy on 26/06/2017.
33
//
44

5+
#include <set>
6+
#include <algorithm>
7+
#include <stdexcept>
8+
#include <cstring>
9+
#include <functional>
10+
511
#include "vulkan_triangle.h"
612

713
const int WIDTH = 800;
@@ -215,14 +221,20 @@ void HelloTriangleApplication::initVulkan() {
215221
createLogicalDevice();
216222
createSwapchain();
217223
createImageViews();
224+
createRenderPass();
225+
createGraphicsPipeline();
218226
}
219227

220228
void HelloTriangleApplication::mainLoop() {
221229

222230
}
223231

224232
void HelloTriangleApplication::cleanUp() {
225-
for (const auto& imageView : swapchainImageViews) {
233+
vkDestroyPipeline(device, graphicsPipeline, nullptr);
234+
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
235+
vkDestroyRenderPass(device, renderPass, nullptr);
236+
237+
for (const auto &imageView : swapchainImageViews) {
226238
vkDestroyImageView(device, imageView, nullptr);
227239
}
228240

@@ -412,8 +424,8 @@ void HelloTriangleApplication::createSwapchain() {
412424
swapchainImages.resize(imageCount);
413425
vkGetSwapchainImagesKHR(device, swapchain, &imageCount, swapchainImages.data());
414426

415-
swapChainImageFormat = surfaceFormat.format;
416-
swapChainExtent = extent;
427+
swapchainImageFormat = surfaceFormat.format;
428+
swapchainExtent = extent;
417429
}
418430

419431
void HelloTriangleApplication::createImageViews() {
@@ -424,7 +436,7 @@ void HelloTriangleApplication::createImageViews() {
424436
createInfo.image = swapchainImages[i];
425437

426438
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
427-
createInfo.format = swapChainImageFormat;
439+
createInfo.format = swapchainImageFormat;
428440

429441
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
430442
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
@@ -444,6 +456,184 @@ void HelloTriangleApplication::createImageViews() {
444456
}
445457
}
446458

459+
void HelloTriangleApplication::createRenderPass() {
460+
VkAttachmentDescription colorAttachment = {};
461+
colorAttachment.format = swapchainImageFormat;
462+
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
463+
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
464+
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
465+
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
466+
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
467+
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
468+
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
469+
470+
VkAttachmentReference colorAttachmentRef = {};
471+
colorAttachmentRef.attachment = 0;
472+
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
473+
474+
VkSubpassDescription subpass = {};
475+
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
476+
subpass.colorAttachmentCount = 1;
477+
subpass.pColorAttachments = &colorAttachmentRef;
478+
479+
VkRenderPassCreateInfo renderPassInfo = {};
480+
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
481+
renderPassInfo.attachmentCount = 1;
482+
renderPassInfo.pAttachments = &colorAttachment;
483+
renderPassInfo.subpassCount = 1;
484+
renderPassInfo.pSubpasses = &subpass;
485+
486+
if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) {
487+
throw std::runtime_error("failed to create render pass!");
488+
}
489+
}
490+
491+
void HelloTriangleApplication::createGraphicsPipeline() {
492+
auto vertexShaderCode = readAsset(vertexShader);
493+
auto fragmentShaderCode = readAsset(fragmentShader);
494+
495+
VkShaderModule vertexShaderModule = createShaderModule(vertexShaderCode);
496+
VkShaderModule fragmentShaderModule = createShaderModule(fragmentShaderCode);
497+
498+
VkPipelineShaderStageCreateInfo vertexShaderStageInfo = {};
499+
vertexShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
500+
vertexShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
501+
vertexShaderStageInfo.module = vertexShaderModule;
502+
vertexShaderStageInfo.pName = "main";
503+
504+
VkPipelineShaderStageCreateInfo fragmentShaderStageInfo = {};
505+
fragmentShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
506+
fragmentShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
507+
fragmentShaderStageInfo.module = fragmentShaderModule;
508+
fragmentShaderStageInfo.pName = "main";
509+
510+
VkPipelineShaderStageCreateInfo shaderStages[] = {
511+
vertexShaderStageInfo, fragmentShaderStageInfo
512+
};
513+
514+
VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
515+
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
516+
vertexInputInfo.vertexBindingDescriptionCount = 0;
517+
vertexInputInfo.vertexAttributeDescriptionCount = 0;
518+
519+
VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
520+
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
521+
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
522+
inputAssembly.primitiveRestartEnable = VK_FALSE;
523+
524+
VkViewport viewport = {};
525+
viewport.x = 0.0f;
526+
viewport.y = 0.0f;
527+
viewport.width = (float) swapchainExtent.width;
528+
viewport.height = (float) swapchainExtent.height;
529+
viewport.minDepth = 0.0f;
530+
viewport.maxDepth = 1.0f;
531+
532+
VkRect2D scissor = {};
533+
scissor.offset = {0, 0};
534+
scissor.extent = swapchainExtent;
535+
536+
VkPipelineViewportStateCreateInfo viewportState = {};
537+
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
538+
viewportState.viewportCount = 1;
539+
viewportState.pViewports = &viewport;
540+
viewportState.scissorCount = 1;
541+
viewportState.pScissors = &scissor;
542+
543+
VkPipelineRasterizationStateCreateInfo rasterizer = {};
544+
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
545+
rasterizer.depthClampEnable = VK_FALSE;
546+
rasterizer.rasterizerDiscardEnable = VK_FALSE;
547+
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
548+
rasterizer.lineWidth = 1.0f;
549+
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
550+
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
551+
rasterizer.depthBiasEnable = VK_FALSE;
552+
553+
VkPipelineMultisampleStateCreateInfo multisampling = {};
554+
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
555+
multisampling.sampleShadingEnable = VK_FALSE;
556+
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
557+
558+
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
559+
colorBlendAttachment.colorWriteMask =
560+
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
561+
VK_COLOR_COMPONENT_A_BIT;
562+
colorBlendAttachment.blendEnable = VK_FALSE;
563+
564+
VkPipelineColorBlendStateCreateInfo colorBlending = {};
565+
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
566+
colorBlending.logicOpEnable = VK_FALSE;
567+
colorBlending.logicOp = VK_LOGIC_OP_COPY;
568+
colorBlending.attachmentCount = 1;
569+
colorBlending.pAttachments = &colorBlendAttachment;
570+
colorBlending.blendConstants[0] = 0.0f;
571+
colorBlending.blendConstants[1] = 0.0f;
572+
colorBlending.blendConstants[2] = 0.0f;
573+
colorBlending.blendConstants[3] = 0.0f;
574+
575+
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
576+
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
577+
pipelineLayoutInfo.setLayoutCount = 0;
578+
pipelineLayoutInfo.pushConstantRangeCount = 0;
579+
580+
if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) !=
581+
VK_SUCCESS) {
582+
throw std::runtime_error("failed to create pipeline layout!");
583+
}
584+
585+
VkGraphicsPipelineCreateInfo pipelineInfo = {};
586+
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
587+
pipelineInfo.stageCount = 2;
588+
pipelineInfo.pStages = shaderStages;
589+
pipelineInfo.pVertexInputState = &vertexInputInfo;
590+
pipelineInfo.pInputAssemblyState = &inputAssembly;
591+
pipelineInfo.pViewportState = &viewportState;
592+
pipelineInfo.pRasterizationState = &rasterizer;
593+
pipelineInfo.pMultisampleState = &multisampling;
594+
pipelineInfo.pColorBlendState = &colorBlending;
595+
pipelineInfo.layout = pipelineLayout;
596+
pipelineInfo.renderPass = renderPass;
597+
pipelineInfo.subpass = 0;
598+
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
599+
600+
if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr,
601+
&graphicsPipeline) != VK_SUCCESS) {
602+
throw std::runtime_error("failed to create graphics pipeline!");
603+
}
604+
605+
vkDestroyShaderModule(device, vertexShaderModule, nullptr);
606+
vkDestroyShaderModule(device, fragmentShaderModule, nullptr);
607+
}
608+
609+
std::vector<char> HelloTriangleApplication::readAsset(const char *name) {
610+
AAsset *file = AAssetManager_open(assetManager, name, AASSET_MODE_BUFFER);
611+
size_t len = AAsset_getLength(file);
612+
std::vector<char> buffer(len);
613+
614+
AAsset_read(file, buffer.data(), len);
615+
616+
AAsset_close(file);
617+
618+
LOGI("read asset %s, length %d", name, len);
619+
620+
return buffer;
621+
}
622+
623+
VkShaderModule HelloTriangleApplication::createShaderModule(const std::vector<char> &code) {
624+
VkShaderModuleCreateInfo createInfo = {};
625+
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
626+
createInfo.codeSize = code.size();
627+
createInfo.pCode = reinterpret_cast<const uint32_t *>(code.data());
628+
629+
VkShaderModule shaderModule;
630+
if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
631+
throw std::runtime_error("failed to create shader module!");
632+
}
633+
634+
return shaderModule;
635+
}
636+
447637
bool HelloTriangleApplication::isDeviceSuitable(VkPhysicalDevice device) {
448638
bool extensionsSupported = checkDeviceExtensionSupport(device);
449639

@@ -531,26 +721,3 @@ SwapchainSupportDetails HelloTriangleApplication::querySwapchainSupport(VkPhysic
531721

532722
return details;
533723
}
534-
535-
extern "C" {
536-
JNIEXPORT void JNICALL
537-
Java_com_github_piasy_vulkantutorial_MainActivity_runVulkan(
538-
JNIEnv *env, jobject instance, jobject surface) {
539-
LOGI("Vulkan app start");
540-
541-
ANativeWindow *window = ANativeWindow_fromSurface(env, surface);
542-
if (window == nullptr) {
543-
LOGE("get window from surface fail!");
544-
return;
545-
}
546-
547-
HelloTriangleApplication app;
548-
try {
549-
app.run(window);
550-
} catch (const std::runtime_error &e) {
551-
LOGE("runtime error: %s", e.what());
552-
}
553-
554-
LOGI("Vulkan app exit");
555-
}
556-
}

app/src/main/cpp/vulkan_triangle.h

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,10 @@
55
#ifndef VULKANTUTORIAL_ANDROID_VULKAN_TRIANGLE_H
66
#define VULKANTUTORIAL_ANDROID_VULKAN_TRIANGLE_H
77

8-
#include <jni.h>
98
#include <android/log.h>
10-
#include<android/native_window_jni.h>
9+
#include <android/asset_manager.h>
1110

12-
#include <iostream>
1311
#include <vector>
14-
#include <set>
15-
#include <algorithm>
16-
#include <stdexcept>
17-
#include <cstring>
18-
#include <functional>
1912

2013
#include "vulkan_wrapper/vulkan_wrapper.h"
2114

@@ -40,6 +33,15 @@ struct SwapchainSupportDetails {
4033

4134
class HelloTriangleApplication {
4235
public:
36+
HelloTriangleApplication(
37+
AAssetManager *assetManager,
38+
const char *vertexShader,
39+
const char *fragmentShader) :
40+
assetManager(assetManager),
41+
vertexShader(vertexShader),
42+
fragmentShader(fragmentShader) {
43+
}
44+
4345
void run(ANativeWindow *window);
4446

4547
private:
@@ -63,6 +65,14 @@ class HelloTriangleApplication {
6365

6466
void createImageViews();
6567

68+
void createRenderPass();
69+
70+
void createGraphicsPipeline();
71+
72+
std::vector<char> readAsset(const char *name);
73+
74+
VkShaderModule createShaderModule(const std::vector<char> &code);
75+
6676
bool isDeviceSuitable(VkPhysicalDevice device);
6777

6878
bool checkDeviceExtensionSupport(VkPhysicalDevice device);
@@ -75,6 +85,10 @@ class HelloTriangleApplication {
7585

7686
void cleanUp();
7787

88+
AAssetManager *assetManager;
89+
const char *vertexShader;
90+
const char *fragmentShader;
91+
7892
VkInstance instance;
7993
VkDebugReportCallbackEXT callback;
8094
ANativeWindow *window;
@@ -86,8 +100,11 @@ class HelloTriangleApplication {
86100
VkSwapchainKHR swapchain;
87101
std::vector<VkImage> swapchainImages;
88102
std::vector<VkImageView> swapchainImageViews;
89-
VkFormat swapChainImageFormat;
90-
VkExtent2D swapChainExtent;
103+
VkFormat swapchainImageFormat;
104+
VkExtent2D swapchainExtent;
105+
VkRenderPass renderPass;
106+
VkPipelineLayout pipelineLayout;
107+
VkPipeline graphicsPipeline;
91108
};
92109

93110
#endif //VULKANTUTORIAL_ANDROID_VULKAN_TRIANGLE_H

0 commit comments

Comments
 (0)