Decoupled noise generation from 3D texture setup, added Android build files

This commit is contained in:
saschawillems 2016-09-10 20:49:14 +02:00
parent 56e35390df
commit 4db98481c0
9 changed files with 279 additions and 122 deletions

View file

@ -100,6 +100,7 @@ set(EXAMPLES
tessellation tessellation
textoverlay textoverlay
texture texture
texture3d
texturearray texturearray
texturecubemap texturecubemap
texturemipmapgen texturemipmapgen

View file

@ -35,3 +35,4 @@ call _build terraintessellation %1
call _build deferredshadows %1 call _build deferredshadows %1
call _build indirectdraw %1 call _build indirectdraw %1
call _build texturemipmapgen %1 call _build texturemipmapgen %1
call _build texture3d %1

10
android/texture3d/.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.vulkanTexture3d"
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="vulkanTexture3d" android:icon="@drawable/icon" android:hasCode="false">
<activity android:name="android.app.NativeActivity"
android:label="Texture3D"
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="vulkanTexture3d" />
<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,19 @@
cd jni
call ndk-build
if %ERRORLEVEL% EQU 0 (
cd..
mkdir "assets\shaders\base"
xcopy "..\..\data\shaders\base\*.spv" "assets\shaders\base" /Y
mkdir "assets\shaders\texture3d"
xcopy "..\..\data\shaders\texture3d\*.spv" "assets\shaders\texture3d" /Y
mkdir "res\drawable"
xcopy "..\..\android\images\icon.png" "res\drawable" /Y
call ant debug -Dout.final.file=vulkanTexture3d.apk
) ELSE (
echo error : ndk-build failed with errors!
cd..
)

View file

@ -0,0 +1,48 @@
LOCAL_PATH := $(call my-dir)/../../texture3d
# 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 := vulkanTexture3d
PROJECT_FILES := $(wildcard $(LOCAL_PATH)/../../texture3d/*.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_DISABLE_FATAL_LINKER_WARNINGS := 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

@ -42,6 +42,7 @@ adb uninstall de.saschawillems.vulkanTerraintessellation
adb uninstall de.saschawillems.vulkanDeferredshadows adb uninstall de.saschawillems.vulkanDeferredshadows
adb uninstall de.saschawillems.vulkanIndirectdraw adb uninstall de.saschawillems.vulkanIndirectdraw
adb uninstall de.saschawillems.vulkanTexturemipmapgen adb uninstall de.saschawillems.vulkanTexturemipmapgen
adb uninstall de.saschawillems.vulkanTexture3d
goto finish goto finish
:exit :exit

View file

@ -61,7 +61,7 @@ public:
PerlinNoise() PerlinNoise()
{ {
// Generate random lookup for permutations containing all numbers from 0..255 // Generate random lookup for permutations containing all numbers from 0..255
std::vector<byte> plookup; std::vector<uint8_t> plookup;
plookup.resize(256); plookup.resize(256);
std::iota(plookup.begin(), plookup.end(), 0); std::iota(plookup.begin(), plookup.end(), 0);
std::default_random_engine rndEngine(std::random_device{}()); std::default_random_engine rndEngine(std::random_device{}());
@ -147,16 +147,23 @@ class VulkanExample : public VulkanExampleBase
public: public:
// Contains all Vulkan objects that are required to store and use a 3D texture // Contains all Vulkan objects that are required to store and use a 3D texture
struct Texture { struct Texture {
VkSampler sampler; VkSampler sampler = VK_NULL_HANDLE;
VkImage image; VkImage image = VK_NULL_HANDLE;
VkImageLayout imageLayout; VkImageLayout imageLayout;
VkDeviceMemory deviceMemory; VkDeviceMemory deviceMemory = VK_NULL_HANDLE;
VkImageView view; VkImageView view = VK_NULL_HANDLE;
VkDescriptorImageInfo descriptor; VkDescriptorImageInfo descriptor;
VkFormat format;
uint32_t width, height, depth; uint32_t width, height, depth;
uint32_t mipLevels; uint32_t mipLevels;
} texture; } texture;
bool regenerateNoise = true;
struct {
vkMeshLoader::MeshBuffer cube;
} meshes;
struct { struct {
VkPipelineVertexInputStateCreateInfo inputState; VkPipelineVertexInputStateCreateInfo inputState;
std::vector<VkVertexInputBindingDescription> inputBinding; std::vector<VkVertexInputBindingDescription> inputBinding;
@ -169,7 +176,7 @@ public:
vk::Buffer uniformBufferVS; vk::Buffer uniformBufferVS;
struct { struct UboVS {
glm::mat4 projection; glm::mat4 projection;
glm::mat4 model; glm::mat4 model;
glm::vec4 viewPos; glm::vec4 viewPos;
@ -190,6 +197,7 @@ public:
rotation = { 0.0f, 15.0f, 0.0f }; rotation = { 0.0f, 15.0f, 0.0f };
title = "Vulkan Example - 3D textures"; title = "Vulkan Example - 3D textures";
enableTextOverlay = true; enableTextOverlay = true;
srand(std::time(0));
} }
~VulkanExample() ~VulkanExample()
@ -209,35 +217,137 @@ public:
uniformBufferVS.destroy(); uniformBufferVS.destroy();
} }
// Generate 3D fractal noise // Prepare all Vulkan resources for the 3D texture (including descriptors)
void generateNoise3D(byte *data, uint32_t width, uint32_t height, uint32_t depth) // Does not fill the texture with data
void prepareNoiseTexture(uint32_t width, uint32_t height, uint32_t depth)
{ {
std::cout << "Generating " << width << " x " << height << " x " << depth << " noise texture..." << std::endl; // A 3D texture is described as width x height x depth
texture.width = width;
texture.height = height;
texture.depth = depth;
texture.mipLevels = 1;
texture.format = VK_FORMAT_R8_UNORM;
// Format support check
// 3D texture support in Vulkan is mandatory (in contrast to OpenGL) so no need to check if it's supported
VkFormatProperties formatProperties;
vkGetPhysicalDeviceFormatProperties(physicalDevice, texture.format, &formatProperties);
// Check if format supports transfer
if (!formatProperties.optimalTilingFeatures & VK_IMAGE_USAGE_TRANSFER_DST_BIT)
{
std::cout << "Error: Device does not support flag TRANSFER_DST for selected texture format!" << std::endl;
return;
}
// Check if GPU supports requested 3D texture dimensions
uint32_t maxImageDimension3D(vulkanDevice->properties.limits.maxImageDimension3D);
if (width > maxImageDimension3D || height > maxImageDimension3D || depth > maxImageDimension3D)
{
std::cout << "Error: Requested texture dimensions is greater than supported 3D texture dimension!" << std::endl;
return;
}
// Create optimal tiled target image
VkImageCreateInfo imageCreateInfo = vkTools::initializers::imageCreateInfo();
imageCreateInfo.imageType = VK_IMAGE_TYPE_3D;
imageCreateInfo.format = texture.format;
imageCreateInfo.mipLevels = texture.mipLevels;
imageCreateInfo.arrayLayers = 1;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageCreateInfo.extent.width = texture.width;
imageCreateInfo.extent.height = texture.width;
imageCreateInfo.extent.depth = texture.depth;
// Set initial layout of the image to undefined
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &texture.image));
// Device local memory to back up image
VkMemoryAllocateInfo memAllocInfo = vkTools::initializers::memoryAllocateInfo();
VkMemoryRequirements memReqs = {};
vkGetImageMemoryRequirements(device, texture.image, &memReqs);
memAllocInfo.allocationSize = memReqs.size;
memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &texture.deviceMemory));
VK_CHECK_RESULT(vkBindImageMemory(device, texture.image, texture.deviceMemory, 0));
// Create sampler
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 = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
sampler.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
sampler.mipLodBias = 0.0f;
sampler.compareOp = VK_COMPARE_OP_NEVER;
sampler.minLod = 0.0f;
sampler.maxLod = 0.0f;
sampler.maxAnisotropy = 1.0;
sampler.anisotropyEnable = VK_FALSE;
sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &texture.sampler));
// Create image view
VkImageViewCreateInfo view = vkTools::initializers::imageViewCreateInfo();
view.image = texture.image;
view.viewType = VK_IMAGE_VIEW_TYPE_3D;
view.format = texture.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;
view.subresourceRange.levelCount = 1;
VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &texture.view));
// Fill image descriptor image info to be used descriptor set setup
texture.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
texture.descriptor.imageView = texture.view;
texture.descriptor.sampler = texture.sampler;
}
// Generate randomized noise and upload it to the 3D texture using staging
void updateNoiseTexture()
{
const uint32_t texMemSize = texture.width * texture.height * texture.depth;
uint8_t *data = new uint8_t[texMemSize];
memset(data, 0, texMemSize);
// Generate perlin based noise
std::cout << "Generating " << texture.width << " x " << texture.height << " x " << texture.depth << " noise texture..." << std::endl;
auto tStart = std::chrono::high_resolution_clock::now(); auto tStart = std::chrono::high_resolution_clock::now();
PerlinNoise<float> perlinNoise; PerlinNoise<float> perlinNoise;
FractalNoise<float> fractalNoise(perlinNoise); FractalNoise<float> fractalNoise(perlinNoise);
std::default_random_engine rndEngine(std::random_device{}());
const int32_t noiseType = rand() % 2;
const float noiseScale = static_cast<float>(rand() % 10) + 4.0f;
#pragma omp parallel for #pragma omp parallel for
for (int32_t z = 0; z < depth; z++) for (int32_t z = 0; z < texture.depth; z++)
{ {
for (int32_t y = 0; y < height; y++) for (int32_t y = 0; y < texture.height; y++)
{ {
for (int32_t x = 0; x < width; x++) for (int32_t x = 0; x < texture.width; x++)
{ {
float nx = (float)x / (float)width; float nx = (float)x / (float)texture.width;
float ny = (float)y / (float)height; float ny = (float)y / (float)texture.height;
float nz = (float)z / (float)depth; float nz = (float)z / (float)texture.depth;
#define FRACTAL #define FRACTAL
#ifdef FRACTAL #ifdef FRACTAL
float n = fractalNoise.noise(nx * 10, ny * 10, nz * 10); float n = fractalNoise.noise(nx * noiseScale, ny * noiseScale, nz * noiseScale);
#else #else
float n = 20.0 * perlinNoise.noise(nx, ny, nz); float n = 20.0 * perlinNoise.noise(nx, ny, nz);
#endif #endif
n = n - floor(n); n = n - floor(n);
data[x + y * width + z * width * height] = floor(n * 255); data[x + y * texture.width + z * texture.width * texture.height] = static_cast<uint8_t>(floor(n * 255));
} }
} }
} }
@ -246,44 +356,21 @@ public:
auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count(); auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count();
std::cout << "Done in " << tDiff << "ms" << std::endl; std::cout << "Done in " << tDiff << "ms" << std::endl;
}
void generateNoiseTexture(uint32_t width, uint32_t height, uint32_t depth)
{
const uint32_t texMemSize = width * height * depth;
const VkFormat texFormat = VK_FORMAT_R8_UNORM;
byte *data = new byte[texMemSize];
memset(data, 0, texMemSize);
generateNoise3D(data, width, height, depth);
VkFormatProperties formatProperties;
// A 3D texture is described as width x height x depth
texture.width = width;
texture.height = height;
texture.depth = depth;
texture.mipLevels = 1;
// Get device properites for the requested texture format
vkGetPhysicalDeviceFormatProperties(physicalDevice, texFormat, &formatProperties);
VkMemoryAllocateInfo memAllocInfo = vkTools::initializers::memoryAllocateInfo();
VkMemoryRequirements memReqs = {};
// Create a host-visible staging buffer that contains the raw image data // Create a host-visible staging buffer that contains the raw image data
VkBuffer stagingBuffer; VkBuffer stagingBuffer;
VkDeviceMemory stagingMemory; VkDeviceMemory stagingMemory;
// Buffer // Buffer object
VkBufferCreateInfo bufferCreateInfo = vkTools::initializers::bufferCreateInfo(); VkBufferCreateInfo bufferCreateInfo = vkTools::initializers::bufferCreateInfo();
bufferCreateInfo.size = texMemSize; bufferCreateInfo.size = texMemSize;
bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &stagingBuffer)); VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &stagingBuffer));
// Allocate host visible memory for data upload // Allocate host visible memory for data upload
VkMemoryAllocateInfo memAllocInfo = vkTools::initializers::memoryAllocateInfo();
VkMemoryRequirements memReqs = {};
vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs); vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs);
memAllocInfo.allocationSize = memReqs.size; memAllocInfo.allocationSize = memReqs.size;
memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
@ -296,31 +383,6 @@ public:
memcpy(mapped, data, texMemSize); memcpy(mapped, data, texMemSize);
vkUnmapMemory(device, stagingMemory); vkUnmapMemory(device, stagingMemory);
// Create optimal tiled target image
VkImageCreateInfo imageCreateInfo = vkTools::initializers::imageCreateInfo();
imageCreateInfo.imageType = VK_IMAGE_TYPE_3D;
imageCreateInfo.format = texFormat;
imageCreateInfo.mipLevels = texture.mipLevels;
imageCreateInfo.arrayLayers = 1;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
// A 3D texture is described as width x height x depth
imageCreateInfo.extent.width = texture.width;
imageCreateInfo.extent.height = texture.width;
imageCreateInfo.extent.depth = texture.depth;
// Set initial layout of the image to undefined
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &texture.image));
vkGetImageMemoryRequirements(device, texture.image, &memReqs);
memAllocInfo.allocationSize = memReqs.size;
memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &texture.deviceMemory));
VK_CHECK_RESULT(vkBindImageMemory(device, texture.image, texture.deviceMemory, 0));
VkCommandBuffer copyCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); VkCommandBuffer copyCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
// Image barrier for optimal image // Image barrier for optimal image
@ -378,50 +440,19 @@ public:
delete[] data; delete[] data;
vkFreeMemory(device, stagingMemory, nullptr); vkFreeMemory(device, stagingMemory, nullptr);
vkDestroyBuffer(device, stagingBuffer, nullptr); vkDestroyBuffer(device, stagingBuffer, nullptr);
regenerateNoise = false;
// Create sampler
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_MIRRORED_REPEAT;
sampler.addressModeV = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
sampler.addressModeW = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
sampler.mipLodBias = 0.0f;
sampler.compareOp = VK_COMPARE_OP_NEVER;
sampler.minLod = 0.0f;
sampler.maxLod = 0.0f;
sampler.maxAnisotropy = 1.0;
sampler.anisotropyEnable = VK_FALSE;
sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &texture.sampler));
// Create image view
VkImageViewCreateInfo view = vkTools::initializers::imageViewCreateInfo();
view.image = VK_NULL_HANDLE;
view.viewType = VK_IMAGE_VIEW_TYPE_3D;
view.format = texFormat;
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;
view.subresourceRange.levelCount = 1;
view.image = texture.image;
VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &texture.view));
// Fill image descriptor image info that can be used during the descriptor set setup
texture.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
texture.descriptor.imageView = texture.view;
texture.descriptor.sampler = texture.sampler;
} }
// Free all Vulkan resources used a texture object // Free all Vulkan resources used a texture object
void destroyTextureImage(Texture texture) void destroyTextureImage(Texture texture)
{ {
if (texture.view != VK_NULL_HANDLE)
vkDestroyImageView(device, texture.view, nullptr); vkDestroyImageView(device, texture.view, nullptr);
if (texture.image != VK_NULL_HANDLE)
vkDestroyImage(device, texture.image, nullptr); vkDestroyImage(device, texture.image, nullptr);
if (texture.sampler != VK_NULL_HANDLE)
vkDestroySampler(device, texture.sampler, nullptr); vkDestroySampler(device, texture.sampler, nullptr);
if (texture.deviceMemory != VK_NULL_HANDLE)
vkFreeMemory(device, texture.deviceMemory, nullptr); vkFreeMemory(device, texture.deviceMemory, nullptr);
} }
@ -463,7 +494,6 @@ public:
VkDeviceSize offsets[1] = { 0 }; VkDeviceSize offsets[1] = { 0 };
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &vertexBuffer.buffer, offsets); vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &vertexBuffer.buffer, offsets);
vkCmdBindIndexBuffer(drawCmdBuffers[i], indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32); vkCmdBindIndexBuffer(drawCmdBuffers[i], indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(drawCmdBuffers[i], indexCount, 1, 0, 0, 0); vkCmdDrawIndexed(drawCmdBuffers[i], indexCount, 1, 0, 0, 0);
vkCmdEndRenderPass(drawCmdBuffers[i]); vkCmdEndRenderPass(drawCmdBuffers[i]);
@ -691,8 +721,8 @@ public:
// Load shaders // Load shaders
std::array<VkPipelineShaderStageCreateInfo,2> shaderStages; std::array<VkPipelineShaderStageCreateInfo,2> shaderStages;
shaderStages[0] = loadShader(getAssetPath() + "shaders/texture3D/texture3D.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages[0] = loadShader(getAssetPath() + "shaders/texture3d/texture3d.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
shaderStages[1] = loadShader(getAssetPath() + "shaders/texture3D/texture3D.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); shaderStages[1] = loadShader(getAssetPath() + "shaders/texture3d/texture3d.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
VkGraphicsPipelineCreateInfo pipelineCreateInfo = VkGraphicsPipelineCreateInfo pipelineCreateInfo =
vkTools::initializers::pipelineCreateInfo( vkTools::initializers::pipelineCreateInfo(
@ -745,8 +775,8 @@ public:
else else
{ {
uboVS.depth += frameTimer * 0.15f; uboVS.depth += frameTimer * 0.15f;
if (uboVS.depth > 2.0f) if (uboVS.depth > 1.0f)
uboVS.depth = uboVS.depth - 2.0f; uboVS.depth = uboVS.depth - 1.0f;
} }
VK_CHECK_RESULT(uniformBufferVS.map()); VK_CHECK_RESULT(uniformBufferVS.map());
@ -760,7 +790,7 @@ public:
generateQuad(); generateQuad();
setupVertexDescriptions(); setupVertexDescriptions();
prepareUniformBuffers(); prepareUniformBuffers();
generateNoiseTexture(256, 256, 256); prepareNoiseTexture(256, 256, 256);
setupDescriptorSetLayout(); setupDescriptorSetLayout();
preparePipelines(); preparePipelines();
setupDescriptorPool(); setupDescriptorPool();
@ -774,6 +804,10 @@ public:
if (!prepared) if (!prepared)
return; return;
draw(); draw();
if (regenerateNoise)
{
updateNoiseTexture();
}
if (!paused) if (!paused)
updateUniformBuffers(false); updateUniformBuffers(false);
} }
@ -787,21 +821,32 @@ public:
{ {
switch (keyCode) switch (keyCode)
{ {
case KEY_KPADD: case KEY_N:
case GAMEPAD_BUTTON_R1: case GAMEPAD_BUTTON_A:
break; if (!regenerateNoise)
case KEY_KPSUB: {
case GAMEPAD_BUTTON_L1: regenerateNoise = true;
updateTextOverlay();
}
break; break;
} }
} }
virtual void getOverlayText(VulkanTextOverlay *textOverlay) virtual void getOverlayText(VulkanTextOverlay *textOverlay)
{ {
#if defined(__ANDROID__) if (regenerateNoise)
{
textOverlay->addText("Generating new noise texture...", 5.0f, 85.0f, VulkanTextOverlay::alignLeft);
}
else
{
#ifdef __ANDROID__
textOverlay->addText("Press \"Button A\" to generate new noise", 5.0f, 85.0f, VulkanTextOverlay::alignLeft);
#else #else
textOverlay->addText("Press \"n\" to generate new noise", 5.0f, 85.0f, VulkanTextOverlay::alignLeft);
#endif #endif
} }
}
}; };
VULKAN_EXAMPLE_MAIN() VULKAN_EXAMPLE_MAIN()