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