mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +09:00
[Feat] (MG_Backend/DirectVulkan): TextureManager supports mipmap
This commit is contained in:
@@ -75,31 +75,40 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SyncTextureResource(texture, level0Target, texelSize, byteSize, outResource)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* mipTexture = dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(&texture);
|
auto* mipTexture = dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(&texture);
|
||||||
if (!mipTexture) {
|
if (!mipTexture) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mipTexture->IsStorageDirty(level0Target, 0)) {
|
const Uint32 mipLevelCount = GetUploadMipLevelCount(*mipTexture, level0Target);
|
||||||
return true;
|
if (mipLevelCount == 0) {
|
||||||
}
|
|
||||||
|
|
||||||
if (!UploadLevel0(*mipTexture, level0Target, byteSize, outResource)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& mutableTexture = *mipTexture;
|
if (!SyncTextureResource(texture, level0Target, texelSize, byteSize, mipLevelCount, outResource)) {
|
||||||
mutableTexture.MarkStorageDirty(level0Target, 0, false);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool hasDirtyMipLevel = false;
|
||||||
|
for (Uint32 level = 0; level < mipLevelCount; ++level) {
|
||||||
|
if (mipTexture->IsStorageDirty(level0Target, level)) {
|
||||||
|
hasDirtyMipLevel = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasDirtyMipLevel) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!UploadDirtyMipLevels(*mipTexture, level0Target, outResource)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool VkTextureManager::SyncTextureResource(const MG_State::GLState::ITextureObject &texture,
|
Bool VkTextureManager::SyncTextureResource(const MG_State::GLState::ITextureObject &texture,
|
||||||
TextureUploadTarget level0Target,
|
TextureUploadTarget level0Target,
|
||||||
const IntVec3 &texelSize, SizeT byteSize,
|
const IntVec3 &texelSize, SizeT byteSize, Uint32 mipLevels,
|
||||||
TextureResource &resource) {
|
TextureResource &resource) {
|
||||||
const VkFormat format = GetVkFormat(texture.GetFormat());
|
const VkFormat format = GetVkFormat(texture.GetFormat());
|
||||||
if (format == VK_FORMAT_UNDEFINED) {
|
if (format == VK_FORMAT_UNDEFINED) {
|
||||||
@@ -108,13 +117,17 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
if (texelSize.x() <= 0 || texelSize.y() <= 0 || byteSize == 0) {
|
if (texelSize.x() <= 0 || texelSize.y() <= 0 || byteSize == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (mipLevels == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (level0Target != TextureUploadTarget::Texture2D) {
|
if (level0Target != TextureUploadTarget::Texture2D) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Bool compatible = resource.image != VK_NULL_HANDLE && resource.format == format &&
|
const Bool compatible = resource.image != VK_NULL_HANDLE && resource.format == format &&
|
||||||
resource.extent.width == static_cast<Uint32>(texelSize.x()) &&
|
resource.extent.width == static_cast<Uint32>(texelSize.x()) &&
|
||||||
resource.extent.height == static_cast<Uint32>(texelSize.y());
|
resource.extent.height == static_cast<Uint32>(texelSize.y()) &&
|
||||||
|
resource.mipLevels == mipLevels;
|
||||||
if (compatible) {
|
if (compatible) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -127,7 +140,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
imageInfo.extent.width = static_cast<Uint32>(texelSize.x());
|
imageInfo.extent.width = static_cast<Uint32>(texelSize.x());
|
||||||
imageInfo.extent.height = static_cast<Uint32>(texelSize.y());
|
imageInfo.extent.height = static_cast<Uint32>(texelSize.y());
|
||||||
imageInfo.extent.depth = 1;
|
imageInfo.extent.depth = 1;
|
||||||
imageInfo.mipLevels = 1;
|
imageInfo.mipLevels = mipLevels;
|
||||||
imageInfo.arrayLayers = 1;
|
imageInfo.arrayLayers = 1;
|
||||||
imageInfo.format = format;
|
imageInfo.format = format;
|
||||||
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
@@ -148,24 +161,57 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
viewInfo.format = format;
|
viewInfo.format = format;
|
||||||
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
viewInfo.subresourceRange.baseMipLevel = 0;
|
viewInfo.subresourceRange.baseMipLevel = 0;
|
||||||
viewInfo.subresourceRange.levelCount = 1;
|
viewInfo.subresourceRange.levelCount = mipLevels;
|
||||||
viewInfo.subresourceRange.baseArrayLayer = 0;
|
viewInfo.subresourceRange.baseArrayLayer = 0;
|
||||||
viewInfo.subresourceRange.layerCount = 1;
|
viewInfo.subresourceRange.layerCount = 1;
|
||||||
VK_VERIFY(vkCreateImageView(m_device, &viewInfo, nullptr, &resource.view), "vkCreateImageView(texture)");
|
VK_VERIFY(vkCreateImageView(m_device, &viewInfo, nullptr, &resource.view), "vkCreateImageView(texture)");
|
||||||
|
|
||||||
resource.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
resource.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
resource.extent = {static_cast<Uint32>(texelSize.x()), static_cast<Uint32>(texelSize.y())};
|
resource.extent = {static_cast<Uint32>(texelSize.x()), static_cast<Uint32>(texelSize.y())};
|
||||||
|
resource.mipLevels = mipLevels;
|
||||||
resource.format = format;
|
resource.format = format;
|
||||||
resource.textureExternalIndex = texture.GetExternalIndex();
|
resource.textureExternalIndex = texture.GetExternalIndex();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool VkTextureManager::UploadLevel0(MG_State::GLState::TextureObjectMipmap &mipmapTexture,
|
Bool VkTextureManager::UploadDirtyMipLevels(MG_State::GLState::TextureObjectMipmap &mipmapTexture,
|
||||||
TextureUploadTarget level0Target, SizeT byteSize,
|
TextureUploadTarget level0Target,
|
||||||
TextureResource &outResource) {
|
TextureResource &outResource) {
|
||||||
const void* source = mipmapTexture.MapMipmapData(level0Target, 0);
|
struct UploadItem {
|
||||||
if (source == nullptr || byteSize == 0) {
|
Uint32 level = 0;
|
||||||
return false;
|
SizeT byteSize = 0;
|
||||||
|
IntVec3 texelSize = {0, 0, 0};
|
||||||
|
const void* source = nullptr;
|
||||||
|
VkDeviceSize offset = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector<UploadItem> uploadItems;
|
||||||
|
uploadItems.reserve(outResource.mipLevels);
|
||||||
|
|
||||||
|
VkDeviceSize stagingSize = 0;
|
||||||
|
for (Uint32 level = 0; level < outResource.mipLevels; ++level) {
|
||||||
|
if (!mipmapTexture.IsStorageDirty(level0Target, level)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto texelSize = mipmapTexture.GetMipmapTexelSize(level0Target, level);
|
||||||
|
const auto byteSize = mipmapTexture.GetMipmapByteSize(level0Target, level);
|
||||||
|
if (texelSize.x() <= 0 || texelSize.y() <= 0 || byteSize == 0) {
|
||||||
|
mipmapTexture.MarkStorageDirty(level0Target, level, false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void* source = mipmapTexture.MapMipmapData(level0Target, level);
|
||||||
|
if (source == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadItems.push_back({level, byteSize, texelSize, source, stagingSize});
|
||||||
|
stagingSize += static_cast<VkDeviceSize>(byteSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uploadItems.empty()) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkBuffer stagingBuffer = VK_NULL_HANDLE;
|
VkBuffer stagingBuffer = VK_NULL_HANDLE;
|
||||||
@@ -173,7 +219,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
VkBufferCreateInfo bufferInfo{};
|
VkBufferCreateInfo bufferInfo{};
|
||||||
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
bufferInfo.size = byteSize;
|
bufferInfo.size = stagingSize;
|
||||||
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||||
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
VmaAllocationCreateInfo stagingAllocationInfo{};
|
VmaAllocationCreateInfo stagingAllocationInfo{};
|
||||||
@@ -185,14 +231,17 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
void* mapped = nullptr;
|
void* mapped = nullptr;
|
||||||
VK_VERIFY(vmaMapMemory(m_allocator, stagingAllocation, &mapped), "vmaMapMemory(staging texture)");
|
VK_VERIFY(vmaMapMemory(m_allocator, stagingAllocation, &mapped), "vmaMapMemory(staging texture)");
|
||||||
std::memcpy(mapped, source, byteSize);
|
for (const auto& item : uploadItems) {
|
||||||
|
std::memcpy(static_cast<Uint8*>(mapped) + item.offset, item.source, item.byteSize);
|
||||||
|
}
|
||||||
vmaUnmapMemory(m_allocator, stagingAllocation);
|
vmaUnmapMemory(m_allocator, stagingAllocation);
|
||||||
|
|
||||||
// Could be uploaded asynchronously?
|
// TODO: Could be uploaded asynchronously?
|
||||||
const Bool ok = ExecuteCmdBufImmediate([&](VkCommandBuffer commandBuffer) {
|
const Bool ok = ExecuteCmdBufImmediate([&](VkCommandBuffer commandBuffer) {
|
||||||
VkImageMemoryBarrier toTransferDst{};
|
VkImageMemoryBarrier toTransferDst{};
|
||||||
toTransferDst.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
toTransferDst.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
toTransferDst.srcAccessMask = 0;
|
toTransferDst.srcAccessMask =
|
||||||
|
outResource.layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ? VK_ACCESS_SHADER_READ_BIT : 0;
|
||||||
toTransferDst.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
toTransferDst.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
toTransferDst.oldLayout = outResource.layout;
|
toTransferDst.oldLayout = outResource.layout;
|
||||||
toTransferDst.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
toTransferDst.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
@@ -201,24 +250,29 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
toTransferDst.image = outResource.image;
|
toTransferDst.image = outResource.image;
|
||||||
toTransferDst.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
toTransferDst.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
toTransferDst.subresourceRange.baseMipLevel = 0;
|
toTransferDst.subresourceRange.baseMipLevel = 0;
|
||||||
toTransferDst.subresourceRange.levelCount = 1;
|
toTransferDst.subresourceRange.levelCount = outResource.mipLevels;
|
||||||
toTransferDst.subresourceRange.baseArrayLayer = 0;
|
toTransferDst.subresourceRange.baseArrayLayer = 0;
|
||||||
toTransferDst.subresourceRange.layerCount = 1;
|
toTransferDst.subresourceRange.layerCount = 1;
|
||||||
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0,
|
const VkPipelineStageFlags srcStage =
|
||||||
nullptr, 0, nullptr, 1, &toTransferDst);
|
outResource.layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ? VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
|
||||||
|
: VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||||
|
vkCmdPipelineBarrier(commandBuffer, srcStage, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1,
|
||||||
|
&toTransferDst);
|
||||||
|
|
||||||
VkBufferImageCopy copy{};
|
for (const auto& item : uploadItems) {
|
||||||
copy.bufferOffset = 0;
|
VkBufferImageCopy copy{};
|
||||||
copy.bufferRowLength = 0;
|
copy.bufferOffset = item.offset;
|
||||||
copy.bufferImageHeight = 0;
|
copy.bufferRowLength = 0;
|
||||||
copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
copy.bufferImageHeight = 0;
|
||||||
copy.imageSubresource.mipLevel = 0;
|
copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
copy.imageSubresource.baseArrayLayer = 0;
|
copy.imageSubresource.mipLevel = item.level;
|
||||||
copy.imageSubresource.layerCount = 1;
|
copy.imageSubresource.baseArrayLayer = 0;
|
||||||
copy.imageOffset = {0, 0, 0};
|
copy.imageSubresource.layerCount = 1;
|
||||||
copy.imageExtent = {outResource.extent.width, outResource.extent.height, 1};
|
copy.imageOffset = {0, 0, 0};
|
||||||
vkCmdCopyBufferToImage(commandBuffer, stagingBuffer, outResource.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
|
copy.imageExtent = {static_cast<Uint32>(item.texelSize.x()), static_cast<Uint32>(item.texelSize.y()), 1};
|
||||||
©);
|
vkCmdCopyBufferToImage(commandBuffer, stagingBuffer, outResource.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
1, ©);
|
||||||
|
}
|
||||||
|
|
||||||
VkImageMemoryBarrier toSampled{};
|
VkImageMemoryBarrier toSampled{};
|
||||||
toSampled.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
toSampled.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
@@ -231,7 +285,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
toSampled.image = outResource.image;
|
toSampled.image = outResource.image;
|
||||||
toSampled.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
toSampled.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
toSampled.subresourceRange.baseMipLevel = 0;
|
toSampled.subresourceRange.baseMipLevel = 0;
|
||||||
toSampled.subresourceRange.levelCount = 1;
|
toSampled.subresourceRange.levelCount = outResource.mipLevels;
|
||||||
toSampled.subresourceRange.baseArrayLayer = 0;
|
toSampled.subresourceRange.baseArrayLayer = 0;
|
||||||
toSampled.subresourceRange.layerCount = 1;
|
toSampled.subresourceRange.layerCount = 1;
|
||||||
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
|
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
|
||||||
@@ -243,6 +297,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
if (!ok) {
|
if (!ok) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
for (const auto& item : uploadItems) {
|
||||||
|
mipmapTexture.MarkStorageDirty(level0Target, item.level, false);
|
||||||
|
}
|
||||||
outResource.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
outResource.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -289,6 +346,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
resource.allocation = nullptr;
|
resource.allocation = nullptr;
|
||||||
resource.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
resource.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
resource.extent = {0, 0};
|
resource.extent = {0, 0};
|
||||||
|
resource.mipLevels = 1;
|
||||||
resource.format = VK_FORMAT_UNDEFINED;
|
resource.format = VK_FORMAT_UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,6 +366,25 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return outTexelSize.x() > 0 && outTexelSize.y() > 0 && outByteSize > 0;
|
return outTexelSize.x() > 0 && outTexelSize.y() > 0 && outByteSize > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Uint32 VkTextureManager::GetUploadMipLevelCount(const MG_State::GLState::TextureObjectMipmap& texture,
|
||||||
|
TextureUploadTarget target) {
|
||||||
|
const Uint totalLevelCount = texture.GetMipmapLevelCount();
|
||||||
|
if (totalLevelCount == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint32 validLevelCount = 0;
|
||||||
|
for (Uint level = 0; level < totalLevelCount; ++level) {
|
||||||
|
const auto size = texture.GetMipmapTexelSize(target, level);
|
||||||
|
const auto byteSize = texture.GetMipmapByteSize(target, level);
|
||||||
|
if (size.x() <= 0 || size.y() <= 0 || byteSize == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++validLevelCount;
|
||||||
|
}
|
||||||
|
return validLevelCount;
|
||||||
|
}
|
||||||
|
|
||||||
VkFormat VkTextureManager::GetVkFormat(TextureInternalFormat format) {
|
VkFormat VkTextureManager::GetVkFormat(TextureInternalFormat format) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case TextureInternalFormat::RGBA:
|
case TextureInternalFormat::RGBA:
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ private:
|
|||||||
VkImageView view = VK_NULL_HANDLE;
|
VkImageView view = VK_NULL_HANDLE;
|
||||||
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
VkExtent2D extent = {0, 0};
|
VkExtent2D extent = {0, 0};
|
||||||
|
Uint32 mipLevels = 1;
|
||||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||||
Uint textureExternalIndex = 0;
|
Uint textureExternalIndex = 0;
|
||||||
};
|
};
|
||||||
@@ -48,15 +49,16 @@ private:
|
|||||||
TextureResource &outResource);
|
TextureResource &outResource);
|
||||||
Bool SyncTextureResource(const MG_State::GLState::ITextureObject &texture,
|
Bool SyncTextureResource(const MG_State::GLState::ITextureObject &texture,
|
||||||
TextureUploadTarget level0Target,
|
TextureUploadTarget level0Target,
|
||||||
const IntVec3 &texelSize, SizeT byteSize,
|
const IntVec3 &texelSize, SizeT byteSize, Uint32 mipLevels,
|
||||||
TextureResource &resource);
|
TextureResource &resource);
|
||||||
Bool UploadLevel0(MG_State::GLState::TextureObjectMipmap &mipmapTexture,
|
Bool UploadDirtyMipLevels(MG_State::GLState::TextureObjectMipmap &mipmapTexture,
|
||||||
TextureUploadTarget level0Target, SizeT byteSize,
|
TextureUploadTarget level0Target,
|
||||||
TextureResource &outResource);
|
TextureResource &outResource);
|
||||||
Bool ExecuteCmdBufImmediate(const std::function<void(VkCommandBuffer)>& recorder) const;
|
Bool ExecuteCmdBufImmediate(const std::function<void(VkCommandBuffer)>& recorder) const;
|
||||||
void DestroyTextureResource(TextureResource& resource) const;
|
void DestroyTextureResource(TextureResource& resource) const;
|
||||||
static Bool CheckLevel0Completeness(const MG_State::GLState::ITextureObject& texture, TextureUploadTarget& outTarget,
|
static Bool CheckLevel0Completeness(const MG_State::GLState::ITextureObject& texture, TextureUploadTarget& outTarget,
|
||||||
IntVec3& outTexelSize, SizeT& outByteSize);
|
IntVec3& outTexelSize, SizeT& outByteSize);
|
||||||
|
static Uint32 GetUploadMipLevelCount(const MG_State::GLState::TextureObjectMipmap& texture, TextureUploadTarget target);
|
||||||
static VkFormat GetVkFormat(TextureInternalFormat format);
|
static VkFormat GetVkFormat(TextureInternalFormat format);
|
||||||
|
|
||||||
VkDevice m_device = VK_NULL_HANDLE;
|
VkDevice m_device = VK_NULL_HANDLE;
|
||||||
|
|||||||
Reference in New Issue
Block a user