Decoupled noise generation from 3D texture setup, added Android build files
This commit is contained in:
parent
56e35390df
commit
4db98481c0
9 changed files with 279 additions and 122 deletions
|
|
@ -100,6 +100,7 @@ set(EXAMPLES
|
||||||
tessellation
|
tessellation
|
||||||
textoverlay
|
textoverlay
|
||||||
texture
|
texture
|
||||||
|
texture3d
|
||||||
texturearray
|
texturearray
|
||||||
texturecubemap
|
texturecubemap
|
||||||
texturemipmapgen
|
texturemipmapgen
|
||||||
|
|
|
||||||
|
|
@ -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
10
android/texture3d/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
/assets/
|
||||||
|
/res/
|
||||||
|
/bin/
|
||||||
|
/libs/
|
||||||
|
/obj/
|
||||||
|
/build.xml
|
||||||
|
/local.properties
|
||||||
|
/project.properties
|
||||||
|
/proguard-project.txt
|
||||||
|
*.apk
|
||||||
27
android/texture3d/AndroidManifest.xml
Normal file
27
android/texture3d/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="de.saschawillems.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>
|
||||||
19
android/texture3d/build.bat
Normal file
19
android/texture3d/build.bat
Normal 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..
|
||||||
|
)
|
||||||
48
android/texture3d/jni/Android.mk
Normal file
48
android/texture3d/jni/Android.mk
Normal 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)
|
||||||
5
android/texture3d/jni/Application.mk
Normal file
5
android/texture3d/jni/Application.mk
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
APP_PLATFORM := android-19
|
||||||
|
APP_ABI := armeabi-v7a
|
||||||
|
APP_STL := c++_static
|
||||||
|
APP_CPPFLAGS := -std=c++11
|
||||||
|
NDK_TOOLCHAIN_VERSION := clang
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue