Vulkan lod mipmaps
This commit is contained in:
parent
a408a475f5
commit
9465083742
|
@ -18,8 +18,8 @@ inline glm::vec4 fromHex(const std::string& str) {
|
||||||
}
|
}
|
||||||
inline std::string toHexa(const glm::vec4& rgb) {
|
inline std::string toHexa(const glm::vec4& rgb) {
|
||||||
std::ostringstream sstr;
|
std::ostringstream sstr;
|
||||||
sstr << std::hex << std::setw(2) << std::setfill('0') <<
|
sstr << '#' << std::hex << std::setw(2) << std::setfill('0') <<
|
||||||
static_cast<int>(rgb.x * UCHAR_MAX) << static_cast<int>(rgb.y * UCHAR_MAX) << static_cast<int>(rgb.z * UCHAR_MAX) << std::endl;
|
static_cast<int>(rgb.x * UCHAR_MAX) << static_cast<int>(rgb.y * UCHAR_MAX) << static_cast<int>(rgb.z * UCHAR_MAX);
|
||||||
return sstr.str();
|
return sstr.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,12 +40,12 @@ std::optional<Image::properties> Image::Read(const std::string& imagepath, std::
|
||||||
info.size.height = *(unsigned int*)&(header[8 ]);
|
info.size.height = *(unsigned int*)&(header[8 ]);
|
||||||
info.size.width = *(unsigned int*)&(header[12]);
|
info.size.width = *(unsigned int*)&(header[12]);
|
||||||
unsigned int linearSize = *(unsigned int*)&(header[16]);
|
unsigned int linearSize = *(unsigned int*)&(header[16]);
|
||||||
info.mipMap = *(unsigned int*)&(header[24]);
|
info.mipmapLevels = *(unsigned int*)&(header[24]);
|
||||||
unsigned int fourCC = *(unsigned int*)&(header[80]);
|
unsigned int fourCC = *(unsigned int*)&(header[80]);
|
||||||
|
|
||||||
|
|
||||||
/* how big is it going to be including all mipmaps? */
|
/* how big is it going to be including all mipmaps? */
|
||||||
unsigned int bufsize = info.mipMap > 1 ? linearSize * 2 : linearSize;
|
unsigned int bufsize = info.mipmapLevels > 1 ? linearSize * 2 : linearSize;
|
||||||
data.resize(bufsize);
|
data.resize(bufsize);
|
||||||
fread(data.data(), 1, bufsize, fp);
|
fread(data.data(), 1, bufsize, fp);
|
||||||
/* close the file pointer */
|
/* close the file pointer */
|
||||||
|
@ -53,9 +53,6 @@ std::optional<Image::properties> Image::Read(const std::string& imagepath, std::
|
||||||
|
|
||||||
switch(fourCC)
|
switch(fourCC)
|
||||||
{
|
{
|
||||||
case FOURCC_DXT1:
|
|
||||||
info.format = Format::BC1;
|
|
||||||
break;
|
|
||||||
case FOURCC_DXT3:
|
case FOURCC_DXT3:
|
||||||
info.format = Format::BC2;
|
info.format = Format::BC2;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -17,15 +17,14 @@ public:
|
||||||
};
|
};
|
||||||
// NOTE: matches VkFormat
|
// NOTE: matches VkFormat
|
||||||
enum class Format {
|
enum class Format {
|
||||||
/// DXT1 RGBA SRGB
|
|
||||||
BC1 = 134,
|
|
||||||
/// DXT3 RGBA SRGB
|
/// DXT3 RGBA SRGB
|
||||||
BC2 = 136,
|
BC2 = 136,
|
||||||
/// DXT1 RGBA SRGB
|
/// DXT5 RGBA SRGB
|
||||||
BC3 = 138,
|
BC3 = 138,
|
||||||
// MAYBE: R8G8B8A8
|
// MAYBE: R8G8B8A8
|
||||||
// MAYBE: For HDR BC6H_SFLOAT = 144,
|
// MAYBE: For HDR BC6H_SFLOAT = 144,
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE: matches VkImageLayout
|
// NOTE: matches VkImageLayout
|
||||||
enum class Layout {
|
enum class Layout {
|
||||||
UNDEFINED = 0,
|
UNDEFINED = 0,
|
||||||
|
@ -68,15 +67,20 @@ public:
|
||||||
|
|
||||||
struct properties {
|
struct properties {
|
||||||
frame size;
|
frame size;
|
||||||
uint32_t mipMap;
|
uint32_t mipmapLevels;
|
||||||
Format format;
|
Format format;
|
||||||
};
|
};
|
||||||
struct requirement {
|
struct requirement: properties {
|
||||||
properties props;
|
requirement(const properties& props, Layout layout, Usage usage, Aspect aspect,
|
||||||
|
bool optimal = true): properties(props), layout(layout), usage(usage),
|
||||||
|
aspect(aspect), optimal(optimal) { }
|
||||||
Layout layout;
|
Layout layout;
|
||||||
Usage usage;
|
Usage usage;
|
||||||
bool linear = false;
|
Aspect aspect;
|
||||||
Aspect aspect = Aspect::COLOR;
|
bool optimal;
|
||||||
|
|
||||||
|
static requirement Texture(const properties &props) {
|
||||||
|
return requirement(props, Layout::SHADER_READ_ONLY, Usage::SAMPLED, Aspect::COLOR); }
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::optional<properties> Read(const std::string&, std::vector<unsigned char>& data);
|
static std::optional<properties> Read(const std::string&, std::vector<unsigned char>& data);
|
||||||
|
@ -97,7 +101,7 @@ public:
|
||||||
bool minLinear = true;
|
bool minLinear = true;
|
||||||
Wrap wrap = Wrap::MIRRORED_REPEAT;
|
Wrap wrap = Wrap::MIRRORED_REPEAT;
|
||||||
int anisotropy = 0;
|
int anisotropy = 0;
|
||||||
//TODO: mipmap
|
bool mipmap = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Only supports dds files
|
/// Only supports dds files
|
||||||
|
|
|
@ -14,7 +14,8 @@ const auto NO_DELETER = memory::Deleter(nullptr);
|
||||||
memory::ptr memory::GetNull() { return memory::ptr(nullptr, NO_DELETER); }
|
memory::ptr memory::GetNull() { return memory::ptr(nullptr, NO_DELETER); }
|
||||||
|
|
||||||
Allocator::Allocator(VkDevice device, const PhysicalDeviceInfo &info): physicalDevice(info.device),
|
Allocator::Allocator(VkDevice device, const PhysicalDeviceInfo &info): physicalDevice(info.device),
|
||||||
capabilities({info.features.samplerAnisotropy == VK_TRUE}), device(device)
|
capabilities({info.features.samplerAnisotropy == VK_TRUE ? std::make_optional(info.properties.limits.maxSamplerAnisotropy) : std::nullopt,
|
||||||
|
info.properties.limits.maxSamplerLodBias}), device(device)
|
||||||
{
|
{
|
||||||
if(info.hasMemoryBudget()) {
|
if(info.hasMemoryBudget()) {
|
||||||
properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
|
properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
|
||||||
|
@ -194,7 +195,7 @@ void Allocator::copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size) {
|
||||||
|
|
||||||
submitCmd(transferBuffer, transferQueue);
|
submitCmd(transferBuffer, transferQueue);
|
||||||
}
|
}
|
||||||
void Allocator::transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout) {
|
void Allocator::transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels) {
|
||||||
beginCmd(graphicsBuffer);
|
beginCmd(graphicsBuffer);
|
||||||
|
|
||||||
VkImageMemoryBarrier barrier{};
|
VkImageMemoryBarrier barrier{};
|
||||||
|
@ -207,7 +208,7 @@ void Allocator::transitionImageLayout(VkImage image, VkFormat format, VkImageLay
|
||||||
|
|
||||||
barrier.image = image;
|
barrier.image = image;
|
||||||
barrier.subresourceRange.baseMipLevel = 0;
|
barrier.subresourceRange.baseMipLevel = 0;
|
||||||
barrier.subresourceRange.levelCount = 1;
|
barrier.subresourceRange.levelCount = mipLevels;
|
||||||
barrier.subresourceRange.baseArrayLayer = 0;
|
barrier.subresourceRange.baseArrayLayer = 0;
|
||||||
barrier.subresourceRange.layerCount = 1;
|
barrier.subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
|
@ -250,28 +251,33 @@ void Allocator::transitionImageLayout(VkImage image, VkFormat format, VkImageLay
|
||||||
|
|
||||||
submitCmd(graphicsBuffer, graphicsQueue);
|
submitCmd(graphicsBuffer, graphicsQueue);
|
||||||
}
|
}
|
||||||
void Allocator::copyBufferToImage(VkBuffer src, VkImage dest, uint32_t width, uint32_t height) {
|
void Allocator::copyBufferToImage(VkBuffer src, VkImage dest, uint32_t width, uint32_t height, uint32_t mipLevels) {
|
||||||
|
|
||||||
beginCmd(transferBuffer);
|
beginCmd(transferBuffer);
|
||||||
|
|
||||||
|
VkDeviceSize offset = 0;
|
||||||
|
std::vector<VkBufferImageCopy> regions{mipLevels};
|
||||||
|
for (size_t i = 0; i < mipLevels; i++) {
|
||||||
|
regions[i].bufferOffset = offset;
|
||||||
|
regions[i].bufferRowLength = std::max<uint32_t>(1, width >> i);
|
||||||
|
regions[i].bufferImageHeight = std::max<uint32_t>(1, height >> i);
|
||||||
|
|
||||||
VkBufferImageCopy region{};
|
regions[i].imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
region.bufferOffset = 0;
|
regions[i].imageSubresource.mipLevel = i;
|
||||||
region.bufferRowLength = 0;
|
regions[i].imageSubresource.baseArrayLayer = 0;
|
||||||
region.bufferImageHeight = 0;
|
regions[i].imageSubresource.layerCount = 1;
|
||||||
|
|
||||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
regions[i].imageOffset = {0, 0, 0};
|
||||||
region.imageSubresource.mipLevel = 0;
|
regions[i].imageExtent = {regions[i].bufferRowLength, regions[i].bufferImageHeight, 1};
|
||||||
region.imageSubresource.baseArrayLayer = 0;
|
|
||||||
region.imageSubresource.layerCount = 1;
|
|
||||||
|
|
||||||
region.imageOffset = {0, 0, 0};
|
//NOTE: may fail without width % 4 && height % 4
|
||||||
region.imageExtent = {width, height, 1};
|
offset += regions[i].imageExtent.height * regions[i].imageExtent.width * regions[i].imageExtent.depth;
|
||||||
|
}
|
||||||
vkCmdCopyBufferToImage(transferBuffer, src, dest, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
vkCmdCopyBufferToImage(transferBuffer, src, dest, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, mipLevels, regions.data());
|
||||||
|
|
||||||
submitCmd(transferBuffer, transferQueue);
|
submitCmd(transferBuffer, transferQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::optional<uint32_t> Allocator::findMemory(uint32_t typeFilter, VkMemoryPropertyFlags requirement, VkDeviceSize size) {
|
std::optional<uint32_t> Allocator::findMemory(uint32_t typeFilter, VkMemoryPropertyFlags requirement, VkDeviceSize size) {
|
||||||
updateProperties();
|
updateProperties();
|
||||||
#if LOG_TRACE
|
#if LOG_TRACE
|
||||||
|
|
|
@ -37,13 +37,14 @@ public:
|
||||||
bool deallocate(const memory::area&);
|
bool deallocate(const memory::area&);
|
||||||
|
|
||||||
void copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size);
|
void copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size);
|
||||||
void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout);
|
void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels);
|
||||||
void copyBufferToImage(VkBuffer src, VkImage dst, uint32_t width, uint32_t height);
|
void copyBufferToImage(VkBuffer src, VkImage dst, uint32_t width, uint32_t height, uint32_t mipLevels = 1);
|
||||||
|
|
||||||
void setTracyZone(const char* name);
|
void setTracyZone(const char* name);
|
||||||
|
|
||||||
struct Capabilities {
|
struct Capabilities {
|
||||||
bool anisotropy;
|
std::optional<float> maxAnisotropy;
|
||||||
|
float maxLodBias;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr VkDevice getDevice() const { return device; }
|
constexpr VkDevice getDevice() const { return device; }
|
||||||
|
|
|
@ -46,8 +46,8 @@ CommandCenter::~CommandCenter() {
|
||||||
void CommandCenter::allocate(const std::vector<VkImageView>& views, const Pipeline& pipe, VkExtent2D extent, const renderOptions& opt) {
|
void CommandCenter::allocate(const std::vector<VkImageView>& views, const Pipeline& pipe, VkExtent2D extent, const renderOptions& opt) {
|
||||||
assert(freed);
|
assert(freed);
|
||||||
|
|
||||||
depthbuffer = Image::Create({{{extent.height, extent.width}, 1, (Image::Format)depthFormat},
|
depthbuffer = Image::Create(Image::requirement({{extent.height, extent.width}, 1, (Image::Format)depthFormat},
|
||||||
Image::Layout::DEPTH_STENCIL_ATTACHMENT, Image::Usage::DEPTH_STENCIL_ATTACHMENT, false, Image::Aspect::DEPTH});
|
Image::Layout::DEPTH_STENCIL_ATTACHMENT, Image::Usage::DEPTH_STENCIL_ATTACHMENT, Image::Aspect::DEPTH));
|
||||||
|
|
||||||
framebuffers.resize(views.size());
|
framebuffers.resize(views.size());
|
||||||
|
|
||||||
|
|
|
@ -263,6 +263,7 @@ bool Renderer::Load(Window& window, const renderOptions& opt) {
|
||||||
volkLoadInstance(instance);
|
volkLoadInstance(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]]
|
||||||
const auto version = volkGetInstanceVersion();
|
const auto version = volkGetInstanceVersion();
|
||||||
LOG_D("Vulkan " << VK_VERSION_MAJOR(version) << '.' << VK_VERSION_MINOR(version) << '.' << VK_VERSION_PATCH(version) << ", GLSL precompiled");
|
LOG_D("Vulkan " << VK_VERSION_MAJOR(version) << '.' << VK_VERSION_MINOR(version) << '.' << VK_VERSION_PATCH(version) << ", GLSL precompiled");
|
||||||
|
|
||||||
|
|
|
@ -20,13 +20,13 @@ memory::ptr createImage(const Image::requirement& req, VkMemoryPropertyFlags pro
|
||||||
VkImageCreateInfo info{};
|
VkImageCreateInfo info{};
|
||||||
info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||||
info.imageType = VK_IMAGE_TYPE_2D;
|
info.imageType = VK_IMAGE_TYPE_2D;
|
||||||
info.extent.width = req.props.size.width;
|
info.extent.width = req.size.width;
|
||||||
info.extent.height = req.props.size.height;
|
info.extent.height = req.size.height;
|
||||||
info.extent.depth = 1;
|
info.extent.depth = 1;
|
||||||
info.mipLevels = req.props.mipMap; //TODO:
|
info.mipLevels = req.mipmapLevels;
|
||||||
info.arrayLayers = 1;
|
info.arrayLayers = 1;
|
||||||
info.format = static_cast<VkFormat>(req.props.format);
|
info.format = static_cast<VkFormat>(req.format);
|
||||||
info.tiling = req.linear ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
|
info.tiling = req.optimal ? VK_IMAGE_TILING_OPTIMAL : VK_IMAGE_TILING_LINEAR;
|
||||||
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
info.usage = static_cast<VkImageUsageFlags>(req.usage);
|
info.usage = static_cast<VkImageUsageFlags>(req.usage);
|
||||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
@ -54,25 +54,24 @@ memory::ptr createImage(const Image::requirement& req, VkMemoryPropertyFlags pro
|
||||||
if (data) {
|
if (data) {
|
||||||
if(auto staging = WritableBuffer::Create(data.size)) {
|
if(auto staging = WritableBuffer::Create(data.size)) {
|
||||||
staging->write(data, 0);
|
staging->write(data, 0);
|
||||||
alloc->transitionImageLayout(out.ref, info.format, info.initialLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
alloc->transitionImageLayout(out.ref, info.format, info.initialLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, req.mipmapLevels);
|
||||||
alloc->copyBufferToImage(staging->getRef(), out.ref, info.extent.width, info.extent.height);
|
info.initialLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
alloc->transitionImageLayout(out.ref, info.format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, static_cast<VkImageLayout>(req.layout));
|
alloc->copyBufferToImage(staging->getRef(), out.ref, info.extent.width, info.extent.height, req.mipmapLevels);
|
||||||
} else {
|
} else {
|
||||||
LOG_E("Cannot allocate staging memory");
|
LOG_E("Cannot allocate staging memory");
|
||||||
return memory::GetNull();
|
return memory::GetNull();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
alloc->transitionImageLayout(out.ref, info.format, info.initialLayout, static_cast<VkImageLayout>(req.layout));
|
|
||||||
}
|
}
|
||||||
|
alloc->transitionImageLayout(out.ref, info.format, info.initialLayout, static_cast<VkImageLayout>(req.layout), req.mipmapLevels);
|
||||||
|
|
||||||
VkImageViewCreateInfo viewInfo{};
|
VkImageViewCreateInfo viewInfo{};
|
||||||
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
viewInfo.image = out.ref;
|
viewInfo.image = out.ref;
|
||||||
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
viewInfo.format = static_cast<VkFormat>(req.props.format);
|
viewInfo.format = static_cast<VkFormat>(req.format);
|
||||||
viewInfo.subresourceRange.aspectMask = static_cast<VkImageAspectFlags>(req.aspect);
|
viewInfo.subresourceRange.aspectMask = static_cast<VkImageAspectFlags>(req.aspect);
|
||||||
viewInfo.subresourceRange.baseMipLevel = 0;
|
viewInfo.subresourceRange.baseMipLevel = 0;
|
||||||
viewInfo.subresourceRange.levelCount = 1; //TODO: mipmap
|
viewInfo.subresourceRange.levelCount = req.mipmapLevels;
|
||||||
viewInfo.subresourceRange.baseArrayLayer = 0;
|
viewInfo.subresourceRange.baseArrayLayer = 0;
|
||||||
viewInfo.subresourceRange.layerCount = 1;
|
viewInfo.subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
|
@ -105,7 +104,7 @@ std::unique_ptr<Texture> Texture::LoadFromFile(const std::string& path, const sa
|
||||||
}();
|
}();
|
||||||
|
|
||||||
vk::Image::info img;
|
vk::Image::info img;
|
||||||
auto mem = createImage({header.size, header.mipMap, header.format, Layout::SHADER_READ_ONLY, Usage::SAMPLED, false},
|
auto mem = createImage(requirement::Texture(header),
|
||||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, data, img);
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, data, img);
|
||||||
if(!mem) {
|
if(!mem) {
|
||||||
FATAL("Cannot create texture image");
|
FATAL("Cannot create texture image");
|
||||||
|
@ -121,9 +120,10 @@ std::unique_ptr<Texture> Texture::LoadFromFile(const std::string& path, const sa
|
||||||
samplerInfo.addressModeV = wrap;
|
samplerInfo.addressModeV = wrap;
|
||||||
samplerInfo.addressModeW = wrap;
|
samplerInfo.addressModeW = wrap;
|
||||||
|
|
||||||
if (Allocator::GetDefault()->getCapabilities().anisotropy && props.anisotropy > 0) {
|
auto maxAnisotropy = Allocator::GetDefault()->getCapabilities().maxAnisotropy;
|
||||||
|
if (maxAnisotropy && props.anisotropy > 0) {
|
||||||
samplerInfo.anisotropyEnable = VK_TRUE;
|
samplerInfo.anisotropyEnable = VK_TRUE;
|
||||||
samplerInfo.maxAnisotropy = 1 << (props.anisotropy-1);
|
samplerInfo.maxAnisotropy = std::min<float>(maxAnisotropy.value(), 1 << (props.anisotropy-1));
|
||||||
} else {
|
} else {
|
||||||
samplerInfo.anisotropyEnable = VK_FALSE;
|
samplerInfo.anisotropyEnable = VK_FALSE;
|
||||||
samplerInfo.maxAnisotropy = 1.f;
|
samplerInfo.maxAnisotropy = 1.f;
|
||||||
|
@ -135,10 +135,10 @@ std::unique_ptr<Texture> Texture::LoadFromFile(const std::string& path, const sa
|
||||||
samplerInfo.compareEnable = VK_FALSE;
|
samplerInfo.compareEnable = VK_FALSE;
|
||||||
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
|
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
|
||||||
|
|
||||||
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
samplerInfo.mipmapMode = props.minLinear ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||||
samplerInfo.mipLodBias = 0.0f; //TODO:
|
samplerInfo.mipLodBias = 0.0f; //TODO:
|
||||||
samplerInfo.minLod = 0.0f;
|
samplerInfo.minLod = 0.0f;
|
||||||
samplerInfo.maxLod = 0.0f;
|
samplerInfo.maxLod = props.mipmap ? header.mipmapLevels : 0.0f;
|
||||||
|
|
||||||
VkSampler sampler;
|
VkSampler sampler;
|
||||||
if (vkCreateSampler(device, &samplerInfo, ALLOC, &sampler) != VK_SUCCESS) {
|
if (vkCreateSampler(device, &samplerInfo, ALLOC, &sampler) != VK_SUCCESS) {
|
||||||
|
|
Loading…
Reference in New Issue