Commit 907a3cee by Mohan Maiya Committed by Commit Bot

Vulkan: Add support for EXT_shader_framebuffer_fetch_non_coherent

EXT_shader_framebuffer_fetch_non_coherent is implemented using subpass input attachments. The extension will be enabled in a follow up change that adds required changes to the Vulkan translator. Bug: angleproject:5454 Test: FramebufferFetchNonCoherentES31.*Vulkan Change-Id: Ic73c66a476c4a21db5269431166a198841f1dc0c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2598059 Commit-Queue: Mohan Maiya <m.maiya@samsung.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent d6e0b0ca
......@@ -8509,7 +8509,7 @@ void Context::eGLImageTargetRenderbufferStorage(GLenum target, GLeglImageOES ima
void Context::framebufferFetchBarrier()
{
UNIMPLEMENTED();
mImplementation->framebufferFetchBarrier();
}
void Context::texStorage1D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width)
......
......@@ -282,6 +282,7 @@ class ProgramState final : angle::NonCopyable
const RangeUI &getSamplerUniformRange() const { return mExecutable->getSamplerUniformRange(); }
const RangeUI &getImageUniformRange() const { return mExecutable->getImageUniformRange(); }
const RangeUI &getAtomicCounterUniformRange() const { return mAtomicCounterUniformRange; }
const RangeUI &getFragmentInoutRange() const { return mExecutable->getFragmentInoutRange(); }
const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
{
......
......@@ -75,6 +75,7 @@ ProgramExecutable::ProgramExecutable()
mDefaultUniformRange(0, 0),
mSamplerUniformRange(0, 0),
mImageUniformRange(0, 0),
mFragmentInoutRange(0, 0),
mPipelineHasGraphicsUniformBuffers(false),
mPipelineHasComputeUniformBuffers(false),
mPipelineHasGraphicsStorageBuffers(false),
......@@ -135,6 +136,7 @@ ProgramExecutable::ProgramExecutable(const ProgramExecutable &other)
mImageUniformRange(other.mImageUniformRange),
mComputeShaderStorageBlocks(other.mComputeShaderStorageBlocks),
mGraphicsShaderStorageBlocks(other.mGraphicsShaderStorageBlocks),
mFragmentInoutRange(other.mFragmentInoutRange),
mPipelineHasGraphicsUniformBuffers(other.mPipelineHasGraphicsUniformBuffers),
mPipelineHasComputeUniformBuffers(other.mPipelineHasComputeUniformBuffers),
mPipelineHasGraphicsStorageBuffers(other.mPipelineHasGraphicsStorageBuffers),
......@@ -219,6 +221,10 @@ void ProgramExecutable::load(gl::BinaryInputStream *stream)
mActiveAttribLocationsMask = gl::AttributesMask(stream->readInt<uint32_t>());
mMaxActiveAttribLocation = stream->readInt<unsigned int>();
unsigned int fragmentInoutRangeLow = stream->readInt<uint32_t>();
unsigned int fragmentInoutRangeHigh = stream->readInt<uint32_t>();
mFragmentInoutRange = RangeUI(fragmentInoutRangeLow, fragmentInoutRangeHigh);
mLinkedGraphicsShaderStages = ShaderBitSet(stream->readInt<uint8_t>());
mLinkedComputeShaderStages = ShaderBitSet(stream->readInt<uint8_t>());
mIsCompute = stream->readBool();
......@@ -419,6 +425,9 @@ void ProgramExecutable::save(gl::BinaryOutputStream *stream) const
stream->writeInt(static_cast<uint32_t>(mActiveAttribLocationsMask.to_ulong()));
stream->writeInt(mMaxActiveAttribLocation);
stream->writeInt(mFragmentInoutRange.low());
stream->writeInt(mFragmentInoutRange.high());
stream->writeInt(mLinkedGraphicsShaderStages.bits());
stream->writeInt(mLinkedComputeShaderStages.bits());
stream->writeBool(mIsCompute);
......@@ -643,6 +652,11 @@ bool ProgramExecutable::hasComputeImages() const
return !mComputeImageBindings.empty() || mPipelineHasComputeImages;
}
bool ProgramExecutable::usesFramebufferFetch() const
{
return (mFragmentInoutRange.length() > 0);
}
GLuint ProgramExecutable::getUniformIndexFromImageIndex(GLuint imageIndex) const
{
ASSERT(imageIndex < mImageUniformRange.length());
......
......@@ -223,6 +223,7 @@ class ProgramExecutable final : public angle::Subject
{
return !getLinkedTransformFeedbackVaryings().empty();
}
bool usesFramebufferFetch() const;
// Count the number of uniform and storage buffer declarations, counting arrays as one.
size_t getTransformFeedbackBufferCount() const { return mTransformFeedbackStrides.size(); }
......@@ -255,6 +256,7 @@ class ProgramExecutable final : public angle::Subject
const RangeUI &getDefaultUniformRange() const { return mDefaultUniformRange; }
const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; }
const RangeUI &getImageUniformRange() const { return mImageUniformRange; }
const RangeUI &getFragmentInoutRange() const { return mFragmentInoutRange; }
const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
{
return mLinkedTransformFeedbackVaryings;
......@@ -432,6 +434,7 @@ class ProgramExecutable final : public angle::Subject
RangeUI mImageUniformRange;
std::vector<InterfaceBlock> mComputeShaderStorageBlocks;
std::vector<InterfaceBlock> mGraphicsShaderStorageBlocks;
RangeUI mFragmentInoutRange;
// An array of the samplers that are used by the program
std::vector<SamplerBinding> mSamplerBindings;
......
......@@ -370,6 +370,19 @@ void ProgramPipeline::updateExecutableTessellationProperties()
}
}
void ProgramPipeline::updateFragmentInoutRange()
{
Program *fragmentProgram = getShaderProgram(gl::ShaderType::Fragment);
if (!fragmentProgram)
{
return;
}
const ProgramExecutable &fragmentExecutable = fragmentProgram->getExecutable();
mState.mExecutable->mFragmentInoutRange = fragmentExecutable.mFragmentInoutRange;
}
void ProgramPipeline::updateHasBooleans()
{
// Need to check all of the shader stages, not just linked, so we handle Compute correctly.
......@@ -455,6 +468,9 @@ void ProgramPipeline::updateExecutable()
// Tessellation Shaders ProgramExecutable properties
updateExecutableTessellationProperties();
// Fragment Shader ProgramExecutable properties
updateFragmentInoutRange();
// All Shader ProgramExecutable properties
mState.updateExecutableTextures();
......
......@@ -153,6 +153,7 @@ class ProgramPipeline final : public RefCountObject<ProgramPipelineID>,
void updateImageBindings();
void updateExecutableGeometryProperties();
void updateExecutableTessellationProperties();
void updateFragmentInoutRange();
void updateHasBooleans();
void updateExecutable();
......
......@@ -179,6 +179,9 @@ class ContextImpl : public GLImplFactory
// GL_ANGLE_texture_storage_external
virtual void invalidateTexture(gl::TextureType target);
// EXT_shader_framebuffer_fetch_non_coherent
virtual void framebufferFetchBarrier() {}
// State sync with dirty bits.
virtual angle::Result syncState(const gl::Context *context,
const gl::State::DirtyBits &dirtyBits,
......
......@@ -392,6 +392,7 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mGpuEventsEnabled(false),
mEGLSyncObjectPendingFlush(false),
mHasDeferredFlush(false),
mLastProgramUsesFramebufferFetch(false),
mGpuClockSync{std::numeric_limits<double>::max(), std::numeric_limits<double>::max()},
mGpuEventTimestampOrigin(0),
mPerfCounters{},
......@@ -447,6 +448,8 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
&ContextVk::handleDirtyGraphicsDriverUniformsBinding;
mGraphicsDirtyBitHandlers[DIRTY_BIT_SHADER_RESOURCES] =
&ContextVk::handleDirtyGraphicsShaderResources;
mGraphicsDirtyBitHandlers[DIRTY_BIT_FRAMEBUFFER_FETCH_BARRIER] =
&ContextVk::handleDirtyGraphicsFramebufferFetchBarrier;
if (getFeatures().supportsTransformFeedbackExtension.enabled)
{
mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS] =
......@@ -1428,6 +1431,22 @@ angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(DirtyBits::Iterator *dir
return angle::Result::Continue;
}
angle::Result ContextVk::handleDirtyGraphicsFramebufferFetchBarrier(
DirtyBits::Iterator *dirtyBitsIterator,
DirtyBits dirtyBitMask)
{
VkMemoryBarrier memoryBarrier = {};
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
memoryBarrier.dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
mRenderPassCommandBuffer->pipelineBarrier(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_DEPENDENCY_BY_REGION_BIT, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
return angle::Result::Continue;
}
ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl(
vk::CommandBufferHelper *commandBufferHelper)
{
......@@ -1440,9 +1459,11 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl(
}
if (executable->hasUniformBuffers() || executable->hasStorageBuffers() ||
executable->hasAtomicCounterBuffers() || executable->hasImages())
executable->hasAtomicCounterBuffers() || executable->hasImages() ||
executable->usesFramebufferFetch())
{
ANGLE_TRY(mExecutable->updateShaderResourcesDescriptorSet(this, commandBufferHelper));
ANGLE_TRY(mExecutable->updateShaderResourcesDescriptorSet(this, mDrawFramebuffer,
commandBufferHelper));
}
return angle::Result::Continue;
}
......@@ -2823,6 +2844,12 @@ angle::Result ContextVk::invalidateProgramExecutableHelper(const gl::Context *co
ASSERT(mExecutable);
mExecutable->updateEarlyFragmentTestsOptimization(this);
if (mLastProgramUsesFramebufferFetch != executable->usesFramebufferFetch())
{
mLastProgramUsesFramebufferFetch = executable->usesFramebufferFetch();
ANGLE_TRY(flushCommandsAndEndRenderPass());
}
}
return angle::Result::Continue;
......@@ -3515,7 +3542,8 @@ void ContextVk::invalidateCurrentShaderResources()
ASSERT(executable);
if (executable->hasUniformBuffers() || executable->hasStorageBuffers() ||
executable->hasAtomicCounterBuffers() || executable->hasImages())
executable->hasAtomicCounterBuffers() || executable->hasImages() ||
executable->usesFramebufferFetch())
{
mGraphicsDirtyBits |= kResourcesAndDescSetDirtyBits;
mComputeDirtyBits |= kResourcesAndDescSetDirtyBits;
......@@ -3552,6 +3580,11 @@ void ContextVk::onFramebufferChange(FramebufferVk *framebufferVk)
// Update scissor.
updateScissor(mState);
if (mState.getProgramExecutable())
{
invalidateCurrentShaderResources();
}
onDrawFramebufferRenderPassDescChange(framebufferVk, nullptr);
}
......@@ -3825,6 +3858,11 @@ angle::Result ContextVk::memoryBarrierImpl(GLbitfield barriers, VkPipelineStageF
return angle::Result::Continue;
}
void ContextVk::framebufferFetchBarrier()
{
mGraphicsDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_FETCH_BARRIER);
}
vk::DynamicQueryPool *ContextVk::getQueryPool(gl::QueryType queryType)
{
ASSERT(queryType == gl::QueryType::AnySamples ||
......
......@@ -294,6 +294,9 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
ANGLE_INLINE void invalidateTexture(gl::TextureType target) override {}
// EXT_shader_framebuffer_fetch_non_coherent
void framebufferFetchBarrier() override;
VkDevice getDevice() const;
egl::ContextPriority getPriority() const { return mContextPriority; }
......@@ -617,6 +620,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS,
DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME,
DIRTY_BIT_DESCRIPTOR_SETS,
DIRTY_BIT_FRAMEBUFFER_FETCH_BARRIER,
DIRTY_BIT_MAX,
};
......@@ -799,6 +803,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
DirtyBits dirtyBitMask);
angle::Result handleDirtyGraphicsShaderResources(DirtyBits::Iterator *dirtyBitsIterator,
DirtyBits dirtyBitMask);
angle::Result handleDirtyGraphicsFramebufferFetchBarrier(DirtyBits::Iterator *dirtyBitsIterator,
DirtyBits dirtyBitMask);
angle::Result handleDirtyGraphicsTransformFeedbackBuffersEmulation(
DirtyBits::Iterator *dirtyBitsIterator,
DirtyBits dirtyBitMask);
......@@ -1031,6 +1037,9 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
bool mEGLSyncObjectPendingFlush;
bool mHasDeferredFlush;
// GL_EXT_shader_framebuffer_fetch_non_coherent
bool mLastProgramUsesFramebufferFetch;
// Semaphores that must be waited on in the next submission.
std::vector<VkSemaphore> mWaitSemaphores;
std::vector<VkPipelineStageFlags> mWaitSemaphoreStageMasks;
......
......@@ -2550,6 +2550,19 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
mCurrentFramebufferDesc.updateUnresolveMask(MakeUnresolveAttachmentMask(mRenderPassDesc));
}
bool framebufferFetchModeUpdated = false;
const gl::State &glState = contextVk->getState();
const gl::ProgramExecutable *executable = glState.getProgramExecutable();
bool programUsesFramebufferFetch = executable != nullptr && executable->usesFramebufferFetch();
if (programUsesFramebufferFetch != mRenderPassDesc.getFramebufferFetchMode())
{
framebufferFetchModeUpdated = true;
mRenderPassDesc.setFramebufferFetchMode(programUsesFramebufferFetch);
// Make sure framebuffer is recreated.
mFramebuffer = nullptr;
mCurrentFramebufferDesc.updateFramebufferFetchMode(programUsesFramebufferFetch);
}
vk::Framebuffer *framebuffer = nullptr;
ANGLE_TRY(getFramebuffer(contextVk, &framebuffer, nullptr));
......@@ -2596,7 +2609,7 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
contextVk->startNextSubpass();
}
if (unresolveChanged || anyUnresolve)
if (unresolveChanged || anyUnresolve || framebufferFetchModeUpdated)
{
contextVk->onDrawFramebufferRenderPassDescChange(this, renderPassDescChangedOut);
}
......
......@@ -11,6 +11,7 @@
#include "libANGLE/renderer/glslang_wrapper_utils.h"
#include "libANGLE/renderer/vulkan/BufferVk.h"
#include "libANGLE/renderer/vulkan/DisplayVk.h"
#include "libANGLE/renderer/vulkan/FramebufferVk.h"
#include "libANGLE/renderer/vulkan/GlslangWrapperVk.h"
#include "libANGLE/renderer/vulkan/ProgramPipelineVk.h"
#include "libANGLE/renderer/vulkan/ProgramVk.h"
......@@ -548,6 +549,36 @@ void ProgramExecutableVk::addImageDescriptorSetDesc(const gl::ProgramExecutable
}
}
void ProgramExecutableVk::addInputAttachmentDescriptorSetDesc(
const gl::ProgramExecutable &executable,
const gl::ShaderType shaderType,
vk::DescriptorSetLayoutDesc *descOut)
{
if (shaderType != gl::ShaderType::Fragment)
{
return;
}
const std::vector<gl::LinkedUniform> &uniforms = executable.getUniforms();
if (!executable.usesFramebufferFetch())
{
return;
}
const uint32_t baseUniformIndex = executable.getFragmentInoutRange().low();
std::string baseMappedName = uniforms[baseUniformIndex].mappedName;
ShaderInterfaceVariableInfo &info = mVariableInfoMap.get(shaderType, baseMappedName);
uint32_t inputAttachmentBinding = info.binding;
for (uint32_t colorIndex = 0; colorIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; ++colorIndex)
{
descOut->update(inputAttachmentBinding, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1,
VK_SHADER_STAGE_FRAGMENT_BIT, nullptr);
inputAttachmentBinding++;
}
}
void ProgramExecutableVk::addTextureDescriptorSetDesc(
const gl::ProgramState &programState,
const gl::ActiveTextureArray<vk::TextureUnit> *activeTextures,
......@@ -865,6 +896,8 @@ angle::Result ProgramExecutableVk::createPipelineLayout(
const gl::ProgramState *programState = programStates[shaderType];
ASSERT(programState);
addImageDescriptorSetDesc(programState->getExecutable(), &resourcesSetDesc);
addInputAttachmentDescriptorSetDesc(programState->getExecutable(), shaderType,
&resourcesSetDesc);
}
ANGLE_TRY(contextVk->getDescriptorSetLayoutCache().getDescriptorSetLayout(
......@@ -1336,6 +1369,7 @@ angle::Result ProgramExecutableVk::updateImagesDescriptorSet(
angle::Result ProgramExecutableVk::updateShaderResourcesDescriptorSet(
ContextVk *contextVk,
FramebufferVk *framebufferVk,
vk::CommandBufferHelper *commandBufferHelper)
{
const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
......@@ -1361,6 +1395,71 @@ angle::Result ProgramExecutableVk::updateShaderResourcesDescriptorSet(
ANGLE_TRY(updateAtomicCounterBuffersDescriptorSet(*programState, shaderType, contextVk,
commandBufferHelper));
ANGLE_TRY(updateImagesDescriptorSet(contextVk, programState->getExecutable(), shaderType));
ANGLE_TRY(updateInputAttachmentDescriptorSet(programState->getExecutable(), shaderType,
contextVk, framebufferVk));
}
return angle::Result::Continue;
}
angle::Result ProgramExecutableVk::updateInputAttachmentDescriptorSet(
const gl::ProgramExecutable &executable,
const gl::ShaderType shaderType,
ContextVk *contextVk,
FramebufferVk *framebufferVk)
{
if (shaderType != gl::ShaderType::Fragment)
{
return angle::Result::Continue;
}
const std::vector<gl::LinkedUniform> &uniforms = executable.getUniforms();
if (!executable.usesFramebufferFetch())
{
return angle::Result::Continue;
}
VkDescriptorSet descriptorSet =
mDescriptorSets[ToUnderlying(DescriptorSetIndex::ShaderResource)];
unsigned int baseUniformIndex = executable.getFragmentInoutRange().low();
std::string baseMappedName = uniforms[baseUniformIndex].mappedName;
ShaderInterfaceVariableInfo &info = mVariableInfoMap.get(shaderType, baseMappedName);
uint32_t baseBinding = info.binding;
for (size_t colorIndex : framebufferVk->getState().getColorAttachmentsMask())
{
// Lazily allocate the descriptor set, since we may not need one if all of the image
// uniforms are inactive.
if (descriptorSet == VK_NULL_HANDLE)
{
ANGLE_TRY(allocateDescriptorSet(contextVk, DescriptorSetIndex::ShaderResource));
descriptorSet = mDescriptorSets[ToUnderlying(DescriptorSetIndex::ShaderResource)];
}
ASSERT(descriptorSet != VK_NULL_HANDLE);
VkWriteDescriptorSet *writeInfos = contextVk->allocWriteDescriptorSets(1);
VkDescriptorImageInfo *imageInfos = contextVk->allocDescriptorImageInfos(1);
RenderTargetVk *renderTargetVk = framebufferVk->getColorDrawRenderTarget(colorIndex);
const vk::ImageView *imageView = nullptr;
ANGLE_TRY(renderTargetVk->getImageView(contextVk, &imageView));
imageInfos[0].sampler = VK_NULL_HANDLE;
imageInfos[0].imageView = imageView->getHandle();
imageInfos[0].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
writeInfos[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeInfos[0].pNext = nullptr;
writeInfos[0].dstSet = descriptorSet;
writeInfos[0].dstBinding = baseBinding + static_cast<uint32_t>(colorIndex);
writeInfos[0].dstArrayElement = 0;
writeInfos[0].descriptorCount = 1;
writeInfos[0].descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
writeInfos[0].pImageInfo = &imageInfos[0];
writeInfos[0].pBufferInfo = nullptr;
writeInfos[0].pTexelBufferView = nullptr;
}
return angle::Result::Continue;
......
......@@ -146,6 +146,7 @@ class ProgramExecutableVk
angle::Result updateTexturesDescriptorSet(ContextVk *contextVk);
angle::Result updateShaderResourcesDescriptorSet(ContextVk *contextVk,
FramebufferVk *framebufferVk,
vk::CommandBufferHelper *commandBufferHelper);
angle::Result updateTransformFeedbackDescriptorSet(
const gl::ProgramState &programState,
......@@ -153,6 +154,10 @@ class ProgramExecutableVk
vk::BufferHelper *defaultUniformBuffer,
ContextVk *contextVk,
const vk::UniformsAndXfbDesc &xfbBufferDesc);
angle::Result updateInputAttachmentDescriptorSet(const gl::ProgramExecutable &executable,
const gl::ShaderType shaderType,
ContextVk *contextVk,
FramebufferVk *framebufferVk);
angle::Result updateDescriptorSets(ContextVk *contextVk, vk::CommandBuffer *commandBuffer);
......@@ -201,6 +206,9 @@ class ProgramExecutableVk
vk::DescriptorSetLayoutDesc *descOut);
void addImageDescriptorSetDesc(const gl::ProgramExecutable &executable,
vk::DescriptorSetLayoutDesc *descOut);
void addInputAttachmentDescriptorSetDesc(const gl::ProgramExecutable &executable,
const gl::ShaderType shaderType,
vk::DescriptorSetLayoutDesc *descOut);
void addTextureDescriptorSetDesc(const gl::ProgramState &programState,
const gl::ActiveTextureArray<vk::TextureUnit> *activeTextures,
vk::DescriptorSetLayoutDesc *descOut);
......
......@@ -569,6 +569,22 @@ void InitializeUnresolveSubpassDependencies(const SubpassVector<VkSubpassDescrip
dependency->dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
}
void InitializeInputAttachmentSubpassDependencies(
std::vector<VkSubpassDependency> *subpassDependencies,
uint32_t subpassIndex)
{
subpassDependencies->emplace_back();
VkSubpassDependency *dependency = &subpassDependencies->back();
dependency->srcSubpass = subpassIndex;
dependency->dstSubpass = subpassIndex;
dependency->srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency->dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependency->srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependency->dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
dependency->dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
}
void ToAttachmentDesciption2(const VkAttachmentDescription &desc,
VkAttachmentDescription2KHR *desc2Out)
{
......@@ -893,6 +909,8 @@ angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk,
VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR, nullptr, VK_ATTACHMENT_UNUSED,
VK_IMAGE_LAYOUT_UNDEFINED, 0};
bool needInputAttachments = desc.getFramebufferFetchMode();
// Unpack the packed and split representation into the format required by Vulkan.
gl::DrawBuffersVector<VkAttachmentReference> colorAttachmentRefs;
gl::DrawBuffersVector<VkAttachmentReference> colorResolveAttachmentRefs;
......@@ -937,7 +955,8 @@ angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk,
VkAttachmentReference colorRef;
colorRef.attachment = attachmentCount.get();
colorRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
colorRef.layout = needInputAttachments ? VK_IMAGE_LAYOUT_GENERAL
: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
colorAttachmentRefs.push_back(colorRef);
......@@ -1069,10 +1088,12 @@ angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk,
subpassDesc.push_back({});
VkSubpassDescription *applicationSubpass = &subpassDesc.back();
applicationSubpass->flags = 0;
applicationSubpass->pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
applicationSubpass->inputAttachmentCount = 0;
applicationSubpass->pInputAttachments = nullptr;
applicationSubpass->flags = 0;
applicationSubpass->pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
applicationSubpass->inputAttachmentCount =
needInputAttachments ? static_cast<uint32_t>(colorAttachmentRefs.size()) : 0;
applicationSubpass->pInputAttachments =
needInputAttachments ? colorAttachmentRefs.data() : nullptr;
applicationSubpass->colorAttachmentCount = static_cast<uint32_t>(colorAttachmentRefs.size());
applicationSubpass->pColorAttachments = colorAttachmentRefs.data();
applicationSubpass->pResolveAttachments = attachmentCount.get() > nonResolveAttachmentCount
......@@ -1117,6 +1138,12 @@ angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk,
desc.hasDepthStencilUnresolveAttachment(), &subpassDependencies);
}
if (needInputAttachments)
{
uint32_t drawSubpassIndex = static_cast<uint32_t>(subpassDesc.size()) - 1;
InitializeInputAttachmentSubpassDependencies(&subpassDependencies, drawSubpassIndex);
}
VkRenderPassCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
createInfo.flags = 0;
......@@ -1307,13 +1334,18 @@ void RenderPassDesc::setSamples(GLint samples)
SetBitField(mLogSamples, PackSampleCount(samples));
}
void RenderPassDesc::setFramebufferFetchMode(bool hasFramebufferFetch)
{
SetBitField(mHasFramebufferFetch, hasFramebufferFetch);
}
void RenderPassDesc::packColorAttachment(size_t colorIndexGL, angle::FormatID formatID)
{
ASSERT(colorIndexGL < mAttachmentFormats.size());
static_assert(angle::kNumANGLEFormats < std::numeric_limits<uint8_t>::max(),
"Too many ANGLE formats to fit in uint8_t");
// Force the user to pack the depth/stencil attachment last.
ASSERT(mHasDepthStencilAttachment == false);
ASSERT(!hasDepthStencilAttachment());
// This function should only be called for enabled GL color attachments.
ASSERT(formatID != angle::FormatID::NONE);
......@@ -1333,7 +1365,7 @@ void RenderPassDesc::packColorAttachmentGap(size_t colorIndexGL)
static_assert(angle::kNumANGLEFormats < std::numeric_limits<uint8_t>::max(),
"Too many ANGLE formats to fit in uint8_t");
// Force the user to pack the depth/stencil attachment last.
ASSERT(mHasDepthStencilAttachment == false);
ASSERT(!hasDepthStencilAttachment());
// Use NONE as a flag for gaps in GL color attachments.
uint8_t &packedFormat = mAttachmentFormats[colorIndexGL];
......@@ -1343,7 +1375,7 @@ void RenderPassDesc::packColorAttachmentGap(size_t colorIndexGL)
void RenderPassDesc::packDepthStencilAttachment(angle::FormatID formatID)
{
// Though written as Count, there is only ever a single depth/stencil attachment.
ASSERT(mHasDepthStencilAttachment == false);
ASSERT(!hasDepthStencilAttachment());
// 3 bits are used to store the depth/stencil attachment format.
ASSERT(static_cast<uint8_t>(formatID) <= kDepthStencilFormatStorageMask);
......@@ -1353,8 +1385,6 @@ void RenderPassDesc::packDepthStencilAttachment(angle::FormatID formatID)
uint8_t &packedFormat = mAttachmentFormats[index];
SetBitField(packedFormat, formatID);
mHasDepthStencilAttachment = true;
}
void RenderPassDesc::packColorResolveAttachment(size_t colorIndexGL)
......@@ -1439,6 +1469,12 @@ bool RenderPassDesc::isColorAttachmentEnabled(size_t colorIndexGL) const
return formatID != angle::FormatID::NONE;
}
bool RenderPassDesc::hasDepthStencilAttachment() const
{
angle::FormatID formatID = operator[](depthStencilAttachmentIndex());
return formatID != angle::FormatID::NONE;
}
size_t RenderPassDesc::attachmentCount() const
{
size_t colorAttachmentCount = 0;
......@@ -2979,13 +3015,14 @@ void FramebufferDesc::updateDepthStencilResolve(ImageOrBufferViewSubresourceSeri
size_t FramebufferDesc::hash() const
{
return angle::ComputeGenericHash(&mSerials, sizeof(mSerials[0]) * mMaxIndex) ^
mLayerCount << 16 ^ mUnresolveAttachmentMask.bits();
mHasFramebufferFetch << 25 ^ mLayerCount << 16 ^ mUnresolveAttachmentMask.bits();
}
void FramebufferDesc::reset()
{
mMaxIndex = 0;
mLayerCount = 0;
mMaxIndex = 0;
mHasFramebufferFetch = false;
mLayerCount = 0;
mUnresolveAttachmentMask.reset();
memset(&mSerials, 0, sizeof(mSerials));
}
......@@ -2993,7 +3030,8 @@ void FramebufferDesc::reset()
bool FramebufferDesc::operator==(const FramebufferDesc &other) const
{
if (mMaxIndex != other.mMaxIndex || mLayerCount != other.mLayerCount ||
mUnresolveAttachmentMask != other.mUnresolveAttachmentMask)
mUnresolveAttachmentMask != other.mUnresolveAttachmentMask ||
mHasFramebufferFetch != other.mHasFramebufferFetch)
{
return false;
}
......@@ -3025,6 +3063,11 @@ void FramebufferDesc::updateLayerCount(uint32_t layerCount)
SetBitField(mLayerCount, layerCount);
}
void FramebufferDesc::updateFramebufferFetchMode(bool hasFramebufferFetch)
{
SetBitField(mHasFramebufferFetch, hasFramebufferFetch);
}
// SamplerDesc implementation.
SamplerDesc::SamplerDesc()
{
......
......@@ -174,7 +174,7 @@ class alignas(4) RenderPassDesc final
size_t depthStencilAttachmentIndex() const { return colorAttachmentRange(); }
bool isColorAttachmentEnabled(size_t colorIndexGL) const;
bool hasDepthStencilAttachment() const { return mHasDepthStencilAttachment; }
bool hasDepthStencilAttachment() const;
bool hasColorResolveAttachment(size_t colorIndexGL) const
{
return mColorResolveAttachmentMask.test(colorIndexGL);
......@@ -220,6 +220,9 @@ class alignas(4) RenderPassDesc final
uint8_t samples() const { return 1u << mLogSamples; }
void setFramebufferFetchMode(bool hasFramebufferFetch);
bool getFramebufferFetchMode() const { return mHasFramebufferFetch; }
angle::FormatID operator[](size_t index) const
{
ASSERT(index < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1);
......@@ -236,7 +239,7 @@ class alignas(4) RenderPassDesc final
// Store log(samples), to be able to store it in 3 bits.
uint8_t mLogSamples : 3;
uint8_t mColorAttachmentRange : 4;
uint8_t mHasDepthStencilAttachment : 1;
uint8_t mHasFramebufferFetch : 1;
// Whether each color attachment has a corresponding resolve attachment. Color resolve
// attachments can be used to optimize resolve through glBlitFramebuffer() as well as support
......@@ -1176,13 +1179,15 @@ class FramebufferDesc
void updateLayerCount(uint32_t layerCount);
uint32_t getLayerCount() const { return mLayerCount; }
void updateFramebufferFetchMode(bool hasFramebufferFetch);
private:
void reset();
void update(uint32_t index, ImageOrBufferViewSubresourceSerial serial);
// Note: this is an exclusive index. If there is one index it will be "1".
uint16_t mMaxIndex : 7;
uint16_t mMaxIndex : 6;
uint16_t mHasFramebufferFetch : 1;
static_assert(gl::IMPLEMENTATION_MAX_FRAMEBUFFER_LAYERS < (1 << 9) - 1,
"Not enough bits for mLayerCount");
uint16_t mLayerCount : 9;
......
......@@ -295,6 +295,9 @@ void RendererVk::ensureCapsInitialized() const
// Enable GL_EXT_buffer_storage
mNativeExtensions.bufferStorageEXT = true;
// Enable GL_EXT_shader_framebuffer_fetch_non_coherent
mNativeExtensions.shaderFramebufferFetchNonCoherentEXT = false;
// To ensure that ETC2/EAC formats are enabled only on hardware that supports them natively,
// this flag is not set by the function above and must be set explicitly. It exposes
// ANGLE_compressed_texture_etc extension string.
......
......@@ -66,6 +66,7 @@ angle_end2end_tests_sources = [
"gl_tests/ExternalWrapTest.cpp",
"gl_tests/FenceSyncTests.cpp",
"gl_tests/FloatingPointSurfaceTest.cpp",
"gl_tests/FramebufferFetchTest.cpp",
"gl_tests/FramebufferMixedSamplesTest.cpp",
"gl_tests/FramebufferMultiviewTest.cpp",
"gl_tests/FramebufferRenderMipmapTest.cpp",
......
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