Commit d192e933 by Cody Northrop Committed by Commit Bot

Vulkan: Support binding texture levels as a rendertarget

This CL refactors how TextureVk handles rendertargets. It removes the single rendertarget that previously supported 2D, and expands the layer/level list of rendertargets to handle all cases. Bug: angleproject:3184 Bug: angleproject:3996 Test: Texture2DTestES3.FramebufferTextureChangingBaselevel/ES3_Vulkan Test: FramebufferRenderMipmapTest.RenderToMipmap/ES2_Vulkan Test: FramebufferRenderMipmapTest.RenderToMipmap/ES3_Vulkan Test: ComputeShaderTest.ImageStoreMipmapSlice/ES3_1_Vulkan Change-Id: I466d0389cc6744994f88c40cc388fca694b53a99 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1854895Reviewed-by: 's avatarIan Elliott <ianelliott@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Cody Northrop <cnorthrop@google.com>
parent bbf0ce28
......@@ -79,6 +79,11 @@ void GetRenderTargetLayerCountAndIndex(vk::ImageHelper *image,
{
switch (index.getType())
{
case gl::TextureType::_2D:
*layerIndex = 0;
*layerCount = 1;
return;
case gl::TextureType::CubeMap:
*layerIndex = index.cubeMapFaceIndex();
*layerCount = gl::kCubeFaceCount;
......@@ -894,10 +899,12 @@ void TextureVk::setImageHelper(ContextVk *contextVk,
mImage->initStagingBuffer(contextVk->getRenderer(), format, vk::kStagingBufferFlags,
mStagingBufferInitialSize);
mRenderTarget.init(mImage, &mDrawImageView, getNativeImageLevel(0), getNativeImageLayer(0));
// Force re-creation of layered render targets next time they are needed
mLayerRenderTargets.clear();
// Force re-creation of render targets next time they are needed
for (vk::RenderTargetVector &renderTargetLevels : mRenderTargets)
{
renderTargetLevels.clear();
}
mRenderTargets.clear();
mSerial = contextVk->generateTextureSerial();
}
......@@ -1251,31 +1258,18 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
GLsizei samples,
FramebufferAttachmentRenderTarget **rtOut)
{
// Non-zero mip level attachments are an ES 3.0 feature.
ASSERT(imageIndex.getLevelIndex() == 0);
ASSERT(imageIndex.getLevelIndex() >= 0);
ContextVk *contextVk = vk::GetImpl(context);
ANGLE_TRY(ensureImageInitialized(contextVk));
GLuint layerIndex = 0, layerCount = 0;
switch (imageIndex.getType())
{
case gl::TextureType::_2D:
*rtOut = &mRenderTarget;
break;
case gl::TextureType::CubeMap:
case gl::TextureType::_2DArray:
case gl::TextureType::_3D:
// Special handling required for different types, grab the count and index
GetRenderTargetLayerCountAndIndex(mImage, imageIndex, &layerCount, &layerIndex);
ANGLE_TRY(initLayerRenderTargets(contextVk, layerCount));
*rtOut = &mLayerRenderTargets[layerIndex];
break;
default:
UNREACHABLE();
}
ANGLE_TRY(initRenderTargets(contextVk, layerCount, imageIndex.getLevelIndex()));
ASSERT(imageIndex.getLevelIndex() < static_cast<int32_t>(mRenderTargets.size()));
*rtOut = &mRenderTargets[imageIndex.getLevelIndex()][layerIndex];
return angle::Result::Continue;
}
......@@ -1317,20 +1311,27 @@ angle::Result TextureVk::ensureImageInitializedImpl(ContextVk *contextVk,
commandBuffer);
}
angle::Result TextureVk::initLayerRenderTargets(ContextVk *contextVk, GLuint layerCount)
angle::Result TextureVk::initRenderTargets(ContextVk *contextVk,
GLuint layerCount,
GLuint levelIndex)
{
if (mRenderTargets.size() <= levelIndex)
{
mRenderTargets.resize(levelIndex + 1);
}
// Lazy init. Check if already initialized.
if (!mLayerRenderTargets.empty())
if (!mRenderTargets[levelIndex].empty())
return angle::Result::Continue;
mLayerRenderTargets.resize(layerCount);
mRenderTargets[levelIndex].resize(layerCount);
for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex)
{
const vk::ImageView *drawView;
ANGLE_TRY(getLayerLevelDrawImageView(contextVk, layerIndex, 0, &drawView));
mLayerRenderTargets[layerIndex].init(mImage, drawView, getNativeImageLevel(0),
getNativeImageLayer(layerIndex));
ANGLE_TRY(getLayerLevelDrawImageView(contextVk, layerIndex, levelIndex, &drawView));
mRenderTargets[levelIndex][layerIndex].init(
mImage, drawView, getNativeImageLevel(levelIndex), getNativeImageLayer(layerIndex));
}
return angle::Result::Continue;
}
......@@ -1692,13 +1693,6 @@ angle::Result TextureVk::initImageViews(ContextVk *contextVk,
layerCount));
}
if (!format.imageFormat().isBlock)
{
ANGLE_TRY(mImage->initLayerImageView(contextVk, mState.getType(), aspectFlags,
gl::SwizzleState(), &mDrawImageView, baseLevel, 1,
baseLayer, layerCount));
}
return angle::Result::Continue;
}
......@@ -1718,7 +1712,13 @@ void TextureVk::releaseImage(ContextVk *contextVk)
releaseImageViews(contextVk);
mLayerRenderTargets.clear();
for (vk::RenderTargetVector &renderTargetLevels : mRenderTargets)
{
// Clear the layers tracked for each level
renderTargetLevels.clear();
}
// Then clear the levels
mRenderTargets.clear();
onStagingBufferChange();
}
......@@ -1728,7 +1728,6 @@ void TextureVk::releaseImageViews(ContextVk *contextVk)
contextVk->addGarbage(&mReadImageView);
contextVk->addGarbage(&mFetchImageView);
contextVk->addGarbage(&mStencilReadImageView);
contextVk->addGarbage(&mDrawImageView);
for (vk::ImageViewVector &layerViews : mLayerLevelDrawImageViews)
{
......
......@@ -299,7 +299,7 @@ class TextureVk : public TextureImpl
const bool sized,
uint32_t levelCount,
uint32_t layerCount);
angle::Result initLayerRenderTargets(ContextVk *contextVk, GLuint layerCount);
angle::Result initRenderTargets(ContextVk *contextVk, GLuint layerCount, GLuint levelIndex);
vk::ImageView *getLevelImageViewImpl(vk::ImageViewVector *imageViews, size_t level);
vk::ImageView *getLayerLevelImageViewImpl(vk::LayerLevelImageViewVector *imageViews,
size_t layer,
......@@ -334,15 +334,16 @@ class TextureVk : public TextureImpl
vk::ImageView mStencilReadImageView;
// Draw views.
vk::ImageView mDrawImageView;
vk::LayerLevelImageViewVector mLayerLevelDrawImageViews;
// Storage image views.
vk::ImageViewVector mLevelStorageImageViews;
vk::Sampler mSampler;
RenderTargetVk mRenderTarget;
std::vector<RenderTargetVk> mLayerRenderTargets;
// Render targets stored as vector of vectors
// Level is first dimension, layer is second
std::vector<vk::RenderTargetVector> mRenderTargets;
// The serial is used for cache indexing.
Serial mSerial;
......
......@@ -124,6 +124,8 @@ void RendererVk::ensureCapsInitialized() const
// Vulkan natively supports 32-bit indices, entry in kIndexTypeMap
mNativeExtensions.elementIndexUint = true;
mNativeExtensions.fboRenderMipmap = true;
// https://vulkan.lunarg.com/doc/view/1.0.30.0/linux/vkspec.chunked/ch31s02.html
mNativeCaps.maxElementIndex = std::numeric_limits<GLuint>::max() - 1;
mNativeCaps.max3DTextureSize = limitsVk.maxImageDimension3D;
......
......@@ -597,6 +597,8 @@ std::string GetMappedSamplerName(const std::string &originalName);
using ImageViewVector = std::vector<ImageView>;
// A vector of vector of image views. Primary index is layer, secondary index is level.
using LayerLevelImageViewVector = std::vector<ImageViewVector>;
// A vector of rendertargets
using RenderTargetVector = std::vector<RenderTargetVk>;
} // namespace vk
......
......@@ -3010,9 +3010,6 @@ TEST_P(ComputeShaderTest, ImageStoreMipmapSlice)
// TODO(xinghua.cao@intel.com): http://anglebug.com/3101
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
// Non-zero-level render target attachments are not yet supported. http://anglebug.com/3184
ANGLE_SKIP_TEST_IF(IsVulkan());
GLTexture texture[2];
GLFramebuffer framebuffer;
constexpr char kCS[] = R"(#version 310 es
......
......@@ -163,4 +163,5 @@ ANGLE_INSTANTIATE_TEST(FramebufferRenderMipmapTest,
ES3_OPENGL(),
ES2_OPENGLES(),
ES3_OPENGLES(),
ES2_VULKAN());
ES2_VULKAN(),
ES3_VULKAN());
......@@ -2017,8 +2017,8 @@ TEST_P(Texture2DTestES3, FramebufferTextureChangingBaselevel)
// TODO(geofflang): Investigate on D3D11. http://anglebug.com/2291
ANGLE_SKIP_TEST_IF(IsD3D11());
// TODO(cnorthrop): Framebuffer level support. http://anglebug.com/3184
ANGLE_SKIP_TEST_IF(IsVulkan());
// TODO(cnorthrop): Failing on Vulkan/Windows/AMD. http://anglebug.com/3996
ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && IsAMD());
setUpProgram();
......
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