diff --git a/include/vsg/core/Data.h b/include/vsg/core/Data.h index aa3dc6db7..8777ba3e2 100644 --- a/include/vsg/core/Data.h +++ b/include/vsg/core/Data.h @@ -190,8 +190,11 @@ namespace vsg virtual uint32_t height() const = 0; virtual uint32_t depth() const = 0; - /// return the {width, height, depth} pixel extents of an image accounting for blockWidth and any mipmapData assigned to image. - std::tuple pixelExtents() const; + /// return the number of faces - uses properties.imageViewType and depth() value. + std::pair faceDepthAndCount() const; + + /// return the {width, height, depth, layers} pixel extents of an image accounting for blockWidth and any mipmapData assigned to image. + std::tuple pixelExtents() const; bool contiguous() const { return valueSize() == properties.stride; } diff --git a/src/vsg/core/Data.cpp b/src/vsg/core/Data.cpp index cab03faaa..bcd971363 100644 --- a/src/vsg/core/Data.cpp +++ b/src/vsg/core/Data.cpp @@ -16,6 +16,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include #include #include +#include using namespace vsg; @@ -145,10 +146,28 @@ const MipmapLayout* Data::getMipmapLayout() const return getObject("mipmapLayout"); } +std::pair Data::faceDepthAndCount() const +{ + // Use properties.imageViewType to set the face count and face depth https://docs.vulkan.org/refpages/latest/refpages/source/VkImageViewType.html + switch(properties.imageViewType) + { + case(VK_IMAGE_VIEW_TYPE_CUBE): + case(VK_IMAGE_VIEW_TYPE_CUBE_ARRAY): + return {depth()/6, 6}; + case(VK_IMAGE_VIEW_TYPE_1D_ARRAY): + case(VK_IMAGE_VIEW_TYPE_2D_ARRAY): + return {1, depth()}; + default: + return {depth(), 1}; + } +} + std::size_t Data::computeValueCountIncludingMipmaps() const { std::size_t count = 0; + auto [faceDepth, faceCount] = faceDepthAndCount(); + if (auto mipmapLayout = getMipmapLayout()) { for (const auto& mipmap : *mipmapLayout) @@ -160,12 +179,13 @@ std::size_t Data::computeValueCountIncludingMipmaps() const count += w * h * d; } + count *= faceCount; } else { std::size_t x = width() * properties.blockWidth; std::size_t y = height() * properties.blockHeight; - std::size_t z = depth() * properties.blockDepth; + std::size_t z = faceDepth * properties.blockDepth; auto mipLevels = std::max(properties.mipLevels, uint8_t(1)); for (uint8_t level = 0; level < mipLevels; ++level) @@ -181,16 +201,20 @@ std::size_t Data::computeValueCountIncludingMipmaps() const if (y > 1) y = y / 2; if (z > 1) z = z / 2; } + + count *= faceCount; } return count; } -std::tuple Data::pixelExtents() const +std::tuple Data::pixelExtents() const { + auto [faceDepth, faceCount] = faceDepthAndCount(); + uint32_t w = width() * properties.blockWidth; uint32_t h = height() * properties.blockHeight; - uint32_t d = depth() * properties.blockDepth; + uint32_t d = faceDepth * properties.blockDepth; if (auto mipmapLayout = getMipmapLayout()) { @@ -200,5 +224,5 @@ std::tuple Data::pixelExtents() const d = mipmap.z; } - return {w, h, d}; + return {w, h, d, faceCount}; } diff --git a/src/vsg/state/Image.cpp b/src/vsg/state/Image.cpp index 64d156450..923557cc1 100644 --- a/src/vsg/state/Image.cpp +++ b/src/vsg/state/Image.cpp @@ -40,57 +40,43 @@ Image::Image(ref_ptr in_data) : auto properties = data->properties; auto dimensions = data->dimensions(); - auto [width, height, depth] = data->pixelExtents(); + std::tie(extent.width, extent.height, extent.depth, arrayLayers) = data->pixelExtents(); switch (properties.imageViewType) { case (VK_IMAGE_VIEW_TYPE_1D): imageType = VK_IMAGE_TYPE_1D; - arrayLayers = 1; break; case (VK_IMAGE_VIEW_TYPE_2D): imageType = VK_IMAGE_TYPE_2D; - arrayLayers = 1; break; case (VK_IMAGE_VIEW_TYPE_3D): imageType = VK_IMAGE_TYPE_3D; - arrayLayers = 1; break; case (VK_IMAGE_VIEW_TYPE_CUBE): imageType = VK_IMAGE_TYPE_2D; flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - arrayLayers = depth; - depth = 1; break; case (VK_IMAGE_VIEW_TYPE_1D_ARRAY): imageType = VK_IMAGE_TYPE_1D; - arrayLayers = height * depth; - height = 1; - depth = 1; /* flags = VK_IMAGE_CREATE_1D_ARRAY_COMPATIBLE_BIT; // comment out as Vulkan headers don't yet provide this. */ break; case (VK_IMAGE_VIEW_TYPE_2D_ARRAY): // imageType = VK_IMAGE_TYPE_3D; // flags = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; imageType = VK_IMAGE_TYPE_2D; - arrayLayers = depth; - depth = 1; break; case (VK_IMAGE_VIEW_TYPE_CUBE_ARRAY): imageType = VK_IMAGE_TYPE_2D; flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - arrayLayers = depth; - depth = 1; break; default: imageType = dimensions >= 3 ? VK_IMAGE_TYPE_3D : (dimensions == 2 ? VK_IMAGE_TYPE_2D : VK_IMAGE_TYPE_1D); - arrayLayers = 1; break; } format = properties.format; mipLevels = std::max(1u, static_cast(data->properties.mipLevels)); - extent = VkExtent3D{width, height, depth}; // vsg::info("Image::Image(", data, ") mpipLevels = ", mipLevels); @@ -212,8 +198,6 @@ VkResult Image::compile(Device* device) info.pQueueFamilyIndices = queueFamilyIndices.data(); info.initialLayout = initialLayout; - // vsg::info("Image::compile(), data = ",data, ", mipLevels = ", mipLevels, ", arrayLayers = ", arrayLayers, ", extent = {", extent.width, ", ", extent.height, ", ", extent.depth, "}"); - vd.device = device; vd.requiresDataCopy = data.valid(); diff --git a/src/vsg/state/ImageInfo.cpp b/src/vsg/state/ImageInfo.cpp index 3d7e791dd..8d320df17 100644 --- a/src/vsg/state/ImageInfo.cpp +++ b/src/vsg/state/ImageInfo.cpp @@ -331,7 +331,7 @@ uint32_t vsg::computeNumMipMapLevels(const Data* data, const Sampler* sampler) if (sampler) { // clamp the mipLevels so that it's no larger than what the data dimensions support - auto [width, height, depth] = data->pixelExtents(); + auto [width, height, depth, numLayers] = data->pixelExtents(); uint32_t maxDimension = std::max({width, height, depth}); if (sampler->maxLod == VK_LOD_CLAMP_NONE) {