File size: 4,670 Bytes
a95d691 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | // Copyright 2018-2020 The Khronos Group Inc.
// SPDX-License-Identifier: Apache-2.0
#include <vulkan/vulkan.h>
#include <ktxvulkan.h>
// Use c++ to keep the example short. Not required.
#include <vulkan/vulkan.hpp>
class Texture {
public:
Texture(const std::string ktxfile);
~Texture();
protected:
ktxVulkanTexture texture;
vk::PhysicalDevice gpu;
vk::Device device;
vk::Queue queue;
vk::CommandPool commandPool;
cleanup();
prepareSamplerAndView();
};
Texture::Texture(const std::string ktxfile)
{
ktxVulkanDeviceInfo kvdi;
ktxTexture* kTexture;
KTX_error_code ktxresult;
createVulkanInstance();
findVulkanGpu(); // Find a suitable physical device
createVulkanSurface();
createVulkanDevice();
prepareVulkanSwapchain();
/*
.
.
.
*/
// This structure is used to pass the Vulkan device information to the loader
// with the expectation that app's will typically load many textures.
ktxVulkanDeviceInfo_Construct(&kvdi, gpu, device, queue, commandPool, nullptr);
ktxresult = ktxTexture_CreateFromNamedFile(
(getAssetPath() + ktxfile).c_str(),
KTX_TEXTURE_CREATE_NO_FLAGS,
&kTexture);
if (KTX_SUCCESS != ktxresult) {
std::stringstream message;
message << "Creation of ktxTexture from \"" << getAssetPath()
<< ktxfile << "\" failed: " << ktxErrorString(ktxresult);
throw std::runtime_error(message.str());
}
ktxresult = ktxTexture_VkUploadEx(kTexture, &kvdi, &texture,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
if (KTX_SUCCESS != ktxresult) {
std::stringstream message;
message << "ktxTexture_VkUpload failed: " << ktxErrorString(ktxresult);
throw std::runtime_error(message.str());
}
char* pValue;
uint32_t valueLen;
if (KTX_SUCCESS == ktxHashTable_FindValue(&kTexture->kvDataHead,
KTX_ORIENTATION_KEY,
&valueLen, (void**)&pValue))
{
char s, t;
if (sscanf(pValue, KTX_ORIENTATION2_FMT, &s, &t) == 2) {
if (s == 'l') sign_s = -1;
if (t == 'u') sign_t = -1;
}
}
ktxTexture_Destroy(kTexture);
ktxVulkanDeviceInfo_destruct(&kvdi);
try {
prepareSamplerAndView(); // See below for implementation.
// Setup a layout with, e.g., a binding for a combined image-sampler.
setupDescriptorSetLayout();
// Create a descriptor set and update it with the sampler and image view handles.
setupDescriptorSet();
preparePipelines();
setupDescriptorPool();
setupDescriptorSet();
buildCommandBuffers();
} catch (std::exception&) {
cleanup();
throw;
}
}
Texture::~Texture()
{
cleanup();
}
Texture::cleanup()
{
destroyCommandBuffers();
destroySampler();
destroyImageview();
ktxVulkanTexture_destruct(&texture, device, nullptr);
/*
.
.
.
*/
}
void
Texture::prepareSamplerAndView()
{
// Create sampler.
vk::SamplerCreateInfo samplerInfo;
// Set the non-default values
samplerInfo.magFilter = vk::Filter::eLinear;
samplerInfo.minFilter = vk::Filter::eLinear;
samplerInfo.mipmapMode = vk::SamplerMipmapMode::eLinear;
samplerInfo.maxLod = texture.levelCount;
samplerInfo.anisotropyEnable = false;
samplerInfo.maxAnisotropy = 1.0;
samplerInfo.borderColor = vk::BorderColor::eFloatOpaqueWhite;
sampler = vkctx.device.createSampler(samplerInfo);
// Create image view.
// Textures are not directly accessed by the shaders and are abstracted
// by image views containing additional information and sub resource
// ranges.
vk::ImageViewCreateInfo viewInfo;
// Set the non-default values.
viewInfo.image = texture.image;
viewInfo.format = static_cast<vk::Format>(texture.imageFormat);
viewInfo.viewType = static_cast<vk::ImageViewType>(texture.viewType);
viewInfo.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
viewInfo.subresourceRange.layerCount = texture.layerCount;
viewInfo.subresourceRange.levelCount = texture.levelCount;
imageView = vkctx.device.createImageView(viewInfo);
}
/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
|