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, ...@@ -4949,6 +4949,8 @@ void Program::updateSamplerUniform(Context *context,
newSamplerType = samplerBinding.textureType; newSamplerType = samplerBinding.textureType;
newSamplerFormat = samplerBinding.format; newSamplerFormat = samplerBinding.format;
mState.mExecutable.mActiveSamplersMask.set(newTextureUnit); mState.mExecutable.mActiveSamplersMask.set(newTextureUnit);
mState.mExecutable.mActiveSamplerShaderBits[newTextureUnit] =
mState.mUniforms[locationInfo.index].activeShaders();
} }
else else
{ {
......
...@@ -181,17 +181,22 @@ size_t ProgramExecutable::getTransformFeedbackBufferCount(const gl::State &glSta ...@@ -181,17 +181,22 @@ size_t ProgramExecutable::getTransformFeedbackBufferCount(const gl::State &glSta
void ProgramExecutable::updateActiveSamplers(const std::vector<SamplerBinding> &samplerBindings) 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) if (samplerBinding.unreferenced)
continue; continue;
uint32_t uniformIndex = mProgramState->getUniformIndexFromSamplerIndex(samplerIndex);
const gl::LinkedUniform &samplerUniform = mProgramState->getUniforms()[uniformIndex];
for (GLint textureUnit : samplerBinding.boundTextureUnits) for (GLint textureUnit : samplerBinding.boundTextureUnits)
{ {
if (++mActiveSamplerRefCounts[textureUnit] == 1) if (++mActiveSamplerRefCounts[textureUnit] == 1)
{ {
mActiveSamplerTypes[textureUnit] = samplerBinding.textureType; mActiveSamplerTypes[textureUnit] = samplerBinding.textureType;
mActiveSamplerFormats[textureUnit] = samplerBinding.format; mActiveSamplerFormats[textureUnit] = samplerBinding.format;
mActiveSamplerShaderBits[textureUnit] = samplerUniform.activeShaders();
} }
else else
{ {
...@@ -211,14 +216,23 @@ void ProgramExecutable::updateActiveSamplers(const std::vector<SamplerBinding> & ...@@ -211,14 +216,23 @@ void ProgramExecutable::updateActiveSamplers(const std::vector<SamplerBinding> &
void ProgramExecutable::updateActiveImages(std::vector<ImageBinding> &imageBindings) 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) if (imageBinding.unreferenced)
continue; continue;
uint32_t uniformIndex = mProgramState->getUniformIndexFromImageIndex(imageIndex);
const gl::LinkedUniform &imageUniform = mProgramState->getUniforms()[uniformIndex];
const ShaderBitSet shaderBits = imageUniform.activeShaders();
for (GLint imageUnit : imageBinding.boundImageUnits) for (GLint imageUnit : imageBinding.boundImageUnits)
{ {
mActiveImagesMask.set(imageUnit); mActiveImagesMask.set(imageUnit);
if (compute)
mActiveImageShaderBits[imageUnit].set(gl::ShaderType::Compute);
else
mActiveImageShaderBits[imageUnit] = shaderBits;
} }
} }
} }
......
...@@ -94,7 +94,15 @@ class ProgramExecutable ...@@ -94,7 +94,15 @@ class ProgramExecutable
{ {
return mActiveSamplerFormats[textureUnitIndex]; return mActiveSamplerFormats[textureUnitIndex];
} }
const ShaderBitSet getSamplerShaderBitsForTextureUnitIndex(size_t textureUnitIndex) const
{
return mActiveSamplerShaderBits[textureUnitIndex];
}
const ActiveTextureMask &getActiveImagesMask() const { return mActiveImagesMask; } const ActiveTextureMask &getActiveImagesMask() const { return mActiveImagesMask; }
const ActiveTextureArray<ShaderBitSet> &getActiveImageShaderBits() const
{
return mActiveImageShaderBits;
}
const ActiveTextureArray<TextureType> &getActiveSamplerTypes() const const ActiveTextureArray<TextureType> &getActiveSamplerTypes() const
{ {
...@@ -157,9 +165,11 @@ class ProgramExecutable ...@@ -157,9 +165,11 @@ class ProgramExecutable
ActiveTextureArray<uint32_t> mActiveSamplerRefCounts; ActiveTextureArray<uint32_t> mActiveSamplerRefCounts;
ActiveTextureArray<TextureType> mActiveSamplerTypes; ActiveTextureArray<TextureType> mActiveSamplerTypes;
ActiveTextureArray<SamplerFormat> mActiveSamplerFormats; ActiveTextureArray<SamplerFormat> mActiveSamplerFormats;
ActiveTextureArray<ShaderBitSet> mActiveSamplerShaderBits;
// Cached mask of active images. // Cached mask of active images.
ActiveTextureMask mActiveImagesMask; ActiveTextureMask mActiveImagesMask;
ActiveTextureArray<ShaderBitSet> mActiveImageShaderBits;
}; };
} // namespace gl } // namespace gl
......
...@@ -100,6 +100,18 @@ GLenum DefaultGLErrorCode(VkResult result) ...@@ -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 = constexpr VkColorComponentFlags kAllColorChannelsMask =
(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
VK_COLOR_COMPONENT_A_BIT); VK_COLOR_COMPONENT_A_BIT);
...@@ -1243,13 +1255,34 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl( ...@@ -1243,13 +1255,34 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
if (textureVk->isBoundAsImageTexture()) if (textureVk->isBoundAsImageTexture())
{ {
textureLayout = executable->isCompute() ? vk::ImageLayout::ComputeShaderWrite textureLayout = executable->isCompute() ? vk::ImageLayout::ComputeShaderWrite
: vk::ImageLayout::AllGraphicsShadersWrite; : vk::ImageLayout::AllGraphicsShadersReadWrite;
} }
else else
{ {
textureLayout = executable->isCompute() ? vk::ImageLayout::ComputeShaderReadOnly gl::ShaderBitSet shaderBits =
: vk::ImageLayout::AllGraphicsShadersReadOnly; 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, commandBufferHelper->imageRead(&mResourceUseList, image.getAspectFlags(), textureLayout,
&image); &image);
...@@ -3590,6 +3623,8 @@ angle::Result ContextVk::updateActiveImages(const gl::Context *context, ...@@ -3590,6 +3623,8 @@ angle::Result ContextVk::updateActiveImages(const gl::Context *context,
mActiveImages.fill(nullptr); mActiveImages.fill(nullptr);
const gl::ActiveTextureMask &activeImages = executable->getActiveImagesMask(); 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 // 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 // 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, ...@@ -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 // 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 // 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. // layers. Therefore we can't verify it has no staged updates right here.
vk::ImageLayout imageLayout;
vk::ImageLayout imageLayout = vk::ImageLayout::AllGraphicsShadersWrite; gl::ShaderBitSet shaderBits = activeImageShaderBits[imageUnitIndex];
if (executable->isCompute()) 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(); VkImageAspectFlags aspectFlags = image->getAspectFlags();
commandBufferHelper->imageWrite(&mResourceUseList, aspectFlags, imageLayout, image); commandBufferHelper->imageWrite(&mResourceUseList, aspectFlags, imageLayout, image);
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
// //
#include "libANGLE/renderer/vulkan/TextureVk.h" #include "libANGLE/renderer/vulkan/TextureVk.h"
#include <vulkan/vulkan.h>
#include "common/debug.h" #include "common/debug.h"
#include "image_util/generatemip.inc" #include "image_util/generatemip.inc"
......
...@@ -1426,8 +1426,8 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk, ...@@ -1426,8 +1426,8 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
pipelineDesc.setScissor(gl_vk::GetRect(params.blitArea)); pipelineDesc.setScissor(gl_vk::GetRect(params.blitArea));
// Change source layout outside render pass // Change source layout outside render pass
ANGLE_TRY(contextVk->onImageRead(src->getAspectFlags(), ANGLE_TRY(contextVk->onImageRead(src->getAspectFlags(), vk::ImageLayout::FragmentShaderReadOnly,
vk::ImageLayout::AllGraphicsShadersReadOnly, src)); src));
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer)); ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer));
...@@ -1735,7 +1735,7 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk, ...@@ -1735,7 +1735,7 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk,
// Change source layout outside render pass // Change source layout outside render pass
ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT, ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT,
vk::ImageLayout::AllGraphicsShadersReadOnly, src)); vk::ImageLayout::FragmentShaderReadOnly, src));
ANGLE_TRY( ANGLE_TRY(
contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorAttachment, dest)); contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorAttachment, dest));
......
...@@ -151,6 +151,84 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -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, ImageLayout::ComputeShaderReadOnly,
{ {
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
...@@ -190,7 +268,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -190,7 +268,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
}, },
}, },
{ {
ImageLayout::AllGraphicsShadersWrite, ImageLayout::AllGraphicsShadersReadWrite,
{ {
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
......
...@@ -615,22 +615,28 @@ class BufferHelper final : public Resource ...@@ -615,22 +615,28 @@ class BufferHelper final : public Resource
// are the same, they may occasionally be BOTTOM_OF_PIPE and TOP_OF_PIPE respectively. // are the same, they may occasionally be BOTTOM_OF_PIPE and TOP_OF_PIPE respectively.
enum class ImageLayout enum class ImageLayout
{ {
Undefined = 0, Undefined = 0,
ExternalPreInitialized = 1, ExternalPreInitialized = 1,
ExternalShadersReadOnly = 2, ExternalShadersReadOnly = 2,
ExternalShadersWrite = 3, ExternalShadersWrite = 3,
TransferSrc = 4, TransferSrc = 4,
TransferDst = 5, TransferDst = 5,
ComputeShaderReadOnly = 6, VertexShaderReadOnly = 6,
ComputeShaderWrite = 7, VertexShaderWrite = 7,
AllGraphicsShadersReadOnly = 8, GeometryShaderReadOnly = 8,
AllGraphicsShadersWrite = 9, GeometryShaderWrite = 9,
ColorAttachment = 10, FragmentShaderReadOnly = 10,
DepthStencilAttachment = 11, FragmentShaderWrite = 11,
Present = 12, ComputeShaderReadOnly = 12,
ComputeShaderWrite = 13,
InvalidEnum = 13, AllGraphicsShadersReadOnly = 14,
EnumCount = 13, AllGraphicsShadersReadWrite = 15,
ColorAttachment = 16,
DepthStencilAttachment = 17,
Present = 18,
InvalidEnum = 19,
EnumCount = 19,
}; };
class ImageHelper final : public Resource, public angle::Subject 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