Commit 912e52d8 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Storage image support

Image bindings are placed after atomic counters in the "resources" descriptor set. There are two issues yet to be addressed: - GL can create a 2D (array) view of a 3D image, but this is not allowed in Vulkan. If this cannot be made possible, emulation needs to be done. https://github.com/KhronosGroup/Vulkan-Docs/issues/1033 - GL can create an image view of a texture with a different format and have the data reinterpreted. This is not currently done. Bug: angleproject:3563 Change-Id: I95c4d92c50bb033212a9a67f3f2d6f97c074c7bf Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1767366 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 93bb092f
......@@ -71,6 +71,9 @@ class FixedVector final
void push_back(const value_type &value);
void push_back(value_type &&value);
template <class... Args>
void emplace_back(Args &&... args);
void pop_back();
reference back();
const_reference back() const;
......@@ -261,6 +264,15 @@ void FixedVector<T, N, Storage>::push_back(value_type &&value)
}
template <class T, size_t N, class Storage>
template <class... Args>
void FixedVector<T, N, Storage>::emplace_back(Args &&... args)
{
ASSERT(mSize < N);
new (&mStorage[mSize]) T{std::forward<Args>(args)...};
mSize++;
}
template <class T, size_t N, class Storage>
void FixedVector<T, N, Storage>::pop_back()
{
ASSERT(mSize > 0);
......
......@@ -44,9 +44,9 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
const TType &type = variable->getType();
bool needsCustomLayout =
(type.getQualifier() == EvqAttribute || type.getQualifier() == EvqFragmentOut ||
type.getQualifier() == EvqVertexIn || IsVarying(type.getQualifier()) ||
IsSampler(type.getBasicType()) || type.isInterfaceBlock());
type.getQualifier() == EvqAttribute || type.getQualifier() == EvqFragmentOut ||
type.getQualifier() == EvqVertexIn || IsVarying(type.getQualifier()) ||
IsSampler(type.getBasicType()) || type.isInterfaceBlock() || IsImage(type.getBasicType());
if (!NeedsToWriteLayoutQualifier(type) && !needsCustomLayout)
{
......
......@@ -3424,6 +3424,11 @@ void Context::initCaps()
}
LimitCap(&mState.mCaps.maxImageUnits, IMPLEMENTATION_MAX_IMAGE_UNITS);
LimitCap(&mState.mCaps.maxCombinedImageUniforms, IMPLEMENTATION_MAX_IMAGE_UNITS);
for (ShaderType shaderType : AllShaderTypes())
{
LimitCap(&mState.mCaps.maxShaderImageUniforms[shaderType], IMPLEMENTATION_MAX_IMAGE_UNITS);
}
for (ShaderType shaderType : AllShaderTypes())
{
......
......@@ -2470,6 +2470,14 @@ GLuint Program::getSamplerUniformBinding(const VariableLocation &uniformLocation
return boundTextureUnits[uniformLocation.arrayIndex];
}
GLuint Program::getImageUniformBinding(const VariableLocation &uniformLocation) const
{
ASSERT(mLinkResolved);
GLuint imageIndex = mState.getImageIndexFromUniformIndex(uniformLocation.index);
const std::vector<GLuint> &boundImageUnits = mState.mImageBindings[imageIndex].boundImageUnits;
return boundImageUnits[uniformLocation.arrayIndex];
}
void Program::getUniformfv(const Context *context, GLint location, GLfloat *v) const
{
ASSERT(mLinkResolved);
......@@ -2481,6 +2489,11 @@ void Program::getUniformfv(const Context *context, GLint location, GLfloat *v) c
*v = static_cast<GLfloat>(getSamplerUniformBinding(uniformLocation));
return;
}
else if (uniform.isImage())
{
*v = static_cast<GLfloat>(getImageUniformBinding(uniformLocation));
return;
}
const GLenum nativeType = gl::VariableComponentType(uniform.type);
if (nativeType == GL_FLOAT)
......@@ -2504,6 +2517,11 @@ void Program::getUniformiv(const Context *context, GLint location, GLint *v) con
*v = static_cast<GLint>(getSamplerUniformBinding(uniformLocation));
return;
}
else if (uniform.isImage())
{
*v = static_cast<GLint>(getImageUniformBinding(uniformLocation));
return;
}
const GLenum nativeType = gl::VariableComponentType(uniform.type);
if (nativeType == GL_INT || nativeType == GL_BOOL)
......@@ -2527,6 +2545,11 @@ void Program::getUniformuiv(const Context *context, GLint location, GLuint *v) c
*v = getSamplerUniformBinding(uniformLocation);
return;
}
else if (uniform.isImage())
{
*v = getImageUniformBinding(uniformLocation);
return;
}
const GLenum nativeType = VariableComponentType(uniform.type);
if (nativeType == GL_UNSIGNED_INT)
......
......@@ -1035,6 +1035,7 @@ class Program final : angle::NonCopyable, public LabeledObject
GLint getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const;
GLuint getSamplerUniformBinding(const VariableLocation &uniformLocation) const;
GLuint getImageUniformBinding(const VariableLocation &uniformLocation) const;
bool validateSamplersImpl(InfoLog *infoLog, const Caps &caps);
......
......@@ -496,6 +496,8 @@ using StorageBuffersArray = std::array<T, IMPLEMENTATION_MAX_SHADER_STORAGE_BUFF
template <typename T>
using AtomicCounterBuffersArray = std::array<T, IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS>;
using AtomicCounterBufferMask = angle::BitSet<IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS>;
template <typename T>
using ImagesArray = std::array<T, IMPLEMENTATION_MAX_IMAGE_UNITS>;
using ImageUnitMask = angle::BitSet<IMPLEMENTATION_MAX_IMAGE_UNITS>;
......
......@@ -300,6 +300,7 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mComputeDirtyBits = mNewComputeCommandBufferDirtyBits;
mActiveTextures.fill({nullptr, nullptr});
mActiveImages.fill(nullptr);
mPipelineDirtyBitsMask.set();
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
......@@ -769,8 +770,13 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl(
vk::CommandBuffer *commandBuffer,
vk::CommandGraphResource *recorder)
{
if (mProgram->hasImages())
{
ANGLE_TRY(updateActiveImages(context, recorder));
}
if (mProgram->hasUniformBuffers() || mProgram->hasStorageBuffers() ||
mProgram->hasAtomicCounterBuffers())
mProgram->hasAtomicCounterBuffers() || mProgram->hasImages())
{
ANGLE_TRY(mProgram->updateShaderResourcesDescriptorSet(this, recorder));
}
......@@ -1812,7 +1818,7 @@ angle::Result ContextVk::syncState(const gl::Context *context,
static_cast<uint32_t>(glState.getStencilClearValue());
break;
case gl::State::DIRTY_BIT_UNPACK_STATE:
// This is a no-op, its only important to use the right unpack state when we do
// This is a no-op, it's only important to use the right unpack state when we do
// setImage or setSubImage in TextureVk, which is plumbed through the frontend call
break;
case gl::State::DIRTY_BIT_UNPACK_BUFFER_BINDING:
......@@ -1926,6 +1932,7 @@ angle::Result ContextVk::syncState(const gl::Context *context,
invalidateDriverUniforms();
break;
case gl::State::DIRTY_BIT_IMAGE_BINDINGS:
invalidateCurrentShaderResources();
break;
case gl::State::DIRTY_BIT_MULTISAMPLING:
// TODO(syoussefi): this should configure the pipeline to render as if
......@@ -2152,7 +2159,7 @@ void ContextVk::invalidateCurrentShaderResources()
{
ASSERT(mProgram);
if (mProgram->hasUniformBuffers() || mProgram->hasStorageBuffers() ||
mProgram->hasAtomicCounterBuffers())
mProgram->hasAtomicCounterBuffers() || mProgram->hasImages())
{
mGraphicsDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
......@@ -2535,9 +2542,60 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context,
return angle::Result::Continue;
}
const gl::ActiveTextureArray<vk::TextureUnit> &ContextVk::getActiveTextures() const
angle::Result ContextVk::updateActiveImages(const gl::Context *context,
vk::CommandGraphResource *recorder)
{
return mActiveTextures;
const gl::State &glState = mState;
const gl::Program *program = glState.getProgram();
mActiveImages.fill(nullptr);
const gl::ActiveTextureMask &activeImages = program->getActiveImagesMask();
for (size_t imageUnitIndex : activeImages)
{
const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
const gl::Texture *texture = imageUnit.texture.get();
if (texture == nullptr)
{
continue;
}
TextureVk *textureVk = vk::GetImpl(texture);
vk::ImageHelper *image = &textureVk->getImage();
// The image should be flushed and ready to use at this point. There may still be lingering
// staged updates in its staging buffer for unused texture mip levels or layers. Therefore
// we can't verify it has no staged updates right here.
// TODO(syoussefi): make sure front-end syncs textures that are used as images (they are
// already notified of content change).
// Test: SimpleStateChangeTestES31.DispatchWithImageTextureTexSubImageThenDispatchAgain
// http://anglebug.com/3539
ANGLE_TRY(textureVk->ensureImageInitialized(this));
vk::ImageLayout imageLayout = vk::ImageLayout::AllGraphicsShadersWrite;
if (program->isCompute())
{
imageLayout = vk::ImageLayout::ComputeShaderWrite;
}
// Ensure the image is in read-only layout
if (image->isLayoutChangeNecessary(imageLayout))
{
vk::CommandBuffer *layoutChange;
ANGLE_TRY(image->recordCommands(this, &layoutChange));
VkImageAspectFlags aspectFlags = image->getAspectFlags();
image->changeLayout(aspectFlags, imageLayout, layoutChange);
}
image->addWriteDependency(recorder);
mActiveImages[imageUnitIndex] = textureVk;
}
return angle::Result::Continue;
}
void ContextVk::insertWaitSemaphore(const vk::Semaphore *waitSemaphore)
......
......@@ -241,7 +241,11 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
const char *file,
const char *function,
unsigned int line) override;
const gl::ActiveTextureArray<vk::TextureUnit> &getActiveTextures() const;
const gl::ActiveTextureArray<vk::TextureUnit> &getActiveTextures() const
{
return mActiveTextures;
}
const gl::ActiveTextureArray<TextureVk *> &getActiveImages() const { return mActiveImages; }
void setIndexBufferDirty()
{
......@@ -407,6 +411,8 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
angle::Result updateActiveTextures(const gl::Context *context,
vk::CommandGraphResource *recorder);
angle::Result updateActiveImages(const gl::Context *context,
vk::CommandGraphResource *recorder);
angle::Result updateDefaultAttribute(size_t attribIndex);
ANGLE_INLINE void invalidateCurrentGraphicsPipeline()
......@@ -588,6 +594,8 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
gl::ActiveTextureArray<vk::TextureUnit> mActiveTextures;
vk::TextureDescriptorDesc mActiveTexturesDesc;
gl::ActiveTextureArray<TextureVk *> mActiveImages;
// "Current Value" aka default vertex attribute state.
gl::AttributesMask mDirtyDefaultAttribsMask;
gl::AttribArray<vk::DynamicBuffer> mDefaultAttribBuffers;
......
......@@ -753,8 +753,35 @@ uint32_t AssignAtomicCounterBufferBindings(const std::vector<gl::AtomicCounterBu
return bindingStart + 1;
}
void AssignBufferBindings(const gl::ProgramState &programState,
gl::ShaderMap<IntermediateShaderSource> *shaderSources)
uint32_t AssignImageBindings(const std::vector<gl::LinkedUniform> &uniforms,
const gl::RangeUI &imageUniformRange,
uint32_t bindingStart,
gl::ShaderMap<IntermediateShaderSource> *shaderSources)
{
const std::string resourcesDescriptorSet = "set = " + Str(kShaderResourceDescriptorSetIndex);
uint32_t bindingIndex = bindingStart;
for (unsigned int uniformIndex : imageUniformRange)
{
const gl::LinkedUniform &imageUniform = uniforms[uniformIndex];
const std::string bindingString =
resourcesDescriptorSet + ", binding = " + Str(bindingIndex++);
std::string name = imageUniform.name;
if (name.back() == ']')
{
name = name.substr(0, name.find('['));
}
AssignResourceBinding(imageUniform.activeShaders(), name, bindingString, kUniformQualifier,
kUnusedUniformSubstitution, shaderSources);
}
return bindingIndex;
}
void AssignNonTextureBindings(const gl::ProgramState &programState,
gl::ShaderMap<IntermediateShaderSource> *shaderSources)
{
uint32_t bindingStart = 0;
......@@ -770,6 +797,10 @@ void AssignBufferBindings(const gl::ProgramState &programState,
programState.getAtomicCounterBuffers();
bindingStart = AssignAtomicCounterBufferBindings(atomicCounterBuffers, kSSBOQualifier,
bindingStart, shaderSources);
const std::vector<gl::LinkedUniform> &uniforms = programState.getUniforms();
const gl::RangeUI &imageUniformRange = programState.getImageUniformRange();
bindingStart = AssignImageBindings(uniforms, imageUniformRange, bindingStart, shaderSources);
}
void AssignTextureBindings(bool useOldRewriteStructSamplers,
......@@ -922,8 +953,8 @@ void GlslangWrapper::GetShaderSource(bool useOldRewriteStructSamplers,
AssignVaryingLocations(resources, vertexSource, fragmentSource);
}
AssignUniformBindings(&intermediateSources);
AssignBufferBindings(programState, &intermediateSources);
AssignTextureBindings(useOldRewriteStructSamplers, programState, &intermediateSources);
AssignNonTextureBindings(programState, &intermediateSources);
for (const auto shaderType : gl::kAllGraphicsShaderTypes)
{
......
......@@ -123,6 +123,7 @@ class ProgramVk : public ProgramImpl
bool hasUniformBuffers() const { return !mState.getUniformBlocks().empty(); }
bool hasStorageBuffers() const { return !mState.getShaderStorageBlocks().empty(); }
bool hasAtomicCounterBuffers() const { return !mState.getAtomicCounterBuffers().empty(); }
bool hasImages() const { return !mState.getImageBindings().empty(); }
bool hasTransformFeedbackOutput() const
{
return !mState.getLinkedTransformFeedbackVaryings().empty();
......@@ -190,6 +191,8 @@ class ProgramVk : public ProgramImpl
VkDescriptorType descriptorType);
void updateAtomicCounterBuffersDescriptorSet(ContextVk *contextVk,
vk::CommandGraphResource *recorder);
angle::Result updateImagesDescriptorSet(ContextVk *contextVk,
vk::CommandGraphResource *recorder);
template <class T>
void getUniformImpl(GLint location, T *v, GLenum entryPointType) const;
......@@ -206,6 +209,7 @@ class ProgramVk : public ProgramImpl
{
return mAtomicCounterBufferBindingsOffset;
}
uint32_t getImageBindingsOffset() const { return mImageBindingsOffset; }
class ShaderInfo;
ANGLE_INLINE angle::Result initShaders(ContextVk *contextVk,
......@@ -321,10 +325,11 @@ class ProgramVk : public ProgramImpl
gl::ShaderMap<std::string> mShaderSources;
// In their descriptor set, uniform buffers are placed first, then storage buffers, then atomic
// counter buffers. These cached values contain the offsets where storage buffer and atomic
// counter buffer bindings start.
// counter buffers and then images. These cached values contain the offsets where storage
// buffer, atomic counter buffer and image bindings start.
uint32_t mStorageBlockBindingsOffset;
uint32_t mAtomicCounterBufferBindingsOffset;
uint32_t mImageBindingsOffset;
// Store descriptor pools here. We store the descriptors in the Program to facilitate descriptor
// cache management. It can also allow fewer descriptors for shaders which use fewer
......
......@@ -66,7 +66,7 @@ bool ForceCPUPathForCopy(RendererVk *renderer, const vk::ImageHelper &image)
return image.getLayerCount() > 1 && renderer->getFeatures().forceCPUPathForCubeMapCopy.enabled;
}
uint32_t GetRenderTargetLayerCount(const vk::ImageHelper &image)
uint32_t GetImageLayerCountForView(const vk::ImageHelper &image)
{
// Depth > 1 means this is a 3D texture and depth is our layer count
return image.getExtents().depth > 1 ? image.getExtents().depth : image.getLayerCount();
......@@ -1208,7 +1208,7 @@ angle::Result TextureVk::init3DRenderTargets(ContextVk *contextVk)
if (!m3DRenderTargets.empty())
return angle::Result::Continue;
uint32_t layerCount = GetRenderTargetLayerCount(*mImage);
uint32_t layerCount = GetImageLayerCountForView(*mImage);
mLayerFetchImageView.resize(layerCount);
m3DRenderTargets.resize(layerCount);
......@@ -1420,37 +1420,51 @@ const vk::ImageView &TextureVk::getFetchImageView() const
return activeView->mFetchMipmapImageView;
}
angle::Result TextureVk::getLayerLevelDrawImageView(vk::Context *context,
size_t layer,
size_t level,
const vk::ImageView **imageViewOut)
vk::ImageView *TextureVk::getLayerLevelImageViewImpl(vk::LayerLevelImageViewVector *imageViews,
size_t layer,
size_t level)
{
ASSERT(mImage->valid());
ASSERT(!mImage->getFormat().imageFormat().isBlock);
// For 3D textures, layer count is tracked as depth
uint32_t layerCount = mState.getType() == gl::TextureType::_3D ? mImage->getExtents().depth
: mImage->getLayerCount();
uint32_t layerCount = GetImageLayerCountForView(*mImage);
// Lazily allocate the storage for image views
if (mLayerLevelDrawImageViews.empty())
if (imageViews->empty())
{
mLayerLevelDrawImageViews.resize(layerCount);
imageViews->resize(layerCount);
}
ASSERT(mLayerLevelDrawImageViews.size() > layer);
ASSERT(imageViews->size() > layer);
return getLevelImageViewImpl(&(*imageViews)[layer], level);
}
if (mLayerLevelDrawImageViews[layer].empty())
vk::ImageView *TextureVk::getLevelImageViewImpl(vk::ImageViewVector *imageViews, size_t level)
{
// Lazily allocate the storage for image views
if (imageViews->empty())
{
mLayerLevelDrawImageViews[layer].resize(mImage->getLevelCount());
imageViews->resize(mImage->getLevelCount());
}
ASSERT(mLayerLevelDrawImageViews[layer].size() > level);
ASSERT(imageViews->size() > level);
return &(*imageViews)[level];
}
vk::ImageView *imageView = &mLayerLevelDrawImageViews[layer][level];
angle::Result TextureVk::getLayerLevelDrawImageView(vk::Context *context,
size_t layer,
size_t level,
const vk::ImageView **imageViewOut)
{
vk::ImageView *imageView = getLayerLevelImageViewImpl(&mLayerLevelDrawImageViews, layer, level);
*imageViewOut = imageView;
if (imageView->valid())
{
return angle::Result::Continue;
}
uint32_t layerCount = GetImageLayerCountForView(*mImage);
// Lazily allocate the image view itself.
// Note that these views are specifically made to be used as color attachments, and therefore
// don't have swizzle.
......@@ -1461,6 +1475,50 @@ angle::Result TextureVk::getLayerLevelDrawImageView(vk::Context *context,
getNativeImageLayer(static_cast<uint32_t>(layer)), 1);
}
angle::Result TextureVk::getLayerLevelStorageImageView(ContextVk *contextVk,
bool allLayers,
size_t singleLayer,
size_t level,
const vk::ImageView **imageViewOut)
{
gl::TextureType viewType = mState.getType();
uint32_t nativeLevel = getNativeImageLevel(static_cast<uint32_t>(level));
uint32_t nativeLayer = getNativeImageLayer(static_cast<uint32_t>(singleLayer));
uint32_t layerCount = 1;
vk::ImageView *imageView = nullptr;
if (allLayers)
{
// Ignore the layer parameter and create a view with all layers of the level.
imageView = getLevelImageViewImpl(&mLevelStorageImageViews, level);
// If layered, the view has the same type as the texture.
nativeLayer = getNativeImageLayer(0);
layerCount = mImage->getLayerCount();
}
else
{
// Create a view of the selected layer.
imageView = getLayerLevelImageViewImpl(&mLayerLevelStorageImageViews, singleLayer, level);
// If viewing a single layer, the image is always 2D. Note that GLES doesn't support
// multisampled storage images.
viewType = gl::TextureType::_2D;
}
*imageViewOut = imageView;
if (imageView->valid())
{
return angle::Result::Continue;
}
// Create the view. Note that storage images are not affected by swizzle parameters.
return mImage->initLayerImageView(contextVk, viewType, mImage->getAspectFlags(),
gl::SwizzleState(), imageView, nativeLevel, 1, nativeLayer,
layerCount);
}
const vk::Sampler &TextureVk::getSampler() const
{
ASSERT(mSampler.valid());
......@@ -1477,6 +1535,8 @@ angle::Result TextureVk::initImage(ContextVk *contextVk,
VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT;
// If the image has depth/stencil support, add those as possible usage.
if (renderer->hasImageFormatFeatureBits(format.vkImageFormat,
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
{
......@@ -1488,6 +1548,13 @@ angle::Result TextureVk::initImage(ContextVk *contextVk,
imageUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
}
// If the image has storage support, add it for ES3.1 image support.
if (renderer->hasImageFormatFeatureBits(format.vkImageFormat,
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
{
imageUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
}
VkExtent3D vkExtent;
uint32_t layerCount;
gl_vk::GetExtentsAndLayerCount(mState.getType(), extents, &vkExtent, &layerCount);
......@@ -1615,7 +1682,7 @@ void TextureVk::releaseImageViews(ContextVk *contextVk)
mStencilViews.release(contextVk, currentSerial);
for (auto &layerViews : mLayerLevelDrawImageViews)
for (vk::ImageViewVector &layerViews : mLayerLevelDrawImageViews)
{
for (vk::ImageView &imageView : layerViews)
{
......@@ -1628,6 +1695,19 @@ void TextureVk::releaseImageViews(ContextVk *contextVk)
contextVk->releaseObject(currentSerial, &imageView);
}
mLayerFetchImageView.clear();
for (vk::ImageView &imageView : mLevelStorageImageViews)
{
contextVk->releaseObject(currentSerial, &imageView);
}
mLevelStorageImageViews.clear();
for (vk::ImageViewVector &layerViews : mLayerLevelStorageImageViews)
{
for (vk::ImageView &imageView : layerViews)
{
contextVk->releaseObject(currentSerial, &imageView);
}
}
mLayerLevelStorageImageViews.clear();
}
void TextureVk::releaseStagingBuffer(ContextVk *contextVk)
......
......@@ -161,6 +161,11 @@ class TextureVk : public TextureImpl
size_t layer,
size_t level,
const vk::ImageView **imageViewOut);
angle::Result getLayerLevelStorageImageView(ContextVk *contextVk,
bool allLayers,
size_t singleLayer,
size_t level,
const vk::ImageView **imageViewOut);
const vk::Sampler &getSampler() const;
angle::Result ensureImageInitialized(ContextVk *contextVk);
......@@ -302,6 +307,10 @@ class TextureVk : public TextureImpl
TextureVkViews *views,
VkImageAspectFlags aspectFlags,
gl::SwizzleState mappedSwizzle);
vk::ImageView *getLevelImageViewImpl(vk::ImageViewVector *imageViews, size_t level);
vk::ImageView *getLayerLevelImageViewImpl(vk::LayerLevelImageViewVector *imageViews,
size_t layer,
size_t level);
angle::Result initCubeMapRenderTargets(ContextVk *contextVk);
angle::Result ensureImageInitializedImpl(ContextVk *contextVk,
......@@ -327,13 +336,19 @@ class TextureVk : public TextureImpl
vk::ImageHelper *mImage;
// Read views.
TextureVkViews mDefaultViews;
TextureVkViews mStencilViews;
std::vector<std::vector<vk::ImageView>> mLayerLevelDrawImageViews;
vk::Sampler mSampler;
// Draw views.
vk::LayerLevelImageViewVector mLayerLevelDrawImageViews;
// Fetch views.
vk::ImageViewVector mLayerFetchImageView;
// Storage image views.
vk::ImageViewVector mLevelStorageImageViews;
vk::LayerLevelImageViewVector mLayerLevelStorageImageViews;
vk::Sampler mSampler;
RenderTargetVk mRenderTarget;
std::vector<vk::ImageView> mLayerFetchImageView;
std::vector<RenderTargetVk> m3DRenderTargets;
std::vector<RenderTargetVk> mCubeMapRenderTargets;
......
......@@ -209,9 +209,10 @@ void RendererVk::ensureCapsInitialized() const
mNativeCaps.maxVertexUniformVectors = maxUniformVectors;
mNativeCaps.maxFragmentUniformVectors = maxUniformVectors;
mNativeCaps.maxFragmentInputComponents = maxUniformComponents;
mNativeCaps.maxShaderUniformComponents[gl::ShaderType::Vertex] = maxUniformComponents;
mNativeCaps.maxShaderUniformComponents[gl::ShaderType::Fragment] = maxUniformComponents;
mNativeCaps.maxShaderUniformComponents[gl::ShaderType::Compute] = maxUniformComponents;
for (gl::ShaderType shaderType : gl::AllShaderTypes())
{
mNativeCaps.maxShaderUniformComponents[shaderType] = maxUniformComponents;
}
mNativeCaps.maxUniformLocations = maxUniformVectors;
// Every stage has 1 reserved uniform buffer for the default uniforms, and 1 for the driver
......@@ -225,9 +226,10 @@ void RendererVk::ensureCapsInitialized() const
limitsVk.maxPerStageDescriptorUniformBuffers - kTotalReservedPerStageUniformBuffers;
const uint32_t maxCombinedUniformBuffers =
limitsVk.maxDescriptorSetUniformBuffers - kTotalReservedUniformBuffers;
mNativeCaps.maxShaderUniformBlocks[gl::ShaderType::Vertex] = maxPerStageUniformBuffers;
mNativeCaps.maxShaderUniformBlocks[gl::ShaderType::Fragment] = maxPerStageUniformBuffers;
mNativeCaps.maxShaderUniformBlocks[gl::ShaderType::Compute] = maxPerStageUniformBuffers;
for (gl::ShaderType shaderType : gl::AllShaderTypes())
{
mNativeCaps.maxShaderUniformBlocks[shaderType] = maxPerStageUniformBuffers;
}
mNativeCaps.maxCombinedUniformBlocks = maxCombinedUniformBuffers;
mNativeCaps.maxUniformBufferBindings = maxCombinedUniformBuffers;
......@@ -241,9 +243,10 @@ void RendererVk::ensureCapsInitialized() const
limitsVk.maxPerStageDescriptorSampledImages);
const uint32_t maxCombinedTextures =
std::min(limitsVk.maxDescriptorSetSamplers, limitsVk.maxDescriptorSetSampledImages);
mNativeCaps.maxShaderTextureImageUnits[gl::ShaderType::Vertex] = maxPerStageTextures;
mNativeCaps.maxShaderTextureImageUnits[gl::ShaderType::Fragment] = maxPerStageTextures;
mNativeCaps.maxShaderTextureImageUnits[gl::ShaderType::Compute] = maxPerStageTextures;
for (gl::ShaderType shaderType : gl::AllShaderTypes())
{
mNativeCaps.maxShaderTextureImageUnits[shaderType] = maxPerStageTextures;
}
mNativeCaps.maxCombinedTextureImageUnits = maxCombinedTextures;
uint32_t maxPerStageStorageBuffers = limitsVk.maxPerStageDescriptorStorageBuffers;
......@@ -341,6 +344,16 @@ void RendererVk::ensureCapsInitialized() const
}
mNativeCaps.maxCombinedAtomicCounters = maxAtomicCounters;
// GL Images correspond to Vulkan Storage Images.
const uint32_t maxPerStageImages = limitsVk.maxPerStageDescriptorStorageImages;
const uint32_t maxCombinedImages = limitsVk.maxDescriptorSetStorageImages;
for (gl::ShaderType shaderType : gl::AllShaderTypes())
{
mNativeCaps.maxShaderImageUniforms[shaderType] = maxPerStageImages;
}
mNativeCaps.maxCombinedImageUniforms = maxCombinedImages;
mNativeCaps.maxImageUnits = maxCombinedImages;
mNativeCaps.minProgramTexelOffset = mPhysicalDeviceProperties.limits.minTexelOffset;
mNativeCaps.maxProgramTexelOffset = mPhysicalDeviceProperties.limits.maxTexelOffset;
......
......@@ -147,6 +147,32 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
},
},
{
ImageLayout::AllGraphicsShadersReadOnly,
{
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
// Transition to: all reads must happen after barrier.
VK_ACCESS_SHADER_READ_BIT,
// Transition from: RAR and WAR don't need memory barrier.
0,
false,
},
},
{
ImageLayout::AllGraphicsShadersWrite,
{
VK_IMAGE_LAYOUT_GENERAL,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
// Transition to: all reads and writes must happen after barrier.
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
// Transition from: all writes must finish before barrier.
VK_ACCESS_SHADER_WRITE_BIT,
true,
},
},
{
ImageLayout::ColorAttachment,
{
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
......@@ -173,19 +199,6 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
},
},
{
ImageLayout::AllGraphicsShadersReadOnly,
{
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
// Transition to: all reads must happen after barrier.
VK_ACCESS_SHADER_READ_BIT,
// Transition from: RAR and WAR don't need memory barrier.
0,
false,
},
},
{
ImageLayout::Present,
{
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
......
......@@ -627,12 +627,13 @@ enum class ImageLayout
ComputeShaderReadOnly = 4,
ComputeShaderWrite = 5,
AllGraphicsShadersReadOnly = 6,
ColorAttachment = 7,
DepthStencilAttachment = 8,
Present = 9,
AllGraphicsShadersWrite = 7,
ColorAttachment = 8,
DepthStencilAttachment = 9,
Present = 10,
InvalidEnum = 10,
EnumCount = 10,
InvalidEnum = 11,
EnumCount = 11,
};
class ImageHelper final : public CommandGraphResource
......
......@@ -570,6 +570,11 @@ class Recycler final : angle::NonCopyable
bool SamplerNameContainsNonZeroArrayElement(const std::string &name);
std::string GetMappedSamplerName(const std::string &originalName);
// A vector of image views, such as one per level or one per layer.
using ImageViewVector = std::vector<vk::ImageView>;
// A vector of vector of image views. Primary index is layer, secondary index is level.
using LayerLevelImageViewVector = std::vector<ImageViewVector>;
} // namespace vk
// List of function pointers for used extensions.
......
......@@ -49,7 +49,7 @@
1442 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.array_size.vertex_fragment.default_block_struct_member = SKIP
1442 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.name_length.vertex_fragment.default_block_struct_member = SKIP
1442 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.type.vertex_fragment.struct.* = SKIP
1442 : dEQP-GLES31.functional.image_load_store.* = SKIP
1442 D3D11 : dEQP-GLES31.functional.image_load_store.* = SKIP
// Times out shader compilation because it uses so many resources.
3445 : dEQP-GLES31.functional.ssbo.layout.random.all_shared_buffer.48 = SKIP
......@@ -546,8 +546,8 @@
2432 NVIDIA OPENGL : dEQP-GLES31.functional.vertex_attribute_binding.usage.mixed_usage.mixed_api_change_binding_point = SKIP
// OpenGL/D3D11/Vulkan Failing Tests
1442 : dEQP-GLES31.functional.compute.basic.copy_image_to_ssbo_large = FAIL
1442 : dEQP-GLES31.functional.compute.basic.copy_ssbo_to_image_large = FAIL
3865 : dEQP-GLES31.functional.compute.basic.copy_image_to_ssbo_large = FAIL
3865 : dEQP-GLES31.functional.compute.basic.copy_ssbo_to_image_large = FAIL
1442 : dEQP-GLES31.functional.shaders.opaque_type_indexing.* = FAIL
1442 : dEQP-GLES31.functional.shaders.helper_invocation.* = FAIL
1442 : dEQP-GLES31.functional.state_query.integer.program_pipeline_binding_* = FAIL
......@@ -649,7 +649,6 @@
3569 VULKAN : dEQP-GLES31.functional.shaders.builtin_functions.precision.ldexp* = FAIL
3569 VULKAN : dEQP-GLES31.functional.shaders.functions* = FAIL
3569 VULKAN : dEQP-GLES31.functional.shaders.linkage*uniform* = FAIL
3569 VULKAN : dEQP-GLES31.functional.shaders.builtin_constants.core.max_* = FAIL
3569 VULKAN : dEQP-GLES31.functional.shaders.builtin_constants.core.min_program_texel_offset = FAIL
3569 VULKAN : dEQP-GLES31.functional.shaders.uniform_block.es31.valid.* = FAIL
......@@ -718,11 +717,6 @@
// Tessellation geometry interaction:
3572 VULKAN : dEQP-GLES31.functional.tessellation_geometry_interaction.* = FAIL
// Storage image:
3563 VULKAN : dEQP-GLES31.functional.state_query.*image* = FAIL
3563 VULKAN : dEQP-GLES31.functional.synchronization.*.image* = FAIL
3563 VULKAN : dEQP-GLES31.functional.compute.*image* = FAIL
// Framebuffer without attachments:
3579 ANDROID VULKAN : dEQP-GLES31.functional.fbo.no_attachments.* = SKIP
......@@ -753,6 +747,12 @@
3520 VULKAN : dEQP-GLES31.functional.state_query.texture_level.texture_2d.compressed_integer = SKIP
3520 VULKAN : dEQP-GLES31.functional.state_query.texture_level.texture_2d.compressed_float = SKIP
// Vulkan creates the image view with the same format as the texture.
3563 VULKAN : dEQP-GLES31.functional.image_load_store.*.format_reinterpret.* = FAIL
// Cannot create 2D (array) view of 3D texture.
3188 VULKAN : dEQP-GLES31.functional.image_load_store.3d.*layer = FAIL
// Inactive SSBOs with flexible array member (about 20% of these tests are affected):
3714 VULKAN : dEQP-GLES31.functional.ssbo.layout.random.* = FAIL
......
......@@ -105,11 +105,14 @@
// Blend equations:
3586 VULKAN : KHR-GLES31.core.blend_equation_advanced.* = SKIP
// Storage image:
3563 VULKAN : KHR-GLES31.core.layout_binding.sampler2D_layout_binding_texture_ComputeShader = FAIL
3563 VULKAN : KHR-GLES31.core.layout_binding.block_layout_binding_block_ComputeShader = FAIL
3563 VULKAN : KHR-GLES31.core.layout_binding.buffer_layout_binding_atomicAdd_ComputeShader = FAIL
3563 VULKAN : KHR-GLES31.core.layout_binding.atomic_uint_layout_binding_atomic_ComputeShader = FAIL
// Storage image front-end crash when unbinding images (given texture 0)
3563 VULKAN : KHR-GLES31.core.layout_binding.sampler2D_layout_binding_texture_ComputeShader = SKIP
3563 VULKAN : KHR-GLES31.core.layout_binding.block_layout_binding_block_ComputeShader = SKIP
3563 VULKAN : KHR-GLES31.core.layout_binding.buffer_layout_binding_atomicAdd_ComputeShader = SKIP
3563 VULKAN : KHR-GLES31.core.layout_binding.atomic_uint_layout_binding_atomic_ComputeShader = SKIP
3563 VULKAN : KHR-GLES31.core.layout_binding.image2D_layout_binding_imageLoad_ComputeShader = SKIP
3563 VULKAN : KHR-GLES31.core.layout_binding.image2D_layout_binding_imageLoad_FragmentShader = SKIP
3563 VULKAN : KHR-GLES31.core.layout_binding.image2D_layout_binding_imageLoad_VertexShader = SKIP
3520 VULKAN : KHR-GLES31.core.internalformat.copy_tex_image* = FAIL
3520 VULKAN : KHR-GLES31.core.internalformat.renderbuffer* = FAIL
......
......@@ -3086,6 +3086,10 @@ TEST_P(SimpleStateChangeTestES31, RebindImageTextureDispatchAgain)
// and then dispatch again correctly.
TEST_P(SimpleStateChangeTestES31, DispatchWithImageTextureTexSubImageThenDispatchAgain)
{
// The change to the texture between the dispatch calls is not flushed in the Vulkan backend.
// http://anglebug.com/3539
ANGLE_SKIP_TEST_IF(IsVulkan());
std::array<GLColor, 4> colors = {{GLColor::red, GLColor::red, GLColor::red, GLColor::red}};
std::array<GLColor, 4> subColors = {
{GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
......@@ -3159,6 +3163,9 @@ TEST_P(SimpleStateChangeTestES31, UpdateImageTextureInUse)
// Test that we can alternate between image textures between different dispatchs.
TEST_P(SimpleStateChangeTestES31, DispatchImageTextureAThenTextureBThenTextureA)
{
// Fails in the last EXPECT call. http://anglebug.com/3879
ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && IsAMD());
std::array<GLColor, 4> colorsTexA = {
{GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
......@@ -3619,6 +3626,9 @@ TEST_P(WebGL2ValidationStateChangeTest, DrawFramebufferNegativeAPI)
// Tests various state change effects on draw framebuffer validation with MRT.
TEST_P(WebGL2ValidationStateChangeTest, MultiAttachmentDrawFramebufferNegativeAPI)
{
// Crashes on 64-bit Android. http://anglebug.com/3878
ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
// Set up a program that writes to two outputs: one int and one float.
constexpr char kVS[] = R"(#version 300 es
layout(location = 0) in vec2 position;
......@@ -3843,6 +3853,10 @@ void main()
// Test sampler format validation caching works.
TEST_P(WebGL2ValidationStateChangeTest, SamplerFormatCache)
{
// Crashes in depth data upload due to lack of support for GL_UNSIGNED_INT data when
// DEPTH_COMPONENT24 is emulated with D32_S8X24. http://anglebug.com/3880
ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && IsAMD());
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
uniform sampler2D sampler;
......@@ -4359,8 +4373,11 @@ ANGLE_INSTANTIATE_TEST(StateChangeRenderTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENG
ANGLE_INSTANTIATE_TEST(StateChangeTestES3, ES3_D3D11(), ES3_OPENGL());
ANGLE_INSTANTIATE_TEST(SimpleStateChangeTest, ES2_D3D11(), ES2_VULKAN(), ES2_OPENGL());
ANGLE_INSTANTIATE_TEST(SimpleStateChangeTestES3, ES3_OPENGL(), ES3_D3D11(), ES3_VULKAN());
ANGLE_INSTANTIATE_TEST(SimpleStateChangeTestES31, ES31_OPENGL(), ES31_D3D11());
ANGLE_INSTANTIATE_TEST(ValidationStateChangeTest, ES3_D3D11(), ES3_OPENGL());
ANGLE_INSTANTIATE_TEST(WebGL2ValidationStateChangeTest, ES3_D3D11(), ES3_OPENGL());
ANGLE_INSTANTIATE_TEST(ValidationStateChangeTestES31, ES31_OPENGL(), ES31_D3D11());
ANGLE_INSTANTIATE_TEST(WebGLComputeValidationStateChangeTest, ES31_D3D11(), ES31_OPENGL());
ANGLE_INSTANTIATE_TEST(SimpleStateChangeTestES31, ES31_OPENGL(), ES31_D3D11(), ES31_VULKAN());
ANGLE_INSTANTIATE_TEST(ValidationStateChangeTest, ES3_D3D11(), ES3_OPENGL(), ES3_VULKAN());
ANGLE_INSTANTIATE_TEST(WebGL2ValidationStateChangeTest, ES3_D3D11(), ES3_OPENGL(), ES3_VULKAN());
ANGLE_INSTANTIATE_TEST(ValidationStateChangeTestES31, ES31_OPENGL(), ES31_D3D11(), ES31_VULKAN());
ANGLE_INSTANTIATE_TEST(WebGLComputeValidationStateChangeTest,
ES31_D3D11(),
ES31_OPENGL(),
ES31_VULKAN());
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