Vulkan: Add an Image helper class.
This class wraps a lot of the common functionality of a vk::Image.
It keeps an associated DeviceMemory and ImageView.
Eventually we can probably merge this class with RenderTargetVk. We
can also use it to implement the same functionality between
Renderbuffer and Texture and abstract different storage types, like
2D and Cube.
Bug: angleproject:2318
Change-Id: I39239f47b483cfb96290a15b06edd264f7f4bb34
Reviewed-on: https://chromium-review.googlesource.com/980772
Reviewed-by: Frank Henigman <fjhenigman@chromium.org>
Reviewed-by: Luc Ferron <lucferron@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/Texture.cpp b/src/libANGLE/Texture.cpp
index 7fad6c6..bbc8fb5 100644
--- a/src/libANGLE/Texture.cpp
+++ b/src/libANGLE/Texture.cpp
@@ -71,10 +71,7 @@
}
SwizzleState::SwizzleState()
- : swizzleRed(GL_INVALID_INDEX),
- swizzleGreen(GL_INVALID_INDEX),
- swizzleBlue(GL_INVALID_INDEX),
- swizzleAlpha(GL_INVALID_INDEX)
+ : swizzleRed(GL_RED), swizzleGreen(GL_GREEN), swizzleBlue(GL_BLUE), swizzleAlpha(GL_ALPHA)
{
}
@@ -102,7 +99,6 @@
TextureState::TextureState(TextureType type)
: mType(type),
- mSwizzleState(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA),
mSamplerState(SamplerState::CreateDefaultForTarget(type)),
mBaseLevel(0),
mMaxLevel(1000),
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index ca9f724..b32440c 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -261,9 +261,10 @@
ASSERT(renderTarget);
vk::Image *readImage = renderTarget->image;
- vk::StagingImage stagingImage;
- ANGLE_TRY(stagingImage.init(contextVk, TextureDimension::TEX_2D, *renderTarget->format,
- gl::Extents(area.width, area.height, 1), vk::StagingUsage::Read));
+ vk::ImageHelper stagingImage;
+ ANGLE_TRY(stagingImage.init2DStaging(
+ device, renderer->getMemoryProperties(), *renderTarget->format,
+ gl::Extents(area.width, area.height, 1), vk::StagingUsage::Read));
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(beginWriteResource(renderer, &commandBuffer));
@@ -302,10 +303,10 @@
// TODO(jmadill): parameters
uint8_t *mapPointer = nullptr;
- ANGLE_TRY(
- stagingImage.getDeviceMemory().map(device, 0, stagingImage.getSize(), 0, &mapPointer));
+ ANGLE_TRY(stagingImage.getDeviceMemory().map(device, 0, stagingImage.getAllocatedMemorySize(),
+ 0, &mapPointer));
- const auto &angleFormat = renderTarget->format->textureFormat();
+ const angle::Format &angleFormat = renderTarget->format->textureFormat();
// TODO(jmadill): Use pixel bytes from the ANGLE format directly.
const auto &glFormat = gl::GetSizedInternalFormatInfo(angleFormat.glInternalFormat);
diff --git a/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp b/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
index a93ed42..0429219 100644
--- a/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
@@ -23,10 +23,9 @@
} // anonymous namespace
-RenderbufferVk::RenderbufferVk(const gl::RenderbufferState &state)
- : RenderbufferImpl(state), mAllocatedMemorySize(0)
+RenderbufferVk::RenderbufferVk(const gl::RenderbufferState &state) : RenderbufferImpl(state)
{
- mRenderTarget.image = &mImage;
+ mRenderTarget.image = &mImage.getImage();
mRenderTarget.imageView = &mImageView;
mRenderTarget.resource = this;
}
@@ -40,8 +39,7 @@
ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer();
- renderer->releaseResource(*this, &mImage);
- renderer->releaseResource(*this, &mDeviceMemory);
+ mImage.release(renderer->getCurrentQueueSerial(), renderer);
renderer->releaseResource(*this, &mImageView);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
@@ -66,11 +64,8 @@
static_cast<GLsizei>(width) != mState.getWidth() ||
static_cast<GLsizei>(height) != mState.getHeight())
{
- ASSERT(mImageView.valid());
- renderer->releaseResource(*this, &mImage);
- renderer->releaseResource(*this, &mDeviceMemory);
+ mImage.release(renderer->getCurrentQueueSerial(), renderer);
renderer->releaseResource(*this, &mImageView);
-
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
}
}
@@ -92,71 +87,34 @@
(textureFormat.redBits > 0 ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) |
(isDepthOrStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0);
- VkImageCreateInfo imageInfo;
- imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
- imageInfo.pNext = nullptr;
- imageInfo.flags = 0;
- imageInfo.imageType = VK_IMAGE_TYPE_2D;
- imageInfo.format = vkFormat.vkTextureFormat;
- imageInfo.extent.width = static_cast<uint32_t>(width);
- imageInfo.extent.height = static_cast<uint32_t>(height);
- imageInfo.extent.depth = 1;
- imageInfo.mipLevels = 1;
- imageInfo.arrayLayers = 1;
- imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
- imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
- imageInfo.usage = usage;
- imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- imageInfo.queueFamilyIndexCount = 0;
- imageInfo.pQueueFamilyIndices = nullptr;
- imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
-
- ANGLE_TRY(mImage.init(device, imageInfo));
+ ANGLE_TRY(mImage.init2D(device, mRenderTarget.extents, vkFormat, 1, usage));
VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
- ANGLE_TRY(vk::AllocateImageMemory(renderer, flags, &mImage, &mDeviceMemory,
- &mAllocatedMemorySize));
+ ANGLE_TRY(mImage.initMemory(device, renderer->getMemoryProperties(), flags));
VkImageAspectFlags aspect =
(textureFormat.depthBits > 0 ? VK_IMAGE_ASPECT_DEPTH_BIT : 0) |
(textureFormat.stencilBits > 0 ? VK_IMAGE_ASPECT_STENCIL_BIT : 0) |
(textureFormat.redBits > 0 ? VK_IMAGE_ASPECT_COLOR_BIT : 0);
- // Allocate ImageView.
- VkImageViewCreateInfo viewInfo;
- viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
- viewInfo.pNext = nullptr;
- viewInfo.flags = 0;
- viewInfo.image = mImage.getHandle();
- viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
- viewInfo.format = vkFormat.vkTextureFormat;
- viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
- viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
- viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
- viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
- viewInfo.subresourceRange.aspectMask = aspect;
- viewInfo.subresourceRange.baseMipLevel = 0;
- viewInfo.subresourceRange.levelCount = 1;
- viewInfo.subresourceRange.baseArrayLayer = 0;
- viewInfo.subresourceRange.layerCount = 1;
-
- ANGLE_TRY(mImageView.init(device, viewInfo));
+ ANGLE_TRY(mImage.initImageView(device, aspect, gl::SwizzleState(), &mImageView));
// TODO(jmadill): Fold this into the RenderPass load/store ops. http://anglebug.com/2361
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(beginWriteResource(renderer, &commandBuffer));
- mImage.changeLayoutWithStages(aspect, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
- VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer);
+
+ mImage.getImage().changeLayoutWithStages(
+ VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer);
if (isDepthOrStencilFormat)
{
- commandBuffer->clearSingleDepthStencilImage(mImage, aspect,
+ commandBuffer->clearSingleDepthStencilImage(mImage.getImage(), aspect,
kDefaultClearDepthStencilValue);
}
else
{
- commandBuffer->clearSingleColorImage(mImage, kBlackClearColorValue);
+ commandBuffer->clearSingleColorImage(mImage.getImage(), kBlackClearColorValue);
}
}
diff --git a/src/libANGLE/renderer/vulkan/RenderbufferVk.h b/src/libANGLE/renderer/vulkan/RenderbufferVk.h
index 045b002..1e7a944 100644
--- a/src/libANGLE/renderer/vulkan/RenderbufferVk.h
+++ b/src/libANGLE/renderer/vulkan/RenderbufferVk.h
@@ -45,10 +45,8 @@
const gl::ImageIndex &imageIndex) override;
private:
- vk::Image mImage;
- vk::DeviceMemory mDeviceMemory;
+ vk::ImageHelper mImage;
vk::ImageView mImageView;
- size_t mAllocatedMemorySize;
RenderTargetVk mRenderTarget;
};
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
index e7b47fb..471a957 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -19,57 +19,32 @@
{
namespace
{
-VkComponentSwizzle ConvertSwizzleStateToVkSwizzle(const GLenum swizzle)
-{
- switch (swizzle)
- {
- case GL_ALPHA:
- return VK_COMPONENT_SWIZZLE_A;
- case GL_RED:
- return VK_COMPONENT_SWIZZLE_R;
- case GL_GREEN:
- return VK_COMPONENT_SWIZZLE_G;
- case GL_BLUE:
- return VK_COMPONENT_SWIZZLE_B;
- case GL_ZERO:
- return VK_COMPONENT_SWIZZLE_ZERO;
- case GL_ONE:
- return VK_COMPONENT_SWIZZLE_ONE;
- default:
- UNREACHABLE();
- return VK_COMPONENT_SWIZZLE_IDENTITY;
- }
-}
-
-void FillComponentsSwizzleParameters(GLenum internalFormat,
- const gl::SwizzleState &swizzleState,
- VkComponentMapping *componentMapping)
+void MapSwizzleState(GLenum internalFormat,
+ const gl::SwizzleState &swizzleState,
+ gl::SwizzleState *swizzleStateOut)
{
switch (internalFormat)
{
case GL_LUMINANCE:
- componentMapping->r = ConvertSwizzleStateToVkSwizzle(swizzleState.swizzleRed);
- componentMapping->g = ConvertSwizzleStateToVkSwizzle(swizzleState.swizzleRed);
- componentMapping->b = ConvertSwizzleStateToVkSwizzle(swizzleState.swizzleRed);
- componentMapping->a = ConvertSwizzleStateToVkSwizzle(swizzleState.swizzleAlpha);
+ swizzleStateOut->swizzleRed = swizzleState.swizzleRed;
+ swizzleStateOut->swizzleGreen = swizzleState.swizzleRed;
+ swizzleStateOut->swizzleBlue = swizzleState.swizzleRed;
+ swizzleStateOut->swizzleAlpha = GL_ONE;
break;
case GL_LUMINANCE_ALPHA:
- componentMapping->r = ConvertSwizzleStateToVkSwizzle(swizzleState.swizzleRed);
- componentMapping->g = ConvertSwizzleStateToVkSwizzle(swizzleState.swizzleRed);
- componentMapping->b = ConvertSwizzleStateToVkSwizzle(swizzleState.swizzleRed);
- componentMapping->a = ConvertSwizzleStateToVkSwizzle(swizzleState.swizzleGreen);
+ swizzleStateOut->swizzleRed = swizzleState.swizzleRed;
+ swizzleStateOut->swizzleGreen = swizzleState.swizzleRed;
+ swizzleStateOut->swizzleBlue = swizzleState.swizzleRed;
+ swizzleStateOut->swizzleAlpha = swizzleState.swizzleGreen;
break;
case GL_ALPHA:
- componentMapping->r = VK_COMPONENT_SWIZZLE_ZERO;
- componentMapping->g = VK_COMPONENT_SWIZZLE_ZERO;
- componentMapping->b = VK_COMPONENT_SWIZZLE_ZERO;
- componentMapping->a = ConvertSwizzleStateToVkSwizzle(swizzleState.swizzleRed);
+ swizzleStateOut->swizzleRed = GL_ZERO;
+ swizzleStateOut->swizzleGreen = GL_ZERO;
+ swizzleStateOut->swizzleBlue = GL_ZERO;
+ swizzleStateOut->swizzleAlpha = swizzleState.swizzleRed;
break;
default:
- componentMapping->r = ConvertSwizzleStateToVkSwizzle(swizzleState.swizzleRed);
- componentMapping->g = ConvertSwizzleStateToVkSwizzle(swizzleState.swizzleGreen);
- componentMapping->b = ConvertSwizzleStateToVkSwizzle(swizzleState.swizzleBlue);
- componentMapping->a = ConvertSwizzleStateToVkSwizzle(swizzleState.swizzleAlpha);
+ *swizzleStateOut = swizzleState;
break;
}
}
@@ -88,8 +63,8 @@
ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer();
- renderer->releaseResource(*this, &mImage);
- renderer->releaseResource(*this, &mDeviceMemory);
+ mImage.release(renderer->getCurrentQueueSerial(), renderer);
+
renderer->releaseResource(*this, &mImageView);
renderer->releaseResource(*this, &mSampler);
@@ -123,8 +98,7 @@
if (desc.size != size ||
!gl::Format::SameSized(desc.format, gl::Format(internalFormat, type)))
{
- renderer->releaseResource(*this, &mImage);
- renderer->releaseResource(*this, &mDeviceMemory);
+ mImage.release(renderer->getCurrentQueueSerial(), renderer);
renderer->releaseResource(*this, &mImageView);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
@@ -148,62 +122,28 @@
if (!mImage.valid())
{
- ASSERT(!mDeviceMemory.valid() && !mImageView.valid());
+ VkImageUsageFlags usage =
+ (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
+ ANGLE_TRY(mImage.init2D(device, size, vkFormat, 1, usage));
- VkImageCreateInfo imageInfo;
- imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
- imageInfo.pNext = nullptr;
- imageInfo.flags = 0;
- imageInfo.imageType = VK_IMAGE_TYPE_2D;
- imageInfo.format = vkFormat.vkTextureFormat;
- imageInfo.extent.width = size.width;
- imageInfo.extent.height = size.height;
- imageInfo.extent.depth = size.depth;
- imageInfo.mipLevels = 1;
- imageInfo.arrayLayers = 1;
- imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
- imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+ VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ ANGLE_TRY(mImage.initMemory(device, renderer->getMemoryProperties(), flags));
- // TODO(jmadill): Are all these image transfer bits necessary?
- imageInfo.usage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
- imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- imageInfo.queueFamilyIndexCount = 0;
- imageInfo.pQueueFamilyIndices = nullptr;
- imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ gl::SwizzleState mappedSwizzle;
+ MapSwizzleState(formatInfo.internalFormat, mState.getSwizzleState(), &mappedSwizzle);
- ANGLE_TRY(mImage.init(device, imageInfo));
-
- VkMemoryPropertyFlags flags = (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
- size_t requiredSize = 0;
- ANGLE_TRY(vk::AllocateImageMemory(renderer, flags, &mImage, &mDeviceMemory, &requiredSize));
-
- VkImageViewCreateInfo viewInfo;
- viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
- viewInfo.pNext = nullptr;
- viewInfo.flags = 0;
- viewInfo.image = mImage.getHandle();
- viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
- viewInfo.format = vkFormat.vkTextureFormat;
- viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- viewInfo.subresourceRange.baseMipLevel = 0;
- viewInfo.subresourceRange.levelCount = 1;
- viewInfo.subresourceRange.baseArrayLayer = 0;
- viewInfo.subresourceRange.layerCount = 1;
-
- FillComponentsSwizzleParameters(internalFormat, mState.getSwizzleState(),
- &viewInfo.components);
-
- ANGLE_TRY(mImageView.init(device, viewInfo));
+ ANGLE_TRY(
+ mImage.initImageView(device, VK_IMAGE_ASPECT_COLOR_BIT, mappedSwizzle, &mImageView));
// TODO(jmadill): Fold this into the RenderPass load/store ops. http://anglebug.com/2361
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(beginWriteResource(renderer, &commandBuffer));
VkClearColorValue black = {{0}};
- mImage.changeLayoutWithStages(
+ mImage.getImage().changeLayoutWithStages(
VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer);
- commandBuffer->clearSingleColorImage(mImage, black);
+ commandBuffer->clearSingleColorImage(mImage.getImage(), black);
}
if (!mSampler.valid())
@@ -233,7 +173,7 @@
ANGLE_TRY(mSampler.init(device, samplerInfo));
}
- mRenderTarget.image = &mImage;
+ mRenderTarget.image = &mImage.getImage();
mRenderTarget.imageView = &mImageView;
mRenderTarget.format = &vkFormat;
mRenderTarget.extents = size;
@@ -275,9 +215,9 @@
const gl::Extents &size = mRenderTarget.extents;
const vk::Format &vkFormat = *mRenderTarget.format;
- vk::StagingImage stagingImage;
- ANGLE_TRY(stagingImage.init(contextVk, TextureDimension::TEX_2D, vkFormat, size,
- vk::StagingUsage::Write));
+ vk::ImageHelper stagingImage;
+ ANGLE_TRY(stagingImage.init2DStaging(device, renderer->getMemoryProperties(), vkFormat, size,
+ vk::StagingUsage::Write));
GLuint inputRowPitch = 0;
ANGLE_TRY_RESULT(
@@ -322,12 +262,12 @@
stagingImage.getImage().changeLayoutWithStages(
VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer);
- mImage.changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
- VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer);
+ mImage.getImage().changeLayoutWithStages(
+ VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer);
gl::Box wholeRegion(0, 0, 0, size.width, size.height, size.depth);
- commandBuffer->copySingleImage(stagingImage.getImage(), mImage, wholeRegion,
+ commandBuffer->copySingleImage(stagingImage.getImage(), mImage.getImage(), wholeRegion,
VK_IMAGE_ASPECT_COLOR_BIT);
// Immediately release staging image.
@@ -472,12 +412,12 @@
const vk::Image &TextureVk::getImage() const
{
ASSERT(mImage.valid());
- return mImage;
+ return mImage.getImage();
}
const vk::ImageView &TextureVk::getImageView() const
{
- ASSERT(mImageView.valid());
+ ASSERT(mImage.valid());
return mImageView;
}
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.h b/src/libANGLE/renderer/vulkan/TextureVk.h
index 7c715f8..15ef6f8 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.h
+++ b/src/libANGLE/renderer/vulkan/TextureVk.h
@@ -122,9 +122,7 @@
GLenum type,
const uint8_t *pixels);
- // TODO(jmadill): support a more flexible storage back-end.
- vk::Image mImage;
- vk::DeviceMemory mDeviceMemory;
+ vk::ImageHelper mImage;
vk::ImageView mImageView;
vk::Sampler mSampler;
diff --git a/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp b/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
index 7af7e04..e70aa77 100644
--- a/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
@@ -107,36 +107,13 @@
}
}
-VkSampleCountFlagBits ConvertSamples(GLint sampleCount)
-{
- switch (sampleCount)
- {
- case 0:
- case 1:
- return VK_SAMPLE_COUNT_1_BIT;
- case 2:
- return VK_SAMPLE_COUNT_2_BIT;
- case 4:
- return VK_SAMPLE_COUNT_4_BIT;
- case 8:
- return VK_SAMPLE_COUNT_8_BIT;
- case 16:
- return VK_SAMPLE_COUNT_16_BIT;
- case 32:
- return VK_SAMPLE_COUNT_32_BIT;
- default:
- UNREACHABLE();
- return VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM;
- }
-}
-
void UnpackAttachmentDesc(VkAttachmentDescription *desc,
const vk::PackedAttachmentDesc &packedDesc,
const vk::PackedAttachmentOpsDesc &ops)
{
desc->flags = static_cast<VkAttachmentDescriptionFlags>(packedDesc.flags);
desc->format = static_cast<VkFormat>(packedDesc.format);
- desc->samples = ConvertSamples(packedDesc.samples);
+ desc->samples = gl_vk::GetSamples(packedDesc.samples);
desc->loadOp = static_cast<VkAttachmentLoadOp>(ops.loadOp);
desc->storeOp = static_cast<VkAttachmentStoreOp>(ops.storeOp);
desc->stencilLoadOp = static_cast<VkAttachmentLoadOp>(ops.stencilLoadOp);
@@ -545,7 +522,7 @@
multisampleState.pNext = nullptr;
multisampleState.flags = 0;
multisampleState.rasterizationSamples =
- ConvertSamples(mMultisampleStateInfo.rasterizationSamples);
+ gl_vk::GetSamples(mMultisampleStateInfo.rasterizationSamples);
multisampleState.sampleShadingEnable =
static_cast<VkBool32>(mMultisampleStateInfo.sampleShadingEnable);
multisampleState.minSampleShading = mMultisampleStateInfo.minSampleShading;
diff --git a/src/libANGLE/renderer/vulkan/vk_utils.cpp b/src/libANGLE/renderer/vulkan/vk_utils.cpp
index 851b416..d0f63dd 100644
--- a/src/libANGLE/renderer/vulkan/vk_utils.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_utils.cpp
@@ -173,15 +173,13 @@
}
template <typename T>
-vk::Error AllocateBufferOrImageMemory(RendererVk *renderer,
+vk::Error AllocateBufferOrImageMemory(VkDevice device,
+ const vk::MemoryProperties &memoryProperties,
VkMemoryPropertyFlags memoryPropertyFlags,
T *bufferOrImage,
vk::DeviceMemory *deviceMemoryOut,
size_t *requiredSizeOut)
{
- VkDevice device = renderer->getDevice();
- const vk::MemoryProperties &memoryProperties = renderer->getMemoryProperties();
-
// Call driver to determine memory requirements.
VkMemoryRequirements memoryRequirements;
bufferOrImage->getMemoryRequirements(device, &memoryRequirements);
@@ -906,79 +904,6 @@
return NoError();
}
-// StagingImage implementation.
-StagingImage::StagingImage() : mSize(0)
-{
-}
-
-StagingImage::StagingImage(StagingImage &&other)
- : mImage(std::move(other.mImage)),
- mDeviceMemory(std::move(other.mDeviceMemory)),
- mSize(other.mSize)
-{
- other.mSize = 0;
-}
-
-void StagingImage::destroy(VkDevice device)
-{
- mImage.destroy(device);
- mDeviceMemory.destroy(device);
-}
-
-Error StagingImage::init(ContextVk *contextVk,
- TextureDimension dimension,
- const Format &format,
- const gl::Extents &extent,
- StagingUsage usage)
-{
- VkDevice device = contextVk->getDevice();
- RendererVk *renderer = contextVk->getRenderer();
- uint32_t queueFamilyIndex = renderer->getQueueFamilyIndex();
-
- VkImageCreateInfo createInfo;
-
- createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
- createInfo.pNext = nullptr;
- createInfo.flags = 0;
- createInfo.imageType = VK_IMAGE_TYPE_2D;
- createInfo.format = format.vkTextureFormat;
- createInfo.extent.width = static_cast<uint32_t>(extent.width);
- createInfo.extent.height = static_cast<uint32_t>(extent.height);
- createInfo.extent.depth = static_cast<uint32_t>(extent.depth);
- createInfo.mipLevels = 1;
- createInfo.arrayLayers = 1;
- createInfo.samples = VK_SAMPLE_COUNT_1_BIT;
- createInfo.tiling = VK_IMAGE_TILING_LINEAR;
- createInfo.usage = GetStagingImageUsageFlags(usage);
- createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- createInfo.queueFamilyIndexCount = 1;
- createInfo.pQueueFamilyIndices = &queueFamilyIndex;
-
- // Use Preinitialized for writable staging images - in these cases we want to map the memory
- // before we do a copy. For readback images, use an undefined layout.
- createInfo.initialLayout = usage == vk::StagingUsage::Read ? VK_IMAGE_LAYOUT_UNDEFINED
- : VK_IMAGE_LAYOUT_PREINITIALIZED;
-
- ANGLE_TRY(mImage.init(device, createInfo));
-
- // Allocate and bind host visible and coherent Image memory.
- // TODO(ynovikov): better approach would be to request just visible memory,
- // and call vkInvalidateMappedMemoryRanges if the allocated memory is not coherent.
- // This would solve potential issues of:
- // 1) not having (enough) coherent memory and 2) coherent memory being slower
- VkMemoryPropertyFlags memoryPropertyFlags =
- (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
- ANGLE_TRY(AllocateImageMemory(renderer, memoryPropertyFlags, &mImage, &mDeviceMemory, &mSize));
-
- return NoError();
-}
-
-void StagingImage::dumpResources(Serial serial, std::vector<vk::GarbageObject> *garbageQueue)
-{
- mImage.dumpResources(serial, garbageQueue);
- mDeviceMemory.dumpResources(serial, garbageQueue);
-}
-
// Buffer implementation.
Buffer::Buffer()
{
@@ -1269,8 +1194,11 @@
DeviceMemory *deviceMemoryOut,
size_t *requiredSizeOut)
{
- return AllocateBufferOrImageMemory(renderer, memoryPropertyFlags, buffer, deviceMemoryOut,
- requiredSizeOut);
+ VkDevice device = renderer->getDevice();
+ const vk::MemoryProperties &memoryProperties = renderer->getMemoryProperties();
+
+ return AllocateBufferOrImageMemory(device, memoryProperties, memoryPropertyFlags, buffer,
+ deviceMemoryOut, requiredSizeOut);
}
Error AllocateImageMemory(RendererVk *renderer,
@@ -1279,8 +1207,11 @@
DeviceMemory *deviceMemoryOut,
size_t *requiredSizeOut)
{
- return AllocateBufferOrImageMemory(renderer, memoryPropertyFlags, image, deviceMemoryOut,
- requiredSizeOut);
+ VkDevice device = renderer->getDevice();
+ const vk::MemoryProperties &memoryProperties = renderer->getMemoryProperties();
+
+ return AllocateBufferOrImageMemory(device, memoryProperties, memoryPropertyFlags, image,
+ deviceMemoryOut, requiredSizeOut);
}
// GarbageObject implementation.
@@ -1488,6 +1419,200 @@
mLineLoopIndexBuffer = VK_NULL_HANDLE;
}
}
+
+// ImageHelper implementation.
+ImageHelper::ImageHelper() : mFormat(nullptr), mSamples(0), mAllocatedMemorySize(0)
+{
+}
+
+ImageHelper::~ImageHelper()
+{
+ ASSERT(!valid());
+}
+
+bool ImageHelper::valid() const
+{
+ return mImage.valid();
+}
+
+Error ImageHelper::init2D(VkDevice device,
+ const gl::Extents &extents,
+ const Format &format,
+ GLint samples,
+ VkImageUsageFlags usage)
+{
+ ASSERT(!valid());
+
+ mExtents = extents;
+ mFormat = &format;
+ mSamples = samples;
+
+ VkImageCreateInfo imageInfo;
+ imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ imageInfo.pNext = nullptr;
+ imageInfo.flags = 0;
+ imageInfo.imageType = VK_IMAGE_TYPE_2D;
+ imageInfo.format = format.vkTextureFormat;
+ imageInfo.extent.width = static_cast<uint32_t>(extents.width);
+ imageInfo.extent.height = static_cast<uint32_t>(extents.height);
+ imageInfo.extent.depth = 1;
+ imageInfo.mipLevels = 1;
+ imageInfo.arrayLayers = 1;
+ imageInfo.samples = gl_vk::GetSamples(samples);
+ imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+ imageInfo.usage = usage;
+ imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ imageInfo.queueFamilyIndexCount = 0;
+ imageInfo.pQueueFamilyIndices = nullptr;
+ imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+
+ ANGLE_TRY(mImage.init(device, imageInfo));
+ return NoError();
+}
+
+void ImageHelper::release(Serial serial, RendererVk *renderer)
+{
+ renderer->releaseObject(serial, &mImage);
+ renderer->releaseObject(serial, &mDeviceMemory);
+}
+
+Error ImageHelper::initMemory(VkDevice device,
+ const MemoryProperties &memoryProperties,
+ VkMemoryPropertyFlags flags)
+{
+ ANGLE_TRY(AllocateBufferOrImageMemory(device, memoryProperties, flags, &mImage, &mDeviceMemory,
+ &mAllocatedMemorySize));
+ return NoError();
+}
+
+Error ImageHelper::initImageView(VkDevice device,
+ VkImageAspectFlags aspectMask,
+ const gl::SwizzleState &swizzleMap,
+ vk::ImageView *imageViewOut)
+{
+ VkImageViewCreateInfo viewInfo;
+ viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ viewInfo.pNext = nullptr;
+ viewInfo.flags = 0;
+ viewInfo.image = mImage.getHandle();
+ viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.format = mFormat->vkTextureFormat;
+ viewInfo.components.r = gl_vk::GetSwizzle(swizzleMap.swizzleRed);
+ viewInfo.components.g = gl_vk::GetSwizzle(swizzleMap.swizzleGreen);
+ viewInfo.components.b = gl_vk::GetSwizzle(swizzleMap.swizzleBlue);
+ viewInfo.components.a = gl_vk::GetSwizzle(swizzleMap.swizzleAlpha);
+ viewInfo.subresourceRange.aspectMask = aspectMask;
+ viewInfo.subresourceRange.baseMipLevel = 0;
+ viewInfo.subresourceRange.levelCount = 1;
+ viewInfo.subresourceRange.baseArrayLayer = 0;
+ viewInfo.subresourceRange.layerCount = 1;
+
+ ANGLE_TRY(imageViewOut->init(device, viewInfo));
+ return NoError();
+}
+
+void ImageHelper::destroy(VkDevice device)
+{
+ mImage.destroy(device);
+ mDeviceMemory.destroy(device);
+}
+
+Error ImageHelper::init2DStaging(VkDevice device,
+ const MemoryProperties &memoryProperties,
+ const Format &format,
+ const gl::Extents &extents,
+ StagingUsage usage)
+{
+ ASSERT(!valid());
+
+ mExtents = extents;
+ mFormat = &format;
+ mSamples = 1;
+
+ // Use Preinitialized for writable staging images - in these cases we want to map the memory
+ // before we do a copy. For readback images, use an undefined layout.
+ VkImageLayout initialLayout = usage == vk::StagingUsage::Read ? VK_IMAGE_LAYOUT_UNDEFINED
+ : VK_IMAGE_LAYOUT_PREINITIALIZED;
+
+ VkImageCreateInfo imageInfo;
+ imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ imageInfo.pNext = nullptr;
+ imageInfo.flags = 0;
+ imageInfo.imageType = VK_IMAGE_TYPE_2D;
+ imageInfo.format = format.vkTextureFormat;
+ imageInfo.extent.width = static_cast<uint32_t>(extents.width);
+ imageInfo.extent.height = static_cast<uint32_t>(extents.height);
+ imageInfo.extent.depth = 1;
+ imageInfo.mipLevels = 1;
+ imageInfo.arrayLayers = 1;
+ imageInfo.samples = gl_vk::GetSamples(mSamples);
+ imageInfo.tiling = VK_IMAGE_TILING_LINEAR;
+ imageInfo.usage = GetStagingImageUsageFlags(usage);
+ imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ imageInfo.queueFamilyIndexCount = 0;
+ imageInfo.pQueueFamilyIndices = nullptr;
+ imageInfo.initialLayout = initialLayout;
+
+ ANGLE_TRY(mImage.init(device, imageInfo));
+
+ // Allocate and bind host visible and coherent Image memory.
+ // TODO(ynovikov): better approach would be to request just visible memory,
+ // and call vkInvalidateMappedMemoryRanges if the allocated memory is not coherent.
+ // This would solve potential issues of:
+ // 1) not having (enough) coherent memory and 2) coherent memory being slower
+ VkMemoryPropertyFlags memoryPropertyFlags =
+ (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
+ ANGLE_TRY(initMemory(device, memoryProperties, memoryPropertyFlags));
+
+ return NoError();
+}
+
+void ImageHelper::dumpResources(Serial serial, std::vector<vk::GarbageObject> *garbageQueue)
+{
+ mImage.dumpResources(serial, garbageQueue);
+ mDeviceMemory.dumpResources(serial, garbageQueue);
+}
+
+Image &ImageHelper::getImage()
+{
+ return mImage;
+}
+
+const Image &ImageHelper::getImage() const
+{
+ return mImage;
+}
+
+DeviceMemory &ImageHelper::getDeviceMemory()
+{
+ return mDeviceMemory;
+}
+
+const DeviceMemory &ImageHelper::getDeviceMemory() const
+{
+ return mDeviceMemory;
+}
+
+const gl::Extents &ImageHelper::getExtents() const
+{
+ return mExtents;
+}
+
+const Format &ImageHelper::getFormat() const
+{
+ return *mFormat;
+}
+
+GLint ImageHelper::getSamples() const
+{
+ return mSamples;
+}
+
+size_t ImageHelper::getAllocatedMemorySize() const
+{
+ return mAllocatedMemorySize;
+}
+
} // namespace vk
namespace gl_vk
@@ -1552,6 +1677,50 @@
}
}
+VkSampleCountFlagBits GetSamples(GLint sampleCount)
+{
+ switch (sampleCount)
+ {
+ case 0:
+ case 1:
+ return VK_SAMPLE_COUNT_1_BIT;
+ case 2:
+ return VK_SAMPLE_COUNT_2_BIT;
+ case 4:
+ return VK_SAMPLE_COUNT_4_BIT;
+ case 8:
+ return VK_SAMPLE_COUNT_8_BIT;
+ case 16:
+ return VK_SAMPLE_COUNT_16_BIT;
+ case 32:
+ return VK_SAMPLE_COUNT_32_BIT;
+ default:
+ UNREACHABLE();
+ return VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM;
+ }
+}
+
+VkComponentSwizzle GetSwizzle(const GLenum swizzle)
+{
+ switch (swizzle)
+ {
+ case GL_ALPHA:
+ return VK_COMPONENT_SWIZZLE_A;
+ case GL_RED:
+ return VK_COMPONENT_SWIZZLE_R;
+ case GL_GREEN:
+ return VK_COMPONENT_SWIZZLE_G;
+ case GL_BLUE:
+ return VK_COMPONENT_SWIZZLE_B;
+ case GL_ZERO:
+ return VK_COMPONENT_SWIZZLE_ZERO;
+ case GL_ONE:
+ return VK_COMPONENT_SWIZZLE_ONE;
+ default:
+ UNREACHABLE();
+ return VK_COMPONENT_SWIZZLE_IDENTITY;
+ }
+}
} // namespace gl_vk
ResourceVk::ResourceVk() : mCurrentWritingNode(nullptr)
diff --git a/src/libANGLE/renderer/vulkan/vk_utils.h b/src/libANGLE/renderer/vulkan/vk_utils.h
index fe3afc7..224a161 100644
--- a/src/libANGLE/renderer/vulkan/vk_utils.h
+++ b/src/libANGLE/renderer/vulkan/vk_utils.h
@@ -41,6 +41,7 @@
struct Extents;
struct RasterizerState;
struct Rectangle;
+struct SwizzleState;
struct VertexAttribute;
class VertexBinding;
@@ -586,34 +587,6 @@
VkResult getStatus(VkDevice device) const;
};
-// Helper class for managing a CPU/GPU transfer Image.
-class StagingImage final : angle::NonCopyable
-{
- public:
- StagingImage();
- StagingImage(StagingImage &&other);
- void destroy(VkDevice device);
-
- vk::Error init(ContextVk *contextVk,
- TextureDimension dimension,
- const Format &format,
- const gl::Extents &extent,
- StagingUsage usage);
-
- Image &getImage() { return mImage; }
- const Image &getImage() const { return mImage; }
- DeviceMemory &getDeviceMemory() { return mDeviceMemory; }
- const DeviceMemory &getDeviceMemory() const { return mDeviceMemory; }
- VkDeviceSize getSize() const { return mSize; }
-
- void dumpResources(Serial serial, std::vector<vk::GarbageObject> *garbageQueue);
-
- private:
- Image mImage;
- DeviceMemory mDeviceMemory;
- size_t mSize;
-};
-
// Similar to StagingImage, for Buffers.
class StagingBuffer final : angle::NonCopyable
{
@@ -730,6 +703,58 @@
Optional<int> mLineLoopBufferLastIndex;
};
+class ImageHelper final : angle::NonCopyable
+{
+ public:
+ ImageHelper();
+ ~ImageHelper();
+
+ bool valid() const;
+
+ Error init2D(VkDevice device,
+ const gl::Extents &extents,
+ const Format &format,
+ GLint samples,
+ VkImageUsageFlags usage);
+ Error initMemory(VkDevice device,
+ const MemoryProperties &memoryProperties,
+ VkMemoryPropertyFlags flags);
+ Error initImageView(VkDevice device,
+ VkImageAspectFlags aspectMask,
+ const gl::SwizzleState &swizzleMap,
+ ImageView *imageViewOut);
+ Error init2DStaging(VkDevice device,
+ const MemoryProperties &memoryProperties,
+ const Format &format,
+ const gl::Extents &extent,
+ StagingUsage usage);
+
+ void release(Serial serial, RendererVk *renderer);
+ void destroy(VkDevice device);
+ void dumpResources(Serial serial, std::vector<vk::GarbageObject> *garbageQueue);
+
+ Image &getImage();
+ const Image &getImage() const;
+ DeviceMemory &getDeviceMemory();
+ const DeviceMemory &getDeviceMemory() const;
+
+ const gl::Extents &getExtents() const;
+ const Format &getFormat() const;
+ GLint getSamples() const;
+ size_t getAllocatedMemorySize() const;
+
+ private:
+ // Vulkan objects.
+ Image mImage;
+ DeviceMemory mDeviceMemory;
+
+ // Image properties.
+ gl::Extents mExtents;
+ const Format *mFormat;
+ GLint mSamples;
+ size_t mAllocatedMemorySize;
+};
+
} // namespace vk
namespace gl_vk
@@ -737,6 +762,8 @@
VkPrimitiveTopology GetPrimitiveTopology(GLenum mode);
VkCullModeFlags GetCullMode(const gl::RasterizerState &rasterState);
VkFrontFace GetFrontFace(GLenum frontFace);
+VkSampleCountFlagBits GetSamples(GLint sampleCount);
+VkComponentSwizzle GetSwizzle(const GLenum swizzle);
} // namespace gl_vk
// This is a helper class for back-end objects used in Vk command buffers. It records a serial