Merge branch 'master' into libktx

# Conflicts:
#	examples/texturemipmapgen/texturemipmapgen.cpp
This commit is contained in:
Sascha Willems 2019-12-07 16:04:45 +01:00
commit 3537d2cca2
12 changed files with 122 additions and 106 deletions

View file

@ -567,5 +567,36 @@ namespace vks
return (std::find(supportedExtensions.begin(), supportedExtensions.end(), extension) != supportedExtensions.end()); return (std::find(supportedExtensions.begin(), supportedExtensions.end(), extension) != supportedExtensions.end());
} }
/**
* Select the best-fit depth format for this device from a list of possible depth (and stencil) formats
*
* @param checkSamplingSupport Check if the format can be sampled from (e.g. for shader reads)
*
* @return The depth format that best fits for the current device
*
* @throw Throws an exception if no depth format fits the requirements
*/
VkFormat getSupportedDepthFormat(bool checkSamplingSupport)
{
// All depth formats may be optional, so we need to find a suitable depth format to use
std::vector<VkFormat> depthFormats = { VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D32_SFLOAT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D16_UNORM };
for (auto& format : depthFormats)
{
VkFormatProperties formatProperties;
vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties);
// Format must support depth stencil attachment for optimal tiling
if (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
{
if (checkSamplingSupport) {
if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
continue;
}
}
return format;
}
}
throw std::runtime_error("Could not find a matching depth format");
}
}; };
} }

View file

@ -351,10 +351,10 @@ namespace vks
VkBufferCopy copyRegion{}; VkBufferCopy copyRegion{};
copyRegion.size = vertices.size; copyRegion.size = vBufferSize;
vkCmdCopyBuffer(copyCmd, vertexStaging.buffer, vertices.buffer, 1, &copyRegion); vkCmdCopyBuffer(copyCmd, vertexStaging.buffer, vertices.buffer, 1, &copyRegion);
copyRegion.size = indices.size; copyRegion.size = iBufferSize;
vkCmdCopyBuffer(copyCmd, indexStaging.buffer, indices.buffer, 1, &copyRegion); vkCmdCopyBuffer(copyCmd, indexStaging.buffer, indices.buffer, 1, &copyRegion);
device->flushCommandBuffer(copyCmd, copyQueue); device->flushCommandBuffer(copyCmd, copyQueue);

View file

@ -1,7 +1,6 @@
#version 450 #version 450
layout (binding = 1) uniform sampler2D samplerColor; layout (binding = 1) uniform sampler2D samplerColor;
layout (binding = 2) uniform sampler2D samplerColorMap;
layout (location = 0) in vec2 inUV; layout (location = 0) in vec2 inUV;
layout (location = 1) in vec4 inPos; layout (location = 1) in vec4 inPos;
@ -21,8 +20,7 @@ void main()
// For demonstration purposes only // For demonstration purposes only
const float blurSize = 1.0 / 512.0; const float blurSize = 1.0 / 512.0;
vec4 color = texture(samplerColorMap, inUV); outFragColor = vec4(vec3(0.0), 1.);
outFragColor = color * 0.25;
if (gl_FrontFacing) if (gl_FrontFacing)
{ {
@ -35,6 +33,6 @@ void main()
reflection += texture(samplerColor, vec2(projCoord.s + x * blurSize, projCoord.t + y * blurSize)) / 49.0; reflection += texture(samplerColor, vec2(projCoord.s + x * blurSize, projCoord.t + y * blurSize)) / 49.0;
} }
} }
outFragColor += reflection * 1.5 * (color.r); outFragColor += reflection;
}; };
} }

View file

@ -412,9 +412,9 @@ public:
Pool Pool
*/ */
std::vector<VkDescriptorPoolSize> poolSizes = { std::vector<VkDescriptorPoolSize> poolSizes = {
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4), vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, attachments.size() + 1),
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 4), vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, attachments.size() + 1),
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 4), vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, attachments.size() * 2 + 1),
}; };
VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(static_cast<uint32_t>(poolSizes.size()), poolSizes.data(), 4); VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(static_cast<uint32_t>(poolSizes.size()), poolSizes.data(), 4);
VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool));

View file

@ -183,6 +183,7 @@ public:
VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{}; VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{};
memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV; memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
memoryRequirementsInfo.accelerationStructure = bottomLevelAS.accelerationStructure; memoryRequirementsInfo.accelerationStructure = bottomLevelAS.accelerationStructure;
VkMemoryRequirements2 memoryRequirements2{}; VkMemoryRequirements2 memoryRequirements2{};
@ -220,6 +221,7 @@ public:
VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{}; VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{};
memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV; memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
memoryRequirementsInfo.accelerationStructure = topLevelAS.accelerationStructure; memoryRequirementsInfo.accelerationStructure = topLevelAS.accelerationStructure;
VkMemoryRequirements2 memoryRequirements2{}; VkMemoryRequirements2 memoryRequirements2{};
@ -244,7 +246,7 @@ public:
*/ */
void createScene() void createScene()
{ {
// Setup vertices for a single uv-mapped quad made from two triangles // Setup vertices for a single triangle
struct Vertex { struct Vertex {
float pos[3]; float pos[3];
}; };
@ -336,7 +338,7 @@ public:
// Acceleration structure build requires some scratch space to store temporary information // Acceleration structure build requires some scratch space to store temporary information
VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{}; VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{};
memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV; memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV; memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
VkMemoryRequirements2 memReqBottomLevelAS; VkMemoryRequirements2 memReqBottomLevelAS;
memoryRequirementsInfo.accelerationStructure = bottomLevelAS.accelerationStructure; memoryRequirementsInfo.accelerationStructure = bottomLevelAS.accelerationStructure;

View file

@ -196,6 +196,7 @@ public:
VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{}; VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{};
memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV; memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
memoryRequirementsInfo.accelerationStructure = bottomLevelAS.accelerationStructure; memoryRequirementsInfo.accelerationStructure = bottomLevelAS.accelerationStructure;
VkMemoryRequirements2 memoryRequirements2{}; VkMemoryRequirements2 memoryRequirements2{};
@ -233,6 +234,7 @@ public:
VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{}; VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{};
memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV; memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
memoryRequirementsInfo.accelerationStructure = topLevelAS.accelerationStructure; memoryRequirementsInfo.accelerationStructure = topLevelAS.accelerationStructure;
VkMemoryRequirements2 memoryRequirements2{}; VkMemoryRequirements2 memoryRequirements2{};
@ -325,7 +327,7 @@ public:
// Acceleration structure build requires some scratch space to store temporary information // Acceleration structure build requires some scratch space to store temporary information
VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{}; VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{};
memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV; memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV; memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
VkMemoryRequirements2 memReqBottomLevelAS; VkMemoryRequirements2 memReqBottomLevelAS;
memoryRequirementsInfo.accelerationStructure = bottomLevelAS.accelerationStructure; memoryRequirementsInfo.accelerationStructure = bottomLevelAS.accelerationStructure;

View file

@ -197,6 +197,7 @@ public:
VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{}; VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{};
memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV; memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
memoryRequirementsInfo.accelerationStructure = bottomLevelAS.accelerationStructure; memoryRequirementsInfo.accelerationStructure = bottomLevelAS.accelerationStructure;
VkMemoryRequirements2 memoryRequirements2{}; VkMemoryRequirements2 memoryRequirements2{};
@ -234,6 +235,7 @@ public:
VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{}; VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{};
memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV; memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
memoryRequirementsInfo.accelerationStructure = topLevelAS.accelerationStructure; memoryRequirementsInfo.accelerationStructure = topLevelAS.accelerationStructure;
VkMemoryRequirements2 memoryRequirements2{}; VkMemoryRequirements2 memoryRequirements2{};
@ -334,7 +336,7 @@ public:
// Acceleration structure build requires some scratch space to store temporary information // Acceleration structure build requires some scratch space to store temporary information
VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{}; VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo{};
memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV; memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV; memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
VkMemoryRequirements2 memReqBottomLevelAS; VkMemoryRequirements2 memReqBottomLevelAS;
memoryRequirementsInfo.accelerationStructure = bottomLevelAS.accelerationStructure; memoryRequirementsInfo.accelerationStructure = bottomLevelAS.accelerationStructure;

View file

@ -19,7 +19,6 @@
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include "vulkanexamplebase.h" #include "vulkanexamplebase.h"
#include "VulkanTexture.hpp"
#include "VulkanModel.hpp" #include "VulkanModel.hpp"
#include "VulkanBuffer.hpp" #include "VulkanBuffer.hpp"
@ -34,10 +33,6 @@ class VulkanExample : public VulkanExampleBase
public: public:
bool debugDisplay = false; bool debugDisplay = false;
struct {
vks::Texture2D colorMap;
} textures;
// Vertex layout for the models // Vertex layout for the models
vks::VertexLayout vertexLayout = vks::VertexLayout({ vks::VertexLayout vertexLayout = vks::VertexLayout({
vks::VERTEX_COMPONENT_POSITION, vks::VERTEX_COMPONENT_POSITION,
@ -124,9 +119,6 @@ public:
// Clean up used Vulkan resources // Clean up used Vulkan resources
// Note : Inherited destructor cleans up resources stored in base class // Note : Inherited destructor cleans up resources stored in base class
// Textures
textures.colorMap.destroy();
// Frame buffer // Frame buffer
// Color attachment // Color attachment
@ -453,20 +445,6 @@ public:
{ {
models.plane.loadFromFile(getAssetPath() + "models/plane.obj", vertexLayout, 0.5f, vulkanDevice, queue); models.plane.loadFromFile(getAssetPath() + "models/plane.obj", vertexLayout, 0.5f, vulkanDevice, queue);
models.example.loadFromFile(getAssetPath() + "models/chinesedragon.dae", vertexLayout, 0.3f, vulkanDevice, queue); models.example.loadFromFile(getAssetPath() + "models/chinesedragon.dae", vertexLayout, 0.3f, vulkanDevice, queue);
// Textures
if (vulkanDevice->features.textureCompressionBC) {
textures.colorMap.loadFromFile(getAssetPath() + "textures/darkmetal_bc3_unorm.ktx", VK_FORMAT_BC3_UNORM_BLOCK, vulkanDevice, queue);
}
else if (vulkanDevice->features.textureCompressionASTC_LDR) {
textures.colorMap.loadFromFile(getAssetPath() + "textures/darkmetal_astc_8x8_unorm.ktx", VK_FORMAT_ASTC_8x8_UNORM_BLOCK, vulkanDevice, queue);
}
else if (vulkanDevice->features.textureCompressionETC2) {
textures.colorMap.loadFromFile(getAssetPath() + "textures/darkmetal_etc2_unorm.ktx", VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, vulkanDevice, queue);
}
else {
vks::tools::exitFatal("Device does not support any compressed texture format!", VK_ERROR_FEATURE_NOT_PRESENT);
}
} }
void generateQuad() void generateQuad()
@ -591,12 +569,6 @@ public:
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
1, 1,
&offscreenPass.descriptor), &offscreenPass.descriptor),
// Binding 2 : Fragment shader texture sampler
vks::initializers::writeDescriptorSet(
descriptorSets.mirror,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
2,
&textures.colorMap.descriptor)
}; };
vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL); vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL);
@ -625,7 +597,6 @@ public:
allocInfo.pSetLayouts = &descriptorSetLayouts.shaded; allocInfo.pSetLayouts = &descriptorSetLayouts.shaded;
// Model // Model
// No texture
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.model)); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.model));
std::vector<VkWriteDescriptorSet> modelWriteDescriptorSets = std::vector<VkWriteDescriptorSet> modelWriteDescriptorSets =

View file

@ -262,8 +262,7 @@ public:
*/ */
void prepareDepthPass() void prepareDepthPass()
{ {
VkFormat depthFormat; VkFormat depthFormat = vulkanDevice->getSupportedDepthFormat(true);
vks::tools::getSupportedDepthFormat(physicalDevice, &depthFormat);
/* /*
Depth map renderpass Depth map renderpass

View file

@ -68,15 +68,16 @@ subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
subresourceRange.levelCount = 1; subresourceRange.levelCount = 1;
subresourceRange.layerCount = 1; subresourceRange.layerCount = 1;
vkTools::setImageLayout( vks::tools::insertImageMemoryBarrier(
copyCmd, copyCmd,
texture.image, texture.image,
VK_IMAGE_ASPECT_COLOR_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_TRANSFER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
subresourceRange,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_HOST_BIT); VK_PIPELINE_STAGE_TRANSFER_BIT,
subresourceRange);
``` ```
### Generating the mip-chain ### Generating the mip-chain
@ -119,16 +120,17 @@ Before we can blit to this mip level, we need to transition it's image layout to
mipSubRange.levelCount = 1; mipSubRange.levelCount = 1;
mipSubRange.layerCount = 1; mipSubRange.layerCount = 1;
// Transiton current mip level to transfer dest // Prepare current mip level as image blit destination
vkTools::setImageLayout( vks::tools::insertImageMemoryBarrier(
blitCmd, blitCmd,
texture.image, texture.image,
VK_IMAGE_ASPECT_COLOR_BIT, 0,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
mipSubRange,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_HOST_BIT); VK_PIPELINE_STAGE_TRANSFER_BIT,
mipSubRange);
``` ```
Note that we set the ```baseMipLevel``` member of the subresource range so the image memory barrier will only affect the one mip level we want to copy to. Note that we set the ```baseMipLevel``` member of the subresource range so the image memory barrier will only affect the one mip level we want to copy to.
@ -150,15 +152,17 @@ Now that the mip level we want to copy from and the one we'll copy to have are i
After the blit is done we can use this mip level as a base for the next level, so we transition the layout from ```TRANSFER_DST_OPTIMAL``` to ```TRANSFER_SRC_OPTIMAL``` so we can use this level as transfer source for the next level: After the blit is done we can use this mip level as a base for the next level, so we transition the layout from ```TRANSFER_DST_OPTIMAL``` to ```TRANSFER_SRC_OPTIMAL``` so we can use this level as transfer source for the next level:
```cpp ```cpp
vkTools::setImageLayout( // Prepare current mip level as image blit source for next level
blitCmd, vks::tools::insertImageMemoryBarrier(
copyCmd,
texture.image, texture.image,
VK_IMAGE_ASPECT_COLOR_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_TRANSFER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
mipSubRange,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_HOST_BIT); VK_PIPELINE_STAGE_TRANSFER_BIT,
mipSubRange);
} }
``` ```
@ -167,15 +171,16 @@ Once the loop is done we need to transition all mip levels of the image to their
```cpp ```cpp
subresourceRange.levelCount = texture.mipLevels; subresourceRange.levelCount = texture.mipLevels;
vkTools::setImageLayout( vks::tools::insertImageMemoryBarrier(
blitCmd, copyCmd,
texture.image, texture.image,
VK_IMAGE_ASPECT_COLOR_BIT, VK_ACCESS_TRANSFER_READ_BIT,
VK_ACCESS_SHADER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
subresourceRange,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_HOST_BIT); VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
subresourceRange);
``` ```
Submitting that command buffer will result in an image with a complete mip-chain and all mip levels being transitioned to the proper image layout for shader reads. Submitting that command buffer will result in an image with a complete mip-chain and all mip levels being transitioned to the proper image layout for shader reads.

View file

@ -34,7 +34,6 @@ class VulkanExample : public VulkanExampleBase
public: public:
struct Texture { struct Texture {
VkImage image; VkImage image;
VkImageLayout imageLayout;
VkDeviceMemory deviceMemory; VkDeviceMemory deviceMemory;
VkImageView view; VkImageView view;
uint32_t width, height; uint32_t width, height;
@ -109,7 +108,14 @@ public:
models.tunnel.destroy(); models.tunnel.destroy();
} }
void loadTexture(std::string filename, VkFormat format, bool forceLinearTiling) virtual void getEnabledFeatures()
{
if (deviceFeatures.samplerAnisotropy) {
enabledFeatures.samplerAnisotropy = VK_TRUE;
}
}
void loadTexture(std::string fileName, VkFormat format, bool forceLinearTiling)
{ {
ktxResult result; ktxResult result;
ktxTexture* ktxTexture; ktxTexture* ktxTexture;
@ -137,6 +143,9 @@ public:
#endif #endif
assert(result == KTX_SUCCESS); assert(result == KTX_SUCCESS);
VkFormatProperties formatProperties;
VkFormatProperties formatProperties; VkFormatProperties formatProperties;
texture.width = ktxTexture->baseWidth; texture.width = ktxTexture->baseWidth;
@ -208,11 +217,15 @@ public:
subresourceRange.layerCount = 1; subresourceRange.layerCount = 1;
// Optimal image will be used as destination for the copy, so we must transfer from our initial undefined image layout to the transfer destination layout // Optimal image will be used as destination for the copy, so we must transfer from our initial undefined image layout to the transfer destination layout
vks::tools::setImageLayout( vks::tools::insertImageMemoryBarrier(
copyCmd, copyCmd,
texture.image, texture.image,
0,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
subresourceRange); subresourceRange);
// Copy the first mip of the chain, remaining mips will be generated // Copy the first mip of the chain, remaining mips will be generated
@ -228,12 +241,15 @@ public:
vkCmdCopyBufferToImage(copyCmd, stagingBuffer, texture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion); vkCmdCopyBufferToImage(copyCmd, stagingBuffer, texture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion);
// Transition first mip level to transfer source for read during blit // Transition first mip level to transfer source for read during blit
texture.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; vks::tools::insertImageMemoryBarrier(
vks::tools::setImageLayout(
copyCmd, copyCmd,
texture.image, texture.image,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_TRANSFER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
subresourceRange); subresourceRange);
VulkanExampleBase::flushCommandBuffer(copyCmd, queue, true); VulkanExampleBase::flushCommandBuffer(copyCmd, queue, true);
@ -276,15 +292,17 @@ public:
mipSubRange.levelCount = 1; mipSubRange.levelCount = 1;
mipSubRange.layerCount = 1; mipSubRange.layerCount = 1;
// Transiton current mip level to transfer dest // Prepare current mip level as image blit destination
vks::tools::setImageLayout( vks::tools::insertImageMemoryBarrier(
blitCmd, blitCmd,
texture.image, texture.image,
0,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
mipSubRange,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_HOST_BIT); VK_PIPELINE_STAGE_TRANSFER_BIT,
mipSubRange);
// Blit from previous level // Blit from previous level
vkCmdBlitImage( vkCmdBlitImage(
@ -297,24 +315,30 @@ public:
&imageBlit, &imageBlit,
VK_FILTER_LINEAR); VK_FILTER_LINEAR);
// Transiton current mip level to transfer source for read in next iteration // Prepare current mip level as image blit source for next level
vks::tools::setImageLayout( vks::tools::insertImageMemoryBarrier(
blitCmd, blitCmd,
texture.image, texture.image,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_TRANSFER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
mipSubRange, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT); mipSubRange);
} }
// After the loop, all mip layers are in TRANSFER_SRC layout, so transition all to SHADER_READ // After the loop, all mip layers are in TRANSFER_SRC layout, so transition all to SHADER_READ
subresourceRange.levelCount = texture.mipLevels; subresourceRange.levelCount = texture.mipLevels;
vks::tools::setImageLayout( vks::tools::insertImageMemoryBarrier(
blitCmd, blitCmd,
texture.image, texture.image,
VK_ACCESS_TRANSFER_READ_BIT,
VK_ACCESS_SHADER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
texture.imageLayout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
subresourceRange); subresourceRange);
VulkanExampleBase::flushCommandBuffer(blitCmd, queue, true); VulkanExampleBase::flushCommandBuffer(blitCmd, queue, true);
@ -543,34 +567,17 @@ public:
void setupDescriptorSet() void setupDescriptorSet()
{ {
VkDescriptorSetAllocateInfo allocInfo = VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout,1);
vks::initializers::descriptorSetAllocateInfo(
descriptorPool,
&descriptorSetLayout,
1);
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet));
std::vector<VkWriteDescriptorSet> writeDescriptorSets; VkDescriptorImageInfo textureDescriptor = vks::initializers::descriptorImageInfo(VK_NULL_HANDLE, texture.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
std::vector<VkWriteDescriptorSet> writeDescriptorSets = {
// Binding 0: Vertex shader uniform buffer // Binding 0: Vertex shader uniform buffer
writeDescriptorSets.push_back(vks::initializers::writeDescriptorSet( vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBufferVS.descriptor),
descriptorSet, // Binding 1: Sampled image
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, &textureDescriptor)
0, };
&uniformBufferVS.descriptor));
// Binding 1: Sampled image
VkDescriptorImageInfo textureDescriptor =
vks::initializers::descriptorImageInfo(
VK_NULL_HANDLE,
texture.view,
texture.imageLayout);
writeDescriptorSets.push_back(vks::initializers::writeDescriptorSet(
descriptorSet,
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
1,
&textureDescriptor));
// Binding 2: Sampler array // Binding 2: Sampler array
std::vector<VkDescriptorImageInfo> samplerDescriptors; std::vector<VkDescriptorImageInfo> samplerDescriptors;
@ -587,7 +594,6 @@ public:
samplerDescriptorWrite.dstBinding = 2; samplerDescriptorWrite.dstBinding = 2;
samplerDescriptorWrite.dstArrayElement = 0; samplerDescriptorWrite.dstArrayElement = 0;
writeDescriptorSets.push_back(samplerDescriptorWrite); writeDescriptorSets.push_back(samplerDescriptorWrite);
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL);
} }