Android support for Compute particles example, replacing separate Android version (#97)

This commit is contained in:
saschawillems 2016-03-23 22:17:14 +01:00
parent a8734f7f46
commit a9fe22426f
26 changed files with 142 additions and 3230 deletions

View file

@ -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, &copyRegion);
// 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;
}
};

View file

@ -0,0 +1 @@
_build computeparticles %1

10
android/computeparticles/.gitignore vendored Normal file
View file

@ -0,0 +1,10 @@
/assets/
/res/
/bin/
/libs/
/obj/
/build.xml
/local.properties
/project.properties
/proguard-project.txt
*.apk

View 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>

View 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..
)

View file

@ -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);
}

View file

@ -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 */

View file

@ -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>

View file

@ -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>

View file

@ -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, &currentBuffer);
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();
}
}

View file

@ -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"

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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

View file

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">VulkanComputeExample</string>
</resources>

View 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)

View 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

View file

@ -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

View file

@ -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
}