Android support for Compute particles example, replacing separate Android version (#97)
This commit is contained in:
parent
a8734f7f46
commit
a9fe22426f
26 changed files with 142 additions and 3230 deletions
|
|
@ -1,881 +0,0 @@
|
|||
/*
|
||||
* Shared android example base
|
||||
*
|
||||
* Will be replaced once the main examples get proper android support
|
||||
*
|
||||
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
|
||||
*
|
||||
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "vulkanandroid.h"
|
||||
#include "vulkanswapchain.hpp"
|
||||
#include "vulkantools.h"
|
||||
|
||||
class VulkanAndroidExampleBase
|
||||
{
|
||||
private:
|
||||
std::chrono::high_resolution_clock::time_point tStart;
|
||||
VkShaderModule loadShaderModule(const char *fileName, VkShaderStageFlagBits stage)
|
||||
{
|
||||
// Load shader from compressed asset
|
||||
AAsset* asset = AAssetManager_open(app->activity->assetManager, fileName, AASSET_MODE_STREAMING);
|
||||
assert(asset);
|
||||
size_t size = AAsset_getLength(asset);
|
||||
assert(size > 0);
|
||||
|
||||
char *shaderCode = new char[size];
|
||||
AAsset_read(asset, shaderCode, size);
|
||||
AAsset_close(asset);
|
||||
|
||||
VkShaderModule shaderModule;
|
||||
VkShaderModuleCreateInfo moduleCreateInfo;
|
||||
VkResult err;
|
||||
|
||||
moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
moduleCreateInfo.pNext = NULL;
|
||||
|
||||
moduleCreateInfo.codeSize = size;
|
||||
moduleCreateInfo.pCode = (uint32_t*)shaderCode;
|
||||
moduleCreateInfo.flags = 0;
|
||||
err = vkCreateShaderModule(device, &moduleCreateInfo, NULL, &shaderModule);
|
||||
assert(!err);
|
||||
|
||||
return shaderModule;
|
||||
}
|
||||
public:
|
||||
bool prepared = false;
|
||||
|
||||
struct android_app* app;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
float frameTimer = 1.0f;
|
||||
|
||||
struct Texture {
|
||||
VkSampler sampler;
|
||||
VkImage image;
|
||||
VkImageLayout imageLayout;
|
||||
VkDeviceMemory deviceMemory;
|
||||
VkImageView view;
|
||||
uint32_t width, height;
|
||||
uint32_t mipLevels;
|
||||
};
|
||||
|
||||
VkPhysicalDeviceMemoryProperties deviceMemoryProperties;
|
||||
VkInstance instance;
|
||||
VkPhysicalDevice physicalDevice;
|
||||
VkDevice device;
|
||||
VkQueue queue;
|
||||
VkCommandPool cmdPool;
|
||||
VkCommandBuffer setupCmdBuffer = VK_NULL_HANDLE;
|
||||
VkCommandBuffer postPresentCmdBuffer = VK_NULL_HANDLE;
|
||||
VkCommandBuffer prePresentCmdBuffer = VK_NULL_HANDLE;
|
||||
std::vector<VkCommandBuffer> drawCmdBuffers;
|
||||
VkPipelineCache pipelineCache;
|
||||
VkDescriptorPool descriptorPool;
|
||||
VulkanSwapChain swapChain;
|
||||
std::vector<VkShaderModule> shaderModules;
|
||||
|
||||
uint32_t currentBuffer = 0;
|
||||
struct
|
||||
{
|
||||
VkImage image;
|
||||
VkDeviceMemory mem;
|
||||
VkImageView view;
|
||||
} depthStencil;
|
||||
std::vector<VkFramebuffer>frameBuffers;
|
||||
VkRenderPass renderPass;
|
||||
|
||||
struct {
|
||||
VkSemaphore presentComplete;
|
||||
VkSemaphore submitSignal;
|
||||
} semaphores;
|
||||
|
||||
VkBool32 getMemoryType(uint32_t typeBits, VkFlags properties, uint32_t * typeIndex)
|
||||
{
|
||||
for (uint32_t i = 0; i < 32; i++)
|
||||
{
|
||||
if ((typeBits & 1) == 1)
|
||||
{
|
||||
if ((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
|
||||
{
|
||||
*typeIndex = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
typeBits >>= 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void initVulkan()
|
||||
{
|
||||
bool libLoaded = loadVulkanLibrary();
|
||||
assert(libLoaded);
|
||||
|
||||
VkResult vkRes;
|
||||
|
||||
// Instance
|
||||
VkApplicationInfo appInfo = {};
|
||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
appInfo.pApplicationName = "Vulkan Android Example";
|
||||
appInfo.applicationVersion = 1;
|
||||
appInfo.pEngineName = "VulkanAndroidExample";
|
||||
appInfo.engineVersion = 1;
|
||||
// todo : Workaround to support implementations that are not using the latest SDK
|
||||
appInfo.apiVersion = VK_MAKE_VERSION(1, 0, 1);
|
||||
|
||||
VkInstanceCreateInfo instanceCreateInfo = {};
|
||||
instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
instanceCreateInfo.pApplicationInfo = &appInfo;
|
||||
|
||||
vkRes = vkCreateInstance(&instanceCreateInfo, NULL, &instance);
|
||||
assert(vkRes == VK_SUCCESS);
|
||||
|
||||
loadVulkanFunctions(instance);
|
||||
|
||||
// Device
|
||||
// Always use first physical device
|
||||
uint32_t gpuCount;
|
||||
vkRes = vkEnumeratePhysicalDevices(instance, &gpuCount, &physicalDevice);
|
||||
assert(vkRes == VK_SUCCESS);
|
||||
|
||||
// Find a queue that supports graphics operations
|
||||
uint32_t graphicsQueueIndex = 0;
|
||||
uint32_t queueCount;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, NULL);
|
||||
assert(queueCount >= 1);
|
||||
|
||||
std::vector<VkQueueFamilyProperties> queueProps;
|
||||
queueProps.resize(queueCount);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, queueProps.data());
|
||||
|
||||
for (graphicsQueueIndex = 0; graphicsQueueIndex < queueCount; graphicsQueueIndex++)
|
||||
{
|
||||
if (queueProps[graphicsQueueIndex].queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
||||
break;
|
||||
}
|
||||
assert(graphicsQueueIndex < queueCount);
|
||||
|
||||
// Request the queue
|
||||
float queuePriorities = 0.0f;
|
||||
VkDeviceQueueCreateInfo queueCreateInfo = {};
|
||||
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
queueCreateInfo.queueFamilyIndex = graphicsQueueIndex;
|
||||
queueCreateInfo.queueCount = 1;
|
||||
queueCreateInfo.pQueuePriorities = &queuePriorities;
|
||||
|
||||
// Create device
|
||||
VkDeviceCreateInfo deviceCreateInfo = {};
|
||||
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
deviceCreateInfo.queueCreateInfoCount = 1;
|
||||
deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
|
||||
|
||||
vkRes = vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device);
|
||||
assert(vkRes == VK_SUCCESS);
|
||||
|
||||
// Get graphics queue
|
||||
vkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue);
|
||||
|
||||
// Device memory properties (for finding appropriate memory types)
|
||||
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties);
|
||||
|
||||
// Swap chain
|
||||
swapChain.connect(instance, physicalDevice, device);
|
||||
swapChain.initSurface(app->window);
|
||||
|
||||
// Command buffer pool
|
||||
VkCommandPoolCreateInfo cmdPoolInfo = {};
|
||||
cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
cmdPoolInfo.queueFamilyIndex = swapChain.queueNodeIndex;
|
||||
cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
vkRes = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &cmdPool);
|
||||
assert(!vkRes);
|
||||
|
||||
// Pipeline cache
|
||||
VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {};
|
||||
pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
|
||||
VkResult err = vkCreatePipelineCache(device, &pipelineCacheCreateInfo, nullptr, &pipelineCache);
|
||||
assert(!err);
|
||||
|
||||
// Create semaphores for synchronization
|
||||
VkSemaphoreCreateInfo semaphoreCreateInfo = vkTools::initializers::semaphoreCreateInfo();
|
||||
|
||||
err = vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &semaphores.presentComplete);
|
||||
assert(!err);
|
||||
err = vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &semaphores.submitSignal);
|
||||
assert(!err);
|
||||
|
||||
createSetupCommandBuffer();
|
||||
startSetupCommandBuffer();
|
||||
|
||||
swapChain.create(setupCmdBuffer, &width, &height);
|
||||
|
||||
setupDepthStencil();
|
||||
setupRenderPass();
|
||||
setupFrameBuffer();
|
||||
|
||||
flushSetupCommandBuffer();
|
||||
|
||||
createCommandBuffers();
|
||||
}
|
||||
|
||||
void cleanUpVulkan()
|
||||
{
|
||||
swapChain.cleanup();
|
||||
|
||||
vkDestroyDescriptorPool(device, descriptorPool, nullptr);
|
||||
if (setupCmdBuffer != VK_NULL_HANDLE)
|
||||
{
|
||||
vkFreeCommandBuffers(device, cmdPool, 1, &setupCmdBuffer);
|
||||
|
||||
}
|
||||
vkFreeCommandBuffers(device, cmdPool, drawCmdBuffers.size(), drawCmdBuffers.data());
|
||||
vkFreeCommandBuffers(device, cmdPool, 1, &prePresentCmdBuffer);
|
||||
vkFreeCommandBuffers(device, cmdPool, 1, &postPresentCmdBuffer);
|
||||
|
||||
vkDestroyRenderPass(device, renderPass, nullptr);
|
||||
for (uint32_t i = 0; i < frameBuffers.size(); i++)
|
||||
{
|
||||
vkDestroyFramebuffer(device, frameBuffers[i], nullptr);
|
||||
}
|
||||
|
||||
for (auto& shaderModule : shaderModules)
|
||||
{
|
||||
vkDestroyShaderModule(device, shaderModule, nullptr);
|
||||
}
|
||||
|
||||
vkDestroyImageView(device, depthStencil.view, nullptr);
|
||||
vkDestroyImage(device, depthStencil.image, nullptr);
|
||||
vkFreeMemory(device, depthStencil.mem, nullptr);
|
||||
|
||||
vkDestroySemaphore(device, semaphores.presentComplete, nullptr);
|
||||
vkDestroySemaphore(device, semaphores.submitSignal, nullptr);
|
||||
|
||||
vkDestroyPipelineCache(device, pipelineCache, nullptr);
|
||||
vkDestroyDevice(device, nullptr);
|
||||
vkDestroyInstance(instance, nullptr);
|
||||
|
||||
freeVulkanLibrary();
|
||||
}
|
||||
|
||||
VkPipelineShaderStageCreateInfo loadShader(const char * fileName, VkShaderStageFlagBits stage)
|
||||
{
|
||||
VkPipelineShaderStageCreateInfo shaderStage = {};
|
||||
shaderStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
shaderStage.stage = stage;
|
||||
shaderStage.module = loadShaderModule(fileName, stage);
|
||||
shaderStage.pName = "main";
|
||||
assert(shaderStage.module != NULL);
|
||||
shaderModules.push_back(shaderStage.module);
|
||||
return shaderStage;
|
||||
}
|
||||
|
||||
void createSetupCommandBuffer()
|
||||
{
|
||||
VkCommandBufferAllocateInfo cmdBufAllocateInfo =
|
||||
vkTools::initializers::commandBufferAllocateInfo(
|
||||
cmdPool,
|
||||
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||
1);
|
||||
|
||||
VkResult vkRes = vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &setupCmdBuffer);
|
||||
assert(!vkRes);
|
||||
}
|
||||
|
||||
void startSetupCommandBuffer()
|
||||
{
|
||||
VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo();
|
||||
vkBeginCommandBuffer(setupCmdBuffer, &cmdBufInfo);
|
||||
}
|
||||
|
||||
void flushSetupCommandBuffer()
|
||||
{
|
||||
VkResult err;
|
||||
|
||||
if (setupCmdBuffer == VK_NULL_HANDLE)
|
||||
return;
|
||||
|
||||
err = vkEndCommandBuffer(setupCmdBuffer);
|
||||
assert(!err);
|
||||
|
||||
VkSubmitInfo submitInfo = {};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &setupCmdBuffer;
|
||||
|
||||
err = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||
assert(!err);
|
||||
|
||||
err = vkQueueWaitIdle(queue);
|
||||
assert(!err);
|
||||
}
|
||||
|
||||
void setupDepthStencil()
|
||||
{
|
||||
VkImageCreateInfo image = {};
|
||||
image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
image.pNext = NULL;
|
||||
image.imageType = VK_IMAGE_TYPE_2D;
|
||||
image.format = VK_FORMAT_D24_UNORM_S8_UINT;
|
||||
image.extent = { width, height, 1 };
|
||||
image.mipLevels = 1;
|
||||
image.arrayLayers = 1;
|
||||
image.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
image.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
image.flags = 0;
|
||||
|
||||
VkMemoryAllocateInfo mem_alloc = {};
|
||||
mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
mem_alloc.pNext = NULL;
|
||||
mem_alloc.allocationSize = 0;
|
||||
mem_alloc.memoryTypeIndex = 0;
|
||||
|
||||
VkImageViewCreateInfo depthStencilView = {};
|
||||
depthStencilView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
depthStencilView.pNext = NULL;
|
||||
depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
depthStencilView.format = VK_FORMAT_D24_UNORM_S8_UINT;
|
||||
depthStencilView.flags = 0;
|
||||
depthStencilView.subresourceRange = {};
|
||||
depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
depthStencilView.subresourceRange.baseMipLevel = 0;
|
||||
depthStencilView.subresourceRange.levelCount = 1;
|
||||
depthStencilView.subresourceRange.baseArrayLayer = 0;
|
||||
depthStencilView.subresourceRange.layerCount = 1;
|
||||
|
||||
VkMemoryRequirements memReqs;
|
||||
VkResult err;
|
||||
|
||||
err = vkCreateImage(device, &image, nullptr, &depthStencil.image);
|
||||
assert(!err);
|
||||
vkGetImageMemoryRequirements(device, depthStencil.image, &memReqs);
|
||||
mem_alloc.allocationSize = memReqs.size;
|
||||
getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &mem_alloc.memoryTypeIndex);
|
||||
err = vkAllocateMemory(device, &mem_alloc, nullptr, &depthStencil.mem);
|
||||
assert(!err);
|
||||
|
||||
err = vkBindImageMemory(device, depthStencil.image, depthStencil.mem, 0);
|
||||
assert(!err);
|
||||
vkTools::setImageLayout(setupCmdBuffer, depthStencil.image, VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
|
||||
depthStencilView.image = depthStencil.image;
|
||||
err = vkCreateImageView(device, &depthStencilView, nullptr, &depthStencil.view);
|
||||
assert(!err);
|
||||
}
|
||||
|
||||
void setupFrameBuffer()
|
||||
{
|
||||
VkImageView attachments[2];
|
||||
|
||||
// Depth/Stencil attachment is the same for all frame buffers
|
||||
attachments[1] = depthStencil.view;
|
||||
|
||||
VkFramebufferCreateInfo frameBufferCreateInfo = {};
|
||||
frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
frameBufferCreateInfo.pNext = NULL;
|
||||
frameBufferCreateInfo.renderPass = renderPass;
|
||||
frameBufferCreateInfo.attachmentCount = 2;
|
||||
frameBufferCreateInfo.pAttachments = attachments;
|
||||
frameBufferCreateInfo.width = width;
|
||||
frameBufferCreateInfo.height = height;
|
||||
frameBufferCreateInfo.layers = 1;
|
||||
|
||||
// Create frame buffers for every swap chain image
|
||||
frameBuffers.resize(swapChain.imageCount);
|
||||
for (uint32_t i = 0; i < frameBuffers.size(); i++)
|
||||
{
|
||||
attachments[0] = swapChain.buffers[i].view;
|
||||
VkResult err = vkCreateFramebuffer(device, &frameBufferCreateInfo, nullptr, &frameBuffers[i]);
|
||||
assert(!err);
|
||||
}
|
||||
}
|
||||
|
||||
void setupRenderPass()
|
||||
{
|
||||
VkAttachmentDescription attachments[2];
|
||||
attachments[0].format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
attachments[1].format = VK_FORMAT_D24_UNORM_S8_UINT;
|
||||
attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
|
||||
VkAttachmentReference colorReference = {};
|
||||
colorReference.attachment = 0;
|
||||
colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
VkAttachmentReference depthReference = {};
|
||||
depthReference.attachment = 1;
|
||||
depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
|
||||
VkSubpassDescription subpass = {};
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.flags = 0;
|
||||
subpass.inputAttachmentCount = 0;
|
||||
subpass.pInputAttachments = NULL;
|
||||
subpass.colorAttachmentCount = 1;
|
||||
subpass.pColorAttachments = &colorReference;
|
||||
subpass.pResolveAttachments = NULL;
|
||||
subpass.pDepthStencilAttachment = &depthReference;
|
||||
subpass.preserveAttachmentCount = 0;
|
||||
subpass.pPreserveAttachments = NULL;
|
||||
|
||||
VkRenderPassCreateInfo renderPassInfo = {};
|
||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
renderPassInfo.pNext = NULL;
|
||||
renderPassInfo.attachmentCount = 2;
|
||||
renderPassInfo.pAttachments = attachments;
|
||||
renderPassInfo.subpassCount = 1;
|
||||
renderPassInfo.pSubpasses = &subpass;
|
||||
renderPassInfo.dependencyCount = 0;
|
||||
renderPassInfo.pDependencies = NULL;
|
||||
|
||||
VkResult err;
|
||||
|
||||
err = vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass);
|
||||
assert(!err);
|
||||
}
|
||||
|
||||
void createCommandBuffers()
|
||||
{
|
||||
drawCmdBuffers.resize(swapChain.imageCount);
|
||||
|
||||
VkCommandBufferAllocateInfo cmdBufAllocateInfo =
|
||||
vkTools::initializers::commandBufferAllocateInfo(
|
||||
cmdPool,
|
||||
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||
drawCmdBuffers.size());
|
||||
|
||||
VkResult vkRes = vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, drawCmdBuffers.data());
|
||||
assert(!vkRes);
|
||||
|
||||
cmdBufAllocateInfo.commandBufferCount = 1;
|
||||
// Pre present
|
||||
vkRes = vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &prePresentCmdBuffer);
|
||||
assert(!vkRes);
|
||||
// Post present
|
||||
vkRes = vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &postPresentCmdBuffer);
|
||||
assert(!vkRes);
|
||||
}
|
||||
|
||||
void submitPrePresentBarrier(VkImage image)
|
||||
{
|
||||
VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo();
|
||||
|
||||
VkResult vkRes = vkBeginCommandBuffer(prePresentCmdBuffer, &cmdBufInfo);
|
||||
assert(!vkRes);
|
||||
|
||||
VkImageMemoryBarrier prePresentBarrier = vkTools::initializers::imageMemoryBarrier();
|
||||
prePresentBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
prePresentBarrier.dstAccessMask = 0;
|
||||
prePresentBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
prePresentBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
prePresentBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
prePresentBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
prePresentBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
|
||||
prePresentBarrier.image = image;
|
||||
|
||||
vkCmdPipelineBarrier(
|
||||
prePresentCmdBuffer,
|
||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_FLAGS_NONE,
|
||||
0, nullptr, // No memory barriers,
|
||||
0, nullptr, // No buffer barriers,
|
||||
1, &prePresentBarrier);
|
||||
|
||||
vkRes = vkEndCommandBuffer(prePresentCmdBuffer);
|
||||
assert(!vkRes);
|
||||
|
||||
VkSubmitInfo submitInfo = vkTools::initializers::submitInfo();
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &prePresentCmdBuffer;
|
||||
|
||||
vkRes = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||
assert(!vkRes);
|
||||
}
|
||||
|
||||
void submitPostPresentBarrier(VkImage image)
|
||||
{
|
||||
VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo();
|
||||
|
||||
VkResult vkRes = vkBeginCommandBuffer(postPresentCmdBuffer, &cmdBufInfo);
|
||||
assert(!vkRes);
|
||||
|
||||
VkImageMemoryBarrier postPresentBarrier = vkTools::initializers::imageMemoryBarrier();
|
||||
postPresentBarrier.srcAccessMask = 0;
|
||||
postPresentBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
postPresentBarrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
postPresentBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
postPresentBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
postPresentBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
postPresentBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
|
||||
postPresentBarrier.image = image;
|
||||
|
||||
vkCmdPipelineBarrier(
|
||||
postPresentCmdBuffer,
|
||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
0,
|
||||
0, nullptr, // No memory barriers,
|
||||
0, nullptr, // No buffer barriers,
|
||||
1, &postPresentBarrier);
|
||||
|
||||
vkRes = vkEndCommandBuffer(postPresentCmdBuffer);
|
||||
assert(!vkRes);
|
||||
|
||||
VkSubmitInfo submitInfo = vkTools::initializers::submitInfo();
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &postPresentCmdBuffer;
|
||||
|
||||
vkRes = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||
assert(!vkRes);
|
||||
}
|
||||
|
||||
void loadTexture(const char* fileName, VkFormat format, Texture *texture, bool forceLinearTiling)
|
||||
{
|
||||
VkFormatProperties formatProperties;
|
||||
VkResult err;
|
||||
|
||||
AAsset* asset = AAssetManager_open(app->activity->assetManager, fileName, AASSET_MODE_STREAMING);
|
||||
assert(asset);
|
||||
size_t size = AAsset_getLength(asset);
|
||||
assert(size > 0);
|
||||
|
||||
void *textureData = malloc(size);
|
||||
AAsset_read(asset, textureData, size);
|
||||
AAsset_close(asset);
|
||||
|
||||
gli::texture2D tex2D(gli::load((const char*)textureData, size));
|
||||
assert(!tex2D.empty());
|
||||
|
||||
texture->width = tex2D[0].dimensions().x;
|
||||
texture->height = tex2D[0].dimensions().y;
|
||||
texture->mipLevels = tex2D.levels();
|
||||
|
||||
// Get device properites for the requested texture format
|
||||
vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties);
|
||||
|
||||
// Only use linear tiling if requested (and supported by the device)
|
||||
// Support for linear tiling is mostly limited, so prefer to use
|
||||
// optimal tiling instead
|
||||
// On most implementations linear tiling will only support a very
|
||||
// limited amount of formats and features (mip maps, cubemaps, arrays, etc.)
|
||||
VkBool32 useStaging = true;
|
||||
|
||||
// Only use linear tiling if forced
|
||||
if (forceLinearTiling)
|
||||
{
|
||||
// Don't use linear if format is not supported for (linear) shader sampling
|
||||
useStaging = !(formatProperties.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
|
||||
}
|
||||
|
||||
VkImageCreateInfo imageCreateInfo = vkTools::initializers::imageCreateInfo();
|
||||
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
imageCreateInfo.format = format;
|
||||
imageCreateInfo.mipLevels = 1;
|
||||
imageCreateInfo.arrayLayers = 1;
|
||||
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
imageCreateInfo.tiling = VK_IMAGE_TILING_LINEAR;
|
||||
imageCreateInfo.usage = (useStaging) ? VK_IMAGE_USAGE_TRANSFER_SRC_BIT : VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
imageCreateInfo.flags = 0;
|
||||
imageCreateInfo.extent = { texture->width, texture->height, 1 };
|
||||
|
||||
VkMemoryAllocateInfo memAllocInfo = vkTools::initializers::memoryAllocateInfo();
|
||||
VkMemoryRequirements memReqs;
|
||||
|
||||
startSetupCommandBuffer();
|
||||
|
||||
if (useStaging)
|
||||
{
|
||||
// Load all available mip levels into linear textures
|
||||
// and copy to optimal tiling target
|
||||
struct MipLevel {
|
||||
VkImage image;
|
||||
VkDeviceMemory memory;
|
||||
};
|
||||
std::vector<MipLevel> mipLevels;
|
||||
mipLevels.resize(texture->mipLevels);
|
||||
|
||||
// Copy mip levels
|
||||
for (uint32_t level = 0; level < texture->mipLevels; ++level)
|
||||
{
|
||||
imageCreateInfo.extent.width = tex2D[level].dimensions().x;
|
||||
imageCreateInfo.extent.height = tex2D[level].dimensions().y;
|
||||
imageCreateInfo.extent.depth = 1;
|
||||
|
||||
err = vkCreateImage(device, &imageCreateInfo, nullptr, &mipLevels[level].image);
|
||||
assert(!err);
|
||||
|
||||
vkGetImageMemoryRequirements(device, mipLevels[level].image, &memReqs);
|
||||
memAllocInfo.allocationSize = memReqs.size;
|
||||
getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAllocInfo.memoryTypeIndex);
|
||||
err = vkAllocateMemory(device, &memAllocInfo, nullptr, &mipLevels[level].memory);
|
||||
assert(!err);
|
||||
err = vkBindImageMemory(device, mipLevels[level].image, mipLevels[level].memory, 0);
|
||||
assert(!err);
|
||||
|
||||
VkImageSubresource subRes = {};
|
||||
subRes.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
|
||||
VkSubresourceLayout subResLayout;
|
||||
void *data;
|
||||
|
||||
vkGetImageSubresourceLayout(device, mipLevels[level].image, &subRes, &subResLayout);
|
||||
assert(!err);
|
||||
err = vkMapMemory(device, mipLevels[level].memory, 0, memReqs.size, 0, &data);
|
||||
assert(!err);
|
||||
size_t levelSize = tex2D[level].size();
|
||||
memcpy(data, tex2D[level].data(), levelSize);
|
||||
vkUnmapMemory(device, mipLevels[level].memory);
|
||||
|
||||
// Image barrier for linear image (base)
|
||||
// Linear image will be used as a source for the copy
|
||||
vkTools::setImageLayout(
|
||||
setupCmdBuffer,
|
||||
mipLevels[level].image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
}
|
||||
|
||||
// Setup texture as blit target with optimal tiling
|
||||
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
imageCreateInfo.mipLevels = texture->mipLevels;
|
||||
imageCreateInfo.extent = { texture->width, texture->height, 1 };
|
||||
|
||||
err = vkCreateImage(device, &imageCreateInfo, nullptr, &texture->image);
|
||||
assert(!err);
|
||||
|
||||
vkGetImageMemoryRequirements(device, texture->image, &memReqs);
|
||||
|
||||
memAllocInfo.allocationSize = memReqs.size;
|
||||
|
||||
getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memAllocInfo.memoryTypeIndex);
|
||||
err = vkAllocateMemory(device, &memAllocInfo, nullptr, &texture->deviceMemory);
|
||||
assert(!err);
|
||||
err = vkBindImageMemory(device, texture->image, texture->deviceMemory, 0);
|
||||
assert(!err);
|
||||
|
||||
// Image barrier for optimal image (target)
|
||||
// Optimal image will be used as destination for the copy
|
||||
vkTools::setImageLayout(
|
||||
setupCmdBuffer,
|
||||
texture->image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
// Copy mip levels one by one
|
||||
for (uint32_t level = 0; level < texture->mipLevels; ++level)
|
||||
{
|
||||
// Copy region for image blit
|
||||
VkImageCopy copyRegion = {};
|
||||
|
||||
copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
copyRegion.srcSubresource.baseArrayLayer = 0;
|
||||
copyRegion.srcSubresource.mipLevel = 0;
|
||||
copyRegion.srcSubresource.layerCount = 1;
|
||||
copyRegion.srcOffset = { 0, 0, 0 };
|
||||
|
||||
copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
copyRegion.dstSubresource.baseArrayLayer = 0;
|
||||
// Set mip level to copy the linear image to
|
||||
copyRegion.dstSubresource.mipLevel = level;
|
||||
copyRegion.dstSubresource.layerCount = 1;
|
||||
copyRegion.dstOffset = { 0, 0, 0 };
|
||||
|
||||
copyRegion.extent.width = tex2D[level].dimensions().x;
|
||||
copyRegion.extent.height = tex2D[level].dimensions().y;
|
||||
copyRegion.extent.depth = 1;
|
||||
|
||||
// Put image copy into command buffer
|
||||
vkCmdCopyImage(
|
||||
setupCmdBuffer,
|
||||
mipLevels[level].image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
texture->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, ©Region);
|
||||
|
||||
// Change texture image layout to shader read after the copy
|
||||
texture->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
vkTools::setImageLayout(
|
||||
setupCmdBuffer,
|
||||
texture->image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
texture->imageLayout);
|
||||
}
|
||||
|
||||
flushSetupCommandBuffer();
|
||||
|
||||
// Clean up linear images
|
||||
// No longer required after mip levels
|
||||
// have been transformed over to optimal tiling
|
||||
for (auto& level : mipLevels)
|
||||
{
|
||||
vkDestroyImage(device, level.image, nullptr);
|
||||
vkFreeMemory(device, level.memory, nullptr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Prefer using optimal tiling, as linear tiling
|
||||
// may support only a small set of features
|
||||
// depending on implementation (e.g. no mip maps, only one layer, etc.)
|
||||
|
||||
VkImage mappableImage;
|
||||
VkDeviceMemory mappableMemory;
|
||||
|
||||
// Load mip map level 0 to linear tiling image
|
||||
err = vkCreateImage(device, &imageCreateInfo, nullptr, &mappableImage);
|
||||
assert(!err);
|
||||
|
||||
// Get memory requirements for this image
|
||||
// like size and alignment
|
||||
vkGetImageMemoryRequirements(device, mappableImage, &memReqs);
|
||||
// Set memory allocation size to required memory size
|
||||
memAllocInfo.allocationSize = memReqs.size;
|
||||
|
||||
// Get memory type that can be mapped to host memory
|
||||
getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAllocInfo.memoryTypeIndex);
|
||||
|
||||
// Allocate host memory
|
||||
err = vkAllocateMemory(device, &memAllocInfo, nullptr, &mappableMemory);
|
||||
assert(!err);
|
||||
|
||||
// Bind allocated image for use
|
||||
err = vkBindImageMemory(device, mappableImage, mappableMemory, 0);
|
||||
assert(!err);
|
||||
|
||||
// Get sub resource layout
|
||||
// Mip map count, array layer, etc.
|
||||
VkImageSubresource subRes = {};
|
||||
subRes.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
|
||||
VkSubresourceLayout subResLayout;
|
||||
void *data;
|
||||
|
||||
// Get sub resources layout
|
||||
// Includes row pitch, size offsets, etc.
|
||||
vkGetImageSubresourceLayout(device, mappableImage, &subRes, &subResLayout);
|
||||
assert(!err);
|
||||
|
||||
// Map image memory
|
||||
err = vkMapMemory(device, mappableMemory, 0, memReqs.size, 0, &data);
|
||||
assert(!err);
|
||||
|
||||
// Copy image data into memory
|
||||
memcpy(data, tex2D[subRes.mipLevel].data(), tex2D[subRes.mipLevel].size());
|
||||
|
||||
vkUnmapMemory(device, mappableMemory);
|
||||
|
||||
// Linear tiled images don't need to be staged
|
||||
// and can be directly used as textures
|
||||
texture->image = mappableImage;
|
||||
texture->deviceMemory = mappableMemory;
|
||||
texture->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
// Setup image memory barrier
|
||||
vkTools::setImageLayout(
|
||||
setupCmdBuffer,
|
||||
texture->image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
texture->imageLayout);
|
||||
|
||||
flushSetupCommandBuffer();
|
||||
}
|
||||
|
||||
|
||||
// Create sampler
|
||||
// In Vulkan textures are accessed by samplers
|
||||
// This separates all the sampling information from the
|
||||
// texture data
|
||||
// This means you could have multiple sampler objects
|
||||
// for the same texture with different settings
|
||||
// Similar to the samplers available with OpenGL 3.3
|
||||
VkSamplerCreateInfo sampler = vkTools::initializers::samplerCreateInfo();
|
||||
sampler.magFilter = VK_FILTER_LINEAR;
|
||||
sampler.minFilter = VK_FILTER_LINEAR;
|
||||
sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
sampler.addressModeV = sampler.addressModeU;
|
||||
sampler.addressModeW = sampler.addressModeU;
|
||||
sampler.mipLodBias = 0.0f;
|
||||
sampler.compareOp = VK_COMPARE_OP_NEVER;
|
||||
sampler.minLod = 0.0f;
|
||||
// Max level-of-detail should match mip level count
|
||||
sampler.maxLod = (useStaging) ? (float)texture->mipLevels : 0.0f;
|
||||
// Enable anisotropic filtering
|
||||
sampler.maxAnisotropy = 8;
|
||||
sampler.anisotropyEnable = VK_TRUE;
|
||||
sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
|
||||
err = vkCreateSampler(device, &sampler, nullptr, &texture->sampler);
|
||||
assert(!err);
|
||||
|
||||
// Create image view
|
||||
// Textures are not directly accessed by the shaders and
|
||||
// are abstracted by image views containing additional
|
||||
// information and sub resource ranges
|
||||
VkImageViewCreateInfo view = vkTools::initializers::imageViewCreateInfo();
|
||||
view.image = VK_NULL_HANDLE;
|
||||
view.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
view.format = format;
|
||||
view.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
|
||||
view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
view.subresourceRange.baseMipLevel = 0;
|
||||
view.subresourceRange.baseArrayLayer = 0;
|
||||
view.subresourceRange.layerCount = 1;
|
||||
// Linear tiling usually won't support mip maps
|
||||
// Only set mip map count if optimal tiling is used
|
||||
view.subresourceRange.levelCount = (useStaging) ? texture->mipLevels : 1;
|
||||
view.image = texture->image;
|
||||
err = vkCreateImageView(device, &view, nullptr, &texture->view);
|
||||
assert(!err);
|
||||
}
|
||||
|
||||
// Free staging resources used while creating a texture
|
||||
void destroyTextureImage(Texture *texture)
|
||||
{
|
||||
vkDestroyImage(device, texture->image, nullptr);
|
||||
vkFreeMemory(device, texture->deviceMemory, nullptr);
|
||||
}
|
||||
|
||||
void startTiming()
|
||||
{
|
||||
tStart = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
void endTiming()
|
||||
{
|
||||
auto tEnd = std::chrono::high_resolution_clock::now();
|
||||
auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count();
|
||||
frameTimer = (float)tDiff;
|
||||
}
|
||||
|
||||
};
|
||||
1
android/build-computeparticles.bat
Normal file
1
android/build-computeparticles.bat
Normal file
|
|
@ -0,0 +1 @@
|
|||
_build computeparticles %1
|
||||
10
android/computeparticles/.gitignore
vendored
Normal file
10
android/computeparticles/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
/assets/
|
||||
/res/
|
||||
/bin/
|
||||
/libs/
|
||||
/obj/
|
||||
/build.xml
|
||||
/local.properties
|
||||
/project.properties
|
||||
/proguard-project.txt
|
||||
*.apk
|
||||
27
android/computeparticles/AndroidManifest.xml
Normal file
27
android/computeparticles/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="de.saschawillems.vulkanComputeparticles"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<uses-sdk android:minSdkVersion="19" />
|
||||
|
||||
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.gamepad" android:required="false"/>
|
||||
<uses-feature android:name="android.software.leanback" android:required="false"/>
|
||||
|
||||
<application android:label="vulkanComputeparticles" android:icon="@drawable/icon" android:hasCode="false">
|
||||
<activity android:name="android.app.NativeActivity"
|
||||
android:label="Vulkan Compute Particles"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||
android:launchMode="singleTask"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden">
|
||||
<meta-data android:name="android.app.lib_name" android:value="vulkanComputeparticles" />
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
20
android/computeparticles/build.bat
Normal file
20
android/computeparticles/build.bat
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
cd jni
|
||||
call ndk-build
|
||||
if %ERRORLEVEL% EQU 0 (
|
||||
echo ndk-build has failed, build cancelled
|
||||
cd..
|
||||
|
||||
mkdir "assets\shaders\computeparticles"
|
||||
xcopy "..\..\data\shaders\computeparticles\*.spv" "assets\shaders\computeparticles" /Y
|
||||
|
||||
mkdir "assets\textures"
|
||||
xcopy "..\..\data\textures\particle01_rgba.ktx" "assets\textures" /Y
|
||||
|
||||
mkdir "res\drawable"
|
||||
xcopy "..\..\android\images\icon.png" "res\drawable" /Y
|
||||
|
||||
call ant debug -Dout.final.file=vulkanComputeparticles.apk
|
||||
) ELSE (
|
||||
echo error : ndk-build failed with errors!
|
||||
cd..
|
||||
)
|
||||
|
|
@ -1,426 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__))
|
||||
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__))
|
||||
|
||||
/* For debug builds, always enable the debug traces in this library */
|
||||
#ifndef NDEBUG
|
||||
# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__))
|
||||
#else
|
||||
# define LOGV(...) ((void)0)
|
||||
#endif
|
||||
|
||||
static void free_saved_state(struct android_app* android_app) {
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
if (android_app->savedState != NULL) {
|
||||
free(android_app->savedState);
|
||||
android_app->savedState = NULL;
|
||||
android_app->savedStateSize = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
}
|
||||
|
||||
int8_t android_app_read_cmd(struct android_app* android_app) {
|
||||
int8_t cmd;
|
||||
if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) {
|
||||
switch (cmd) {
|
||||
case APP_CMD_SAVE_STATE:
|
||||
free_saved_state(android_app);
|
||||
break;
|
||||
}
|
||||
return cmd;
|
||||
} else {
|
||||
LOGE("No data on command pipe!");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void print_cur_config(struct android_app* android_app) {
|
||||
char lang[2], country[2];
|
||||
AConfiguration_getLanguage(android_app->config, lang);
|
||||
AConfiguration_getCountry(android_app->config, country);
|
||||
|
||||
LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d "
|
||||
"keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d "
|
||||
"modetype=%d modenight=%d",
|
||||
AConfiguration_getMcc(android_app->config),
|
||||
AConfiguration_getMnc(android_app->config),
|
||||
lang[0], lang[1], country[0], country[1],
|
||||
AConfiguration_getOrientation(android_app->config),
|
||||
AConfiguration_getTouchscreen(android_app->config),
|
||||
AConfiguration_getDensity(android_app->config),
|
||||
AConfiguration_getKeyboard(android_app->config),
|
||||
AConfiguration_getNavigation(android_app->config),
|
||||
AConfiguration_getKeysHidden(android_app->config),
|
||||
AConfiguration_getNavHidden(android_app->config),
|
||||
AConfiguration_getSdkVersion(android_app->config),
|
||||
AConfiguration_getScreenSize(android_app->config),
|
||||
AConfiguration_getScreenLong(android_app->config),
|
||||
AConfiguration_getUiModeType(android_app->config),
|
||||
AConfiguration_getUiModeNight(android_app->config));
|
||||
}
|
||||
|
||||
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) {
|
||||
switch (cmd) {
|
||||
case APP_CMD_INPUT_CHANGED:
|
||||
LOGV("APP_CMD_INPUT_CHANGED\n");
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
if (android_app->inputQueue != NULL) {
|
||||
AInputQueue_detachLooper(android_app->inputQueue);
|
||||
}
|
||||
android_app->inputQueue = android_app->pendingInputQueue;
|
||||
if (android_app->inputQueue != NULL) {
|
||||
LOGV("Attaching input queue to looper");
|
||||
AInputQueue_attachLooper(android_app->inputQueue,
|
||||
android_app->looper, LOOPER_ID_INPUT, NULL,
|
||||
&android_app->inputPollSource);
|
||||
}
|
||||
pthread_cond_broadcast(&android_app->cond);
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
break;
|
||||
|
||||
case APP_CMD_INIT_WINDOW:
|
||||
LOGV("APP_CMD_INIT_WINDOW\n");
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app->window = android_app->pendingWindow;
|
||||
pthread_cond_broadcast(&android_app->cond);
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
break;
|
||||
|
||||
case APP_CMD_TERM_WINDOW:
|
||||
LOGV("APP_CMD_TERM_WINDOW\n");
|
||||
pthread_cond_broadcast(&android_app->cond);
|
||||
break;
|
||||
|
||||
case APP_CMD_RESUME:
|
||||
case APP_CMD_START:
|
||||
case APP_CMD_PAUSE:
|
||||
case APP_CMD_STOP:
|
||||
LOGV("activityState=%d\n", cmd);
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app->activityState = cmd;
|
||||
pthread_cond_broadcast(&android_app->cond);
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
break;
|
||||
|
||||
case APP_CMD_CONFIG_CHANGED:
|
||||
LOGV("APP_CMD_CONFIG_CHANGED\n");
|
||||
AConfiguration_fromAssetManager(android_app->config,
|
||||
android_app->activity->assetManager);
|
||||
print_cur_config(android_app);
|
||||
break;
|
||||
|
||||
case APP_CMD_DESTROY:
|
||||
LOGV("APP_CMD_DESTROY\n");
|
||||
android_app->destroyRequested = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) {
|
||||
switch (cmd) {
|
||||
case APP_CMD_TERM_WINDOW:
|
||||
LOGV("APP_CMD_TERM_WINDOW\n");
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app->window = NULL;
|
||||
pthread_cond_broadcast(&android_app->cond);
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
break;
|
||||
|
||||
case APP_CMD_SAVE_STATE:
|
||||
LOGV("APP_CMD_SAVE_STATE\n");
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app->stateSaved = 1;
|
||||
pthread_cond_broadcast(&android_app->cond);
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
break;
|
||||
|
||||
case APP_CMD_RESUME:
|
||||
free_saved_state(android_app);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void android_app_destroy(struct android_app* android_app) {
|
||||
LOGV("android_app_destroy!");
|
||||
free_saved_state(android_app);
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
if (android_app->inputQueue != NULL) {
|
||||
AInputQueue_detachLooper(android_app->inputQueue);
|
||||
}
|
||||
AConfiguration_delete(android_app->config);
|
||||
android_app->destroyed = 1;
|
||||
pthread_cond_broadcast(&android_app->cond);
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
// Can't touch android_app object after this.
|
||||
}
|
||||
|
||||
static void process_input(struct android_app* app, struct android_poll_source* source) {
|
||||
AInputEvent* event = NULL;
|
||||
while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
|
||||
LOGV("New input event: type=%d\n", AInputEvent_getType(event));
|
||||
if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {
|
||||
continue;
|
||||
}
|
||||
int32_t handled = 0;
|
||||
if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
|
||||
AInputQueue_finishEvent(app->inputQueue, event, handled);
|
||||
}
|
||||
}
|
||||
|
||||
static void process_cmd(struct android_app* app, struct android_poll_source* source) {
|
||||
int8_t cmd = android_app_read_cmd(app);
|
||||
android_app_pre_exec_cmd(app, cmd);
|
||||
if (app->onAppCmd != NULL) app->onAppCmd(app, cmd);
|
||||
android_app_post_exec_cmd(app, cmd);
|
||||
}
|
||||
|
||||
static void* android_app_entry(void* param) {
|
||||
struct android_app* android_app = (struct android_app*)param;
|
||||
|
||||
android_app->config = AConfiguration_new();
|
||||
AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager);
|
||||
|
||||
print_cur_config(android_app);
|
||||
|
||||
android_app->cmdPollSource.id = LOOPER_ID_MAIN;
|
||||
android_app->cmdPollSource.app = android_app;
|
||||
android_app->cmdPollSource.process = process_cmd;
|
||||
android_app->inputPollSource.id = LOOPER_ID_INPUT;
|
||||
android_app->inputPollSource.app = android_app;
|
||||
android_app->inputPollSource.process = process_input;
|
||||
|
||||
ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
|
||||
ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL,
|
||||
&android_app->cmdPollSource);
|
||||
android_app->looper = looper;
|
||||
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app->running = 1;
|
||||
pthread_cond_broadcast(&android_app->cond);
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
|
||||
android_main(android_app);
|
||||
|
||||
android_app_destroy(android_app);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Native activity interaction (called from main thread)
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
static struct android_app* android_app_create(ANativeActivity* activity,
|
||||
void* savedState, size_t savedStateSize) {
|
||||
struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app));
|
||||
memset(android_app, 0, sizeof(struct android_app));
|
||||
android_app->activity = activity;
|
||||
|
||||
pthread_mutex_init(&android_app->mutex, NULL);
|
||||
pthread_cond_init(&android_app->cond, NULL);
|
||||
|
||||
if (savedState != NULL) {
|
||||
android_app->savedState = malloc(savedStateSize);
|
||||
android_app->savedStateSize = savedStateSize;
|
||||
memcpy(android_app->savedState, savedState, savedStateSize);
|
||||
}
|
||||
|
||||
int msgpipe[2];
|
||||
if (pipe(msgpipe)) {
|
||||
LOGE("could not create pipe: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
android_app->msgread = msgpipe[0];
|
||||
android_app->msgwrite = msgpipe[1];
|
||||
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
pthread_create(&android_app->thread, &attr, android_app_entry, android_app);
|
||||
|
||||
// Wait for thread to start.
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
while (!android_app->running) {
|
||||
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
|
||||
return android_app;
|
||||
}
|
||||
|
||||
static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
|
||||
if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {
|
||||
LOGE("Failure writing android_app cmd: %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) {
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app->pendingInputQueue = inputQueue;
|
||||
android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);
|
||||
while (android_app->inputQueue != android_app->pendingInputQueue) {
|
||||
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
}
|
||||
|
||||
static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) {
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
if (android_app->pendingWindow != NULL) {
|
||||
android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW);
|
||||
}
|
||||
android_app->pendingWindow = window;
|
||||
if (window != NULL) {
|
||||
android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW);
|
||||
}
|
||||
while (android_app->window != android_app->pendingWindow) {
|
||||
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
}
|
||||
|
||||
static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) {
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app_write_cmd(android_app, cmd);
|
||||
while (android_app->activityState != cmd) {
|
||||
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
}
|
||||
|
||||
static void android_app_free(struct android_app* android_app) {
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app_write_cmd(android_app, APP_CMD_DESTROY);
|
||||
while (!android_app->destroyed) {
|
||||
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
|
||||
close(android_app->msgread);
|
||||
close(android_app->msgwrite);
|
||||
pthread_cond_destroy(&android_app->cond);
|
||||
pthread_mutex_destroy(&android_app->mutex);
|
||||
free(android_app);
|
||||
}
|
||||
|
||||
static void onDestroy(ANativeActivity* activity) {
|
||||
LOGV("Destroy: %p\n", activity);
|
||||
android_app_free((struct android_app*)activity->instance);
|
||||
}
|
||||
|
||||
static void onStart(ANativeActivity* activity) {
|
||||
LOGV("Start: %p\n", activity);
|
||||
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START);
|
||||
}
|
||||
|
||||
static void onResume(ANativeActivity* activity) {
|
||||
LOGV("Resume: %p\n", activity);
|
||||
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME);
|
||||
}
|
||||
|
||||
static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {
|
||||
struct android_app* android_app = (struct android_app*)activity->instance;
|
||||
void* savedState = NULL;
|
||||
|
||||
LOGV("SaveInstanceState: %p\n", activity);
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app->stateSaved = 0;
|
||||
android_app_write_cmd(android_app, APP_CMD_SAVE_STATE);
|
||||
while (!android_app->stateSaved) {
|
||||
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||
}
|
||||
|
||||
if (android_app->savedState != NULL) {
|
||||
savedState = android_app->savedState;
|
||||
*outLen = android_app->savedStateSize;
|
||||
android_app->savedState = NULL;
|
||||
android_app->savedStateSize = 0;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
|
||||
return savedState;
|
||||
}
|
||||
|
||||
static void onPause(ANativeActivity* activity) {
|
||||
LOGV("Pause: %p\n", activity);
|
||||
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE);
|
||||
}
|
||||
|
||||
static void onStop(ANativeActivity* activity) {
|
||||
LOGV("Stop: %p\n", activity);
|
||||
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP);
|
||||
}
|
||||
|
||||
static void onConfigurationChanged(ANativeActivity* activity) {
|
||||
struct android_app* android_app = (struct android_app*)activity->instance;
|
||||
LOGV("ConfigurationChanged: %p\n", activity);
|
||||
android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED);
|
||||
}
|
||||
|
||||
static void onLowMemory(ANativeActivity* activity) {
|
||||
struct android_app* android_app = (struct android_app*)activity->instance;
|
||||
LOGV("LowMemory: %p\n", activity);
|
||||
android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY);
|
||||
}
|
||||
|
||||
static void onWindowFocusChanged(ANativeActivity* activity, int focused) {
|
||||
LOGV("WindowFocusChanged: %p -- %d\n", activity, focused);
|
||||
android_app_write_cmd((struct android_app*)activity->instance,
|
||||
focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
|
||||
}
|
||||
|
||||
static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
|
||||
LOGV("NativeWindowCreated: %p -- %p\n", activity, window);
|
||||
android_app_set_window((struct android_app*)activity->instance, window);
|
||||
}
|
||||
|
||||
static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
|
||||
LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window);
|
||||
android_app_set_window((struct android_app*)activity->instance, NULL);
|
||||
}
|
||||
|
||||
static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
|
||||
LOGV("InputQueueCreated: %p -- %p\n", activity, queue);
|
||||
android_app_set_input((struct android_app*)activity->instance, queue);
|
||||
}
|
||||
|
||||
static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
|
||||
LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue);
|
||||
android_app_set_input((struct android_app*)activity->instance, NULL);
|
||||
}
|
||||
|
||||
void ANativeActivity_onCreate(ANativeActivity* activity,
|
||||
void* savedState, size_t savedStateSize) {
|
||||
LOGV("Creating: %p\n", activity);
|
||||
activity->callbacks->onDestroy = onDestroy;
|
||||
activity->callbacks->onStart = onStart;
|
||||
activity->callbacks->onResume = onResume;
|
||||
activity->callbacks->onSaveInstanceState = onSaveInstanceState;
|
||||
activity->callbacks->onPause = onPause;
|
||||
activity->callbacks->onStop = onStop;
|
||||
activity->callbacks->onConfigurationChanged = onConfigurationChanged;
|
||||
activity->callbacks->onLowMemory = onLowMemory;
|
||||
activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
|
||||
activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
|
||||
activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
|
||||
activity->callbacks->onInputQueueCreated = onInputQueueCreated;
|
||||
activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
|
||||
|
||||
activity->instance = android_app_create(activity, savedState, savedStateSize);
|
||||
}
|
||||
|
|
@ -1,344 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_NATIVE_APP_GLUE_H
|
||||
#define _ANDROID_NATIVE_APP_GLUE_H
|
||||
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
|
||||
#include <android/configuration.h>
|
||||
#include <android/looper.h>
|
||||
#include <android/native_activity.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The native activity interface provided by <android/native_activity.h>
|
||||
* is based on a set of application-provided callbacks that will be called
|
||||
* by the Activity's main thread when certain events occur.
|
||||
*
|
||||
* This means that each one of this callbacks _should_ _not_ block, or they
|
||||
* risk having the system force-close the application. This programming
|
||||
* model is direct, lightweight, but constraining.
|
||||
*
|
||||
* The 'threaded_native_app' static library is used to provide a different
|
||||
* execution model where the application can implement its own main event
|
||||
* loop in a different thread instead. Here's how it works:
|
||||
*
|
||||
* 1/ The application must provide a function named "android_main()" that
|
||||
* will be called when the activity is created, in a new thread that is
|
||||
* distinct from the activity's main thread.
|
||||
*
|
||||
* 2/ android_main() receives a pointer to a valid "android_app" structure
|
||||
* that contains references to other important objects, e.g. the
|
||||
* ANativeActivity obejct instance the application is running in.
|
||||
*
|
||||
* 3/ the "android_app" object holds an ALooper instance that already
|
||||
* listens to two important things:
|
||||
*
|
||||
* - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX
|
||||
* declarations below.
|
||||
*
|
||||
* - input events coming from the AInputQueue attached to the activity.
|
||||
*
|
||||
* Each of these correspond to an ALooper identifier returned by
|
||||
* ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT,
|
||||
* respectively.
|
||||
*
|
||||
* Your application can use the same ALooper to listen to additional
|
||||
* file-descriptors. They can either be callback based, or with return
|
||||
* identifiers starting with LOOPER_ID_USER.
|
||||
*
|
||||
* 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event,
|
||||
* the returned data will point to an android_poll_source structure. You
|
||||
* can call the process() function on it, and fill in android_app->onAppCmd
|
||||
* and android_app->onInputEvent to be called for your own processing
|
||||
* of the event.
|
||||
*
|
||||
* Alternatively, you can call the low-level functions to read and process
|
||||
* the data directly... look at the process_cmd() and process_input()
|
||||
* implementations in the glue to see how to do this.
|
||||
*
|
||||
* See the sample named "native-activity" that comes with the NDK with a
|
||||
* full usage example. Also look at the JavaDoc of NativeActivity.
|
||||
*/
|
||||
|
||||
struct android_app;
|
||||
|
||||
/**
|
||||
* Data associated with an ALooper fd that will be returned as the "outData"
|
||||
* when that source has data ready.
|
||||
*/
|
||||
struct android_poll_source {
|
||||
// The identifier of this source. May be LOOPER_ID_MAIN or
|
||||
// LOOPER_ID_INPUT.
|
||||
int32_t id;
|
||||
|
||||
// The android_app this ident is associated with.
|
||||
struct android_app* app;
|
||||
|
||||
// Function to call to perform the standard processing of data from
|
||||
// this source.
|
||||
void (*process)(struct android_app* app, struct android_poll_source* source);
|
||||
};
|
||||
|
||||
/**
|
||||
* This is the interface for the standard glue code of a threaded
|
||||
* application. In this model, the application's code is running
|
||||
* in its own thread separate from the main thread of the process.
|
||||
* It is not required that this thread be associated with the Java
|
||||
* VM, although it will need to be in order to make JNI calls any
|
||||
* Java objects.
|
||||
*/
|
||||
struct android_app {
|
||||
// The application can place a pointer to its own state object
|
||||
// here if it likes.
|
||||
void* userData;
|
||||
|
||||
// Fill this in with the function to process main app commands (APP_CMD_*)
|
||||
void (*onAppCmd)(struct android_app* app, int32_t cmd);
|
||||
|
||||
// Fill this in with the function to process input events. At this point
|
||||
// the event has already been pre-dispatched, and it will be finished upon
|
||||
// return. Return 1 if you have handled the event, 0 for any default
|
||||
// dispatching.
|
||||
int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
|
||||
|
||||
// The ANativeActivity object instance that this app is running in.
|
||||
ANativeActivity* activity;
|
||||
|
||||
// The current configuration the app is running in.
|
||||
AConfiguration* config;
|
||||
|
||||
// This is the last instance's saved state, as provided at creation time.
|
||||
// It is NULL if there was no state. You can use this as you need; the
|
||||
// memory will remain around until you call android_app_exec_cmd() for
|
||||
// APP_CMD_RESUME, at which point it will be freed and savedState set to NULL.
|
||||
// These variables should only be changed when processing a APP_CMD_SAVE_STATE,
|
||||
// at which point they will be initialized to NULL and you can malloc your
|
||||
// state and place the information here. In that case the memory will be
|
||||
// freed for you later.
|
||||
void* savedState;
|
||||
size_t savedStateSize;
|
||||
|
||||
// The ALooper associated with the app's thread.
|
||||
ALooper* looper;
|
||||
|
||||
// When non-NULL, this is the input queue from which the app will
|
||||
// receive user input events.
|
||||
AInputQueue* inputQueue;
|
||||
|
||||
// When non-NULL, this is the window surface that the app can draw in.
|
||||
ANativeWindow* window;
|
||||
|
||||
// Current content rectangle of the window; this is the area where the
|
||||
// window's content should be placed to be seen by the user.
|
||||
ARect contentRect;
|
||||
|
||||
// Current state of the app's activity. May be either APP_CMD_START,
|
||||
// APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
|
||||
int activityState;
|
||||
|
||||
// This is non-zero when the application's NativeActivity is being
|
||||
// destroyed and waiting for the app thread to complete.
|
||||
int destroyRequested;
|
||||
|
||||
// -------------------------------------------------
|
||||
// Below are "private" implementation of the glue code.
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
|
||||
int msgread;
|
||||
int msgwrite;
|
||||
|
||||
pthread_t thread;
|
||||
|
||||
struct android_poll_source cmdPollSource;
|
||||
struct android_poll_source inputPollSource;
|
||||
|
||||
int running;
|
||||
int stateSaved;
|
||||
int destroyed;
|
||||
int redrawNeeded;
|
||||
AInputQueue* pendingInputQueue;
|
||||
ANativeWindow* pendingWindow;
|
||||
ARect pendingContentRect;
|
||||
};
|
||||
|
||||
enum {
|
||||
/**
|
||||
* Looper data ID of commands coming from the app's main thread, which
|
||||
* is returned as an identifier from ALooper_pollOnce(). The data for this
|
||||
* identifier is a pointer to an android_poll_source structure.
|
||||
* These can be retrieved and processed with android_app_read_cmd()
|
||||
* and android_app_exec_cmd().
|
||||
*/
|
||||
LOOPER_ID_MAIN = 1,
|
||||
|
||||
/**
|
||||
* Looper data ID of events coming from the AInputQueue of the
|
||||
* application's window, which is returned as an identifier from
|
||||
* ALooper_pollOnce(). The data for this identifier is a pointer to an
|
||||
* android_poll_source structure. These can be read via the inputQueue
|
||||
* object of android_app.
|
||||
*/
|
||||
LOOPER_ID_INPUT = 2,
|
||||
|
||||
/**
|
||||
* Start of user-defined ALooper identifiers.
|
||||
*/
|
||||
LOOPER_ID_USER = 3,
|
||||
};
|
||||
|
||||
enum {
|
||||
/**
|
||||
* Command from main thread: the AInputQueue has changed. Upon processing
|
||||
* this command, android_app->inputQueue will be updated to the new queue
|
||||
* (or NULL).
|
||||
*/
|
||||
APP_CMD_INPUT_CHANGED,
|
||||
|
||||
/**
|
||||
* Command from main thread: a new ANativeWindow is ready for use. Upon
|
||||
* receiving this command, android_app->window will contain the new window
|
||||
* surface.
|
||||
*/
|
||||
APP_CMD_INIT_WINDOW,
|
||||
|
||||
/**
|
||||
* Command from main thread: the existing ANativeWindow needs to be
|
||||
* terminated. Upon receiving this command, android_app->window still
|
||||
* contains the existing window; after calling android_app_exec_cmd
|
||||
* it will be set to NULL.
|
||||
*/
|
||||
APP_CMD_TERM_WINDOW,
|
||||
|
||||
/**
|
||||
* Command from main thread: the current ANativeWindow has been resized.
|
||||
* Please redraw with its new size.
|
||||
*/
|
||||
APP_CMD_WINDOW_RESIZED,
|
||||
|
||||
/**
|
||||
* Command from main thread: the system needs that the current ANativeWindow
|
||||
* be redrawn. You should redraw the window before handing this to
|
||||
* android_app_exec_cmd() in order to avoid transient drawing glitches.
|
||||
*/
|
||||
APP_CMD_WINDOW_REDRAW_NEEDED,
|
||||
|
||||
/**
|
||||
* Command from main thread: the content area of the window has changed,
|
||||
* such as from the soft input window being shown or hidden. You can
|
||||
* find the new content rect in android_app::contentRect.
|
||||
*/
|
||||
APP_CMD_CONTENT_RECT_CHANGED,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity window has gained
|
||||
* input focus.
|
||||
*/
|
||||
APP_CMD_GAINED_FOCUS,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity window has lost
|
||||
* input focus.
|
||||
*/
|
||||
APP_CMD_LOST_FOCUS,
|
||||
|
||||
/**
|
||||
* Command from main thread: the current device configuration has changed.
|
||||
*/
|
||||
APP_CMD_CONFIG_CHANGED,
|
||||
|
||||
/**
|
||||
* Command from main thread: the system is running low on memory.
|
||||
* Try to reduce your memory use.
|
||||
*/
|
||||
APP_CMD_LOW_MEMORY,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity has been started.
|
||||
*/
|
||||
APP_CMD_START,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity has been resumed.
|
||||
*/
|
||||
APP_CMD_RESUME,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app should generate a new saved state
|
||||
* for itself, to restore from later if needed. If you have saved state,
|
||||
* allocate it with malloc and place it in android_app.savedState with
|
||||
* the size in android_app.savedStateSize. The will be freed for you
|
||||
* later.
|
||||
*/
|
||||
APP_CMD_SAVE_STATE,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity has been paused.
|
||||
*/
|
||||
APP_CMD_PAUSE,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity has been stopped.
|
||||
*/
|
||||
APP_CMD_STOP,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity is being destroyed,
|
||||
* and waiting for the app thread to clean up and exit before proceeding.
|
||||
*/
|
||||
APP_CMD_DESTROY,
|
||||
};
|
||||
|
||||
/**
|
||||
* Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next
|
||||
* app command message.
|
||||
*/
|
||||
int8_t android_app_read_cmd(struct android_app* android_app);
|
||||
|
||||
/**
|
||||
* Call with the command returned by android_app_read_cmd() to do the
|
||||
* initial pre-processing of the given command. You can perform your own
|
||||
* actions for the command after calling this function.
|
||||
*/
|
||||
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd);
|
||||
|
||||
/**
|
||||
* Call with the command returned by android_app_read_cmd() to do the
|
||||
* final post-processing of the given command. You must have done your own
|
||||
* actions for the command before calling this function.
|
||||
*/
|
||||
void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd);
|
||||
|
||||
/**
|
||||
* This is the function that application code must implement, representing
|
||||
* the main entry to the app.
|
||||
*/
|
||||
extern void android_main(struct android_app* app);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ANDROID_NATIVE_APP_GLUE_H */
|
||||
|
|
@ -1,224 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x86">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x86</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x86">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x86</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{1C538546-0768-4071-81A6-86EE8F33AA1A}</ProjectGuid>
|
||||
<Keyword>Android</Keyword>
|
||||
<RootNamespace>computeparticles</RootNamespace>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
<ApplicationType>Android</ApplicationType>
|
||||
<ApplicationTypeRevision>1.0</ApplicationTypeRevision>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>Clang_3_6</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>Clang_3_6</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>Clang_3_6</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>Clang_3_6</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>Clang_3_6</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>Clang_3_6</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>Clang_3_6</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>Clang_3_6</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<LibraryDependencies>%(LibraryDependencies);GLESv1_CM;EGL;</LibraryDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<LibraryDependencies>%(LibraryDependencies);GLESv1_CM;EGL;</LibraryDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<PreprocessorDefinitions>VK_NO_PROTOTYPES;VK_USE_PLATFORM_ANDROID_KHR;__STDINT_LIMITS</PreprocessorDefinitions>
|
||||
<CppLanguageStandard>c++11</CppLanguageStandard>
|
||||
<AdditionalIncludeDirectories>../../../external;../../../base;../../../external/gli;../../../external/glm;../../base;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<LibraryDependencies>%(LibraryDependencies);GLESv1_CM;EGL;</LibraryDependencies>
|
||||
<AdditionalOptions>-lm %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<LibraryDependencies>%(LibraryDependencies);GLESv1_CM;EGL;</LibraryDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<LibraryDependencies>%(LibraryDependencies);GLESv1_CM;EGL;</LibraryDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<LibraryDependencies>%(LibraryDependencies);GLESv1_CM;EGL;</LibraryDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<LibraryDependencies>%(LibraryDependencies);GLESv1_CM;EGL;</LibraryDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<LibraryDependencies>%(LibraryDependencies);GLESv1_CM;EGL;</LibraryDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\base\vulkanandroid.h" />
|
||||
<ClInclude Include="..\..\base\vulkanandroidbase.hpp" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="android_native_app_glue.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\base\vulkanandroid.cpp" />
|
||||
<ClCompile Include="..\..\..\base\vulkantools.cpp" />
|
||||
<ClCompile Include="android_native_app_glue.c" />
|
||||
<ClCompile Include="computeparticles.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="android_native_app_glue.h" />
|
||||
<ClInclude Include="..\..\..\base\vulkanandroid.h" />
|
||||
<ClInclude Include="..\..\base\vulkanandroidbase.hpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="android_native_app_glue.c" />
|
||||
<ClCompile Include="..\..\..\base\vulkanandroid.cpp" />
|
||||
<ClCompile Include="..\..\..\base\vulkantools.cpp" />
|
||||
<ClCompile Include="computeparticles.cpp" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -1,822 +0,0 @@
|
|||
/*
|
||||
* Vulkan Example - Compute shader particle system
|
||||
*
|
||||
* Note :
|
||||
* This is a basic android example. It may be integrated into the other examples at some point in the future.
|
||||
* Until then this serves as a starting point for using Vulkan on Android, with some of the functionality required
|
||||
* already moved to the example base classes (e.g. swap chain)
|
||||
*
|
||||
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
|
||||
*
|
||||
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "vulkanandroid.h"
|
||||
#include "vulkanswapchain.hpp"
|
||||
#include "vulkanandroidbase.hpp"
|
||||
#include <android/asset_manager.h>
|
||||
|
||||
#define GLM_FORCE_RADIANS
|
||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
||||
#include "glm/glm.hpp"
|
||||
#include "glm/gtc/matrix_transform.hpp"
|
||||
|
||||
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "AndroidProject1.NativeActivity", __VA_ARGS__))
|
||||
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "AndroidProject1.NativeActivity", __VA_ARGS__))
|
||||
|
||||
#define VERTEX_BUFFER_BIND_ID 0
|
||||
#define PARTICLE_COUNT 4 * 1024
|
||||
|
||||
struct saved_state {
|
||||
glm::vec3 rotation;
|
||||
float zoom;
|
||||
};
|
||||
|
||||
struct VulkanExample : public VulkanAndroidExampleBase
|
||||
{
|
||||
public:
|
||||
int animating;
|
||||
struct saved_state state;
|
||||
|
||||
float timer = 0.0f;
|
||||
float animStart = 50.0f;
|
||||
bool animate = true;
|
||||
|
||||
// Vulkan
|
||||
struct Vertex {
|
||||
float pos[3];
|
||||
float uv[2];
|
||||
};
|
||||
|
||||
Texture texture;
|
||||
|
||||
VkDescriptorSetLayout descriptorSetLayout;
|
||||
VkDescriptorSet descriptorSet;
|
||||
VkPipelineLayout pipelineLayout;
|
||||
|
||||
struct {
|
||||
VkPipelineVertexInputStateCreateInfo inputState;
|
||||
std::vector<VkVertexInputBindingDescription> bindingDescriptions;
|
||||
std::vector<VkVertexInputAttributeDescription> attributeDescriptions;
|
||||
} vertices;
|
||||
|
||||
struct {
|
||||
VkPipeline solid;
|
||||
VkPipeline compute;
|
||||
} pipelines;
|
||||
|
||||
VkQueue computeQueue;
|
||||
VkCommandBuffer computeCmdBuffer;
|
||||
VkPipelineLayout computePipelineLayout;
|
||||
VkDescriptorSet computeDescriptorSet;
|
||||
VkDescriptorSetLayout computeDescriptorSetLayout;
|
||||
|
||||
vkTools::UniformData computeStorageBuffer;
|
||||
|
||||
struct Particle {
|
||||
glm::vec4 pos;
|
||||
glm::vec4 col;
|
||||
glm::vec4 vel;
|
||||
};
|
||||
|
||||
struct {
|
||||
float deltaT;
|
||||
float destX;
|
||||
float destY;
|
||||
int32_t particleCount = PARTICLE_COUNT;
|
||||
} computeUbo;
|
||||
|
||||
vkTools::UniformData uniformDataCompute;
|
||||
|
||||
void initVulkan()
|
||||
{
|
||||
VulkanAndroidExampleBase::initVulkan();
|
||||
|
||||
loadTexture(
|
||||
"textures/android_robot.ktx",
|
||||
VK_FORMAT_R8G8B8A8_UNORM,
|
||||
&texture,
|
||||
false);
|
||||
|
||||
createCommandBuffers();
|
||||
|
||||
// Compute stuff
|
||||
getComputeQueue();
|
||||
createComputeCommandBuffer();
|
||||
prepareStorageBuffers();
|
||||
|
||||
prepareUniformBuffers();
|
||||
setupDescriptorSetLayout();
|
||||
preparePipelines();
|
||||
setupDescriptorPool();
|
||||
setupDescriptorSet();
|
||||
|
||||
prepareCompute();
|
||||
|
||||
buildCommandBuffers();
|
||||
buildComputeCommandBuffer();
|
||||
|
||||
state.zoom = -5.0f;
|
||||
state.rotation = glm::vec3();
|
||||
|
||||
prepared = true;
|
||||
}
|
||||
|
||||
void cleanupVulkan()
|
||||
{
|
||||
prepared = false;
|
||||
vkDestroyPipeline(device, pipelines.solid, nullptr);
|
||||
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
|
||||
vkDestroyPipelineLayout(device, computePipelineLayout, nullptr);
|
||||
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
|
||||
vkDestroyDescriptorSetLayout(device, computeDescriptorSetLayout, nullptr);
|
||||
vkDestroyBuffer(device, uniformDataCompute.buffer, nullptr);
|
||||
vkFreeMemory(device, uniformDataCompute.memory, nullptr);
|
||||
vkDestroyBuffer(device, computeStorageBuffer.buffer, nullptr);
|
||||
vkFreeMemory(device, computeStorageBuffer.memory, nullptr);
|
||||
|
||||
destroyTextureImage(&texture);
|
||||
|
||||
vkFreeCommandBuffers(device, cmdPool, 1, &computeCmdBuffer);
|
||||
|
||||
VulkanExample::cleanUpVulkan();
|
||||
}
|
||||
|
||||
// Find and create a compute capable device queue
|
||||
void getComputeQueue()
|
||||
{
|
||||
uint32_t queueIndex = 0;
|
||||
uint32_t queueCount;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, NULL);
|
||||
assert(queueCount >= 1);
|
||||
|
||||
std::vector<VkQueueFamilyProperties> queueProps;
|
||||
queueProps.resize(queueCount);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, queueProps.data());
|
||||
|
||||
for (queueIndex = 0; queueIndex < queueCount; queueIndex++)
|
||||
{
|
||||
if (queueProps[queueIndex].queueFlags & VK_QUEUE_COMPUTE_BIT)
|
||||
break;
|
||||
}
|
||||
assert(queueIndex < queueCount);
|
||||
|
||||
VkDeviceQueueCreateInfo queueCreateInfo = {};
|
||||
queueCreateInfo.queueFamilyIndex = queueIndex;
|
||||
queueCreateInfo.queueCount = 1;
|
||||
vkGetDeviceQueue(device, queueIndex, 0, &computeQueue);
|
||||
}
|
||||
|
||||
void createComputeCommandBuffer()
|
||||
{
|
||||
VkCommandBufferAllocateInfo cmdBufAllocateInfo =
|
||||
vkTools::initializers::commandBufferAllocateInfo(
|
||||
cmdPool,
|
||||
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||
1);
|
||||
|
||||
VkResult vkRes = vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &computeCmdBuffer);
|
||||
assert(!vkRes);
|
||||
}
|
||||
|
||||
void buildComputeCommandBuffer()
|
||||
{
|
||||
VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo();;
|
||||
|
||||
vkBeginCommandBuffer(computeCmdBuffer, &cmdBufInfo);
|
||||
|
||||
vkCmdBindPipeline(computeCmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelines.compute);
|
||||
vkCmdBindDescriptorSets(computeCmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipelineLayout, 0, 1, &computeDescriptorSet, 0, 0);
|
||||
|
||||
vkCmdDispatch(computeCmdBuffer, PARTICLE_COUNT / 16, 1, 1);
|
||||
|
||||
vkEndCommandBuffer(computeCmdBuffer);
|
||||
}
|
||||
|
||||
void updateUniformBuffers()
|
||||
{
|
||||
computeUbo.deltaT = (1.0f / frameTimer) * 0.15f;
|
||||
computeUbo.destX = sin(glm::radians(timer*360.0)) * 0.75f;
|
||||
computeUbo.destY = cos(glm::radians(timer*360.0)) * 0.10f;
|
||||
uint8_t *pData;
|
||||
VkResult err = vkMapMemory(device, uniformDataCompute.memory, 0, sizeof(computeUbo), 0, (void **)&pData);
|
||||
assert(!err);
|
||||
memcpy(pData, &computeUbo, sizeof(computeUbo));
|
||||
vkUnmapMemory(device, uniformDataCompute.memory);
|
||||
}
|
||||
|
||||
void prepareUniformBuffers()
|
||||
{
|
||||
// Prepare and initialize uniform buffer containing shader uniforms
|
||||
VkMemoryRequirements memReqs;
|
||||
|
||||
// Vertex shader uniform buffer block
|
||||
VkBufferCreateInfo bufferInfo = {};
|
||||
VkMemoryAllocateInfo allocInfo = vkTools::initializers::memoryAllocateInfo();
|
||||
VkResult err;
|
||||
|
||||
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
bufferInfo.size = sizeof(computeUbo);
|
||||
bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||
|
||||
err = vkCreateBuffer(device, &bufferInfo, nullptr, &uniformDataCompute.buffer);
|
||||
assert(!err);
|
||||
vkGetBufferMemoryRequirements(device, uniformDataCompute.buffer, &memReqs);
|
||||
allocInfo.allocationSize = memReqs.size;
|
||||
getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &allocInfo.memoryTypeIndex);
|
||||
err = vkAllocateMemory(device, &allocInfo, nullptr, &(uniformDataCompute.memory));
|
||||
assert(!err);
|
||||
err = vkBindBufferMemory(device, uniformDataCompute.buffer, uniformDataCompute.memory, 0);
|
||||
assert(!err);
|
||||
|
||||
uniformDataCompute.descriptor.buffer = uniformDataCompute.buffer;
|
||||
uniformDataCompute.descriptor.offset = 0;
|
||||
uniformDataCompute.descriptor.range = sizeof(computeUbo);
|
||||
|
||||
updateUniformBuffers();
|
||||
}
|
||||
|
||||
void preparePipelines()
|
||||
{
|
||||
VkResult err;
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
|
||||
vkTools::initializers::pipelineInputAssemblyStateCreateInfo(
|
||||
VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
|
||||
0,
|
||||
VK_FALSE);
|
||||
|
||||
VkPipelineRasterizationStateCreateInfo rasterizationState =
|
||||
vkTools::initializers::pipelineRasterizationStateCreateInfo(
|
||||
VK_POLYGON_MODE_FILL,
|
||||
VK_CULL_MODE_NONE,
|
||||
VK_FRONT_FACE_COUNTER_CLOCKWISE,
|
||||
0);
|
||||
|
||||
VkPipelineColorBlendAttachmentState blendAttachmentState =
|
||||
vkTools::initializers::pipelineColorBlendAttachmentState(
|
||||
0xf,
|
||||
VK_FALSE);
|
||||
|
||||
VkPipelineColorBlendStateCreateInfo colorBlendState =
|
||||
vkTools::initializers::pipelineColorBlendStateCreateInfo(
|
||||
1,
|
||||
&blendAttachmentState);
|
||||
|
||||
VkPipelineDepthStencilStateCreateInfo depthStencilState =
|
||||
vkTools::initializers::pipelineDepthStencilStateCreateInfo(
|
||||
VK_TRUE,
|
||||
VK_TRUE,
|
||||
VK_COMPARE_OP_LESS_OR_EQUAL);
|
||||
|
||||
VkPipelineViewportStateCreateInfo viewportState =
|
||||
vkTools::initializers::pipelineViewportStateCreateInfo(1, 1, 0);
|
||||
|
||||
VkPipelineMultisampleStateCreateInfo multisampleState =
|
||||
vkTools::initializers::pipelineMultisampleStateCreateInfo(
|
||||
VK_SAMPLE_COUNT_1_BIT,
|
||||
0);
|
||||
|
||||
std::vector<VkDynamicState> dynamicStateEnables;
|
||||
dynamicStateEnables.push_back(VK_DYNAMIC_STATE_VIEWPORT);
|
||||
dynamicStateEnables.push_back(VK_DYNAMIC_STATE_SCISSOR);
|
||||
|
||||
VkPipelineDynamicStateCreateInfo dynamicState =
|
||||
vkTools::initializers::pipelineDynamicStateCreateInfo(
|
||||
dynamicStateEnables.data(),
|
||||
dynamicStateEnables.size(),
|
||||
0);
|
||||
|
||||
// Rendering pipeline
|
||||
// Load shaders
|
||||
std::array<VkPipelineShaderStageCreateInfo, 2> shaderStages;
|
||||
|
||||
shaderStages[0] = loadShader("shaders/particle.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||
shaderStages[1] = loadShader("shaders/particle.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipelineCreateInfo =
|
||||
vkTools::initializers::pipelineCreateInfo(
|
||||
pipelineLayout,
|
||||
renderPass,
|
||||
0);
|
||||
|
||||
pipelineCreateInfo.pVertexInputState = &vertices.inputState;
|
||||
pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
|
||||
pipelineCreateInfo.pRasterizationState = &rasterizationState;
|
||||
pipelineCreateInfo.pColorBlendState = &colorBlendState;
|
||||
pipelineCreateInfo.pMultisampleState = &multisampleState;
|
||||
pipelineCreateInfo.pViewportState = &viewportState;
|
||||
pipelineCreateInfo.pDepthStencilState = &depthStencilState;
|
||||
pipelineCreateInfo.pDynamicState = &dynamicState;
|
||||
pipelineCreateInfo.stageCount = shaderStages.size();
|
||||
pipelineCreateInfo.pStages = shaderStages.data();
|
||||
pipelineCreateInfo.renderPass = renderPass;
|
||||
|
||||
// Additive blending
|
||||
blendAttachmentState.blendEnable = VK_TRUE;
|
||||
blendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
|
||||
blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||
blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA;
|
||||
|
||||
|
||||
err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.solid);
|
||||
assert(!err);
|
||||
}
|
||||
|
||||
// Setup and fill the compute shader storage buffers for
|
||||
// vertex positions and velocities
|
||||
void prepareStorageBuffers()
|
||||
{
|
||||
float destPosX = 0.0f;
|
||||
float destPosY = 0.0f;
|
||||
|
||||
// Initial particle positions
|
||||
std::vector<Particle> particleBuffer;
|
||||
for (int i = 0; i < PARTICLE_COUNT; ++i)
|
||||
{
|
||||
// Position
|
||||
float aspectRatio = (float)height / (float)width;
|
||||
float rndVal = (float)rand() / (float)(RAND_MAX / (360.0f * 3.14f * 2.0f));
|
||||
float rndRad = (float)rand() / (float)(RAND_MAX)* 0.65f;
|
||||
Particle p;
|
||||
p.pos = glm::vec4(
|
||||
destPosX + cos(rndVal) * rndRad * aspectRatio,
|
||||
destPosY + sin(rndVal) * rndRad,
|
||||
0.0f,
|
||||
1.0f);
|
||||
p.col = glm::vec4(
|
||||
(float)(rand() % 255) / 255.0f,
|
||||
(float)(rand() % 255) / 255.0f,
|
||||
(float)(rand() % 255) / 255.0f,
|
||||
1.0f);
|
||||
p.vel = glm::vec4(0.0f);
|
||||
particleBuffer.push_back(p);
|
||||
}
|
||||
|
||||
// Buffer size is the same for all storage buffers
|
||||
uint32_t storageBufferSize = particleBuffer.size() * sizeof(Particle);
|
||||
|
||||
VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo();
|
||||
VkMemoryRequirements memReqs;
|
||||
|
||||
VkResult err;
|
||||
void *data;
|
||||
|
||||
// Allocate and fill storage buffer object
|
||||
VkBufferCreateInfo vBufferInfo =
|
||||
vkTools::initializers::bufferCreateInfo(
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
||||
storageBufferSize);
|
||||
err = vkCreateBuffer(device, &vBufferInfo, nullptr, &computeStorageBuffer.buffer);
|
||||
assert(!err);
|
||||
vkGetBufferMemoryRequirements(device, computeStorageBuffer.buffer, &memReqs);
|
||||
memAlloc.allocationSize = memReqs.size;
|
||||
getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAlloc.memoryTypeIndex);
|
||||
err = vkAllocateMemory(device, &memAlloc, nullptr, &computeStorageBuffer.memory);
|
||||
assert(!err);
|
||||
err = vkMapMemory(device, computeStorageBuffer.memory, 0, storageBufferSize, 0, &data);
|
||||
assert(!err);
|
||||
memcpy(data, particleBuffer.data(), storageBufferSize);
|
||||
vkUnmapMemory(device, computeStorageBuffer.memory);
|
||||
err = vkBindBufferMemory(device, computeStorageBuffer.buffer, computeStorageBuffer.memory, 0);
|
||||
assert(!err);
|
||||
|
||||
computeStorageBuffer.descriptor.buffer = computeStorageBuffer.buffer;
|
||||
computeStorageBuffer.descriptor.offset = 0;
|
||||
computeStorageBuffer.descriptor.range = storageBufferSize;
|
||||
|
||||
// Binding description
|
||||
vertices.bindingDescriptions.resize(1);
|
||||
vertices.bindingDescriptions[0] =
|
||||
vkTools::initializers::vertexInputBindingDescription(
|
||||
VERTEX_BUFFER_BIND_ID,
|
||||
sizeof(Particle),
|
||||
VK_VERTEX_INPUT_RATE_VERTEX);
|
||||
|
||||
// Attribute descriptions
|
||||
// Describes memory layout and shader positions
|
||||
vertices.attributeDescriptions.resize(2);
|
||||
// Location 0 : Position
|
||||
vertices.attributeDescriptions[0] =
|
||||
vkTools::initializers::vertexInputAttributeDescription(
|
||||
VERTEX_BUFFER_BIND_ID,
|
||||
0,
|
||||
VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
0);
|
||||
// Location 1 : Color
|
||||
vertices.attributeDescriptions[1] =
|
||||
vkTools::initializers::vertexInputAttributeDescription(
|
||||
VERTEX_BUFFER_BIND_ID,
|
||||
1,
|
||||
VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
sizeof(float) * 4);
|
||||
|
||||
// Assign to vertex buffer
|
||||
vertices.inputState = vkTools::initializers::pipelineVertexInputStateCreateInfo();
|
||||
vertices.inputState.vertexBindingDescriptionCount = vertices.bindingDescriptions.size();
|
||||
vertices.inputState.pVertexBindingDescriptions = vertices.bindingDescriptions.data();
|
||||
vertices.inputState.vertexAttributeDescriptionCount = vertices.attributeDescriptions.size();
|
||||
vertices.inputState.pVertexAttributeDescriptions = vertices.attributeDescriptions.data();
|
||||
}
|
||||
|
||||
void prepareCompute()
|
||||
{
|
||||
// Create compute pipeline
|
||||
// Compute pipelines are created separate from graphics pipelines
|
||||
// even if they use the same queue
|
||||
|
||||
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings;
|
||||
setLayoutBindings.push_back(
|
||||
// Binding 0 : Particle position storage buffer
|
||||
vkTools::initializers::descriptorSetLayoutBinding(
|
||||
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
VK_SHADER_STAGE_COMPUTE_BIT,
|
||||
0));
|
||||
setLayoutBindings.push_back(
|
||||
// Binding 1 : Uniform buffer
|
||||
vkTools::initializers::descriptorSetLayoutBinding(
|
||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
VK_SHADER_STAGE_COMPUTE_BIT,
|
||||
1));
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo descriptorLayout =
|
||||
vkTools::initializers::descriptorSetLayoutCreateInfo(
|
||||
setLayoutBindings.data(),
|
||||
setLayoutBindings.size());
|
||||
|
||||
VkResult err = vkCreateDescriptorSetLayout(
|
||||
device,
|
||||
&descriptorLayout,
|
||||
nullptr,
|
||||
&computeDescriptorSetLayout);
|
||||
assert(!err);
|
||||
|
||||
VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo =
|
||||
vkTools::initializers::pipelineLayoutCreateInfo(
|
||||
&computeDescriptorSetLayout,
|
||||
1);
|
||||
|
||||
err = vkCreatePipelineLayout(
|
||||
device,
|
||||
&pPipelineLayoutCreateInfo,
|
||||
nullptr,
|
||||
&computePipelineLayout);
|
||||
assert(!err);
|
||||
|
||||
VkDescriptorSetAllocateInfo allocInfo =
|
||||
vkTools::initializers::descriptorSetAllocateInfo(
|
||||
descriptorPool,
|
||||
&computeDescriptorSetLayout,
|
||||
1);
|
||||
|
||||
err = vkAllocateDescriptorSets(device, &allocInfo, &computeDescriptorSet);
|
||||
assert(!err);
|
||||
|
||||
std::vector<VkWriteDescriptorSet> computeWriteDescriptorSets;
|
||||
computeWriteDescriptorSets.push_back(
|
||||
// Binding 0 : Particle position storage buffer
|
||||
vkTools::initializers::writeDescriptorSet(
|
||||
computeDescriptorSet,
|
||||
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
0,
|
||||
&computeStorageBuffer.descriptor));
|
||||
computeWriteDescriptorSets.push_back(
|
||||
// Binding 1 : Uniform buffer
|
||||
vkTools::initializers::writeDescriptorSet(
|
||||
computeDescriptorSet,
|
||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
1,
|
||||
&uniformDataCompute.descriptor));
|
||||
|
||||
vkUpdateDescriptorSets(device, computeWriteDescriptorSets.size(), computeWriteDescriptorSets.data(), 0, NULL);
|
||||
|
||||
// Create pipeline
|
||||
VkComputePipelineCreateInfo computePipelineCreateInfo =
|
||||
vkTools::initializers::computePipelineCreateInfo(
|
||||
computePipelineLayout,
|
||||
0);
|
||||
computePipelineCreateInfo.stage = loadShader("shaders/particle.comp.spv", VK_SHADER_STAGE_COMPUTE_BIT);
|
||||
|
||||
err = vkCreateComputePipelines(device, pipelineCache, 1, &computePipelineCreateInfo, nullptr, &pipelines.compute);
|
||||
assert(!err);
|
||||
}
|
||||
|
||||
void setupDescriptorPool()
|
||||
{
|
||||
std::vector<VkDescriptorPoolSize> poolSizes;
|
||||
poolSizes.push_back(vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1));
|
||||
poolSizes.push_back(vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1));
|
||||
poolSizes.push_back(vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1));
|
||||
|
||||
VkDescriptorPoolCreateInfo descriptorPoolInfo =
|
||||
vkTools::initializers::descriptorPoolCreateInfo(
|
||||
poolSizes.size(),
|
||||
poolSizes.data(),
|
||||
2);
|
||||
|
||||
VkResult vkRes = vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool);
|
||||
assert(!vkRes);
|
||||
}
|
||||
|
||||
void setupDescriptorSetLayout()
|
||||
{
|
||||
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings;
|
||||
setLayoutBindings.push_back(
|
||||
// Binding 0 : Fragment shader image sampler
|
||||
vkTools::initializers::descriptorSetLayoutBinding(
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
0));
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo descriptorLayout =
|
||||
vkTools::initializers::descriptorSetLayoutCreateInfo(
|
||||
setLayoutBindings.data(),
|
||||
setLayoutBindings.size());
|
||||
|
||||
VkResult err = vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout);
|
||||
assert(!err);
|
||||
|
||||
VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo =
|
||||
vkTools::initializers::pipelineLayoutCreateInfo(
|
||||
&descriptorSetLayout,
|
||||
1);
|
||||
|
||||
err = vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayout);
|
||||
assert(!err);
|
||||
}
|
||||
|
||||
void setupDescriptorSet()
|
||||
{
|
||||
VkDescriptorSetAllocateInfo allocInfo =
|
||||
vkTools::initializers::descriptorSetAllocateInfo(
|
||||
descriptorPool,
|
||||
&descriptorSetLayout,
|
||||
1);
|
||||
|
||||
VkResult vkRes = vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet);
|
||||
assert(!vkRes);
|
||||
|
||||
// Image descriptor for the color map texture
|
||||
VkDescriptorImageInfo texDescriptor =
|
||||
vkTools::initializers::descriptorImageInfo(
|
||||
texture.sampler,
|
||||
texture.view,
|
||||
VK_IMAGE_LAYOUT_GENERAL);
|
||||
|
||||
std::vector<VkWriteDescriptorSet> writeDescriptorSets;
|
||||
writeDescriptorSets.push_back(
|
||||
// Binding 0 : Fragment shader texture sampler
|
||||
vkTools::initializers::writeDescriptorSet(
|
||||
descriptorSet,
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
0,
|
||||
&texDescriptor));
|
||||
|
||||
vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL);
|
||||
}
|
||||
|
||||
void buildCommandBuffers()
|
||||
{
|
||||
VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo();
|
||||
|
||||
VkClearValue clearValues[2];
|
||||
clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 0.0f } };
|
||||
clearValues[1].depthStencil = { 1.0f, 0 };
|
||||
|
||||
VkRenderPassBeginInfo renderPassBeginInfo = vkTools::initializers::renderPassBeginInfo();
|
||||
renderPassBeginInfo.renderPass = renderPass;
|
||||
renderPassBeginInfo.renderArea.offset.x = 0;
|
||||
renderPassBeginInfo.renderArea.offset.y = 0;
|
||||
renderPassBeginInfo.renderArea.extent.width = width;
|
||||
renderPassBeginInfo.renderArea.extent.height = height;
|
||||
renderPassBeginInfo.clearValueCount = 2;
|
||||
renderPassBeginInfo.pClearValues = clearValues;
|
||||
|
||||
VkResult err;
|
||||
|
||||
for (int32_t i = 0; i < drawCmdBuffers.size(); ++i)
|
||||
{
|
||||
// Set target frame buffer
|
||||
renderPassBeginInfo.framebuffer = frameBuffers[i];
|
||||
|
||||
err = vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo);
|
||||
assert(!err);
|
||||
|
||||
// Buffer memory barrier to make sure that compute shader
|
||||
// writes are finished before using the storage buffer
|
||||
// in the vertex shader
|
||||
VkBufferMemoryBarrier bufferBarrier = vkTools::initializers::bufferMemoryBarrier();
|
||||
// Source access : Compute shader buffer write
|
||||
bufferBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
|
||||
// Dest access : Vertex shader access (attribute binding)
|
||||
bufferBarrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
|
||||
bufferBarrier.buffer = computeStorageBuffer.buffer;
|
||||
bufferBarrier.offset = 0;
|
||||
bufferBarrier.size = computeStorageBuffer.descriptor.range;
|
||||
bufferBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
bufferBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
|
||||
vkCmdPipelineBarrier(
|
||||
drawCmdBuffers[i],
|
||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_FLAGS_NONE,
|
||||
0, nullptr,
|
||||
1, &bufferBarrier,
|
||||
0, nullptr);
|
||||
|
||||
vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
VkViewport viewport = vkTools::initializers::viewport(
|
||||
(float)width,
|
||||
(float)height,
|
||||
0.0f,
|
||||
1.0f
|
||||
);
|
||||
vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport);
|
||||
|
||||
VkRect2D scissor = vkTools::initializers::rect2D(
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
0
|
||||
);
|
||||
vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor);
|
||||
|
||||
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL);
|
||||
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.solid);
|
||||
|
||||
VkDeviceSize offsets[1] = { 0 };
|
||||
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &computeStorageBuffer.buffer, offsets);
|
||||
vkCmdDraw(drawCmdBuffers[i], PARTICLE_COUNT, 1, 0, 0);
|
||||
|
||||
vkCmdEndRenderPass(drawCmdBuffers[i]);
|
||||
|
||||
VkImageMemoryBarrier prePresentBarrier = vkTools::prePresentBarrier(swapChain.buffers[i].image);
|
||||
vkCmdPipelineBarrier(
|
||||
drawCmdBuffers[i],
|
||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_FLAGS_NONE,
|
||||
0, nullptr,
|
||||
0, nullptr,
|
||||
1, &prePresentBarrier);
|
||||
|
||||
err = vkEndCommandBuffer(drawCmdBuffers[i]);
|
||||
assert(!err);
|
||||
}
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
VkResult err;
|
||||
|
||||
// Get next image in the swap chain (back/front buffer)
|
||||
err = swapChain.acquireNextImage(semaphores.presentComplete, ¤tBuffer);
|
||||
assert(!err);
|
||||
|
||||
submitPostPresentBarrier(swapChain.buffers[currentBuffer].image);
|
||||
|
||||
VkPipelineStageFlags pipelineStages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
||||
VkSubmitInfo submitInfo = vkTools::initializers::submitInfo();
|
||||
submitInfo.waitSemaphoreCount = 1;
|
||||
submitInfo.pWaitSemaphores = &semaphores.presentComplete;
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
|
||||
submitInfo.pWaitDstStageMask = &pipelineStages;
|
||||
submitInfo.signalSemaphoreCount = 1;
|
||||
submitInfo.pSignalSemaphores = &semaphores.submitSignal;
|
||||
|
||||
// Submit to the graphics queue
|
||||
err = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||
assert(!err);
|
||||
|
||||
submitPrePresentBarrier(swapChain.buffers[currentBuffer].image);
|
||||
|
||||
// Present the current buffer to the swap chain
|
||||
// This will display the image
|
||||
err = swapChain.queuePresent(queue, currentBuffer, semaphores.submitSignal);
|
||||
assert(!err);
|
||||
|
||||
// Compute
|
||||
VkSubmitInfo computeSubmitInfo = vkTools::initializers::submitInfo();
|
||||
computeSubmitInfo.commandBufferCount = 1;
|
||||
computeSubmitInfo.pCommandBuffers = &computeCmdBuffer;
|
||||
|
||||
err = vkQueueSubmit(computeQueue, 1, &computeSubmitInfo, VK_NULL_HANDLE);
|
||||
assert(!err);
|
||||
|
||||
err = vkQueueWaitIdle(computeQueue);
|
||||
assert(!err);
|
||||
}
|
||||
|
||||
void render()
|
||||
{
|
||||
// Render frame
|
||||
if (prepared)
|
||||
{
|
||||
startTiming();
|
||||
if (animating)
|
||||
{
|
||||
if (animStart > 0.0f)
|
||||
{
|
||||
animStart -= 0.15f * (1.0f / frameTimer);
|
||||
}
|
||||
if ((animate) & (animStart <= 0.0f))
|
||||
{
|
||||
timer += 0.5f * (1.0f / frameTimer);
|
||||
if (timer > 1.0)
|
||||
{
|
||||
timer -= 1.0f;
|
||||
}
|
||||
}
|
||||
updateUniformBuffers();
|
||||
}
|
||||
draw();
|
||||
endTiming();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static int32_t handleInput(struct android_app* app, AInputEvent* event)
|
||||
{
|
||||
struct VulkanExample* vulkanExample = (struct VulkanExample*)app->userData;
|
||||
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION)
|
||||
{
|
||||
// todo
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void handleCommand(struct android_app* app, int32_t cmd)
|
||||
{
|
||||
VulkanExample* vulkanExample = (VulkanExample*)app->userData;
|
||||
switch (cmd)
|
||||
{
|
||||
case APP_CMD_SAVE_STATE:
|
||||
vulkanExample->app->savedState = malloc(sizeof(struct saved_state));
|
||||
*((struct saved_state*)vulkanExample->app->savedState) = vulkanExample->state;
|
||||
vulkanExample->app->savedStateSize = sizeof(struct saved_state);
|
||||
break;
|
||||
case APP_CMD_INIT_WINDOW:
|
||||
if (vulkanExample->app->window != NULL)
|
||||
{
|
||||
vulkanExample->initVulkan();
|
||||
assert(vulkanExample->prepared);
|
||||
}
|
||||
break;
|
||||
case APP_CMD_LOST_FOCUS:
|
||||
vulkanExample->animating = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the main entry point of a native application that is using
|
||||
* android_native_app_glue. It runs in its own thread, with its own
|
||||
* event loop for receiving input events and doing other things.
|
||||
*/
|
||||
void android_main(struct android_app* state)
|
||||
{
|
||||
VulkanExample *engine = new VulkanExample();
|
||||
|
||||
state->userData = engine;
|
||||
state->onAppCmd = handleCommand;
|
||||
state->onInputEvent = handleInput;
|
||||
engine->app = state;
|
||||
|
||||
engine->animating = 1;
|
||||
|
||||
// loop waiting for stuff to do.
|
||||
|
||||
while (1)
|
||||
{
|
||||
// Read all pending events.
|
||||
int ident;
|
||||
int events;
|
||||
struct android_poll_source* source;
|
||||
|
||||
while ((ident = ALooper_pollAll(engine->animating ? 0 : -1, NULL, &events, (void**)&source)) >= 0)
|
||||
{
|
||||
if (source != NULL)
|
||||
{
|
||||
source->process(state, source);
|
||||
}
|
||||
|
||||
if (state->destroyRequested != 0)
|
||||
{
|
||||
engine->cleanupVulkan();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
engine->render();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
//
|
||||
// pch.h
|
||||
// Header for standard system include files.
|
||||
//
|
||||
// Used by the build system to generate the precompiled header. Note that no
|
||||
// pch.cpp is needed and the pch.h is automatically included in all cpp files
|
||||
// that are part of the project
|
||||
//
|
||||
|
||||
#include <jni.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include "gli/gli.hpp"
|
||||
|
||||
#include <android/sensor.h>
|
||||
|
||||
#include <android/log.h>
|
||||
#include "android_native_app_glue.h"
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Changes made to Package Name should also be reflected in the Debugging - Package Name property, in the Property Pages -->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.$(ApplicationName)"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<!-- This is the platform API where NativeActivity was introduced. -->
|
||||
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="21"/>
|
||||
|
||||
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.gamepad" android:required="false"/>
|
||||
<uses-feature android:name="android.software.leanback" android:required="false"/>
|
||||
|
||||
<!-- This .apk has no Java code itself, so set hasCode to false. -->
|
||||
<application android:label="@string/app_name" android:icon="@drawable/icon" android:hasCode="false">
|
||||
|
||||
<!-- Our activity is the built-in NativeActivity framework class.
|
||||
This will take care of integrating with our NDK code. -->
|
||||
<activity android:name="android.app.NativeActivity"
|
||||
android:label="@string/app_name"
|
||||
android:banner="@drawable/banner"
|
||||
android:configChanges="orientation|keyboardHidden">
|
||||
<!-- Tell NativeActivity the name of our .so -->
|
||||
<meta-data android:name="android.app.lib_name"
|
||||
android:value="$(AndroidAppLibName)" />
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,90 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="$(projectname)" default="help">
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- if sdk.dir was not set from one of the property file, then
|
||||
get it from the ANDROID_HOME env var. -->
|
||||
<property environment="env" />
|
||||
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
|
||||
<isset property="env.ANDROID_HOME" />
|
||||
</condition>
|
||||
|
||||
<!-- The project.properties file contains project specific properties such as
|
||||
project target, and library dependencies. Lower level build properties are
|
||||
stored in ant.properties
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure ANDROID_HOME environment variable is correctly set."
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
<!--
|
||||
Import per project custom build rules if present at the root of the project.
|
||||
This is the place to put custom intermediary targets such as:
|
||||
-pre-build
|
||||
-pre-compile
|
||||
-post-compile (This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir})
|
||||
-post-package
|
||||
-post-build
|
||||
-pre-clean
|
||||
-->
|
||||
<import file="custom_rules.xml" optional="true" />
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: 1 -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
<target name="-pre-compile">
|
||||
<path id="project.all.jars.path">
|
||||
<path path="${toString:project.all.jars.path}"/>
|
||||
<fileset dir="${jar.libs.dir}">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
</target>
|
||||
</project>
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x86">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x86</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x86">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x86</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<RootNamespace>computeparticles</RootNamespace>
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
<ProjectVersion>1.0</ProjectVersion>
|
||||
<ProjectGuid>07b432c0-5242-4eb4-982b-ca895d032ae5</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(AndroidTargetsPath)\Android.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<AndroidAPILevel>android-21</AndroidAPILevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" Label="Configuration">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(AndroidTargetsPath)\Android.props" />
|
||||
<ImportGroup Label="ExtensionSettings" />
|
||||
<ImportGroup Label="Shared" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\$(RootNamespace)</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<AntPackage>
|
||||
<AndroidAppLibName>$(RootNamespace)</AndroidAppLibName>
|
||||
</AntPackage>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<AntPackage>
|
||||
<AndroidAppLibName>$(RootNamespace)</AndroidAppLibName>
|
||||
</AntPackage>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<AntPackage>
|
||||
<AndroidAppLibName>$(RootNamespace)</AndroidAppLibName>
|
||||
</AntPackage>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<AntPackage>
|
||||
<AndroidAppLibName>$(RootNamespace)</AndroidAppLibName>
|
||||
</AntPackage>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<AntPackage>
|
||||
<AndroidAppLibName>$(RootNamespace)</AndroidAppLibName>
|
||||
</AntPackage>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<AntPackage>
|
||||
<AndroidAppLibName>$(RootNamespace)</AndroidAppLibName>
|
||||
</AntPackage>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
|
||||
<AntPackage>
|
||||
<AndroidAppLibName>$(RootNamespace)</AndroidAppLibName>
|
||||
</AntPackage>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
|
||||
<AntPackage>
|
||||
<AndroidAppLibName>$(RootNamespace)</AndroidAppLibName>
|
||||
</AntPackage>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="assets\shaders\particle.comp.spv" />
|
||||
<Content Include="assets\shaders\particle.frag.spv" />
|
||||
<Content Include="assets\shaders\particle.vert.spv" />
|
||||
<Content Include="assets\textures\android_robot.ktx" />
|
||||
<Content Include="res\drawable\banner.png" />
|
||||
<Content Include="res\drawable\icon.png" />
|
||||
<Content Include="res\values\strings.xml" />
|
||||
<AntBuildXml Include="build.xml" />
|
||||
<AndroidManifest Include="AndroidManifest.xml" />
|
||||
<AntProjectPropertiesFile Include="project.properties" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\computeparticles.NativeActivity\computeparticles.NativeActivity.vcxproj">
|
||||
<Project>{622593a1-7b0d-4d71-8369-371601b8bee1}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(AndroidTargetsPath)\Android.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# Project target
|
||||
target=$(androidapilevel)
|
||||
# Provide path to the directory where prebuilt external jar files are by setting jar.libs.dir=
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 33 KiB |
|
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">VulkanComputeExample</string>
|
||||
</resources>
|
||||
47
android/computeparticles/jni/Android.mk
Normal file
47
android/computeparticles/jni/Android.mk
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
LOCAL_PATH := $(call my-dir)/../../computeparticles
|
||||
|
||||
# assimp
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := assimp
|
||||
LOCAL_SRC_FILES := $(LOCAL_PATH)/../../libs/assimp/$(TARGET_ARCH_ABI)/libassimp.a
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
# vulkan example
|
||||
|
||||
DATADIR := $(LOCAL_PATH)/../../data
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := vulkanComputeparticles
|
||||
|
||||
PROJECT_FILES := $(wildcard $(LOCAL_PATH)/../../computeparticles/*.cpp)
|
||||
PROJECT_FILES += $(wildcard $(LOCAL_PATH)/../../base/*.cpp)
|
||||
|
||||
LOCAL_CPPFLAGS := -std=c++11
|
||||
LOCAL_CPPFLAGS += -D__STDC_LIMIT_MACROS
|
||||
LOCAL_CPPFLAGS += -DVK_NO_PROTOTYPES
|
||||
LOCAL_CPPFLAGS += -DVK_USE_PLATFORM_ANDROID_KHR
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../external/
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../external/glm
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../external/gli
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../external/assimp
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../base/
|
||||
#LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../base/android
|
||||
|
||||
LOCAL_SRC_FILES := $(PROJECT_FILES)
|
||||
|
||||
LOCAL_LDLIBS := -landroid -llog -lz
|
||||
|
||||
LOCAL_DISABLE_FORMAT_STRING_CHECKS := true
|
||||
|
||||
LOCAL_STATIC_LIBRARIES += android_native_app_glue
|
||||
LOCAL_STATIC_LIBRARIES += cpufeatures
|
||||
LOCAL_STATIC_LIBRARIES += libassimp
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
$(call import-module, android/native_app_glue)
|
||||
$(call import-module, android/cpufeatures)
|
||||
5
android/computeparticles/jni/Application.mk
Normal file
5
android/computeparticles/jni/Application.mk
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
APP_PLATFORM := android-19
|
||||
APP_ABI := armeabi-v7a
|
||||
APP_STL := c++_static
|
||||
APP_CPPFLAGS := -std=c++11
|
||||
NDK_TOOLCHAIN_VERSION := clang
|
||||
|
|
@ -1,216 +0,0 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.24720.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "triangle", "triangle", "{1E7F5677-399F-4C32-B47D-F6497CEC8977}"
|
||||
EndProject
|
||||
Project("{39E2626F-3545-4960-A6E8-258AD8476CE5}") = "triangle.Packaging", "triangle\triangle.Packaging\triangle.Packaging.androidproj", "{740E3731-7142-4CC6-931A-32FF8D672FCA}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "triangle.NativeActivity", "triangle\triangle.NativeActivity\triangle.NativeActivity.vcxproj", "{622593A1-7B0D-4D71-8369-371601B8BEE1}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "texture", "texture", "{DE733C33-3FDC-4164-9FFA-65515BC9FBAB}"
|
||||
EndProject
|
||||
Project("{39E2626F-3545-4960-A6E8-258AD8476CE5}") = "texture.Packaging", "texture\texture.Packaging\texture.Packaging.androidproj", "{46AAFC56-77C9-4666-B7C0-959B9A6C3400}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "texture.NativeActivity", "texture\texture.NativeActivity\texture.NativeActivity.vcxproj", "{1A536FCE-940C-4184-86A7-808AC521B3C3}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "computeparticles", "computeparticles", "{DA3A5B44-6038-4656-A8B9-22944BD2917D}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "computeparticles.NativeActivity", "computeparticles\computeparticles.NativeActivity\computeparticles.NativeActivity.vcxproj", "{1C538546-0768-4071-81A6-86EE8F33AA1A}"
|
||||
EndProject
|
||||
Project("{39E2626F-3545-4960-A6E8-258AD8476CE5}") = "computeparticles.Packaging", "computeparticles\computeparticles.Packaging\computeparticles.Packaging.androidproj", "{07B432C0-5242-4EB4-982B-CA895D032AE5}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "mesh", "mesh", "{8E46E97F-B3AB-45B1-9C90-876A8D7C7DB6}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mesh.NativeActivity", "mesh\mesh.NativeActivity\mesh.NativeActivity.vcxproj", "{18423C3F-1E8D-4D48-829D-554EFAD2F17E}"
|
||||
EndProject
|
||||
Project("{39E2626F-3545-4960-A6E8-258AD8476CE5}") = "mesh.Packaging", "mesh\mesh.Packaging\mesh.Packaging.androidproj", "{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|ARM = Release|ARM
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Debug|x64.Build.0 = Debug|x64
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Debug|x86.Build.0 = Debug|x86
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Release|ARM.Build.0 = Release|ARM
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Release|x64.ActiveCfg = Release|x64
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Release|x64.Build.0 = Release|x64
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Release|x64.Deploy.0 = Release|x64
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Release|x86.ActiveCfg = Release|x86
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Release|x86.Build.0 = Release|x86
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA}.Release|x86.Deploy.0 = Release|x86
|
||||
{622593A1-7B0D-4D71-8369-371601B8BEE1}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{622593A1-7B0D-4D71-8369-371601B8BEE1}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{622593A1-7B0D-4D71-8369-371601B8BEE1}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{622593A1-7B0D-4D71-8369-371601B8BEE1}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{622593A1-7B0D-4D71-8369-371601B8BEE1}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{622593A1-7B0D-4D71-8369-371601B8BEE1}.Debug|x64.Build.0 = Debug|x64
|
||||
{622593A1-7B0D-4D71-8369-371601B8BEE1}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{622593A1-7B0D-4D71-8369-371601B8BEE1}.Debug|x86.Build.0 = Debug|x86
|
||||
{622593A1-7B0D-4D71-8369-371601B8BEE1}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{622593A1-7B0D-4D71-8369-371601B8BEE1}.Release|ARM.Build.0 = Release|ARM
|
||||
{622593A1-7B0D-4D71-8369-371601B8BEE1}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{622593A1-7B0D-4D71-8369-371601B8BEE1}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{622593A1-7B0D-4D71-8369-371601B8BEE1}.Release|x64.ActiveCfg = Release|x64
|
||||
{622593A1-7B0D-4D71-8369-371601B8BEE1}.Release|x64.Build.0 = Release|x64
|
||||
{622593A1-7B0D-4D71-8369-371601B8BEE1}.Release|x86.ActiveCfg = Release|x86
|
||||
{622593A1-7B0D-4D71-8369-371601B8BEE1}.Release|x86.Build.0 = Release|x86
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Debug|x64.Build.0 = Debug|x64
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Debug|x86.Build.0 = Debug|x86
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Release|ARM.Build.0 = Release|ARM
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Release|x64.ActiveCfg = Release|x64
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Release|x64.Build.0 = Release|x64
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Release|x64.Deploy.0 = Release|x64
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Release|x86.ActiveCfg = Release|x86
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Release|x86.Build.0 = Release|x86
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400}.Release|x86.Deploy.0 = Release|x86
|
||||
{1A536FCE-940C-4184-86A7-808AC521B3C3}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{1A536FCE-940C-4184-86A7-808AC521B3C3}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{1A536FCE-940C-4184-86A7-808AC521B3C3}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{1A536FCE-940C-4184-86A7-808AC521B3C3}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{1A536FCE-940C-4184-86A7-808AC521B3C3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{1A536FCE-940C-4184-86A7-808AC521B3C3}.Debug|x64.Build.0 = Debug|x64
|
||||
{1A536FCE-940C-4184-86A7-808AC521B3C3}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{1A536FCE-940C-4184-86A7-808AC521B3C3}.Debug|x86.Build.0 = Debug|x86
|
||||
{1A536FCE-940C-4184-86A7-808AC521B3C3}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{1A536FCE-940C-4184-86A7-808AC521B3C3}.Release|ARM.Build.0 = Release|ARM
|
||||
{1A536FCE-940C-4184-86A7-808AC521B3C3}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{1A536FCE-940C-4184-86A7-808AC521B3C3}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{1A536FCE-940C-4184-86A7-808AC521B3C3}.Release|x64.ActiveCfg = Release|x64
|
||||
{1A536FCE-940C-4184-86A7-808AC521B3C3}.Release|x64.Build.0 = Release|x64
|
||||
{1A536FCE-940C-4184-86A7-808AC521B3C3}.Release|x86.ActiveCfg = Release|x86
|
||||
{1A536FCE-940C-4184-86A7-808AC521B3C3}.Release|x86.Build.0 = Release|x86
|
||||
{1C538546-0768-4071-81A6-86EE8F33AA1A}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{1C538546-0768-4071-81A6-86EE8F33AA1A}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{1C538546-0768-4071-81A6-86EE8F33AA1A}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{1C538546-0768-4071-81A6-86EE8F33AA1A}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{1C538546-0768-4071-81A6-86EE8F33AA1A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{1C538546-0768-4071-81A6-86EE8F33AA1A}.Debug|x64.Build.0 = Debug|x64
|
||||
{1C538546-0768-4071-81A6-86EE8F33AA1A}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{1C538546-0768-4071-81A6-86EE8F33AA1A}.Debug|x86.Build.0 = Debug|x86
|
||||
{1C538546-0768-4071-81A6-86EE8F33AA1A}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{1C538546-0768-4071-81A6-86EE8F33AA1A}.Release|ARM.Build.0 = Release|ARM
|
||||
{1C538546-0768-4071-81A6-86EE8F33AA1A}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{1C538546-0768-4071-81A6-86EE8F33AA1A}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{1C538546-0768-4071-81A6-86EE8F33AA1A}.Release|x64.ActiveCfg = Release|x64
|
||||
{1C538546-0768-4071-81A6-86EE8F33AA1A}.Release|x64.Build.0 = Release|x64
|
||||
{1C538546-0768-4071-81A6-86EE8F33AA1A}.Release|x86.ActiveCfg = Release|x86
|
||||
{1C538546-0768-4071-81A6-86EE8F33AA1A}.Release|x86.Build.0 = Release|x86
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Debug|x64.Build.0 = Debug|x64
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Debug|x86.Build.0 = Debug|x86
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Release|ARM.Build.0 = Release|ARM
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Release|x64.ActiveCfg = Release|x64
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Release|x64.Build.0 = Release|x64
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Release|x64.Deploy.0 = Release|x64
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Release|x86.ActiveCfg = Release|x86
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Release|x86.Build.0 = Release|x86
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5}.Release|x86.Deploy.0 = Release|x86
|
||||
{18423C3F-1E8D-4D48-829D-554EFAD2F17E}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{18423C3F-1E8D-4D48-829D-554EFAD2F17E}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{18423C3F-1E8D-4D48-829D-554EFAD2F17E}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{18423C3F-1E8D-4D48-829D-554EFAD2F17E}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{18423C3F-1E8D-4D48-829D-554EFAD2F17E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{18423C3F-1E8D-4D48-829D-554EFAD2F17E}.Debug|x64.Build.0 = Debug|x64
|
||||
{18423C3F-1E8D-4D48-829D-554EFAD2F17E}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{18423C3F-1E8D-4D48-829D-554EFAD2F17E}.Debug|x86.Build.0 = Debug|x86
|
||||
{18423C3F-1E8D-4D48-829D-554EFAD2F17E}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{18423C3F-1E8D-4D48-829D-554EFAD2F17E}.Release|ARM.Build.0 = Release|ARM
|
||||
{18423C3F-1E8D-4D48-829D-554EFAD2F17E}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{18423C3F-1E8D-4D48-829D-554EFAD2F17E}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{18423C3F-1E8D-4D48-829D-554EFAD2F17E}.Release|x64.ActiveCfg = Release|x64
|
||||
{18423C3F-1E8D-4D48-829D-554EFAD2F17E}.Release|x64.Build.0 = Release|x64
|
||||
{18423C3F-1E8D-4D48-829D-554EFAD2F17E}.Release|x86.ActiveCfg = Release|x86
|
||||
{18423C3F-1E8D-4D48-829D-554EFAD2F17E}.Release|x86.Build.0 = Release|x86
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Debug|x64.Build.0 = Debug|x64
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Debug|x86.Build.0 = Debug|x86
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Release|ARM.Build.0 = Release|ARM
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Release|x64.ActiveCfg = Release|x64
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Release|x64.Build.0 = Release|x64
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Release|x64.Deploy.0 = Release|x64
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Release|x86.ActiveCfg = Release|x86
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Release|x86.Build.0 = Release|x86
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF}.Release|x86.Deploy.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{740E3731-7142-4CC6-931A-32FF8D672FCA} = {1E7F5677-399F-4C32-B47D-F6497CEC8977}
|
||||
{622593A1-7B0D-4D71-8369-371601B8BEE1} = {1E7F5677-399F-4C32-B47D-F6497CEC8977}
|
||||
{46AAFC56-77C9-4666-B7C0-959B9A6C3400} = {DE733C33-3FDC-4164-9FFA-65515BC9FBAB}
|
||||
{1A536FCE-940C-4184-86A7-808AC521B3C3} = {DE733C33-3FDC-4164-9FFA-65515BC9FBAB}
|
||||
{1C538546-0768-4071-81A6-86EE8F33AA1A} = {DA3A5B44-6038-4656-A8B9-22944BD2917D}
|
||||
{07B432C0-5242-4EB4-982B-CA895D032AE5} = {DA3A5B44-6038-4656-A8B9-22944BD2917D}
|
||||
{18423C3F-1E8D-4D48-829D-554EFAD2F17E} = {8E46E97F-B3AB-45B1-9C90-876A8D7C7DB6}
|
||||
{BAB95B1F-293D-440D-B19F-95FBFA3AA6EF} = {8E46E97F-B3AB-45B1-9C90-876A8D7C7DB6}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -110,7 +110,7 @@ public:
|
|||
void loadTextures()
|
||||
{
|
||||
textureLoader->loadTexture(
|
||||
"./../data/textures/particle01_rgba.ktx",
|
||||
getAssetPath() + "textures/particle01_rgba.ktx",
|
||||
VK_FORMAT_R8G8B8A8_UNORM,
|
||||
&textureColorMap,
|
||||
false);
|
||||
|
|
@ -530,8 +530,8 @@ public:
|
|||
// Load shaders
|
||||
std::array<VkPipelineShaderStageCreateInfo,2> shaderStages;
|
||||
|
||||
shaderStages[0] = loadShader("./../data/shaders/computeparticles/particle.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||
shaderStages[1] = loadShader("./../data/shaders/computeparticles/particle.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
shaderStages[0] = loadShader(getAssetPath() + "shaders/computeparticles/particle.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||
shaderStages[1] = loadShader(getAssetPath() + "shaders/computeparticles/particle.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipelineCreateInfo =
|
||||
vkTools::initializers::pipelineCreateInfo(
|
||||
|
|
@ -641,7 +641,7 @@ public:
|
|||
vkTools::initializers::computePipelineCreateInfo(
|
||||
computePipelineLayout,
|
||||
0);
|
||||
computePipelineCreateInfo.stage = loadShader("./../data/shaders/computeparticles/particle.comp.spv", VK_SHADER_STAGE_COMPUTE_BIT);
|
||||
computePipelineCreateInfo.stage = loadShader(getAssetPath() + "shaders/computeparticles/particle.comp.spv", VK_SHADER_STAGE_COMPUTE_BIT);
|
||||
err = vkCreateComputePipelines(device, pipelineCache, 1, &computePipelineCreateInfo, nullptr, &pipelines.compute);
|
||||
assert(!err);
|
||||
}
|
||||
|
|
@ -746,8 +746,7 @@ public:
|
|||
|
||||
VulkanExample *vulkanExample;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#if defined(_WIN32)
|
||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (vulkanExample != NULL)
|
||||
|
|
@ -765,9 +764,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
return (DefWindowProc(hWnd, uMsg, wParam, lParam));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#elif defined(__linux__) && !defined(__ANDROID__)
|
||||
static void handleEvent(const xcb_generic_event_t *event)
|
||||
{
|
||||
if (vulkanExample != NULL)
|
||||
|
|
@ -777,21 +774,42 @@ static void handleEvent(const xcb_generic_event_t *event)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
// Main entry point
|
||||
#if defined(_WIN32)
|
||||
// Windows entry point
|
||||
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow)
|
||||
#else
|
||||
#elif defined(__ANDROID__)
|
||||
// Android entry point
|
||||
void android_main(android_app* state)
|
||||
#elif defined(__linux__)
|
||||
// Linux entry point
|
||||
int main(const int argc, const char *argv[])
|
||||
#endif
|
||||
{
|
||||
#if defined(__ANDROID__)
|
||||
// Removing this may cause the compiler to omit the main entry point
|
||||
// which would make the application crash at start
|
||||
app_dummy();
|
||||
#endif
|
||||
vulkanExample = new VulkanExample();
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32)
|
||||
vulkanExample->setupWindow(hInstance, WndProc);
|
||||
#else
|
||||
#elif defined(__ANDROID__)
|
||||
// Attach vulkan example to global android application state
|
||||
state->userData = vulkanExample;
|
||||
state->onAppCmd = VulkanExample::handleAppCommand;
|
||||
state->onInputEvent = VulkanExample::handleAppInput;
|
||||
vulkanExample->androidApp = state;
|
||||
#elif defined(__linux__)
|
||||
vulkanExample->setupWindow();
|
||||
#endif
|
||||
#if !defined(__ANDROID__)
|
||||
vulkanExample->initSwapchain();
|
||||
vulkanExample->prepare();
|
||||
#endif
|
||||
vulkanExample->renderLoop();
|
||||
#if !defined(__ANDROID__)
|
||||
delete(vulkanExample);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue