Commit f3e823db by Geoff Lang Committed by Commit Bot

Vulkan: Store ImageHelper as a pointer in TextureVk and RenderbufferVk

Storing ImageHelper as a pointer allows the storage to be swapped or shared with other objects. BUG=angleproject:2668 Change-Id: I2e51f24737be59ffe9f472e9b0b592774a792cd1 Reviewed-on: https://chromium-review.googlesource.com/c/1409404 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent eb67ca6e
...@@ -16,11 +16,8 @@ ...@@ -16,11 +16,8 @@
namespace rx namespace rx
{ {
RenderTargetVk::RenderTargetVk(vk::ImageHelper *image, RenderTargetVk::RenderTargetVk()
vk::ImageView *imageView, : mImage(nullptr), mImageView(nullptr), mLayerIndex(0), mOwner(nullptr)
size_t layerIndex,
TextureVk *owner)
: mImage(image), mImageView(imageView), mLayerIndex(layerIndex), mOwner(owner)
{} {}
RenderTargetVk::~RenderTargetVk() {} RenderTargetVk::~RenderTargetVk() {}
...@@ -32,6 +29,25 @@ RenderTargetVk::RenderTargetVk(RenderTargetVk &&other) ...@@ -32,6 +29,25 @@ RenderTargetVk::RenderTargetVk(RenderTargetVk &&other)
mOwner(other.mOwner) mOwner(other.mOwner)
{} {}
void RenderTargetVk::init(vk::ImageHelper *image,
vk::ImageView *imageView,
size_t layerIndex,
TextureVk *owner)
{
mImage = image;
mImageView = imageView;
mLayerIndex = layerIndex;
mOwner = owner;
}
void RenderTargetVk::reset()
{
mImage = nullptr;
mImageView = nullptr;
mLayerIndex = 0;
mOwner = nullptr;
}
void RenderTargetVk::onColorDraw(vk::FramebufferHelper *framebufferVk, void RenderTargetVk::onColorDraw(vk::FramebufferHelper *framebufferVk,
vk::CommandBuffer *commandBuffer, vk::CommandBuffer *commandBuffer,
vk::RenderPassDesc *renderPassDesc) vk::RenderPassDesc *renderPassDesc)
......
...@@ -37,15 +37,18 @@ class TextureVk; ...@@ -37,15 +37,18 @@ class TextureVk;
class RenderTargetVk final : public FramebufferAttachmentRenderTarget class RenderTargetVk final : public FramebufferAttachmentRenderTarget
{ {
public: public:
RenderTargetVk(vk::ImageHelper *image, RenderTargetVk();
vk::ImageView *imageView,
size_t layerIndex,
TextureVk *ownwer);
~RenderTargetVk() override; ~RenderTargetVk() override;
// Used in std::vector initialization. // Used in std::vector initialization.
RenderTargetVk(RenderTargetVk &&other); RenderTargetVk(RenderTargetVk &&other);
void init(vk::ImageHelper *image,
vk::ImageView *imageView,
size_t layerIndex,
TextureVk *owner);
void reset();
// Note: RenderTargets should be called in order, with the depth/stencil onRender last. // Note: RenderTargets should be called in order, with the depth/stencil onRender last.
void onColorDraw(vk::FramebufferHelper *framebufferVk, void onColorDraw(vk::FramebufferHelper *framebufferVk,
vk::CommandBuffer *commandBuffer, vk::CommandBuffer *commandBuffer,
......
...@@ -24,7 +24,7 @@ constexpr VkClearColorValue kBlackClearColorValue = {{0}}; ...@@ -24,7 +24,7 @@ constexpr VkClearColorValue kBlackClearColorValue = {{0}};
} // anonymous namespace } // anonymous namespace
RenderbufferVk::RenderbufferVk(const gl::RenderbufferState &state) RenderbufferVk::RenderbufferVk(const gl::RenderbufferState &state)
: RenderbufferImpl(state), mRenderTarget(&mImage, &mImageView, 0, nullptr) : RenderbufferImpl(state), mImage(nullptr)
{} {}
RenderbufferVk::~RenderbufferVk() {} RenderbufferVk::~RenderbufferVk() {}
...@@ -34,8 +34,12 @@ void RenderbufferVk::onDestroy(const gl::Context *context) ...@@ -34,8 +34,12 @@ void RenderbufferVk::onDestroy(const gl::Context *context)
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
mImage.releaseImage(renderer); if (mImage)
mImage.releaseStagingBuffer(renderer); {
mImage->releaseImage(renderer);
mImage->releaseStagingBuffer(renderer);
SafeDelete(mImage);
}
renderer->releaseObject(renderer->getCurrentQueueSerial(), &mImageView); renderer->releaseObject(renderer->getCurrentQueueSerial(), &mImageView);
} }
...@@ -49,20 +53,25 @@ angle::Result RenderbufferVk::setStorage(const gl::Context *context, ...@@ -49,20 +53,25 @@ angle::Result RenderbufferVk::setStorage(const gl::Context *context,
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
const vk::Format &vkFormat = renderer->getFormat(internalformat); const vk::Format &vkFormat = renderer->getFormat(internalformat);
if (mImage.valid()) if (mImage != nullptr && mImage->valid())
{ {
// Check against the state if we need to recreate the storage. // Check against the state if we need to recreate the storage.
if (internalformat != mState.getFormat().info->internalFormat || if (internalformat != mState.getFormat().info->internalFormat ||
static_cast<GLsizei>(width) != mState.getWidth() || static_cast<GLsizei>(width) != mState.getWidth() ||
static_cast<GLsizei>(height) != mState.getHeight()) static_cast<GLsizei>(height) != mState.getHeight())
{ {
mImage.releaseImage(renderer); mImage->releaseImage(renderer);
renderer->releaseObject(renderer->getCurrentQueueSerial(), &mImageView); renderer->releaseObject(renderer->getCurrentQueueSerial(), &mImageView);
} }
} }
if (!mImage.valid() && (width != 0 && height != 0)) if ((mImage == nullptr || !mImage->valid()) && (width != 0 && height != 0))
{ {
if (mImage == nullptr)
{
mImage = new vk::ImageHelper();
}
const angle::Format &textureFormat = vkFormat.textureFormat(); const angle::Format &textureFormat = vkFormat.textureFormat();
bool isDepthOrStencilFormat = textureFormat.depthBits > 0 || textureFormat.stencilBits > 0; bool isDepthOrStencilFormat = textureFormat.depthBits > 0 || textureFormat.stencilBits > 0;
const VkImageUsageFlags usage = const VkImageUsageFlags usage =
...@@ -72,30 +81,33 @@ angle::Result RenderbufferVk::setStorage(const gl::Context *context, ...@@ -72,30 +81,33 @@ angle::Result RenderbufferVk::setStorage(const gl::Context *context,
(isDepthOrStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0); (isDepthOrStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0);
gl::Extents extents(static_cast<int>(width), static_cast<int>(height), 1); gl::Extents extents(static_cast<int>(width), static_cast<int>(height), 1);
ANGLE_TRY(mImage.init(contextVk, gl::TextureType::_2D, extents, vkFormat, 1, usage, 1, 1)); ANGLE_TRY(mImage->init(contextVk, gl::TextureType::_2D, extents, vkFormat, 1, usage, 1, 1));
VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
ANGLE_TRY(mImage.initMemory(contextVk, renderer->getMemoryProperties(), flags)); ANGLE_TRY(mImage->initMemory(contextVk, renderer->getMemoryProperties(), flags));
VkImageAspectFlags aspect = vk::GetFormatAspectFlags(textureFormat); VkImageAspectFlags aspect = vk::GetFormatAspectFlags(textureFormat);
// Note that LUMA textures are not color-renderable, so a read-view with swizzle is not // Note that LUMA textures are not color-renderable, so a read-view with swizzle is not
// needed. // needed.
ANGLE_TRY(mImage.initImageView(contextVk, gl::TextureType::_2D, aspect, gl::SwizzleState(), ANGLE_TRY(mImage->initImageView(contextVk, gl::TextureType::_2D, aspect, gl::SwizzleState(),
&mImageView, 1)); &mImageView, 1));
// 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(mImage.recordCommands(contextVk, &commandBuffer)); ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
if (isDepthOrStencilFormat) if (isDepthOrStencilFormat)
{ {
mImage.clearDepthStencil(aspect, aspect, kDefaultClearDepthStencilValue, commandBuffer); mImage->clearDepthStencil(aspect, aspect, kDefaultClearDepthStencilValue,
commandBuffer);
} }
else else
{ {
mImage.clearColor(kBlackClearColorValue, 0, 1, commandBuffer); mImage->clearColor(kBlackClearColorValue, 0, 1, commandBuffer);
} }
mRenderTarget.init(mImage, &mImageView, 0, nullptr);
} }
return angle::Result::Continue; return angle::Result::Continue;
...@@ -123,7 +135,7 @@ angle::Result RenderbufferVk::getAttachmentRenderTarget(const gl::Context *conte ...@@ -123,7 +135,7 @@ angle::Result RenderbufferVk::getAttachmentRenderTarget(const gl::Context *conte
const gl::ImageIndex &imageIndex, const gl::ImageIndex &imageIndex,
FramebufferAttachmentRenderTarget **rtOut) FramebufferAttachmentRenderTarget **rtOut)
{ {
ASSERT(mImage.valid()); ASSERT(mImage && mImage->valid());
*rtOut = &mRenderTarget; *rtOut = &mRenderTarget;
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -45,7 +45,7 @@ class RenderbufferVk : public RenderbufferImpl ...@@ -45,7 +45,7 @@ class RenderbufferVk : public RenderbufferImpl
const gl::ImageIndex &imageIndex) override; const gl::ImageIndex &imageIndex) override;
private: private:
vk::ImageHelper mImage; vk::ImageHelper *mImage;
vk::ImageView mImageView; vk::ImageView mImageView;
RenderTargetVk mRenderTarget; RenderTargetVk mRenderTarget;
}; };
......
...@@ -75,8 +75,9 @@ constexpr VkImageUsageFlags kSurfaceVKDepthStencilImageUsageFlags = ...@@ -75,8 +75,9 @@ constexpr VkImageUsageFlags kSurfaceVKDepthStencilImageUsageFlags =
} // namespace } // namespace
OffscreenSurfaceVk::AttachmentImage::AttachmentImage() OffscreenSurfaceVk::AttachmentImage::AttachmentImage()
: renderTarget(&image, &imageView, 0, nullptr) {
{} renderTarget.init(&image, &imageView, 0, nullptr);
}
OffscreenSurfaceVk::AttachmentImage::~AttachmentImage() = default; OffscreenSurfaceVk::AttachmentImage::~AttachmentImage() = default;
...@@ -273,11 +274,11 @@ WindowSurfaceVk::WindowSurfaceVk(const egl::SurfaceState &surfaceState, ...@@ -273,11 +274,11 @@ WindowSurfaceVk::WindowSurfaceVk(const egl::SurfaceState &surfaceState,
mInstance(VK_NULL_HANDLE), mInstance(VK_NULL_HANDLE),
mSwapchain(VK_NULL_HANDLE), mSwapchain(VK_NULL_HANDLE),
mSwapchainPresentMode(VK_PRESENT_MODE_FIFO_KHR), mSwapchainPresentMode(VK_PRESENT_MODE_FIFO_KHR),
mColorRenderTarget(nullptr, nullptr, 0, nullptr),
mDepthStencilRenderTarget(&mDepthStencilImage, &mDepthStencilImageView, 0, nullptr),
mCurrentSwapchainImageIndex(0), mCurrentSwapchainImageIndex(0),
mCurrentSwapSerialIndex(0) mCurrentSwapSerialIndex(0)
{} {
mDepthStencilRenderTarget.init(&mDepthStencilImage, &mDepthStencilImageView, 0, nullptr);
}
WindowSurfaceVk::~WindowSurfaceVk() WindowSurfaceVk::~WindowSurfaceVk()
{ {
......
...@@ -97,7 +97,7 @@ angle::Result TextureVk::generateMipmapLevelsWithCPU(ContextVk *contextVk, ...@@ -97,7 +97,7 @@ angle::Result TextureVk::generateMipmapLevelsWithCPU(ContextVk *contextVk,
size_t mipAllocationSize = destRowPitch * mipHeight; size_t mipAllocationSize = destRowPitch * mipHeight;
gl::Extents mipLevelExtents(static_cast<int>(mipWidth), static_cast<int>(mipHeight), 1); gl::Extents mipLevelExtents(static_cast<int>(mipWidth), static_cast<int>(mipHeight), 1);
ANGLE_TRY(mImage.stageSubresourceUpdateAndGetData( ANGLE_TRY(mImage->stageSubresourceUpdateAndGetData(
contextVk, mipAllocationSize, contextVk, mipAllocationSize,
gl::ImageIndex::MakeFromType(mState.getType(), currentMipLevel, layer), mipLevelExtents, gl::ImageIndex::MakeFromType(mState.getType(), currentMipLevel, layer), mipLevelExtents,
gl::Offset(), &destData)); gl::Offset(), &destData));
...@@ -119,10 +119,8 @@ angle::Result TextureVk::generateMipmapLevelsWithCPU(ContextVk *contextVk, ...@@ -119,10 +119,8 @@ angle::Result TextureVk::generateMipmapLevelsWithCPU(ContextVk *contextVk,
// TextureVk implementation. // TextureVk implementation.
TextureVk::TextureVk(const gl::TextureState &state, RendererVk *renderer) TextureVk::TextureVk(const gl::TextureState &state, RendererVk *renderer)
: TextureImpl(state), mRenderTarget(&mImage, &mDrawBaseLevelImageView, 0, this) : TextureImpl(state), mImage(nullptr)
{ {}
mImage.initStagingBuffer(renderer);
}
TextureVk::~TextureVk() = default; TextureVk::~TextureVk() = default;
...@@ -134,6 +132,8 @@ void TextureVk::onDestroy(const gl::Context *context) ...@@ -134,6 +132,8 @@ void TextureVk::onDestroy(const gl::Context *context)
releaseImage(renderer); releaseImage(renderer);
releaseStagingBuffer(renderer); releaseStagingBuffer(renderer);
renderer->releaseObject(renderer->getCurrentQueueSerial(), &mSampler); renderer->releaseObject(renderer->getCurrentQueueSerial(), &mSampler);
SafeDelete(mImage);
} }
angle::Result TextureVk::setImage(const gl::Context *context, angle::Result TextureVk::setImage(const gl::Context *context,
...@@ -160,13 +160,13 @@ angle::Result TextureVk::setImage(const gl::Context *context, ...@@ -160,13 +160,13 @@ angle::Result TextureVk::setImage(const gl::Context *context,
} }
// Create a new graph node to store image initialization commands. // Create a new graph node to store image initialization commands.
mImage.finishCurrentCommands(renderer); mImage->finishCurrentCommands(renderer);
// Handle initial data. // Handle initial data.
if (pixels) if (pixels)
{ {
ANGLE_TRY(mImage.stageSubresourceUpdate(contextVk, index, size, gl::Offset(), formatInfo, ANGLE_TRY(mImage->stageSubresourceUpdate(contextVk, index, size, gl::Offset(), formatInfo,
unpack, type, pixels)); unpack, type, pixels));
} }
return angle::Result::Continue; return angle::Result::Continue;
...@@ -183,12 +183,12 @@ angle::Result TextureVk::setSubImage(const gl::Context *context, ...@@ -183,12 +183,12 @@ angle::Result TextureVk::setSubImage(const gl::Context *context,
{ {
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type); const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
ANGLE_TRY(mImage.stageSubresourceUpdate( ANGLE_TRY(mImage->stageSubresourceUpdate(
contextVk, index, gl::Extents(area.width, area.height, area.depth), contextVk, index, gl::Extents(area.width, area.height, area.depth),
gl::Offset(area.x, area.y, area.z), formatInfo, unpack, type, pixels)); gl::Offset(area.x, area.y, area.z), formatInfo, unpack, type, pixels));
// Create a new graph node to store image initialization commands. // Create a new graph node to store image initialization commands.
mImage.finishCurrentCommands(contextVk->getRenderer()); mImage->finishCurrentCommands(contextVk->getRenderer());
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -310,7 +310,7 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context, ...@@ -310,7 +310,7 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context,
const vk::Format &srcFormat = framebufferVk->getColorReadRenderTarget()->getImageFormat(); const vk::Format &srcFormat = framebufferVk->getColorReadRenderTarget()->getImageFormat();
const vk::Format &destFormat = renderer->getFormat(internalFormat.sizedInternalFormat); const vk::Format &destFormat = renderer->getFormat(internalFormat.sizedInternalFormat);
bool forceCpuPath = ForceCpuPathForCopy(renderer, &mImage); bool forceCpuPath = ForceCpuPathForCopy(renderer, mImage);
// If it's possible to perform the copy with a draw call, do that. // If it's possible to perform the copy with a draw call, do that.
if (CanCopyWithDraw(renderer, srcFormat, destFormat) && !forceCpuPath) if (CanCopyWithDraw(renderer, srcFormat, destFormat) && !forceCpuPath)
...@@ -329,13 +329,13 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context, ...@@ -329,13 +329,13 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context,
} }
// Do a CPU readback that does the conversion, and then stage the change to the pixel buffer. // Do a CPU readback that does the conversion, and then stage the change to the pixel buffer.
ANGLE_TRY(mImage.stageSubresourceUpdateFromFramebuffer( ANGLE_TRY(mImage->stageSubresourceUpdateFromFramebuffer(
context, index, clippedSourceArea, modifiedDestOffset, context, index, clippedSourceArea, modifiedDestOffset,
gl::Extents(clippedSourceArea.width, clippedSourceArea.height, 1), internalFormat, gl::Extents(clippedSourceArea.width, clippedSourceArea.height, 1), internalFormat,
framebufferVk)); framebufferVk));
mImage.finishCurrentCommands(renderer); mImage->finishCurrentCommands(renderer);
framebufferVk->getFramebuffer()->addReadDependency(&mImage); framebufferVk->getFramebuffer()->addReadDependency(mImage);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -357,7 +357,7 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk, ...@@ -357,7 +357,7 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
const vk::Format &sourceVkFormat = source->getImage().getFormat(); const vk::Format &sourceVkFormat = source->getImage().getFormat();
const vk::Format &destVkFormat = renderer->getFormat(destFormat.sizedInternalFormat); const vk::Format &destVkFormat = renderer->getFormat(destFormat.sizedInternalFormat);
bool forceCpuPath = ForceCpuPathForCopy(renderer, &mImage); bool forceCpuPath = ForceCpuPathForCopy(renderer, mImage);
// If it's possible to perform the copy with a draw call, do that. // If it's possible to perform the copy with a draw call, do that.
if (CanCopyWithDraw(renderer, sourceVkFormat, destVkFormat) && !forceCpuPath) if (CanCopyWithDraw(renderer, sourceVkFormat, destVkFormat) && !forceCpuPath)
...@@ -387,7 +387,7 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk, ...@@ -387,7 +387,7 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
// Allocate memory in the destination texture for the copy/conversion // Allocate memory in the destination texture for the copy/conversion
uint8_t *destData = nullptr; uint8_t *destData = nullptr;
ANGLE_TRY(mImage.stageSubresourceUpdateAndGetData( ANGLE_TRY(mImage->stageSubresourceUpdateAndGetData(
contextVk, destinationAllocationSize, index, contextVk, destinationAllocationSize, index,
gl::Extents(sourceArea.width, sourceArea.height, 1), destOffset, &destData)); gl::Extents(sourceArea.width, sourceArea.height, 1), destOffset, &destData));
...@@ -417,7 +417,7 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk, ...@@ -417,7 +417,7 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
unpackUnmultiplyAlpha); unpackUnmultiplyAlpha);
// Create a new graph node to store image initialization commands. // Create a new graph node to store image initialization commands.
mImage.finishCurrentCommands(contextVk->getRenderer()); mImage->finishCurrentCommands(contextVk->getRenderer());
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -458,7 +458,7 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk, ...@@ -458,7 +458,7 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk,
uint32_t layerCount = index.getLayerCount(); uint32_t layerCount = index.getLayerCount();
// If destination is valid, copy the source directly into it. // If destination is valid, copy the source directly into it.
if (mImage.valid()) if (mImage->valid())
{ {
// Make sure any updates to the image are already flushed. // Make sure any updates to the image are already flushed.
ANGLE_TRY(ensureImageInitialized(contextVk)); ANGLE_TRY(ensureImageInitialized(contextVk));
...@@ -471,7 +471,7 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk, ...@@ -471,7 +471,7 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk,
ANGLE_TRY( ANGLE_TRY(
getLayerLevelDrawImageView(contextVk, baseLayer + layerIndex, level, &destView)); getLayerLevelDrawImageView(contextVk, baseLayer + layerIndex, level, &destView));
ANGLE_TRY(utilsVk.copyImage(contextVk, &mImage, destView, srcImage, srcView, params)); ANGLE_TRY(utilsVk.copyImage(contextVk, mImage, destView, srcImage, srcView, params));
} }
} }
else else
...@@ -510,8 +510,9 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk, ...@@ -510,8 +510,9 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk,
} }
// Stage the copy for when the image storage is actually created. // Stage the copy for when the image storage is actually created.
mImage.stageSubresourceUpdateFromImage(stagingImage.release(), index, destOffset, mImage->stageSubresourceUpdateFromImage(
gl::Extents(sourceArea.width, sourceArea.height, 1)); stagingImage.release(), index, destOffset,
gl::Extents(sourceArea.width, sourceArea.height, 1));
} }
return angle::Result::Continue; return angle::Result::Continue;
...@@ -525,11 +526,14 @@ angle::Result TextureVk::setStorage(const gl::Context *context, ...@@ -525,11 +526,14 @@ angle::Result TextureVk::setStorage(const gl::Context *context,
{ {
ContextVk *contextVk = GetAs<ContextVk>(context->getImplementation()); ContextVk *contextVk = GetAs<ContextVk>(context->getImplementation());
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
ANGLE_TRY(ensureImageAllocated(renderer));
const vk::Format &format = renderer->getFormat(internalFormat); const vk::Format &format = renderer->getFormat(internalFormat);
vk::CommandBuffer *commandBuffer = nullptr; vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(mImage.recordCommands(contextVk, &commandBuffer)); ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
if (mImage.valid()) if (mImage->valid())
{ {
releaseImage(renderer); releaseImage(renderer);
} }
...@@ -555,6 +559,22 @@ angle::Result TextureVk::setImageExternal(const gl::Context *context, ...@@ -555,6 +559,22 @@ angle::Result TextureVk::setImageExternal(const gl::Context *context,
return angle::Result::Stop; return angle::Result::Stop;
} }
angle::Result TextureVk::ensureImageAllocated(RendererVk *renderer)
{
if (mImage == nullptr)
{
mImage = new vk::ImageHelper();
mImage->initStagingBuffer(renderer);
mRenderTarget.init(mImage, &mDrawBaseLevelImageView, 0, this);
// Force re-creation of cube map render targets next time they are needed
mCubeMapRenderTargets.clear();
}
return angle::Result::Continue;
}
angle::Result TextureVk::redefineImage(const gl::Context *context, angle::Result TextureVk::redefineImage(const gl::Context *context,
const gl::ImageIndex &index, const gl::ImageIndex &index,
const gl::InternalFormat &internalFormat, const gl::InternalFormat &internalFormat,
...@@ -563,20 +583,28 @@ angle::Result TextureVk::redefineImage(const gl::Context *context, ...@@ -563,20 +583,28 @@ angle::Result TextureVk::redefineImage(const gl::Context *context,
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
// If there is any staged changes for this index, we can remove them since we're going to if (!size.empty())
// override them with this call. {
mImage.removeStagedUpdates(renderer, index); ANGLE_TRY(ensureImageAllocated(renderer));
}
if (mImage.valid()) if (mImage != nullptr)
{ {
const vk::Format &vkFormat = renderer->getFormat(internalFormat.sizedInternalFormat); // If there is any staged changes for this index, we can remove them since we're going to
// override them with this call.
mImage->removeStagedUpdates(renderer, index);
// Calculate the expected size for the index we are defining. If the size is different from if (mImage->valid())
// the given size, or the format is different, we are redefining the image so we must
// release it.
if (mImage.getFormat() != vkFormat || size != mImage.getSize(index))
{ {
releaseImage(renderer); const vk::Format &vkFormat = renderer->getFormat(internalFormat.sizedInternalFormat);
// Calculate the expected size for the index we are defining. If the size is different
// from the given size, or the format is different, we are redefining the image so we
// must release it.
if (mImage->getFormat() != vkFormat || size != mImage->getSize(index))
{
releaseImage(renderer);
}
} }
} }
...@@ -597,19 +625,19 @@ angle::Result TextureVk::copyImageDataToBuffer(ContextVk *contextVk, ...@@ -597,19 +625,19 @@ angle::Result TextureVk::copyImageDataToBuffer(ContextVk *contextVk,
sourceArea.width * sourceArea.height * imageFormat.pixelBytes * layerCount; sourceArea.width * sourceArea.height * imageFormat.pixelBytes * layerCount;
vk::CommandBuffer *commandBuffer = nullptr; vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(mImage.recordCommands(contextVk, &commandBuffer)); ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
// Requirement of the copyImageToBuffer, the source image must be in SRC_OPTIMAL layout. // Requirement of the copyImageToBuffer, the source image must be in SRC_OPTIMAL layout.
mImage.changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, mImage->changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, commandBuffer); VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, commandBuffer);
// Allocate enough memory to copy the sourceArea region of the source texture into its pixel // Allocate enough memory to copy the sourceArea region of the source texture into its pixel
// buffer. // buffer.
VkBuffer copyBufferHandle = VK_NULL_HANDLE; VkBuffer copyBufferHandle = VK_NULL_HANDLE;
VkDeviceSize sourceCopyOffset = 0; VkDeviceSize sourceCopyOffset = 0;
ANGLE_TRY(mImage.allocateStagingMemory(contextVk, sourceCopyAllocationSize, outDataPtr, ANGLE_TRY(mImage->allocateStagingMemory(contextVk, sourceCopyAllocationSize, outDataPtr,
&copyBufferHandle, &sourceCopyOffset, nullptr)); &copyBufferHandle, &sourceCopyOffset, nullptr));
VkBufferImageCopy region = {}; VkBufferImageCopy region = {};
region.bufferOffset = sourceCopyOffset; region.bufferOffset = sourceCopyOffset;
...@@ -626,8 +654,8 @@ angle::Result TextureVk::copyImageDataToBuffer(ContextVk *contextVk, ...@@ -626,8 +654,8 @@ angle::Result TextureVk::copyImageDataToBuffer(ContextVk *contextVk,
region.imageSubresource.layerCount = layerCount; region.imageSubresource.layerCount = layerCount;
region.imageSubresource.mipLevel = static_cast<uint32_t>(sourceLevel); region.imageSubresource.mipLevel = static_cast<uint32_t>(sourceLevel);
commandBuffer->copyImageToBuffer(mImage.getImage(), mImage.getCurrentLayout(), copyBufferHandle, commandBuffer->copyImageToBuffer(mImage->getImage(), mImage->getCurrentLayout(),
1, &region); copyBufferHandle, 1, &region);
// Explicitly finish. If new use cases arise where we don't want to block we can change this. // Explicitly finish. If new use cases arise where we don't want to block we can change this.
ANGLE_TRY(contextVk->getRenderer()->finish(contextVk)); ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
...@@ -639,15 +667,15 @@ angle::Result TextureVk::generateMipmapsWithCPU(const gl::Context *context) ...@@ -639,15 +667,15 @@ angle::Result TextureVk::generateMipmapsWithCPU(const gl::Context *context)
{ {
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
const gl::Extents baseLevelExtents = mImage.getExtents(); const gl::Extents baseLevelExtents = mImage->getExtents();
uint32_t imageLayerCount = mImage.getLayerCount(); uint32_t imageLayerCount = mImage->getLayerCount();
uint8_t *imageData = nullptr; uint8_t *imageData = nullptr;
gl::Rectangle imageArea(0, 0, baseLevelExtents.width, baseLevelExtents.height); gl::Rectangle imageArea(0, 0, baseLevelExtents.width, baseLevelExtents.height);
ANGLE_TRY(copyImageDataToBuffer(contextVk, mState.getEffectiveBaseLevel(), imageLayerCount, ANGLE_TRY(copyImageDataToBuffer(contextVk, mState.getEffectiveBaseLevel(), imageLayerCount,
imageArea, &imageData)); imageArea, &imageData));
const angle::Format &angleFormat = mImage.getFormat().textureFormat(); const angle::Format &angleFormat = mImage->getFormat().textureFormat();
GLuint sourceRowPitch = baseLevelExtents.width * angleFormat.pixelBytes; GLuint sourceRowPitch = baseLevelExtents.width * angleFormat.pixelBytes;
size_t baseLevelAllocationSize = sourceRowPitch * baseLevelExtents.height; size_t baseLevelAllocationSize = sourceRowPitch * baseLevelExtents.height;
...@@ -665,8 +693,8 @@ angle::Result TextureVk::generateMipmapsWithCPU(const gl::Context *context) ...@@ -665,8 +693,8 @@ angle::Result TextureVk::generateMipmapsWithCPU(const gl::Context *context)
} }
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY(mImage.recordCommands(contextVk, &commandBuffer)); ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
return mImage.flushStagedUpdates(contextVk, getLevelCount(), commandBuffer); return mImage->flushStagedUpdates(contextVk, getLevelCount(), commandBuffer);
} }
angle::Result TextureVk::generateMipmap(const gl::Context *context) angle::Result TextureVk::generateMipmap(const gl::Context *context)
...@@ -674,13 +702,13 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context) ...@@ -674,13 +702,13 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context)
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
// Some data is pending, or the image has not been defined at all yet // Some data is pending, or the image has not been defined at all yet
if (!mImage.valid()) if (!mImage->valid())
{ {
// lets initialize the image so we can generate the next levels. // lets initialize the image so we can generate the next levels.
if (mImage.hasStagedUpdates()) if (mImage->hasStagedUpdates())
{ {
ANGLE_TRY(ensureImageInitialized(contextVk)); ANGLE_TRY(ensureImageInitialized(contextVk));
ASSERT(mImage.valid()); ASSERT(mImage->valid());
} }
else else
{ {
...@@ -693,11 +721,11 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context) ...@@ -693,11 +721,11 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context)
// Check if the image supports blit. If it does, we can do the mipmap generation on the gpu // Check if the image supports blit. If it does, we can do the mipmap generation on the gpu
// only. // only.
if (renderer->hasTextureFormatFeatureBits(mImage.getFormat().vkTextureFormat, if (renderer->hasTextureFormatFeatureBits(mImage->getFormat().vkTextureFormat,
kBlitFeatureFlags)) kBlitFeatureFlags))
{ {
ANGLE_TRY(ensureImageInitialized(contextVk)); ANGLE_TRY(ensureImageInitialized(contextVk));
ANGLE_TRY(mImage.generateMipmapsWithBlit(contextVk, mState.getMipmapMaxLevel())); ANGLE_TRY(mImage->generateMipmapsWithBlit(contextVk, mState.getMipmapMaxLevel()));
} }
else else
{ {
...@@ -705,7 +733,7 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context) ...@@ -705,7 +733,7 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context)
} }
// We're changing this textureVk content, make sure we let the graph know. // We're changing this textureVk content, make sure we let the graph know.
mImage.finishCurrentCommands(renderer); mImage->finishCurrentCommands(renderer);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -772,19 +800,19 @@ angle::Result TextureVk::ensureImageInitializedImpl(ContextVk *contextVk, ...@@ -772,19 +800,19 @@ angle::Result TextureVk::ensureImageInitializedImpl(ContextVk *contextVk,
uint32_t levelCount, uint32_t levelCount,
const vk::Format &format) const vk::Format &format)
{ {
if (mImage.valid() && !mImage.hasStagedUpdates()) if (mImage->valid() && !mImage->hasStagedUpdates())
{ {
return angle::Result::Continue; return angle::Result::Continue;
} }
vk::CommandBuffer *commandBuffer = nullptr; vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(mImage.recordCommands(contextVk, &commandBuffer)); ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
if (!mImage.valid()) if (!mImage->valid())
{ {
ANGLE_TRY(initImage(contextVk, format, baseLevelExtents, levelCount, commandBuffer)); ANGLE_TRY(initImage(contextVk, format, baseLevelExtents, levelCount, commandBuffer));
} }
return mImage.flushStagedUpdates(contextVk, levelCount, commandBuffer); return mImage->flushStagedUpdates(contextVk, levelCount, commandBuffer);
} }
angle::Result TextureVk::initCubeMapRenderTargets(ContextVk *contextVk) angle::Result TextureVk::initCubeMapRenderTargets(ContextVk *contextVk)
...@@ -793,11 +821,12 @@ angle::Result TextureVk::initCubeMapRenderTargets(ContextVk *contextVk) ...@@ -793,11 +821,12 @@ angle::Result TextureVk::initCubeMapRenderTargets(ContextVk *contextVk)
if (!mCubeMapRenderTargets.empty()) if (!mCubeMapRenderTargets.empty())
return angle::Result::Continue; return angle::Result::Continue;
mCubeMapRenderTargets.resize(gl::kCubeFaceCount);
for (size_t cubeMapFaceIndex = 0; cubeMapFaceIndex < gl::kCubeFaceCount; ++cubeMapFaceIndex) for (size_t cubeMapFaceIndex = 0; cubeMapFaceIndex < gl::kCubeFaceCount; ++cubeMapFaceIndex)
{ {
vk::ImageView *imageView; vk::ImageView *imageView;
ANGLE_TRY(getLayerLevelDrawImageView(contextVk, cubeMapFaceIndex, 0, &imageView)); ANGLE_TRY(getLayerLevelDrawImageView(contextVk, cubeMapFaceIndex, 0, &imageView));
mCubeMapRenderTargets.emplace_back(&mImage, imageView, cubeMapFaceIndex, this); mCubeMapRenderTargets[cubeMapFaceIndex].init(mImage, imageView, cubeMapFaceIndex, this);
} }
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -867,7 +896,7 @@ angle::Result TextureVk::initializeContents(const gl::Context *context, ...@@ -867,7 +896,7 @@ angle::Result TextureVk::initializeContents(const gl::Context *context,
const vk::ImageView &TextureVk::getReadImageView() const const vk::ImageView &TextureVk::getReadImageView() const
{ {
ASSERT(mImage.valid()); ASSERT(mImage->valid());
const GLenum minFilter = mState.getSamplerState().getMinFilter(); const GLenum minFilter = mState.getSamplerState().getMinFilter();
if (minFilter == GL_LINEAR || minFilter == GL_NEAREST) if (minFilter == GL_LINEAR || minFilter == GL_NEAREST)
...@@ -883,18 +912,18 @@ angle::Result TextureVk::getLayerLevelDrawImageView(vk::Context *context, ...@@ -883,18 +912,18 @@ angle::Result TextureVk::getLayerLevelDrawImageView(vk::Context *context,
size_t level, size_t level,
vk::ImageView **imageViewOut) vk::ImageView **imageViewOut)
{ {
ASSERT(mImage.valid()); ASSERT(mImage->valid());
// Lazily allocate the storage for image views // Lazily allocate the storage for image views
if (mLayerLevelDrawImageViews.empty()) if (mLayerLevelDrawImageViews.empty())
{ {
mLayerLevelDrawImageViews.resize(mImage.getLayerCount()); mLayerLevelDrawImageViews.resize(mImage->getLayerCount());
} }
ASSERT(mLayerLevelDrawImageViews.size() > layer); ASSERT(mLayerLevelDrawImageViews.size() > layer);
if (mLayerLevelDrawImageViews[layer].empty()) if (mLayerLevelDrawImageViews[layer].empty())
{ {
mLayerLevelDrawImageViews[layer].resize(mImage.getLevelCount()); mLayerLevelDrawImageViews[layer].resize(mImage->getLevelCount());
} }
ASSERT(mLayerLevelDrawImageViews[layer].size() > level); ASSERT(mLayerLevelDrawImageViews[layer].size() > level);
...@@ -907,8 +936,8 @@ angle::Result TextureVk::getLayerLevelDrawImageView(vk::Context *context, ...@@ -907,8 +936,8 @@ angle::Result TextureVk::getLayerLevelDrawImageView(vk::Context *context,
// Lazily allocate the image view itself. // Lazily allocate the image view itself.
// Note that these views are specifically made to be used as color attachments, and therefore // Note that these views are specifically made to be used as color attachments, and therefore
// don't have swizzle. // don't have swizzle.
return mImage.initLayerImageView(context, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT, return mImage->initLayerImageView(context, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
gl::SwizzleState(), *imageViewOut, level, 1, layer, 1); gl::SwizzleState(), *imageViewOut, level, 1, layer, 1);
} }
const vk::Sampler &TextureVk::getSampler() const const vk::Sampler &TextureVk::getSampler() const
...@@ -929,32 +958,35 @@ angle::Result TextureVk::initImage(ContextVk *contextVk, ...@@ -929,32 +958,35 @@ angle::Result TextureVk::initImage(ContextVk *contextVk,
(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
ANGLE_TRY(mImage.init(contextVk, mState.getType(), extents, format, 1, usage, levelCount, ANGLE_TRY(mImage->init(contextVk, mState.getType(), extents, format, 1, usage, levelCount,
mState.getType() == gl::TextureType::CubeMap ? gl::kCubeFaceCount : 1)); mState.getType() == gl::TextureType::CubeMap ? gl::kCubeFaceCount : 1));
const VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; const VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
ANGLE_TRY(mImage.initMemory(contextVk, renderer->getMemoryProperties(), flags)); ANGLE_TRY(mImage->initMemory(contextVk, renderer->getMemoryProperties(), flags));
gl::SwizzleState mappedSwizzle; gl::SwizzleState mappedSwizzle;
MapSwizzleState(format, mState.getSwizzleState(), &mappedSwizzle); MapSwizzleState(format, mState.getSwizzleState(), &mappedSwizzle);
ANGLE_TRY(mImage.initImageView(contextVk, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT, ANGLE_TRY(mImage->initImageView(contextVk, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
mappedSwizzle, &mReadMipmapImageView, levelCount)); mappedSwizzle, &mReadMipmapImageView, levelCount));
ANGLE_TRY(mImage.initImageView(contextVk, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT, ANGLE_TRY(mImage->initImageView(contextVk, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
mappedSwizzle, &mReadBaseLevelImageView, 1)); mappedSwizzle, &mReadBaseLevelImageView, 1));
ANGLE_TRY(mImage.initImageView(contextVk, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT, ANGLE_TRY(mImage->initImageView(contextVk, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
gl::SwizzleState(), &mDrawBaseLevelImageView, 1)); gl::SwizzleState(), &mDrawBaseLevelImageView, 1));
// 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
VkClearColorValue black = {{0, 0, 0, 1.0f}}; VkClearColorValue black = {{0, 0, 0, 1.0f}};
mImage.clearColor(black, 0, levelCount, commandBuffer); mImage->clearColor(black, 0, levelCount, commandBuffer);
return angle::Result::Continue; return angle::Result::Continue;
} }
void TextureVk::releaseImage(RendererVk *renderer) void TextureVk::releaseImage(RendererVk *renderer)
{ {
mImage.releaseImage(renderer); if (mImage)
{
mImage->releaseImage(renderer);
}
Serial currentSerial = renderer->getCurrentQueueSerial(); Serial currentSerial = renderer->getCurrentQueueSerial();
...@@ -978,7 +1010,10 @@ void TextureVk::releaseImage(RendererVk *renderer) ...@@ -978,7 +1010,10 @@ void TextureVk::releaseImage(RendererVk *renderer)
void TextureVk::releaseStagingBuffer(RendererVk *renderer) void TextureVk::releaseStagingBuffer(RendererVk *renderer)
{ {
mImage.releaseStagingBuffer(renderer); if (mImage)
{
mImage->releaseStagingBuffer(renderer);
}
} }
uint32_t TextureVk::getLevelCount() const uint32_t TextureVk::getLevelCount() const
......
...@@ -129,14 +129,14 @@ class TextureVk : public TextureImpl ...@@ -129,14 +129,14 @@ class TextureVk : public TextureImpl
const vk::ImageHelper &getImage() const const vk::ImageHelper &getImage() const
{ {
ASSERT(mImage.valid()); ASSERT(mImage && mImage->valid());
return mImage; return *mImage;
} }
vk::ImageHelper &getImage() vk::ImageHelper &getImage()
{ {
ASSERT(mImage.valid()); ASSERT(mImage && mImage->valid());
return mImage; return *mImage;
} }
const vk::ImageView &getReadImageView() const; const vk::ImageView &getReadImageView() const;
...@@ -149,6 +149,8 @@ class TextureVk : public TextureImpl ...@@ -149,6 +149,8 @@ class TextureVk : public TextureImpl
angle::Result ensureImageInitialized(ContextVk *contextVk); angle::Result ensureImageInitialized(ContextVk *contextVk);
private: private:
angle::Result ensureImageAllocated(RendererVk *renderer);
angle::Result redefineImage(const gl::Context *context, angle::Result redefineImage(const gl::Context *context,
const gl::ImageIndex &index, const gl::ImageIndex &index,
const gl::InternalFormat &internalFormat, const gl::InternalFormat &internalFormat,
...@@ -218,7 +220,7 @@ class TextureVk : public TextureImpl ...@@ -218,7 +220,7 @@ class TextureVk : public TextureImpl
uint32_t levelCount, uint32_t levelCount,
const vk::Format &format); const vk::Format &format);
vk::ImageHelper mImage; vk::ImageHelper *mImage;
vk::ImageView mDrawBaseLevelImageView; vk::ImageView mDrawBaseLevelImageView;
vk::ImageView mReadBaseLevelImageView; vk::ImageView mReadBaseLevelImageView;
vk::ImageView mReadMipmapImageView; vk::ImageView mReadMipmapImageView;
......
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