Commit 20e375eb by Jamie Madill Committed by Commit Bot

Vulkan: Use shader stage specific barrier

Seperate vertex and fragment shader read/write with shader stage specific barriers Bug: angleproject:4467 Change-Id: Id18909b497b087e58d750023399943bc9d414edf Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2102957 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 6281e30d
......@@ -4949,6 +4949,8 @@ void Program::updateSamplerUniform(Context *context,
newSamplerType = samplerBinding.textureType;
newSamplerFormat = samplerBinding.format;
mState.mExecutable.mActiveSamplersMask.set(newTextureUnit);
mState.mExecutable.mActiveSamplerShaderBits[newTextureUnit] =
mState.mUniforms[locationInfo.index].activeShaders();
}
else
{
......
......@@ -181,17 +181,22 @@ size_t ProgramExecutable::getTransformFeedbackBufferCount(const gl::State &glSta
void ProgramExecutable::updateActiveSamplers(const std::vector<SamplerBinding> &samplerBindings)
{
for (const SamplerBinding &samplerBinding : samplerBindings)
for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
{
const SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
if (samplerBinding.unreferenced)
continue;
uint32_t uniformIndex = mProgramState->getUniformIndexFromSamplerIndex(samplerIndex);
const gl::LinkedUniform &samplerUniform = mProgramState->getUniforms()[uniformIndex];
for (GLint textureUnit : samplerBinding.boundTextureUnits)
{
if (++mActiveSamplerRefCounts[textureUnit] == 1)
{
mActiveSamplerTypes[textureUnit] = samplerBinding.textureType;
mActiveSamplerFormats[textureUnit] = samplerBinding.format;
mActiveSamplerTypes[textureUnit] = samplerBinding.textureType;
mActiveSamplerFormats[textureUnit] = samplerBinding.format;
mActiveSamplerShaderBits[textureUnit] = samplerUniform.activeShaders();
}
else
{
......@@ -211,14 +216,23 @@ void ProgramExecutable::updateActiveSamplers(const std::vector<SamplerBinding> &
void ProgramExecutable::updateActiveImages(std::vector<ImageBinding> &imageBindings)
{
for (ImageBinding &imageBinding : imageBindings)
const bool compute = isCompute() ? true : false;
for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
{
const gl::ImageBinding &imageBinding = imageBindings[imageIndex];
if (imageBinding.unreferenced)
continue;
uint32_t uniformIndex = mProgramState->getUniformIndexFromImageIndex(imageIndex);
const gl::LinkedUniform &imageUniform = mProgramState->getUniforms()[uniformIndex];
const ShaderBitSet shaderBits = imageUniform.activeShaders();
for (GLint imageUnit : imageBinding.boundImageUnits)
{
mActiveImagesMask.set(imageUnit);
if (compute)
mActiveImageShaderBits[imageUnit].set(gl::ShaderType::Compute);
else
mActiveImageShaderBits[imageUnit] = shaderBits;
}
}
}
......
......@@ -94,7 +94,15 @@ class ProgramExecutable
{
return mActiveSamplerFormats[textureUnitIndex];
}
const ShaderBitSet getSamplerShaderBitsForTextureUnitIndex(size_t textureUnitIndex) const
{
return mActiveSamplerShaderBits[textureUnitIndex];
}
const ActiveTextureMask &getActiveImagesMask() const { return mActiveImagesMask; }
const ActiveTextureArray<ShaderBitSet> &getActiveImageShaderBits() const
{
return mActiveImageShaderBits;
}
const ActiveTextureArray<TextureType> &getActiveSamplerTypes() const
{
......@@ -157,9 +165,11 @@ class ProgramExecutable
ActiveTextureArray<uint32_t> mActiveSamplerRefCounts;
ActiveTextureArray<TextureType> mActiveSamplerTypes;
ActiveTextureArray<SamplerFormat> mActiveSamplerFormats;
ActiveTextureArray<ShaderBitSet> mActiveSamplerShaderBits;
// Cached mask of active images.
ActiveTextureMask mActiveImagesMask;
ActiveTextureArray<ShaderBitSet> mActiveImageShaderBits;
};
} // namespace gl
......
......@@ -100,6 +100,18 @@ GLenum DefaultGLErrorCode(VkResult result)
}
}
constexpr gl::ShaderMap<vk::ImageLayout> kShaderReadOnlyImageLayouts = {
{gl::ShaderType::Vertex, vk::ImageLayout::VertexShaderReadOnly},
{gl::ShaderType::Fragment, vk::ImageLayout::FragmentShaderReadOnly},
{gl::ShaderType::Geometry, vk::ImageLayout::GeometryShaderReadOnly},
{gl::ShaderType::Compute, vk::ImageLayout::ComputeShaderReadOnly}};
constexpr gl::ShaderMap<vk::ImageLayout> kShaderWriteImageLayouts = {
{gl::ShaderType::Vertex, vk::ImageLayout::VertexShaderWrite},
{gl::ShaderType::Fragment, vk::ImageLayout::FragmentShaderWrite},
{gl::ShaderType::Geometry, vk::ImageLayout::GeometryShaderWrite},
{gl::ShaderType::Compute, vk::ImageLayout::ComputeShaderWrite}};
constexpr VkColorComponentFlags kAllColorChannelsMask =
(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
VK_COLOR_COMPONENT_A_BIT);
......@@ -1243,13 +1255,34 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
if (textureVk->isBoundAsImageTexture())
{
textureLayout = executable->isCompute() ? vk::ImageLayout::ComputeShaderWrite
: vk::ImageLayout::AllGraphicsShadersWrite;
: vk::ImageLayout::AllGraphicsShadersReadWrite;
}
else
{
textureLayout = executable->isCompute() ? vk::ImageLayout::ComputeShaderReadOnly
: vk::ImageLayout::AllGraphicsShadersReadOnly;
gl::ShaderBitSet shaderBits =
executable->getSamplerShaderBitsForTextureUnitIndex(textureUnit);
if (shaderBits.any())
{
gl::ShaderType shader =
static_cast<gl::ShaderType>(gl::ScanForward(shaderBits.bits()));
shaderBits.reset(shader);
// If we have multiple shader accessing it, we barrier against all shader stage read
// given that we only support vertex/frag shaders
if (shaderBits.any())
{
textureLayout = vk::ImageLayout::AllGraphicsShadersReadOnly;
}
else
{
textureLayout = kShaderReadOnlyImageLayouts[shader];
}
}
else
{
textureLayout = vk::ImageLayout::AllGraphicsShadersReadOnly;
}
}
// Ensure the image is in read-only layout
commandBufferHelper->imageRead(&mResourceUseList, image.getAspectFlags(), textureLayout,
&image);
......@@ -3590,6 +3623,8 @@ angle::Result ContextVk::updateActiveImages(const gl::Context *context,
mActiveImages.fill(nullptr);
const gl::ActiveTextureMask &activeImages = executable->getActiveImagesMask();
const gl::ActiveTextureArray<gl::ShaderBitSet> &activeImageShaderBits =
executable->getActiveImageShaderBits();
// Note: currently, the image layout is transitioned entirely even if only one level or layer is
// used. This is an issue if one subresource of the image is used as framebuffer attachment and
......@@ -3622,13 +3657,26 @@ angle::Result ContextVk::updateActiveImages(const gl::Context *context,
// 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.
vk::ImageLayout imageLayout = vk::ImageLayout::AllGraphicsShadersWrite;
if (executable->isCompute())
vk::ImageLayout imageLayout;
gl::ShaderBitSet shaderBits = activeImageShaderBits[imageUnitIndex];
if (shaderBits.any())
{
gl::ShaderType shader = static_cast<gl::ShaderType>(gl::ScanForward(shaderBits.bits()));
shaderBits.reset(shader);
// This is accessed by multiple shaders
if (shaderBits.any())
{
imageLayout = vk::ImageLayout::AllGraphicsShadersReadWrite;
}
else
{
imageLayout = kShaderWriteImageLayouts[shader];
}
}
else
{
imageLayout = vk::ImageLayout::ComputeShaderWrite;
imageLayout = vk::ImageLayout::AllGraphicsShadersReadWrite;
}
VkImageAspectFlags aspectFlags = image->getAspectFlags();
commandBufferHelper->imageWrite(&mResourceUseList, aspectFlags, imageLayout, image);
......
......@@ -8,6 +8,7 @@
//
#include "libANGLE/renderer/vulkan/TextureVk.h"
#include <vulkan/vulkan.h>
#include "common/debug.h"
#include "image_util/generatemip.inc"
......
......@@ -1426,8 +1426,8 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
pipelineDesc.setScissor(gl_vk::GetRect(params.blitArea));
// Change source layout outside render pass
ANGLE_TRY(contextVk->onImageRead(src->getAspectFlags(),
vk::ImageLayout::AllGraphicsShadersReadOnly, src));
ANGLE_TRY(contextVk->onImageRead(src->getAspectFlags(), vk::ImageLayout::FragmentShaderReadOnly,
src));
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer));
......@@ -1735,7 +1735,7 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk,
// Change source layout outside render pass
ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT,
vk::ImageLayout::AllGraphicsShadersReadOnly, src));
vk::ImageLayout::FragmentShaderReadOnly, src));
ANGLE_TRY(
contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorAttachment, dest));
......
......@@ -151,6 +151,84 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
},
},
{
ImageLayout::VertexShaderReadOnly,
{
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
VK_PIPELINE_STAGE_VERTEX_SHADER_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::VertexShaderWrite,
{
VK_IMAGE_LAYOUT_GENERAL,
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
VK_PIPELINE_STAGE_VERTEX_SHADER_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::GeometryShaderReadOnly,
{
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
VK_PIPELINE_STAGE_VERTEX_SHADER_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::GeometryShaderWrite,
{
VK_IMAGE_LAYOUT_GENERAL,
VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT,
VK_PIPELINE_STAGE_GEOMETRY_SHADER_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::FragmentShaderReadOnly,
{
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_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::FragmentShaderWrite,
{
VK_IMAGE_LAYOUT_GENERAL,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_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::ComputeShaderReadOnly,
{
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
......@@ -190,7 +268,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
},
},
{
ImageLayout::AllGraphicsShadersWrite,
ImageLayout::AllGraphicsShadersReadWrite,
{
VK_IMAGE_LAYOUT_GENERAL,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
......
......@@ -615,22 +615,28 @@ class BufferHelper final : public Resource
// are the same, they may occasionally be BOTTOM_OF_PIPE and TOP_OF_PIPE respectively.
enum class ImageLayout
{
Undefined = 0,
ExternalPreInitialized = 1,
ExternalShadersReadOnly = 2,
ExternalShadersWrite = 3,
TransferSrc = 4,
TransferDst = 5,
ComputeShaderReadOnly = 6,
ComputeShaderWrite = 7,
AllGraphicsShadersReadOnly = 8,
AllGraphicsShadersWrite = 9,
ColorAttachment = 10,
DepthStencilAttachment = 11,
Present = 12,
InvalidEnum = 13,
EnumCount = 13,
Undefined = 0,
ExternalPreInitialized = 1,
ExternalShadersReadOnly = 2,
ExternalShadersWrite = 3,
TransferSrc = 4,
TransferDst = 5,
VertexShaderReadOnly = 6,
VertexShaderWrite = 7,
GeometryShaderReadOnly = 8,
GeometryShaderWrite = 9,
FragmentShaderReadOnly = 10,
FragmentShaderWrite = 11,
ComputeShaderReadOnly = 12,
ComputeShaderWrite = 13,
AllGraphicsShadersReadOnly = 14,
AllGraphicsShadersReadWrite = 15,
ColorAttachment = 16,
DepthStencilAttachment = 17,
Present = 18,
InvalidEnum = 19,
EnumCount = 19,
};
class ImageHelper final : public Resource, public angle::Subject
......
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