Commit a0d048a4 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Fool-proof usage of GL and VK level indices

Using boxed types, this change allows the compiler to catch errors when a level index in one space (e.g. GL) is mistakenly used in another space (e.g. VK). This change uncovered a number of bugs due to such mistakes which are fixed. Mistakes are still possible when the index is explicitly extracted, for example to be given to a Vulkan command, or when it's created, for example when retrieved from gl::ImageIndex::getLevelIndex. Future work can include using gl::LevelIndex in gl::ImageIndex directly to alleviate the latter at least. Bug: angleproject:4880 Change-Id: I6427c68c3bc096f771402f51c8554d8171758aa9 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2380232 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCharlie Lao <cclao@google.com>
parent 8d412db2
...@@ -815,6 +815,63 @@ using TextureBarrierVector = BarrierVector<TextureAndLayout>; ...@@ -815,6 +815,63 @@ using TextureBarrierVector = BarrierVector<TextureAndLayout>;
// necessary. Returns 0 if no buffer is bound or if integer overflow occurs. // necessary. Returns 0 if no buffer is bound or if integer overflow occurs.
GLsizeiptr GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> &binding); GLsizeiptr GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> &binding);
// A texture level index.
template <typename T>
class LevelIndexWrapper
{
public:
LevelIndexWrapper() = default;
explicit constexpr LevelIndexWrapper(T levelIndex) : mLevelIndex(levelIndex) {}
constexpr LevelIndexWrapper(const LevelIndexWrapper &other) = default;
constexpr LevelIndexWrapper &operator=(const LevelIndexWrapper &other) = default;
constexpr T get() const { return mLevelIndex; }
LevelIndexWrapper &operator++()
{
++mLevelIndex;
return *this;
}
constexpr bool operator<(const LevelIndexWrapper &other) const
{
return mLevelIndex < other.mLevelIndex;
}
constexpr bool operator<=(const LevelIndexWrapper &other) const
{
return mLevelIndex <= other.mLevelIndex;
}
constexpr bool operator>(const LevelIndexWrapper &other) const
{
return mLevelIndex > other.mLevelIndex;
}
constexpr bool operator>=(const LevelIndexWrapper &other) const
{
return mLevelIndex >= other.mLevelIndex;
}
constexpr bool operator==(const LevelIndexWrapper &other) const
{
return mLevelIndex == other.mLevelIndex;
}
constexpr bool operator!=(const LevelIndexWrapper &other) const
{
return mLevelIndex != other.mLevelIndex;
}
constexpr LevelIndexWrapper operator+(T other) const
{
return LevelIndexWrapper(mLevelIndex + other);
}
constexpr LevelIndexWrapper operator-(T other) const
{
return LevelIndexWrapper(mLevelIndex - other);
}
constexpr T operator-(LevelIndexWrapper other) const { return mLevelIndex - other.mLevelIndex; }
private:
T mLevelIndex;
};
// A GL texture level index.
using LevelIndex = LevelIndexWrapper<GLint>;
} // namespace gl } // namespace gl
namespace rx namespace rx
......
...@@ -779,15 +779,15 @@ angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk, ...@@ -779,15 +779,15 @@ angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk,
ANGLE_TRY(contextVk->onImageTransferWrite(imageAspectMask, dstImage)); ANGLE_TRY(contextVk->onImageTransferWrite(imageAspectMask, dstImage));
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer(); vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
VkImageBlit blit = {}; VkImageBlit blit = {};
blit.srcSubresource.aspectMask = blitAspectMask; blit.srcSubresource.aspectMask = blitAspectMask;
blit.srcSubresource.mipLevel = readRenderTarget->getLevelIndex(); blit.srcSubresource.mipLevel = srcImage->toVKLevel(readRenderTarget->getLevelIndex()).get();
blit.srcSubresource.baseArrayLayer = readRenderTarget->getLayerIndex(); blit.srcSubresource.baseArrayLayer = readRenderTarget->getLayerIndex();
blit.srcSubresource.layerCount = 1; blit.srcSubresource.layerCount = 1;
blit.srcOffsets[0] = {sourceArea.x0(), sourceArea.y0(), 0}; blit.srcOffsets[0] = {sourceArea.x0(), sourceArea.y0(), 0};
blit.srcOffsets[1] = {sourceArea.x1(), sourceArea.y1(), 1}; blit.srcOffsets[1] = {sourceArea.x1(), sourceArea.y1(), 1};
blit.dstSubresource.aspectMask = blitAspectMask; blit.dstSubresource.aspectMask = blitAspectMask;
blit.dstSubresource.mipLevel = drawRenderTarget->getLevelIndex(); blit.dstSubresource.mipLevel = dstImage->toVKLevel(drawRenderTarget->getLevelIndex()).get();
blit.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex(); blit.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex();
blit.dstSubresource.layerCount = 1; blit.dstSubresource.layerCount = 1;
blit.dstOffsets[0] = {destArea.x0(), destArea.y0(), 0}; blit.dstOffsets[0] = {destArea.x0(), destArea.y0(), 0};
...@@ -1028,7 +1028,7 @@ angle::Result FramebufferVk::blit(const gl::Context *context, ...@@ -1028,7 +1028,7 @@ angle::Result FramebufferVk::blit(const gl::Context *context,
params.srcLayer = readRenderTarget->getLayerIndex(); params.srcLayer = readRenderTarget->getLayerIndex();
// Multisampled images are not allowed to have mips. // Multisampled images are not allowed to have mips.
ASSERT(!isColorResolve || readRenderTarget->getLevelIndex() == 0); ASSERT(!isColorResolve || readRenderTarget->getLevelIndex() == gl::LevelIndex(0));
// If there was no clipping and the format capabilities allow us, use Vulkan's builtin blit. // If there was no clipping and the format capabilities allow us, use Vulkan's builtin blit.
// The reason clipping is prohibited in this path is that due to rounding errors, it would // The reason clipping is prohibited in this path is that due to rounding errors, it would
...@@ -1127,7 +1127,7 @@ angle::Result FramebufferVk::blit(const gl::Context *context, ...@@ -1127,7 +1127,7 @@ angle::Result FramebufferVk::blit(const gl::Context *context,
params.srcLayer = readRenderTarget->getLayerIndex(); params.srcLayer = readRenderTarget->getLayerIndex();
// Multisampled images are not allowed to have mips. // Multisampled images are not allowed to have mips.
ASSERT(!isDepthStencilResolve || readRenderTarget->getLevelIndex() == 0); ASSERT(!isDepthStencilResolve || readRenderTarget->getLevelIndex() == gl::LevelIndex(0));
// Similarly, only blit if there's been no clipping or rotating. // Similarly, only blit if there's been no clipping or rotating.
bool canBlitWithCommand = !isDepthStencilResolve && noClip && bool canBlitWithCommand = !isDepthStencilResolve && noClip &&
...@@ -1158,8 +1158,9 @@ angle::Result FramebufferVk::blit(const gl::Context *context, ...@@ -1158,8 +1158,9 @@ angle::Result FramebufferVk::blit(const gl::Context *context,
vk::DeviceScoped<vk::ImageView> stencilView(contextVk->getDevice()); vk::DeviceScoped<vk::ImageView> stencilView(contextVk->getDevice());
vk::ImageHelper *depthStencilImage = &readRenderTarget->getImageForCopy(); vk::ImageHelper *depthStencilImage = &readRenderTarget->getImageForCopy();
uint32_t levelIndex = readRenderTarget->getLevelIndex(); vk::LevelIndex levelIndex =
uint32_t layerIndex = readRenderTarget->getLayerIndex(); depthStencilImage->toVKLevel(readRenderTarget->getLevelIndex());
uint32_t layerIndex = readRenderTarget->getLayerIndex();
gl::TextureType textureType = vk::Get2DTextureType(depthStencilImage->getLayerCount(), gl::TextureType textureType = vk::Get2DTextureType(depthStencilImage->getLayerCount(),
depthStencilImage->getSamples()); depthStencilImage->getSamples());
...@@ -1302,8 +1303,8 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk, ...@@ -1302,8 +1303,8 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer(); vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
vk::ImageHelper &dstImage = drawRenderTarget->getImageForWrite(); vk::ImageHelper &dstImage = drawRenderTarget->getImageForWrite();
uint32_t levelVK = drawRenderTarget->getLevelIndex() - dstImage.getBaseLevel(); vk::LevelIndex levelVK = dstImage.toVKLevel(drawRenderTarget->getLevelIndex());
resolveRegion.dstSubresource.mipLevel = levelVK; resolveRegion.dstSubresource.mipLevel = levelVK.get();
resolveRegion.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex(); resolveRegion.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex();
srcImage->resolve(&dstImage, resolveRegion, &commandBuffer); srcImage->resolve(&dstImage, resolveRegion, &commandBuffer);
...@@ -1331,9 +1332,9 @@ angle::Result FramebufferVk::copyResolveToMultisampedAttachment(ContextVk *conte ...@@ -1331,9 +1332,9 @@ angle::Result FramebufferVk::copyResolveToMultisampedAttachment(ContextVk *conte
// Note: neither vkCmdCopyImage nor vkCmdBlitImage allow the destination to be multisampled. // Note: neither vkCmdCopyImage nor vkCmdBlitImage allow the destination to be multisampled.
// There's no choice but to use a draw-based path to perform this copy. // There's no choice but to use a draw-based path to perform this copy.
gl::Extents extents = colorRenderTarget->getExtents(); gl::Extents extents = colorRenderTarget->getExtents();
uint32_t levelVK = colorRenderTarget->getLevelIndex() - src->getBaseLevel(); vk::LevelIndex levelVK = src->toVKLevel(colorRenderTarget->getLevelIndex());
uint32_t layer = colorRenderTarget->getLayerIndex(); uint32_t layer = colorRenderTarget->getLayerIndex();
UtilsVk::CopyImageParameters params; UtilsVk::CopyImageParameters params;
params.srcOffset[0] = 0; params.srcOffset[0] = 0;
...@@ -1342,7 +1343,7 @@ angle::Result FramebufferVk::copyResolveToMultisampedAttachment(ContextVk *conte ...@@ -1342,7 +1343,7 @@ angle::Result FramebufferVk::copyResolveToMultisampedAttachment(ContextVk *conte
params.srcExtents[1] = extents.height; params.srcExtents[1] = extents.height;
params.destOffset[0] = 0; params.destOffset[0] = 0;
params.destOffset[1] = 0; params.destOffset[1] = 0;
params.srcMip = levelVK; params.srcMip = levelVK.get();
params.srcLayer = layer; params.srcLayer = layer;
params.srcHeight = extents.height; params.srcHeight = extents.height;
params.srcPremultiplyAlpha = false; params.srcPremultiplyAlpha = false;
...@@ -2395,8 +2396,8 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk, ...@@ -2395,8 +2396,8 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
void *pixels) void *pixels)
{ {
ANGLE_TRACE_EVENT0("gpu.angle", "FramebufferVk::readPixelsImpl"); ANGLE_TRACE_EVENT0("gpu.angle", "FramebufferVk::readPixelsImpl");
uint32_t levelGL = renderTarget->getLevelIndex(); gl::LevelIndex levelGL = renderTarget->getLevelIndex();
uint32_t layer = renderTarget->getLayerIndex(); uint32_t layer = renderTarget->getLayerIndex();
return renderTarget->getImageForCopy().readPixels(contextVk, area, packPixelsParams, return renderTarget->getImageForCopy().readPixels(contextVk, area, packPixelsParams,
copyAspectFlags, levelGL, layer, pixels, copyAspectFlags, levelGL, layer, pixels,
&mReadPixelBuffer); &mReadPixelBuffer);
......
...@@ -67,7 +67,7 @@ egl::Error ImageVk::initialize(const egl::Display *display) ...@@ -67,7 +67,7 @@ egl::Error ImageVk::initialize(const egl::Display *display)
mOwnsImage = false; mOwnsImage = false;
mImageTextureType = mState.imageIndex.getType(); mImageTextureType = mState.imageIndex.getType();
mImageLevel = mState.imageIndex.getLevelIndex(); mImageLevel = gl::LevelIndex(mState.imageIndex.getLevelIndex());
mImageLayer = mState.imageIndex.hasLayer() ? mState.imageIndex.getLayerIndex() : 0; mImageLayer = mState.imageIndex.hasLayer() ? mState.imageIndex.getLayerIndex() : 0;
} }
else else
...@@ -108,7 +108,7 @@ egl::Error ImageVk::initialize(const egl::Display *display) ...@@ -108,7 +108,7 @@ egl::Error ImageVk::initialize(const egl::Display *display)
mOwnsImage = false; mOwnsImage = false;
mImageTextureType = gl::TextureType::_2D; mImageTextureType = gl::TextureType::_2D;
mImageLevel = 0; mImageLevel = gl::LevelIndex(0);
mImageLayer = 0; mImageLayer = 0;
} }
......
...@@ -40,12 +40,12 @@ class ImageVk : public ImageImpl ...@@ -40,12 +40,12 @@ class ImageVk : public ImageImpl
vk::ImageHelper *getImage() const { return mImage; } vk::ImageHelper *getImage() const { return mImage; }
gl::TextureType getImageTextureType() const { return mImageTextureType; } gl::TextureType getImageTextureType() const { return mImageTextureType; }
uint32_t getImageLevel() const { return mImageLevel; } gl::LevelIndex getImageLevel() const { return mImageLevel; }
uint32_t getImageLayer() const { return mImageLayer; } uint32_t getImageLayer() const { return mImageLayer; }
private: private:
gl::TextureType mImageTextureType; gl::TextureType mImageTextureType;
uint32_t mImageLevel; gl::LevelIndex mImageLevel;
uint32_t mImageLayer; uint32_t mImageLayer;
bool mOwnsImage; bool mOwnsImage;
......
...@@ -204,10 +204,11 @@ angle::Result MemoryObjectVk::createImage(ContextVk *contextVk, ...@@ -204,10 +204,11 @@ angle::Result MemoryObjectVk::createImage(ContextVk *contextVk,
// ANGLE_external_objects_flags allows create flags to be specified by the application instead // ANGLE_external_objects_flags allows create flags to be specified by the application instead
// of getting defaulted to zero. Note that the GL enum values constituting the bits of // of getting defaulted to zero. Note that the GL enum values constituting the bits of
// |createFlags| are identical to their corresponding Vulkan value. // |createFlags| are identical to their corresponding Vulkan value.
ANGLE_TRY(image->initExternal( ANGLE_TRY(image->initExternal(contextVk, type, vkExtents, vkFormat, 1, imageUsageFlags,
contextVk, type, vkExtents, vkFormat, 1, imageUsageFlags, createFlags, createFlags, vk::ImageLayout::Undefined,
vk::ImageLayout::Undefined, &externalMemoryImageCreateInfo, 0, &externalMemoryImageCreateInfo, gl::LevelIndex(0),
static_cast<uint32_t>(levels) - 1, static_cast<uint32_t>(levels), layerCount)); gl::LevelIndex(static_cast<uint32_t>(levels) - 1),
static_cast<uint32_t>(levels), layerCount));
VkMemoryRequirements externalMemoryRequirements; VkMemoryRequirements externalMemoryRequirements;
image->getImage().getMemoryRequirements(renderer->getDevice(), &externalMemoryRequirements); image->getImage().getMemoryRequirements(renderer->getDevice(), &externalMemoryRequirements);
......
...@@ -110,13 +110,13 @@ angle::Result OverlayVk::createFont(ContextVk *contextVk) ...@@ -110,13 +110,13 @@ angle::Result OverlayVk::createFont(ContextVk *contextVk)
mFontImage.init(contextVk, gl::TextureType::_2D, mFontImage.init(contextVk, gl::TextureType::_2D,
VkExtent3D{gl::overlay::kFontImageWidth, gl::overlay::kFontImageHeight, 1}, VkExtent3D{gl::overlay::kFontImageWidth, gl::overlay::kFontImageHeight, 1},
renderer->getFormat(angle::FormatID::R8_UNORM), 1, renderer->getFormat(angle::FormatID::R8_UNORM), 1,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 0, 0, 1, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
gl::overlay::kFontCount)); gl::LevelIndex(0), gl::LevelIndex(0), 1, gl::overlay::kFontCount));
ANGLE_TRY(mFontImage.initMemory(contextVk, renderer->getMemoryProperties(), ANGLE_TRY(mFontImage.initMemory(contextVk, renderer->getMemoryProperties(),
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)); VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
ANGLE_TRY(mFontImage.initImageView(contextVk, gl::TextureType::_2DArray, ANGLE_TRY(mFontImage.initImageView(contextVk, gl::TextureType::_2DArray,
VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(), VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(),
&mFontImageView, 0, 1)); &mFontImageView, vk::LevelIndex(0), 1));
// Copy font data from staging buffer. // Copy font data from staging buffer.
ANGLE_TRY(contextVk->onBufferTransferRead(&fontDataBuffer.get())); ANGLE_TRY(contextVk->onBufferTransferRead(&fontDataBuffer.get()));
...@@ -177,13 +177,13 @@ angle::Result OverlayVk::cullWidgets(ContextVk *contextVk) ...@@ -177,13 +177,13 @@ angle::Result OverlayVk::cullWidgets(ContextVk *contextVk)
ANGLE_TRY(mCulledWidgets.init(contextVk, gl::TextureType::_2D, culledWidgetsExtent, ANGLE_TRY(mCulledWidgets.init(contextVk, gl::TextureType::_2D, culledWidgetsExtent,
renderer->getFormat(angle::FormatID::R32G32_UINT), 1, renderer->getFormat(angle::FormatID::R32G32_UINT), 1,
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 0, 0, 1, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
1)); gl::LevelIndex(0), gl::LevelIndex(0), 1, 1));
ANGLE_TRY(mCulledWidgets.initMemory(contextVk, renderer->getMemoryProperties(), ANGLE_TRY(mCulledWidgets.initMemory(contextVk, renderer->getMemoryProperties(),
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)); VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
ANGLE_TRY(mCulledWidgets.initImageView(contextVk, gl::TextureType::_2D, ANGLE_TRY(mCulledWidgets.initImageView(contextVk, gl::TextureType::_2D,
VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(), VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(),
&mCulledWidgetsView, 0, 1)); &mCulledWidgetsView, vk::LevelIndex(0), 1));
UtilsVk::OverlayCullParameters params; UtilsVk::OverlayCullParameters params;
params.subgroupSize[0] = mSubgroupSize[0]; params.subgroupSize[0] = mSubgroupSize[0];
......
...@@ -41,7 +41,7 @@ void RenderTargetVk::init(vk::ImageHelper *image, ...@@ -41,7 +41,7 @@ void RenderTargetVk::init(vk::ImageHelper *image,
vk::ImageViewHelper *imageViews, vk::ImageViewHelper *imageViews,
vk::ImageHelper *resolveImage, vk::ImageHelper *resolveImage,
vk::ImageViewHelper *resolveImageViews, vk::ImageViewHelper *resolveImageViews,
uint32_t levelIndexGL, gl::LevelIndex levelIndexGL,
uint32_t layerIndex, uint32_t layerIndex,
bool isImageTransient) bool isImageTransient)
{ {
...@@ -64,7 +64,7 @@ void RenderTargetVk::reset() ...@@ -64,7 +64,7 @@ void RenderTargetVk::reset()
mImageViews = nullptr; mImageViews = nullptr;
mResolveImage = nullptr; mResolveImage = nullptr;
mResolveImageViews = nullptr; mResolveImageViews = nullptr;
mLevelIndexGL = 0; mLevelIndexGL = gl::LevelIndex(0);
mLayerIndex = 0; mLayerIndex = 0;
mContentDefined = false; mContentDefined = false;
} }
...@@ -74,7 +74,7 @@ vk::ImageViewSubresourceSerial RenderTargetVk::getSubresourceSerialImpl( ...@@ -74,7 +74,7 @@ vk::ImageViewSubresourceSerial RenderTargetVk::getSubresourceSerialImpl(
{ {
ASSERT(imageViews); ASSERT(imageViews);
ASSERT(mLayerIndex < std::numeric_limits<uint16_t>::max()); ASSERT(mLayerIndex < std::numeric_limits<uint16_t>::max());
ASSERT(mLevelIndexGL < std::numeric_limits<uint16_t>::max()); ASSERT(mLevelIndexGL.get() < std::numeric_limits<uint16_t>::max());
vk::ImageViewSubresourceSerial imageViewSerial = vk::ImageViewSubresourceSerial imageViewSerial =
imageViews->getSubresourceSerial(mLevelIndexGL, 1, mLayerIndex, vk::LayerMode::Single); imageViews->getSubresourceSerial(mLevelIndexGL, 1, mLayerIndex, vk::LayerMode::Single);
...@@ -165,7 +165,7 @@ angle::Result RenderTargetVk::getImageViewImpl(ContextVk *contextVk, ...@@ -165,7 +165,7 @@ angle::Result RenderTargetVk::getImageViewImpl(ContextVk *contextVk,
const vk::ImageView **imageViewOut) const const vk::ImageView **imageViewOut) const
{ {
ASSERT(image.valid() && imageViews); ASSERT(image.valid() && imageViews);
int32_t levelVK = mLevelIndexGL - mImage->getBaseLevel(); vk::LevelIndex levelVK = mImage->toVKLevel(mLevelIndexGL);
return imageViews->getLevelLayerDrawImageView(contextVk, image, levelVK, mLayerIndex, return imageViews->getLevelLayerDrawImageView(contextVk, image, levelVK, mLayerIndex,
imageViewOut); imageViewOut);
} }
...@@ -224,7 +224,7 @@ const vk::Format &RenderTargetVk::getImageFormat() const ...@@ -224,7 +224,7 @@ const vk::Format &RenderTargetVk::getImageFormat() const
gl::Extents RenderTargetVk::getExtents() const gl::Extents RenderTargetVk::getExtents() const
{ {
ASSERT(mImage && mImage->valid()); ASSERT(mImage && mImage->valid());
uint32_t levelVK = mLevelIndexGL - mImage->getBaseLevel(); vk::LevelIndex levelVK = mImage->toVKLevel(mLevelIndexGL);
return mImage->getLevelExtents2D(levelVK); return mImage->getLevelExtents2D(levelVK);
} }
...@@ -306,16 +306,16 @@ gl::ImageIndex RenderTargetVk::getImageIndex() const ...@@ -306,16 +306,16 @@ gl::ImageIndex RenderTargetVk::getImageIndex() const
// Determine the GL type from the Vk Image properties. // Determine the GL type from the Vk Image properties.
if (mImage->getType() == VK_IMAGE_TYPE_3D) if (mImage->getType() == VK_IMAGE_TYPE_3D)
{ {
return gl::ImageIndex::Make3D(mLevelIndexGL, mLayerIndex); return gl::ImageIndex::Make3D(mLevelIndexGL.get(), mLayerIndex);
} }
// We don't need to distinguish 2D array and cube. // We don't need to distinguish 2D array and cube.
if (mImage->getLayerCount() > 1) if (mImage->getLayerCount() > 1)
{ {
return gl::ImageIndex::Make2DArray(mLevelIndexGL, mLayerIndex); return gl::ImageIndex::Make2DArray(mLevelIndexGL.get(), mLayerIndex);
} }
ASSERT(mLayerIndex == 0); ASSERT(mLayerIndex == 0);
return gl::ImageIndex::Make2D(mLevelIndexGL); return gl::ImageIndex::Make2D(mLevelIndexGL.get());
} }
} // namespace rx } // namespace rx
...@@ -46,7 +46,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget ...@@ -46,7 +46,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget
vk::ImageViewHelper *imageViews, vk::ImageViewHelper *imageViews,
vk::ImageHelper *resolveImage, vk::ImageHelper *resolveImage,
vk::ImageViewHelper *resolveImageViews, vk::ImageViewHelper *resolveImageViews,
uint32_t levelIndexGL, gl::LevelIndex levelIndexGL,
uint32_t layerIndex, uint32_t layerIndex,
bool isImageTransient); bool isImageTransient);
void reset(); void reset();
...@@ -79,7 +79,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget ...@@ -79,7 +79,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget
const vk::Format &getImageFormat() const; const vk::Format &getImageFormat() const;
gl::Extents getExtents() const; gl::Extents getExtents() const;
uint32_t getLevelIndex() const { return mLevelIndexGL; } gl::LevelIndex getLevelIndex() const { return mLevelIndexGL; }
uint32_t getLayerIndex() const { return mLayerIndex; } uint32_t getLayerIndex() const { return mLayerIndex; }
gl::ImageIndex getImageIndex() const; gl::ImageIndex getImageIndex() const;
...@@ -133,7 +133,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget ...@@ -133,7 +133,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget
vk::ImageViewHelper *mResolveImageViews; vk::ImageViewHelper *mResolveImageViews;
// Which subresource of the image is used as render target. // Which subresource of the image is used as render target.
uint32_t mLevelIndexGL; gl::LevelIndex mLevelIndexGL;
uint32_t mLayerIndex; uint32_t mLayerIndex;
// Whether the render target has been invalidated. If so, DONT_CARE is used instead of LOAD for // Whether the render target has been invalidated. If so, DONT_CARE is used instead of LOAD for
......
...@@ -88,12 +88,13 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context, ...@@ -88,12 +88,13 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context,
VkExtent3D extents = {static_cast<uint32_t>(width), static_cast<uint32_t>(height), 1u}; VkExtent3D extents = {static_cast<uint32_t>(width), static_cast<uint32_t>(height), 1u};
ANGLE_TRY(mImage->init(contextVk, gl::TextureType::_2D, extents, vkFormat, ANGLE_TRY(mImage->init(contextVk, gl::TextureType::_2D, extents, vkFormat,
static_cast<uint32_t>(samples), usage, 0, 0, 1, 1)); static_cast<uint32_t>(samples), usage, gl::LevelIndex(0),
gl::LevelIndex(0), 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));
mRenderTarget.init(mImage, &mImageViews, nullptr, nullptr, 0, 0, false); mRenderTarget.init(mImage, &mImageViews, nullptr, nullptr, gl::LevelIndex(0), 0, false);
} }
return angle::Result::Continue; return angle::Result::Continue;
...@@ -245,8 +246,8 @@ angle::Result RenderbufferVk::getRenderbufferImage(const gl::Context *context, ...@@ -245,8 +246,8 @@ angle::Result RenderbufferVk::getRenderbufferImage(const gl::Context *context,
gl::MaybeOverrideLuminance(format, type, getColorReadFormat(context), gl::MaybeOverrideLuminance(format, type, getColorReadFormat(context),
getColorReadType(context)); getColorReadType(context));
return mImage->readPixelsForGetImage(contextVk, packState, packBuffer, 0, 0, format, type, return mImage->readPixelsForGetImage(contextVk, packState, packBuffer, gl::LevelIndex(0), 0,
pixels); format, type, pixels);
} }
void RenderbufferVk::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) void RenderbufferVk::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
......
...@@ -170,8 +170,8 @@ angle::Result OffscreenSurfaceVk::AttachmentImage::initialize(DisplayVk *display ...@@ -170,8 +170,8 @@ angle::Result OffscreenSurfaceVk::AttachmentImage::initialize(DisplayVk *display
VkExtent3D extents = {std::max(static_cast<uint32_t>(width), 1u), VkExtent3D extents = {std::max(static_cast<uint32_t>(width), 1u),
std::max(static_cast<uint32_t>(height), 1u), 1u}; std::max(static_cast<uint32_t>(height), 1u), 1u};
ANGLE_TRY( ANGLE_TRY(image.init(displayVk, gl::TextureType::_2D, extents, vkFormat, samples, usage,
image.init(displayVk, gl::TextureType::_2D, extents, vkFormat, samples, usage, 0, 0, 1, 1)); gl::LevelIndex(0), gl::LevelIndex(0), 1, 1));
VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
ANGLE_TRY(image.initMemory(displayVk, renderer->getMemoryProperties(), flags)); ANGLE_TRY(image.initMemory(displayVk, renderer->getMemoryProperties(), flags));
...@@ -200,8 +200,8 @@ angle::Result OffscreenSurfaceVk::AttachmentImage::initializeWithExternalMemory( ...@@ -200,8 +200,8 @@ angle::Result OffscreenSurfaceVk::AttachmentImage::initializeWithExternalMemory(
VkExtent3D extents = {std::max(static_cast<uint32_t>(width), 1u), VkExtent3D extents = {std::max(static_cast<uint32_t>(width), 1u),
std::max(static_cast<uint32_t>(height), 1u), 1u}; std::max(static_cast<uint32_t>(height), 1u), 1u};
ANGLE_TRY( ANGLE_TRY(image.init(displayVk, gl::TextureType::_2D, extents, vkFormat, samples, usage,
image.init(displayVk, gl::TextureType::_2D, extents, vkFormat, samples, usage, 0, 0, 1, 1)); gl::LevelIndex(0), gl::LevelIndex(0), 1, 1));
VkImportMemoryHostPointerInfoEXT importMemoryHostPointerInfo = {}; VkImportMemoryHostPointerInfoEXT importMemoryHostPointerInfo = {};
importMemoryHostPointerInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT; importMemoryHostPointerInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT;
...@@ -240,10 +240,10 @@ OffscreenSurfaceVk::OffscreenSurfaceVk(const egl::SurfaceState &surfaceState, Re ...@@ -240,10 +240,10 @@ OffscreenSurfaceVk::OffscreenSurfaceVk(const egl::SurfaceState &surfaceState, Re
mDepthStencilAttachment(this) mDepthStencilAttachment(this)
{ {
mColorRenderTarget.init(&mColorAttachment.image, &mColorAttachment.imageViews, nullptr, nullptr, mColorRenderTarget.init(&mColorAttachment.image, &mColorAttachment.imageViews, nullptr, nullptr,
0, 0, false); gl::LevelIndex(0), 0, false);
mDepthStencilRenderTarget.init(&mDepthStencilAttachment.image, mDepthStencilRenderTarget.init(&mDepthStencilAttachment.image,
&mDepthStencilAttachment.imageViews, nullptr, nullptr, 0, 0, &mDepthStencilAttachment.imageViews, nullptr, nullptr,
false); gl::LevelIndex(0), 0, false);
} }
OffscreenSurfaceVk::~OffscreenSurfaceVk() {} OffscreenSurfaceVk::~OffscreenSurfaceVk() {}
...@@ -270,7 +270,7 @@ angle::Result OffscreenSurfaceVk::initializeImpl(DisplayVk *displayVk) ...@@ -270,7 +270,7 @@ angle::Result OffscreenSurfaceVk::initializeImpl(DisplayVk *displayVk)
ANGLE_TRY(mColorAttachment.initialize( ANGLE_TRY(mColorAttachment.initialize(
displayVk, mWidth, mHeight, renderer->getFormat(config->renderTargetFormat), samples)); displayVk, mWidth, mHeight, renderer->getFormat(config->renderTargetFormat), samples));
mColorRenderTarget.init(&mColorAttachment.image, &mColorAttachment.imageViews, nullptr, mColorRenderTarget.init(&mColorAttachment.image, &mColorAttachment.imageViews, nullptr,
nullptr, 0, 0, false); nullptr, gl::LevelIndex(0), 0, false);
} }
if (config->depthStencilFormat != GL_NONE) if (config->depthStencilFormat != GL_NONE)
...@@ -278,8 +278,8 @@ angle::Result OffscreenSurfaceVk::initializeImpl(DisplayVk *displayVk) ...@@ -278,8 +278,8 @@ angle::Result OffscreenSurfaceVk::initializeImpl(DisplayVk *displayVk)
ANGLE_TRY(mDepthStencilAttachment.initialize( ANGLE_TRY(mDepthStencilAttachment.initialize(
displayVk, mWidth, mHeight, renderer->getFormat(config->depthStencilFormat), samples)); displayVk, mWidth, mHeight, renderer->getFormat(config->depthStencilFormat), samples));
mDepthStencilRenderTarget.init(&mDepthStencilAttachment.image, mDepthStencilRenderTarget.init(&mDepthStencilAttachment.image,
&mDepthStencilAttachment.imageViews, nullptr, nullptr, 0, 0, &mDepthStencilAttachment.imageViews, nullptr, nullptr,
false); gl::LevelIndex(0), 0, false);
} }
return angle::Result::Continue; return angle::Result::Continue;
...@@ -481,9 +481,10 @@ WindowSurfaceVk::WindowSurfaceVk(const egl::SurfaceState &surfaceState, EGLNativ ...@@ -481,9 +481,10 @@ WindowSurfaceVk::WindowSurfaceVk(const egl::SurfaceState &surfaceState, EGLNativ
{ {
// Initialize the color render target with the multisampled targets. If not multisampled, the // Initialize the color render target with the multisampled targets. If not multisampled, the
// render target will be updated to refer to a swapchain image on every acquire. // render target will be updated to refer to a swapchain image on every acquire.
mColorRenderTarget.init(&mColorImageMS, &mColorImageMSViews, nullptr, nullptr, 0, 0, false); mColorRenderTarget.init(&mColorImageMS, &mColorImageMSViews, nullptr, nullptr,
gl::LevelIndex(0), 0, false);
mDepthStencilRenderTarget.init(&mDepthStencilImage, &mDepthStencilImageViews, nullptr, nullptr, mDepthStencilRenderTarget.init(&mDepthStencilImage, &mDepthStencilImageViews, nullptr, nullptr,
0, 0, false); gl::LevelIndex(0), 0, false);
mDepthStencilImageBinding.bind(&mDepthStencilImage); mDepthStencilImageBinding.bind(&mDepthStencilImage);
mColorImageMSBinding.bind(&mColorImageMS); mColorImageMSBinding.bind(&mColorImageMS);
} }
...@@ -941,13 +942,14 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context, ...@@ -941,13 +942,14 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context,
const VkImageUsageFlags usage = kSurfaceVKColorImageUsageFlags; const VkImageUsageFlags usage = kSurfaceVKColorImageUsageFlags;
ANGLE_TRY(mColorImageMS.init(context, gl::TextureType::_2D, vkExtents, format, samples, ANGLE_TRY(mColorImageMS.init(context, gl::TextureType::_2D, vkExtents, format, samples,
usage, 0, 0, 1, 1)); usage, gl::LevelIndex(0), gl::LevelIndex(0), 1, 1));
ANGLE_TRY(mColorImageMS.initMemory(context, renderer->getMemoryProperties(), ANGLE_TRY(mColorImageMS.initMemory(context, renderer->getMemoryProperties(),
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)); VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
// Initialize the color render target with the multisampled targets. If not multisampled, // Initialize the color render target with the multisampled targets. If not multisampled,
// the render target will be updated to refer to a swapchain image on every acquire. // the render target will be updated to refer to a swapchain image on every acquire.
mColorRenderTarget.init(&mColorImageMS, &mColorImageMSViews, nullptr, nullptr, 0, 0, false); mColorRenderTarget.init(&mColorImageMS, &mColorImageMSViews, nullptr, nullptr,
gl::LevelIndex(0), 0, false);
} }
ANGLE_TRY(resizeSwapchainImages(context, imageCount)); ANGLE_TRY(resizeSwapchainImages(context, imageCount));
...@@ -967,12 +969,13 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context, ...@@ -967,12 +969,13 @@ angle::Result WindowSurfaceVk::createSwapChain(vk::Context *context,
const VkImageUsageFlags dsUsage = kSurfaceVKDepthStencilImageUsageFlags; const VkImageUsageFlags dsUsage = kSurfaceVKDepthStencilImageUsageFlags;
ANGLE_TRY(mDepthStencilImage.init(context, gl::TextureType::_2D, vkExtents, dsFormat, ANGLE_TRY(mDepthStencilImage.init(context, gl::TextureType::_2D, vkExtents, dsFormat,
samples, dsUsage, 0, 0, 1, 1)); samples, dsUsage, gl::LevelIndex(0), gl::LevelIndex(0), 1,
1));
ANGLE_TRY(mDepthStencilImage.initMemory(context, renderer->getMemoryProperties(), ANGLE_TRY(mDepthStencilImage.initMemory(context, renderer->getMemoryProperties(),
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)); VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
mDepthStencilRenderTarget.init(&mDepthStencilImage, &mDepthStencilImageViews, nullptr, mDepthStencilRenderTarget.init(&mDepthStencilImage, &mDepthStencilImageViews, nullptr,
nullptr, 0, 0, false); nullptr, gl::LevelIndex(0), 0, false);
// We will need to pass depth/stencil image views to the RenderTargetVk in the future. // We will need to pass depth/stencil image views to the RenderTargetVk in the future.
} }
...@@ -1594,7 +1597,7 @@ angle::Result WindowSurfaceVk::getCurrentFramebuffer(ContextVk *contextVk, ...@@ -1594,7 +1597,7 @@ angle::Result WindowSurfaceVk::getCurrentFramebuffer(ContextVk *contextVk,
{ {
const vk::ImageView *imageView = nullptr; const vk::ImageView *imageView = nullptr;
ANGLE_TRY(swapchainImage.imageViews.getLevelLayerDrawImageView( ANGLE_TRY(swapchainImage.imageViews.getLevelLayerDrawImageView(
contextVk, swapchainImage.image, 0, 0, &imageView)); contextVk, swapchainImage.image, vk::LevelIndex(0), 0, &imageView));
imageViews[0] = imageView->getHandle(); imageViews[0] = imageView->getHandle();
ANGLE_VK_TRY(contextVk, ANGLE_VK_TRY(contextVk,
...@@ -1674,8 +1677,8 @@ angle::Result WindowSurfaceVk::drawOverlay(ContextVk *contextVk, SwapchainImage ...@@ -1674,8 +1677,8 @@ angle::Result WindowSurfaceVk::drawOverlay(ContextVk *contextVk, SwapchainImage
// Draw overlay // Draw overlay
const vk::ImageView *imageView = nullptr; const vk::ImageView *imageView = nullptr;
ANGLE_TRY( ANGLE_TRY(image->imageViews.getLevelLayerDrawImageView(contextVk, image->image,
image->imageViews.getLevelLayerDrawImageView(contextVk, image->image, 0, 0, &imageView)); vk::LevelIndex(0), 0, &imageView));
ANGLE_TRY(overlayVk->onPresent(contextVk, &image->image, imageView)); ANGLE_TRY(overlayVk->onPresent(contextVk, &image->image, imageView));
return angle::Result::Continue; return angle::Result::Continue;
......
...@@ -218,7 +218,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface ...@@ -218,7 +218,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
// Transform an image index from the frontend into one that can be used on the backing // Transform an image index from the frontend into one that can be used on the backing
// ImageHelper, taking into account mipmap or cube face offsets // ImageHelper, taking into account mipmap or cube face offsets
gl::ImageIndex getNativeImageIndex(const gl::ImageIndex &inputImageIndex) const; gl::ImageIndex getNativeImageIndex(const gl::ImageIndex &inputImageIndex) const;
uint32_t getNativeImageLevel(uint32_t frontendLevel) const; gl::LevelIndex getNativeImageLevel(gl::LevelIndex frontendLevel) const;
uint32_t getNativeImageLayer(uint32_t frontendLayer) const; uint32_t getNativeImageLayer(uint32_t frontendLayer) const;
void releaseAndDeleteImage(ContextVk *contextVk); void releaseAndDeleteImage(ContextVk *contextVk);
...@@ -229,7 +229,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface ...@@ -229,7 +229,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
const vk::Format &format, const vk::Format &format,
uint32_t imageLevelOffset, uint32_t imageLevelOffset,
uint32_t imageLayerOffset, uint32_t imageLayerOffset,
uint32_t imageBaseLevel, gl::LevelIndex imageBaseLevel,
bool selfOwned); bool selfOwned);
void updateImageHelper(ContextVk *contextVk, size_t imageCopyBufferAlignment); void updateImageHelper(ContextVk *contextVk, size_t imageCopyBufferAlignment);
vk::ImageViewHelper &getImageViews() vk::ImageViewHelper &getImageViews()
...@@ -272,7 +272,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface ...@@ -272,7 +272,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
const vk::Format &vkFormat); const vk::Format &vkFormat);
angle::Result copyImageDataToBufferAndGetData(ContextVk *contextVk, angle::Result copyImageDataToBufferAndGetData(ContextVk *contextVk,
GLint sourceLevelGL, gl::LevelIndex sourceLevelGL,
uint32_t layerCount, uint32_t layerCount,
const gl::Box &sourceArea, const gl::Box &sourceArea,
uint8_t **outDataPtr); uint8_t **outDataPtr);
...@@ -297,8 +297,8 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface ...@@ -297,8 +297,8 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
angle::Result generateMipmapLevelsWithCPU(ContextVk *contextVk, angle::Result generateMipmapLevelsWithCPU(ContextVk *contextVk,
const angle::Format &sourceFormat, const angle::Format &sourceFormat,
GLuint layer, GLuint layer,
GLuint firstMipLevel, gl::LevelIndex firstMipLevel,
GLuint maxMipLevel, gl::LevelIndex maxMipLevel,
const size_t sourceWidth, const size_t sourceWidth,
const size_t sourceHeight, const size_t sourceHeight,
const size_t sourceDepth, const size_t sourceDepth,
...@@ -317,7 +317,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface ...@@ -317,7 +317,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
const gl::ImageIndex &index, const gl::ImageIndex &index,
const gl::Offset &destOffset, const gl::Offset &destOffset,
const gl::InternalFormat &destFormat, const gl::InternalFormat &destFormat,
GLint sourceLevelGL, gl::LevelIndex sourceLevelGL,
const gl::Box &sourceBox, const gl::Box &sourceBox,
bool unpackFlipY, bool unpackFlipY,
bool unpackPremultiplyAlpha, bool unpackPremultiplyAlpha,
...@@ -328,7 +328,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface ...@@ -328,7 +328,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
const gl::ImageIndex &index, const gl::ImageIndex &index,
const gl::Offset &destOffset, const gl::Offset &destOffset,
const vk::Format &destFormat, const vk::Format &destFormat,
GLint sourceLevelGL, gl::LevelIndex sourceLevelGL,
size_t sourceLayer, size_t sourceLayer,
const gl::Box &sourceBox, const gl::Box &sourceBox,
vk::ImageHelper *srcImage); vk::ImageHelper *srcImage);
...@@ -337,7 +337,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface ...@@ -337,7 +337,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
const gl::ImageIndex &index, const gl::ImageIndex &index,
const gl::Offset &destOffset, const gl::Offset &destOffset,
const vk::Format &destFormat, const vk::Format &destFormat,
GLint sourceLevelGL, gl::LevelIndex sourceLevelGL,
const gl::Box &sourceBox, const gl::Box &sourceBox,
bool isSrcFlipY, bool isSrcFlipY,
bool unpackFlipY, bool unpackFlipY,
...@@ -362,8 +362,8 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface ...@@ -362,8 +362,8 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
angle::Result copyAndStageImageSubresource(ContextVk *contextVk, angle::Result copyAndStageImageSubresource(ContextVk *contextVk,
bool ignoreLayerCount, bool ignoreLayerCount,
uint32_t currentLayer, uint32_t currentLayer,
uint32_t srcLevelVk, vk::LevelIndex srcLevelVk,
uint32_t dstLevelGL); gl::LevelIndex dstLevelGL);
angle::Result initImageViews(ContextVk *contextVk, angle::Result initImageViews(ContextVk *contextVk,
const vk::Format &format, const vk::Format &format,
const bool sized, const bool sized,
...@@ -371,10 +371,10 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface ...@@ -371,10 +371,10 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
uint32_t layerCount); uint32_t layerCount);
angle::Result initRenderTargets(ContextVk *contextVk, angle::Result initRenderTargets(ContextVk *contextVk,
GLuint layerCount, GLuint layerCount,
GLuint levelIndex, gl::LevelIndex levelIndexGL,
gl::RenderToTextureImageIndex renderToTextureIndex); gl::RenderToTextureImageIndex renderToTextureIndex);
angle::Result getLevelLayerImageView(ContextVk *contextVk, angle::Result getLevelLayerImageView(ContextVk *contextVk,
size_t level, gl::LevelIndex levelGL,
size_t layer, size_t layer,
const vk::ImageView **imageViewOut); const vk::ImageView **imageViewOut);
...@@ -387,16 +387,18 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface ...@@ -387,16 +387,18 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
// attributes at the next opportunity. // attributes at the next opportunity.
angle::Result respecifyImageAttributes(ContextVk *contextVk); angle::Result respecifyImageAttributes(ContextVk *contextVk);
angle::Result respecifyImageAttributesAndLevels(ContextVk *contextVk, angle::Result respecifyImageAttributesAndLevels(ContextVk *contextVk,
GLuint previousBaseLevel, gl::LevelIndex previousBaseLevelGL,
GLuint baseLevel, gl::LevelIndex baseLevelGL,
GLuint maxLevel); gl::LevelIndex maxLevelGL);
// Update base and max levels, and re-create image if needed. // Update base and max levels, and re-create image if needed.
angle::Result updateBaseMaxLevels(ContextVk *contextVk, GLuint baseLevel, GLuint maxLevel); angle::Result updateBaseMaxLevels(ContextVk *contextVk,
gl::LevelIndex baseLevelGL,
gl::LevelIndex maxLevelGL);
bool isFastUnpackPossible(const vk::Format &vkFormat, size_t offset) const; bool isFastUnpackPossible(const vk::Format &vkFormat, size_t offset) const;
bool shouldUpdateBeStaged(uint32_t textureLevelIndexGL) const; bool shouldUpdateBeStaged(gl::LevelIndex textureLevelIndexGL) const;
// We monitor the staging buffer and set dirty bits if the staging buffer changes. Note that we // We monitor the staging buffer and set dirty bits if the staging buffer changes. Note that we
// support changes in the staging buffer even outside the TextureVk class. // support changes in the staging buffer even outside the TextureVk class.
......
...@@ -1652,12 +1652,14 @@ angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk, ...@@ -1652,12 +1652,14 @@ angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk,
0, nullptr); 0, nullptr);
// Copy the resulting buffer into dest. // Copy the resulting buffer into dest.
VkBufferImageCopy region = {}; VkBufferImageCopy region = {};
region.bufferOffset = 0; region.bufferOffset = 0;
region.bufferRowLength = bufferRowLengthInUints * sizeof(uint32_t); region.bufferRowLength = bufferRowLengthInUints * sizeof(uint32_t);
region.bufferImageHeight = params.blitArea.height; region.bufferImageHeight = params.blitArea.height;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
region.imageSubresource.mipLevel = depthStencilRenderTarget->getLevelIndex(); region.imageSubresource.mipLevel =
depthStencilImage->toVKLevel(gl::LevelIndex(depthStencilRenderTarget->getLevelIndex()))
.get();
region.imageSubresource.baseArrayLayer = depthStencilRenderTarget->getLayerIndex(); region.imageSubresource.baseArrayLayer = depthStencilRenderTarget->getLayerIndex();
region.imageSubresource.layerCount = 1; region.imageSubresource.layerCount = 1;
region.imageOffset.x = params.blitArea.x; region.imageOffset.x = params.blitArea.x;
...@@ -1868,7 +1870,7 @@ angle::Result UtilsVk::generateMipmap(ContextVk *contextVk, ...@@ -1868,7 +1870,7 @@ angle::Result UtilsVk::generateMipmap(ContextVk *contextVk,
{ {
ANGLE_TRY(ensureGenerateMipmapResourcesInitialized(contextVk)); ANGLE_TRY(ensureGenerateMipmapResourcesInitialized(contextVk));
const gl::Extents &srcExtents = src->getLevelExtents(params.srcLevel); const gl::Extents &srcExtents = src->getLevelExtents(vk::LevelIndex(params.srcLevel));
ASSERT(srcExtents.depth == 1); ASSERT(srcExtents.depth == 1);
// Each workgroup processes a 64x64 tile of the image. // Each workgroup processes a 64x64 tile of the image.
......
...@@ -206,7 +206,7 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk ...@@ -206,7 +206,7 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk
displayVk, gl::TextureType::_2D, vkExtents, displayVk, gl::TextureType::_2D, vkExtents,
bufferFormatProperties.format == VK_FORMAT_UNDEFINED ? externalVkFormat : vkFormat, 1, bufferFormatProperties.format == VK_FORMAT_UNDEFINED ? externalVkFormat : vkFormat, 1,
usage, vk::kVkImageCreateFlagsNone, vk::ImageLayout::ExternalPreInitialized, usage, vk::kVkImageCreateFlagsNone, vk::ImageLayout::ExternalPreInitialized,
&externalMemoryImageCreateInfo, 0, 0, 1, 1)); &externalMemoryImageCreateInfo, gl::LevelIndex(0), gl::LevelIndex(0), 1, 1));
VkImportAndroidHardwareBufferInfoANDROID importHardwareBufferInfo = {}; VkImportAndroidHardwareBufferInfoANDROID importHardwareBufferInfo = {};
importHardwareBufferInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID; importHardwareBufferInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
......
...@@ -119,7 +119,7 @@ angle::Result IOSurfaceSurfaceVkMac::initializeImpl(DisplayVk *displayVk) ...@@ -119,7 +119,7 @@ angle::Result IOSurfaceSurfaceVkMac::initializeImpl(DisplayVk *displayVk)
renderer->getFormat(kIOSurfaceFormats[mFormatIndex].nativeSizedInternalFormat), samples, renderer->getFormat(kIOSurfaceFormats[mFormatIndex].nativeSizedInternalFormat), samples,
IOSurfaceGetBaseAddressOfPlane(mIOSurface, mPlane))); IOSurfaceGetBaseAddressOfPlane(mIOSurface, mPlane)));
mColorRenderTarget.init(&mColorAttachment.image, &mColorAttachment.imageViews, nullptr, nullptr, mColorRenderTarget.init(&mColorAttachment.image, &mColorAttachment.imageViews, nullptr, nullptr,
0, 0, false); gl::LevelIndex(0), 0, false);
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -1296,6 +1296,12 @@ void GetExtentsAndLayerCount(gl::TextureType textureType, ...@@ -1296,6 +1296,12 @@ void GetExtentsAndLayerCount(gl::TextureType textureType,
break; break;
} }
} }
vk::LevelIndex GetLevelIndex(gl::LevelIndex levelGL, gl::LevelIndex baseLevel)
{
ASSERT(baseLevel <= levelGL);
return vk::LevelIndex(levelGL.get() - baseLevel.get());
}
} // namespace gl_vk } // namespace gl_vk
namespace vk_gl namespace vk_gl
...@@ -1334,5 +1340,10 @@ GLuint GetSampleCount(VkSampleCountFlags supportedCounts, GLuint requestedCount) ...@@ -1334,5 +1340,10 @@ GLuint GetSampleCount(VkSampleCountFlags supportedCounts, GLuint requestedCount)
UNREACHABLE(); UNREACHABLE();
return 0; return 0;
} }
gl::LevelIndex GetLevelIndex(vk::LevelIndex levelVK, gl::LevelIndex baseLevel)
{
return gl::LevelIndex(levelVK.get() + baseLevel.get());
}
} // namespace vk_gl } // namespace vk_gl
} // namespace rx } // namespace rx
...@@ -762,6 +762,9 @@ struct PerfCounters ...@@ -762,6 +762,9 @@ struct PerfCounters
uint32_t stencilLoads; uint32_t stencilLoads;
uint32_t stencilStores; uint32_t stencilStores;
}; };
// A Vulkan image level index.
using LevelIndex = gl::LevelIndexWrapper<uint32_t>;
} // namespace vk } // namespace vk
#if !defined(ANGLE_SHARED_LIBVULKAN) #if !defined(ANGLE_SHARED_LIBVULKAN)
...@@ -845,6 +848,8 @@ void GetExtentsAndLayerCount(gl::TextureType textureType, ...@@ -845,6 +848,8 @@ void GetExtentsAndLayerCount(gl::TextureType textureType,
const gl::Extents &extents, const gl::Extents &extents,
VkExtent3D *extentsOut, VkExtent3D *extentsOut,
uint32_t *layerCountOut); uint32_t *layerCountOut);
vk::LevelIndex GetLevelIndex(gl::LevelIndex levelGL, gl::LevelIndex baseLevel);
} // namespace gl_vk } // namespace gl_vk
namespace vk_gl namespace vk_gl
...@@ -869,6 +874,8 @@ void AddSampleCounts(VkSampleCountFlags sampleCounts, gl::SupportedSampleSet *ou ...@@ -869,6 +874,8 @@ void AddSampleCounts(VkSampleCountFlags sampleCounts, gl::SupportedSampleSet *ou
GLuint GetMaxSampleCount(VkSampleCountFlags sampleCounts); GLuint GetMaxSampleCount(VkSampleCountFlags sampleCounts);
// Return a supported sample count that's at least as large as the requested one. // Return a supported sample count that's at least as large as the requested one.
GLuint GetSampleCount(VkSampleCountFlags supportedCounts, GLuint requestedCount); GLuint GetSampleCount(VkSampleCountFlags supportedCounts, GLuint requestedCount);
gl::LevelIndex GetLevelIndex(vk::LevelIndex levelVK, gl::LevelIndex baseLevel);
} // namespace vk_gl } // namespace vk_gl
} // namespace rx } // namespace rx
......
...@@ -21,6 +21,7 @@ const unsigned int kPixelTolerance = 1u; ...@@ -21,6 +21,7 @@ const unsigned int kPixelTolerance = 1u;
const std::array<GLubyte, 16> kBC7Data4x4 = {0x50, 0x1f, 0xfc, 0xf, 0x0, 0xf0, 0xe3, 0xe1, const std::array<GLubyte, 16> kBC7Data4x4 = {0x50, 0x1f, 0xfc, 0xf, 0x0, 0xf0, 0xe3, 0xe1,
0xe1, 0xe1, 0xc1, 0xf, 0xfc, 0xc0, 0xf, 0xfc}; 0xe1, 0xe1, 0xc1, 0xf, 0xfc, 0xc0, 0xf, 0xfc};
const std::array<GLubyte, 16> kBC7BlackData4x4 = {};
} // anonymous namespace } // anonymous namespace
class BPTCCompressedTextureTest : public ANGLETest class BPTCCompressedTextureTest : public ANGLETest
...@@ -293,6 +294,83 @@ TEST_P(BPTCCompressedTextureTestES3, PBOCompressedTexImage) ...@@ -293,6 +294,83 @@ TEST_P(BPTCCompressedTextureTestES3, PBOCompressedTexImage)
EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, 0, GLColor::green, kPixelTolerance); EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, 0, GLColor::green, kPixelTolerance);
EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green, EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green,
kPixelTolerance); kPixelTolerance);
// Destroy the data
glBufferData(GL_PIXEL_UNPACK_BUFFER, kBC7BlackData4x4.size(), kBC7BlackData4x4.data(),
GL_STREAM_DRAW);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 4, 4, 0,
kBC7BlackData4x4.size(), nullptr);
ASSERT_GL_NO_ERROR();
drawTexture();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
// Initialize again. This time, the texture's image is already allocated, so the PBO data
// upload could be directly done.
glBufferData(GL_PIXEL_UNPACK_BUFFER, kBC7Data4x4.size(), kBC7Data4x4.data(), GL_STREAM_DRAW);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 4, 4, 0,
kBC7Data4x4.size(), nullptr);
ASSERT_GL_NO_ERROR();
drawTexture();
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::red, kPixelTolerance);
EXPECT_PIXEL_COLOR_NEAR(0, getWindowHeight() - 1, GLColor::red, kPixelTolerance);
EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, 0, GLColor::green, kPixelTolerance);
EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green,
kPixelTolerance);
}
// Test uploading texture data from a PBO to a non-zero base texture.
TEST_P(BPTCCompressedTextureTestES3, PBOCompressedTexImageNonZeroBase)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_bptc"));
GLTexture texture;
setupTextureParameters(texture);
GLBuffer buffer;
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
glBufferData(GL_PIXEL_UNPACK_BUFFER, kBC7Data4x4.size(), kBC7Data4x4.data(), GL_STREAM_DRAW);
ASSERT_GL_NO_ERROR();
glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 4, 4, 0,
kBC7Data4x4.size(), nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
ASSERT_GL_NO_ERROR();
drawTexture();
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::red, kPixelTolerance);
EXPECT_PIXEL_COLOR_NEAR(0, getWindowHeight() - 1, GLColor::red, kPixelTolerance);
EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, 0, GLColor::green, kPixelTolerance);
EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green,
kPixelTolerance);
// Destroy the data
glBufferData(GL_PIXEL_UNPACK_BUFFER, kBC7BlackData4x4.size(), kBC7BlackData4x4.data(),
GL_STREAM_DRAW);
glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 4, 4, 0,
kBC7BlackData4x4.size(), nullptr);
ASSERT_GL_NO_ERROR();
drawTexture();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
// Initialize again. This time, the texture's image is already allocated, so the PBO data
// upload could be directly done.
glBufferData(GL_PIXEL_UNPACK_BUFFER, kBC7Data4x4.size(), kBC7Data4x4.data(), GL_STREAM_DRAW);
glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 4, 4, 0,
kBC7Data4x4.size(), nullptr);
ASSERT_GL_NO_ERROR();
drawTexture();
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::red, kPixelTolerance);
EXPECT_PIXEL_COLOR_NEAR(0, getWindowHeight() - 1, GLColor::red, kPixelTolerance);
EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, 0, GLColor::green, kPixelTolerance);
EXPECT_PIXEL_COLOR_NEAR(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green,
kPixelTolerance);
} }
// Test uploading texture data from a PBO to a texture allocated with texStorage2D. // Test uploading texture data from a PBO to a texture allocated with texStorage2D.
......
...@@ -746,8 +746,9 @@ TEST_P(ClearTestES3, ClearMultipleAttachmentsFollowedBySpecificOne) ...@@ -746,8 +746,9 @@ TEST_P(ClearTestES3, ClearMultipleAttachmentsFollowedBySpecificOne)
// done in a single render pass. // done in a single render pass.
TEST_P(ClearTestES3, ClearMultipleAttachmentsIndividually) TEST_P(ClearTestES3, ClearMultipleAttachmentsIndividually)
{ {
// https://issuetracker.google.com/issues/161553839 // http://anglebug.com/4855
ANGLE_SKIP_TEST_IF(IsIntel() && IsVulkan()); ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
constexpr uint32_t kSize = 16; constexpr uint32_t kSize = 16;
constexpr uint32_t kAttachmentCount = 2; constexpr uint32_t kAttachmentCount = 2;
constexpr float kDepthClearValue = 0.125f; constexpr float kDepthClearValue = 0.125f;
...@@ -986,8 +987,8 @@ TEST_P(ClearTestES3, MaskedIndexedClearMultipleAttachments) ...@@ -986,8 +987,8 @@ TEST_P(ClearTestES3, MaskedIndexedClearMultipleAttachments)
// and the relevant internal shaders. // and the relevant internal shaders.
TEST_P(ClearTestES3, MaskedClearHeterogeneousAttachments) TEST_P(ClearTestES3, MaskedClearHeterogeneousAttachments)
{ {
// https://issuetracker.google.com/issues/161553839 // http://anglebug.com/4855
ANGLE_SKIP_TEST_IF(IsIntel() && IsVulkan()); ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
constexpr uint32_t kSize = 16; constexpr uint32_t kSize = 16;
constexpr uint32_t kAttachmentCount = 3; constexpr uint32_t kAttachmentCount = 3;
......
...@@ -1139,6 +1139,68 @@ void main() ...@@ -1139,6 +1139,68 @@ void main()
} }
} }
// Use image uniform to read and write Texture2D with non-zero base in compute shader, and verify
// the contents.
TEST_P(ComputeShaderTest, BindImageTextureWithNonZeroBaseTexture2D)
{
GLTexture texture[2];
GLFramebuffer framebuffer;
constexpr char kCS[] = R"(#version 310 es
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
void main()
{
uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
})";
constexpr int kWidth = 1, kHeight = 1;
constexpr GLuint kInputValues[2][1] = {{200}, {100}};
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth * 2, kHeight * 2);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
kInputValues[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
EXPECT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth * 2, kHeight * 2);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
kInputValues[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
EXPECT_GL_NO_ERROR();
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
glUseProgram(program.get());
glBindImageTexture(0, texture[0], 1, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
EXPECT_GL_NO_ERROR();
glBindImageTexture(1, texture[1], 1, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
EXPECT_GL_NO_ERROR();
glDispatchCompute(1, 1, 1);
EXPECT_GL_NO_ERROR();
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
GLuint outputValues[kWidth * kHeight];
constexpr GLuint expectedValue = 200;
glUseProgram(0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 1);
EXPECT_GL_NO_ERROR();
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
EXPECT_GL_NO_ERROR();
for (int i = 0; i < kWidth * kHeight; i++)
{
EXPECT_EQ(expectedValue, outputValues[i]) << " at index: " << i;
}
}
// Use image uniform to read and write Texture2DArray in compute shader, and verify the contents. // Use image uniform to read and write Texture2DArray in compute shader, and verify the contents.
TEST_P(ComputeShaderTest, BindImageTextureWithTexture2DArray) TEST_P(ComputeShaderTest, BindImageTextureWithTexture2DArray)
{ {
...@@ -1206,6 +1268,76 @@ void main() ...@@ -1206,6 +1268,76 @@ void main()
} }
} }
// Use image uniform to read and write Texture2DArray with non-zero base in compute shader, and
// verify the contents.
TEST_P(ComputeShaderTest, BindImageTextureWithNonZeroBaseTexture2DArray)
{
GLTexture texture[2];
GLFramebuffer framebuffer;
constexpr char kCS[] = R"(#version 310 es
layout(local_size_x=2, local_size_y=2, local_size_z=2) in;
layout(r32ui, binding = 0) readonly uniform highp uimage2DArray uImage_1;
layout(r32ui, binding = 1) writeonly uniform highp uimage2DArray uImage_2;
void main()
{
uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
})";
constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};
glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32UI, kWidth * 2, kHeight * 2, kDepth);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
GL_UNSIGNED_INT, kInputValues[0]);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
EXPECT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32UI, kWidth * 2, kHeight * 2, kDepth);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
GL_UNSIGNED_INT, kInputValues[1]);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
EXPECT_GL_NO_ERROR();
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
glUseProgram(program.get());
glBindImageTexture(0, texture[0], 1, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
EXPECT_GL_NO_ERROR();
glBindImageTexture(1, texture[1], 1, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
EXPECT_GL_NO_ERROR();
glDispatchCompute(1, 1, 1);
EXPECT_GL_NO_ERROR();
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
GLuint outputValues[kWidth * kHeight];
constexpr GLuint expectedValue = 200;
glUseProgram(0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 1, 0);
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 1, 1);
EXPECT_GL_NO_ERROR();
glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
EXPECT_GL_NO_ERROR();
for (int i = 0; i < kWidth * kHeight; i++)
{
EXPECT_EQ(expectedValue, outputValues[i]);
}
glReadBuffer(GL_COLOR_ATTACHMENT1);
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
EXPECT_GL_NO_ERROR();
for (int i = 0; i < kWidth * kHeight; i++)
{
EXPECT_EQ(expectedValue, outputValues[i]);
}
}
// Use image uniform to read and write Texture3D in compute shader, and verify the contents. // Use image uniform to read and write Texture3D in compute shader, and verify the contents.
TEST_P(ComputeShaderTest, BindImageTextureWithTexture3D) TEST_P(ComputeShaderTest, BindImageTextureWithTexture3D)
{ {
......
...@@ -64,7 +64,7 @@ class CopyTexImageTest : public ANGLETest ...@@ -64,7 +64,7 @@ class CopyTexImageTest : public ANGLETest
} }
void verifyResults(GLuint texture, void verifyResults(GLuint texture,
GLubyte data[4], const GLubyte data[4],
GLint fboSize, GLint fboSize,
GLint xs, GLint xs,
GLint ys, GLint ys,
...@@ -710,6 +710,114 @@ TEST_P(CopyTexImageTestES3, CopyTexSubImageFromTexture3D) ...@@ -710,6 +710,114 @@ TEST_P(CopyTexImageTestES3, CopyTexSubImageFromTexture3D)
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
} }
// Test that copying from a non-zero base texture works.
TEST_P(CopyTexImageTestES3, CopyTexSubImageFromNonZeroBase)
{
// http://anglebug.com/5000
ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsWindows());
constexpr GLsizei kTexSize = 4;
std::vector<GLColor> red(kTexSize * kTexSize, GLColor::red);
std::vector<GLColor> green(kTexSize * kTexSize, GLColor::green);
// Create a framebuffer attached to a non-zero base texture
GLTexture srcColor;
glBindTexture(GL_TEXTURE_2D, srcColor);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
red.data());
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
green.data());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
ASSERT_GL_NO_ERROR();
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcColor, 1);
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
// Create a texture with an identical format
GLTexture dstColor;
glBindTexture(GL_TEXTURE_2D, dstColor);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
ASSERT_GL_NO_ERROR();
// Copy into a part of this texture.
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kTexSize / 2, kTexSize / 2);
ASSERT_GL_NO_ERROR();
// Verify it.
constexpr std::array<GLubyte, 4> kExpected = {0, 255, 0, 255};
verifyResults(dstColor, kExpected.data(), kTexSize, 0, 0, kTexSize / 2, kTexSize / 2);
// Copy into another part of the texture. The previous verification ensures that the texture's
// internal image is allocated, so this should be a direct copy.
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kTexSize / 2, kTexSize / 2, 0, 0, kTexSize / 2,
kTexSize / 2);
ASSERT_GL_NO_ERROR();
// Verify it.
verifyResults(dstColor, kExpected.data(), kTexSize, kTexSize / 2, kTexSize / 2, kTexSize,
kTexSize);
}
// Test that copying into a non-zero base texture works.
TEST_P(CopyTexImageTestES3, CopyTexSubImageToNonZeroBase)
{
// http://anglebug.com/5000
ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsWindows());
constexpr GLsizei kTexSize = 4;
std::vector<GLColor> green(kTexSize * kTexSize, GLColor::green);
// Create a framebuffer attached to a non-zero base texture
GLTexture srcColor;
glBindTexture(GL_TEXTURE_2D, srcColor);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
green.data());
ASSERT_GL_NO_ERROR();
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcColor, 0);
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
// Create a texture with an identical format
GLTexture dstColor;
glBindTexture(GL_TEXTURE_2D, dstColor);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
ASSERT_GL_NO_ERROR();
// Copy into a part of this texture.
glCopyTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 0, 0, kTexSize / 2, kTexSize / 2);
ASSERT_GL_NO_ERROR();
// Verify it.
constexpr std::array<GLubyte, 4> kExpected = {0, 255, 0, 255};
verifyResults(dstColor, kExpected.data(), kTexSize, 0, 0, kTexSize / 2, kTexSize / 2);
// Copy into another part of the texture. The previous verification ensures that the texture's
// internal image is allocated, so this should be a direct copy.
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glCopyTexSubImage2D(GL_TEXTURE_2D, 1, kTexSize / 2, kTexSize / 2, 0, 0, kTexSize / 2,
kTexSize / 2);
ASSERT_GL_NO_ERROR();
// Verify it.
verifyResults(dstColor, kExpected.data(), kTexSize, kTexSize / 2, kTexSize / 2, kTexSize,
kTexSize);
}
// Initialize the 3D texture we will copy the subImage data into // Initialize the 3D texture we will copy the subImage data into
void CopyTexImageTestES3::initialize3DTexture(GLTexture &texture, void CopyTexImageTestES3::initialize3DTexture(GLTexture &texture,
const GLsizei imageWidth, const GLsizei imageWidth,
......
...@@ -7166,6 +7166,29 @@ TEST_P(Texture2DTestES3, MinificationWithSamplerNoMipmapping) ...@@ -7166,6 +7166,29 @@ TEST_P(Texture2DTestES3, MinificationWithSamplerNoMipmapping)
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, angle::GLColor::white); EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, angle::GLColor::white);
} }
// Test that clears due to emulated formats are to the correct level given non-zero base level.
TEST_P(Texture2DTestES3, NonZeroBaseEmulatedClear)
{
// Tests behavior of the Vulkan backend with emulated formats.
ANGLE_SKIP_TEST_IF(!IsVulkan());
setUpProgram();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mTexture2D);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 4, 4, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 4);
EXPECT_GL_NO_ERROR();
drawQuad(mProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
}
// Draw a quad with an integer texture with a non-zero base level, and test that the color of the // Draw a quad with an integer texture with a non-zero base level, and test that the color of the
// texture is output. // texture is output.
TEST_P(Texture2DIntegerTestES3, IntegerTextureNonZeroBaseLevel) TEST_P(Texture2DIntegerTestES3, IntegerTextureNonZeroBaseLevel)
...@@ -7533,7 +7556,7 @@ ANGLE_INSTANTIATE_TEST_ES2(Texture2DTestWithDrawScale); ...@@ -7533,7 +7556,7 @@ ANGLE_INSTANTIATE_TEST_ES2(Texture2DTestWithDrawScale);
ANGLE_INSTANTIATE_TEST_ES2(Sampler2DAsFunctionParameterTest); ANGLE_INSTANTIATE_TEST_ES2(Sampler2DAsFunctionParameterTest);
ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayTest); ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayTest);
ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayAsFunctionParameterTest); ANGLE_INSTANTIATE_TEST_ES2(SamplerArrayAsFunctionParameterTest);
ANGLE_INSTANTIATE_TEST_ES3(Texture2DTestES3); ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DTestES3, WithAllocateNonZeroMemory(ES3_VULKAN()));
ANGLE_INSTANTIATE_TEST_ES31(Texture2DTestES31PPO); ANGLE_INSTANTIATE_TEST_ES31(Texture2DTestES31PPO);
ANGLE_INSTANTIATE_TEST_ES3(Texture2DBaseMaxTestES3); ANGLE_INSTANTIATE_TEST_ES3(Texture2DBaseMaxTestES3);
ANGLE_INSTANTIATE_TEST_ES2(Texture3DTestES2); ANGLE_INSTANTIATE_TEST_ES2(Texture3DTestES2);
......
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