Commit 93edca16 by Jamie Madill Committed by Commit Bot

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/980772Reviewed-by: 's avatarFrank Henigman <fjhenigman@chromium.org> Reviewed-by: 's avatarLuc Ferron <lucferron@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 6bc264ae
...@@ -71,10 +71,7 @@ bool IsMipmapFiltered(const SamplerState &samplerState) ...@@ -71,10 +71,7 @@ bool IsMipmapFiltered(const SamplerState &samplerState)
} }
SwizzleState::SwizzleState() SwizzleState::SwizzleState()
: swizzleRed(GL_INVALID_INDEX), : swizzleRed(GL_RED), swizzleGreen(GL_GREEN), swizzleBlue(GL_BLUE), swizzleAlpha(GL_ALPHA)
swizzleGreen(GL_INVALID_INDEX),
swizzleBlue(GL_INVALID_INDEX),
swizzleAlpha(GL_INVALID_INDEX)
{ {
} }
...@@ -102,7 +99,6 @@ bool SwizzleState::operator!=(const SwizzleState &other) const ...@@ -102,7 +99,6 @@ bool SwizzleState::operator!=(const SwizzleState &other) const
TextureState::TextureState(TextureType type) TextureState::TextureState(TextureType type)
: mType(type), : mType(type),
mSwizzleState(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA),
mSamplerState(SamplerState::CreateDefaultForTarget(type)), mSamplerState(SamplerState::CreateDefaultForTarget(type)),
mBaseLevel(0), mBaseLevel(0),
mMaxLevel(1000), mMaxLevel(1000),
......
...@@ -261,8 +261,9 @@ gl::Error FramebufferVk::readPixels(const gl::Context *context, ...@@ -261,8 +261,9 @@ gl::Error FramebufferVk::readPixels(const gl::Context *context,
ASSERT(renderTarget); ASSERT(renderTarget);
vk::Image *readImage = renderTarget->image; vk::Image *readImage = renderTarget->image;
vk::StagingImage stagingImage; vk::ImageHelper stagingImage;
ANGLE_TRY(stagingImage.init(contextVk, TextureDimension::TEX_2D, *renderTarget->format, ANGLE_TRY(stagingImage.init2DStaging(
device, renderer->getMemoryProperties(), *renderTarget->format,
gl::Extents(area.width, area.height, 1), vk::StagingUsage::Read)); gl::Extents(area.width, area.height, 1), vk::StagingUsage::Read));
vk::CommandBuffer *commandBuffer = nullptr; vk::CommandBuffer *commandBuffer = nullptr;
...@@ -302,10 +303,10 @@ gl::Error FramebufferVk::readPixels(const gl::Context *context, ...@@ -302,10 +303,10 @@ gl::Error FramebufferVk::readPixels(const gl::Context *context,
// TODO(jmadill): parameters // TODO(jmadill): parameters
uint8_t *mapPointer = nullptr; uint8_t *mapPointer = nullptr;
ANGLE_TRY( ANGLE_TRY(stagingImage.getDeviceMemory().map(device, 0, stagingImage.getAllocatedMemorySize(),
stagingImage.getDeviceMemory().map(device, 0, stagingImage.getSize(), 0, &mapPointer)); 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. // TODO(jmadill): Use pixel bytes from the ANGLE format directly.
const auto &glFormat = gl::GetSizedInternalFormatInfo(angleFormat.glInternalFormat); const auto &glFormat = gl::GetSizedInternalFormatInfo(angleFormat.glInternalFormat);
......
...@@ -23,10 +23,9 @@ constexpr VkClearColorValue kBlackClearColorValue = {{0}}; ...@@ -23,10 +23,9 @@ constexpr VkClearColorValue kBlackClearColorValue = {{0}};
} // anonymous namespace } // anonymous namespace
RenderbufferVk::RenderbufferVk(const gl::RenderbufferState &state) RenderbufferVk::RenderbufferVk(const gl::RenderbufferState &state) : RenderbufferImpl(state)
: RenderbufferImpl(state), mAllocatedMemorySize(0)
{ {
mRenderTarget.image = &mImage; mRenderTarget.image = &mImage.getImage();
mRenderTarget.imageView = &mImageView; mRenderTarget.imageView = &mImageView;
mRenderTarget.resource = this; mRenderTarget.resource = this;
} }
...@@ -40,8 +39,7 @@ gl::Error RenderbufferVk::onDestroy(const gl::Context *context) ...@@ -40,8 +39,7 @@ gl::Error RenderbufferVk::onDestroy(const gl::Context *context)
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
renderer->releaseResource(*this, &mImage); mImage.release(renderer->getCurrentQueueSerial(), renderer);
renderer->releaseResource(*this, &mDeviceMemory);
renderer->releaseResource(*this, &mImageView); renderer->releaseResource(*this, &mImageView);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS); onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
...@@ -66,11 +64,8 @@ gl::Error RenderbufferVk::setStorage(const gl::Context *context, ...@@ -66,11 +64,8 @@ gl::Error RenderbufferVk::setStorage(const gl::Context *context,
static_cast<GLsizei>(width) != mState.getWidth() || static_cast<GLsizei>(width) != mState.getWidth() ||
static_cast<GLsizei>(height) != mState.getHeight()) static_cast<GLsizei>(height) != mState.getHeight())
{ {
ASSERT(mImageView.valid()); mImage.release(renderer->getCurrentQueueSerial(), renderer);
renderer->releaseResource(*this, &mImage);
renderer->releaseResource(*this, &mDeviceMemory);
renderer->releaseResource(*this, &mImageView); renderer->releaseResource(*this, &mImageView);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS); onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
} }
} }
...@@ -92,71 +87,34 @@ gl::Error RenderbufferVk::setStorage(const gl::Context *context, ...@@ -92,71 +87,34 @@ gl::Error RenderbufferVk::setStorage(const gl::Context *context,
(textureFormat.redBits > 0 ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) | (textureFormat.redBits > 0 ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) |
(isDepthOrStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0); (isDepthOrStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0);
VkImageCreateInfo imageInfo; ANGLE_TRY(mImage.init2D(device, mRenderTarget.extents, vkFormat, 1, usage));
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));
VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
ANGLE_TRY(vk::AllocateImageMemory(renderer, flags, &mImage, &mDeviceMemory, ANGLE_TRY(mImage.initMemory(device, renderer->getMemoryProperties(), flags));
&mAllocatedMemorySize));
VkImageAspectFlags aspect = VkImageAspectFlags aspect =
(textureFormat.depthBits > 0 ? VK_IMAGE_ASPECT_DEPTH_BIT : 0) | (textureFormat.depthBits > 0 ? VK_IMAGE_ASPECT_DEPTH_BIT : 0) |
(textureFormat.stencilBits > 0 ? VK_IMAGE_ASPECT_STENCIL_BIT : 0) | (textureFormat.stencilBits > 0 ? VK_IMAGE_ASPECT_STENCIL_BIT : 0) |
(textureFormat.redBits > 0 ? VK_IMAGE_ASPECT_COLOR_BIT : 0); (textureFormat.redBits > 0 ? VK_IMAGE_ASPECT_COLOR_BIT : 0);
// Allocate ImageView. ANGLE_TRY(mImage.initImageView(device, aspect, gl::SwizzleState(), &mImageView));
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));
// TODO(jmadill): Fold this into the RenderPass load/store ops. http://anglebug.com/2361 // TODO(jmadill): Fold this into the RenderPass load/store ops. http://anglebug.com/2361
vk::CommandBuffer *commandBuffer = nullptr; vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(beginWriteResource(renderer, &commandBuffer)); ANGLE_TRY(beginWriteResource(renderer, &commandBuffer));
mImage.changeLayoutWithStages(aspect, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, mImage.getImage().changeLayoutWithStages(
VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer); 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) if (isDepthOrStencilFormat)
{ {
commandBuffer->clearSingleDepthStencilImage(mImage, aspect, commandBuffer->clearSingleDepthStencilImage(mImage.getImage(), aspect,
kDefaultClearDepthStencilValue); kDefaultClearDepthStencilValue);
} }
else else
{ {
commandBuffer->clearSingleColorImage(mImage, kBlackClearColorValue); commandBuffer->clearSingleColorImage(mImage.getImage(), kBlackClearColorValue);
} }
} }
......
...@@ -45,10 +45,8 @@ class RenderbufferVk : public RenderbufferImpl, public ResourceVk ...@@ -45,10 +45,8 @@ class RenderbufferVk : public RenderbufferImpl, public ResourceVk
const gl::ImageIndex &imageIndex) override; const gl::ImageIndex &imageIndex) override;
private: private:
vk::Image mImage; vk::ImageHelper mImage;
vk::DeviceMemory mDeviceMemory;
vk::ImageView mImageView; vk::ImageView mImageView;
size_t mAllocatedMemorySize;
RenderTargetVk mRenderTarget; RenderTargetVk mRenderTarget;
}; };
......
...@@ -122,9 +122,7 @@ class TextureVk : public TextureImpl, public ResourceVk ...@@ -122,9 +122,7 @@ class TextureVk : public TextureImpl, public ResourceVk
GLenum type, GLenum type,
const uint8_t *pixels); const uint8_t *pixels);
// TODO(jmadill): support a more flexible storage back-end. vk::ImageHelper mImage;
vk::Image mImage;
vk::DeviceMemory mDeviceMemory;
vk::ImageView mImageView; vk::ImageView mImageView;
vk::Sampler mSampler; vk::Sampler mSampler;
......
...@@ -107,36 +107,13 @@ uint8_t PackGLCompareFunc(GLenum compareFunc) ...@@ -107,36 +107,13 @@ uint8_t PackGLCompareFunc(GLenum compareFunc)
} }
} }
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, void UnpackAttachmentDesc(VkAttachmentDescription *desc,
const vk::PackedAttachmentDesc &packedDesc, const vk::PackedAttachmentDesc &packedDesc,
const vk::PackedAttachmentOpsDesc &ops) const vk::PackedAttachmentOpsDesc &ops)
{ {
desc->flags = static_cast<VkAttachmentDescriptionFlags>(packedDesc.flags); desc->flags = static_cast<VkAttachmentDescriptionFlags>(packedDesc.flags);
desc->format = static_cast<VkFormat>(packedDesc.format); 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->loadOp = static_cast<VkAttachmentLoadOp>(ops.loadOp);
desc->storeOp = static_cast<VkAttachmentStoreOp>(ops.storeOp); desc->storeOp = static_cast<VkAttachmentStoreOp>(ops.storeOp);
desc->stencilLoadOp = static_cast<VkAttachmentLoadOp>(ops.stencilLoadOp); desc->stencilLoadOp = static_cast<VkAttachmentLoadOp>(ops.stencilLoadOp);
...@@ -545,7 +522,7 @@ Error PipelineDesc::initializePipeline(VkDevice device, ...@@ -545,7 +522,7 @@ Error PipelineDesc::initializePipeline(VkDevice device,
multisampleState.pNext = nullptr; multisampleState.pNext = nullptr;
multisampleState.flags = 0; multisampleState.flags = 0;
multisampleState.rasterizationSamples = multisampleState.rasterizationSamples =
ConvertSamples(mMultisampleStateInfo.rasterizationSamples); gl_vk::GetSamples(mMultisampleStateInfo.rasterizationSamples);
multisampleState.sampleShadingEnable = multisampleState.sampleShadingEnable =
static_cast<VkBool32>(mMultisampleStateInfo.sampleShadingEnable); static_cast<VkBool32>(mMultisampleStateInfo.sampleShadingEnable);
multisampleState.minSampleShading = mMultisampleStateInfo.minSampleShading; multisampleState.minSampleShading = mMultisampleStateInfo.minSampleShading;
......
...@@ -41,6 +41,7 @@ struct Box; ...@@ -41,6 +41,7 @@ struct Box;
struct Extents; struct Extents;
struct RasterizerState; struct RasterizerState;
struct Rectangle; struct Rectangle;
struct SwizzleState;
struct VertexAttribute; struct VertexAttribute;
class VertexBinding; class VertexBinding;
...@@ -586,34 +587,6 @@ class Fence final : public WrappedObject<Fence, VkFence> ...@@ -586,34 +587,6 @@ class Fence final : public WrappedObject<Fence, VkFence>
VkResult getStatus(VkDevice device) const; 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. // Similar to StagingImage, for Buffers.
class StagingBuffer final : angle::NonCopyable class StagingBuffer final : angle::NonCopyable
{ {
...@@ -730,6 +703,58 @@ class LineLoopHandler final : angle::NonCopyable, angle::ObserverInterface ...@@ -730,6 +703,58 @@ class LineLoopHandler final : angle::NonCopyable, angle::ObserverInterface
Optional<int> mLineLoopBufferLastIndex; 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 vk
namespace gl_vk namespace gl_vk
...@@ -737,6 +762,8 @@ namespace gl_vk ...@@ -737,6 +762,8 @@ namespace gl_vk
VkPrimitiveTopology GetPrimitiveTopology(GLenum mode); VkPrimitiveTopology GetPrimitiveTopology(GLenum mode);
VkCullModeFlags GetCullMode(const gl::RasterizerState &rasterState); VkCullModeFlags GetCullMode(const gl::RasterizerState &rasterState);
VkFrontFace GetFrontFace(GLenum frontFace); VkFrontFace GetFrontFace(GLenum frontFace);
VkSampleCountFlagBits GetSamples(GLint sampleCount);
VkComponentSwizzle GetSwizzle(const GLenum swizzle);
} // namespace gl_vk } // namespace gl_vk
// This is a helper class for back-end objects used in Vk command buffers. It records a serial // This is a helper class for back-end objects used in Vk command buffers. It records a serial
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment