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);
......@@ -1071,8 +1090,10 @@ angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk,
applicationSubpass->flags = 0;
applicationSubpass->pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
applicationSubpass->inputAttachmentCount = 0;
applicationSubpass->pInputAttachments = nullptr;
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,12 +3015,13 @@ 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;
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",
......
//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ExternalBufferTest:
// Tests the correctness of EXT_shader_framebuffer_fetch_non_coherent extension.
//
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
#include "util/EGLWindow.h"
namespace angle
{
class FramebufferFetchNonCoherentES31 : public ANGLETest
{
protected:
static constexpr GLuint kMaxColorBuffer = 4u;
static constexpr GLuint kViewportWidth = 16u;
static constexpr GLuint kViewportHeight = 16u;
FramebufferFetchNonCoherentES31()
{
setWindowWidth(16);
setWindowHeight(16);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
setConfigDepthBits(24);
}
void render(GLuint coordLoc, GLboolean isFramebufferFetchProgram)
{
const GLfloat coords[] = {
-1.0f, -1.0f, +1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f,
};
const GLushort indices[] = {
0, 1, 2, 2, 3, 0,
};
glViewport(0, 0, kViewportWidth, kViewportHeight);
GLBuffer coordinatesBuffer;
GLBuffer elementsBuffer;
glBindBuffer(GL_ARRAY_BUFFER, coordinatesBuffer);
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW);
glEnableVertexAttribArray(coordLoc);
glVertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementsBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)sizeof(indices), &indices[0],
GL_STATIC_DRAW);
if (isFramebufferFetchProgram)
{
glFramebufferFetchBarrierEXT();
}
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
ASSERT_GL_NO_ERROR();
}
};
// Testing EXT_shader_framebuffer_fetch_non_coherent with inout qualifier
TEST_P(FramebufferFetchNonCoherentES31, BasicInout)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent"));
constexpr char kVS[] =
"#version 310 es\n"
"in highp vec4 a_position;\n"
"\n"
"void main (void)\n"
"{\n"
" gl_Position = a_position;\n"
"}\n";
constexpr char kFS[] =
"#version 310 es\n"
"#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n"
"layout(noncoherent, location = 0) inout highp vec4 o_color;\n"
"\n"
"uniform highp vec4 u_color;\n"
"void main (void)\n"
"{\n"
" o_color += u_color;\n"
"}\n";
GLProgram program;
program.makeRaster(kVS, kFS);
glUseProgram(program);
ASSERT_GL_NO_ERROR();
GLFramebuffer framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
std::vector<GLColor> greenColor(kViewportWidth * kViewportHeight, GLColor::green);
GLTexture colorBufferTex;
glBindTexture(GL_TEXTURE_2D, colorBufferTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, greenColor.data());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTex, 0);
ASSERT_GL_NO_ERROR();
float color[4] = {1.0f, 0.0f, 0.0f, 1.0f};
GLint colorLocation = glGetUniformLocation(program, "u_color");
glUniform4fv(colorLocation, 1, color);
GLint positionLocation = glGetAttribLocation(program, "a_position");
render(positionLocation, GL_TRUE);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::yellow);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
// Testing EXT_shader_framebuffer_fetch_non_coherent with gl_LastFragData
TEST_P(FramebufferFetchNonCoherentES31, BasicLastFragData)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent"));
constexpr char kVS[] =
"#version 100\n"
"attribute vec4 a_position;\n"
"\n"
"void main (void)\n"
"{\n"
" gl_Position = a_position;\n"
"}\n";
constexpr char kFS[] =
"#version 100\n"
"#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n"
"layout(noncoherent) mediump vec4 gl_LastFragData[gl_MaxDrawBuffers];\n"
"uniform highp vec4 u_color;\n"
"\n"
"void main (void)\n"
"{\n"
" gl_FragColor = u_color + gl_LastFragData[0];\n"
"}\n";
GLProgram program;
program.makeRaster(kVS, kFS);
glUseProgram(program);
ASSERT_GL_NO_ERROR();
GLFramebuffer framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
std::vector<GLColor> greenColor(kViewportWidth * kViewportHeight, GLColor::green);
GLTexture colorBufferTex;
glBindTexture(GL_TEXTURE_2D, colorBufferTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, greenColor.data());
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTex, 0);
ASSERT_GL_NO_ERROR();
float color[4] = {1.0f, 0.0f, 0.0f, 1.0f};
GLint colorLocation = glGetUniformLocation(program, "u_color");
glUniform4fv(colorLocation, 1, color);
GLint positionLocation = glGetAttribLocation(program, "a_position");
render(positionLocation, GL_TRUE);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::yellow);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
// Testing EXT_shader_framebuffer_fetch_non_coherent with multiple render target
TEST_P(FramebufferFetchNonCoherentES31, MultipleRenderTarget)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent"));
constexpr char kVS[] =
"#version 310 es\n"
"in highp vec4 a_position;\n"
"\n"
"void main (void)\n"
"{\n"
" gl_Position = a_position;\n"
"}\n";
constexpr char kFS[] =
"#version 310 es\n"
"#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n"
"layout(noncoherent, location = 0) inout highp vec4 o_color0;\n"
"layout(noncoherent, location = 1) inout highp vec4 o_color1;\n"
"layout(noncoherent, location = 2) inout highp vec4 o_color2;\n"
"layout(noncoherent, location = 3) inout highp vec4 o_color3;\n"
"uniform highp vec4 u_color;\n"
"\n"
"void main (void)\n"
"{\n"
" o_color0 += u_color;\n"
" o_color1 += u_color;\n"
" o_color2 += u_color;\n"
" o_color3 += u_color;\n"
"}\n";
GLProgram program;
program.makeRaster(kVS, kFS);
glUseProgram(program);
ASSERT_GL_NO_ERROR();
GLFramebuffer framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
std::vector<GLColor> color0(kViewportWidth * kViewportHeight, GLColor::black);
std::vector<GLColor> color1(kViewportWidth * kViewportHeight, GLColor::green);
std::vector<GLColor> color2(kViewportWidth * kViewportHeight, GLColor::blue);
std::vector<GLColor> color3(kViewportWidth * kViewportHeight, GLColor::cyan);
GLTexture colorBufferTex[kMaxColorBuffer];
GLenum colorAttachments[kMaxColorBuffer] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
glBindTexture(GL_TEXTURE_2D, colorBufferTex[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color0.data());
glBindTexture(GL_TEXTURE_2D, colorBufferTex[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color1.data());
glBindTexture(GL_TEXTURE_2D, colorBufferTex[2]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color2.data());
glBindTexture(GL_TEXTURE_2D, colorBufferTex[3]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color3.data());
glBindTexture(GL_TEXTURE_2D, 0);
for (unsigned int i = 0; i < kMaxColorBuffer; i++)
{
glFramebufferTexture2D(GL_FRAMEBUFFER, colorAttachments[i], GL_TEXTURE_2D,
colorBufferTex[i], 0);
}
glDrawBuffers(kMaxColorBuffer, &colorAttachments[0]);
ASSERT_GL_NO_ERROR();
float color[4] = {1.0f, 0.0f, 0.0f, 1.0f};
GLint colorLocation = glGetUniformLocation(program, "u_color");
glUniform4fv(colorLocation, 1, color);
GLint positionLocation = glGetAttribLocation(program, "a_position");
render(positionLocation, GL_TRUE);
ASSERT_GL_NO_ERROR();
glReadBuffer(colorAttachments[0]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
glReadBuffer(colorAttachments[1]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::yellow);
glReadBuffer(colorAttachments[2]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::magenta);
glReadBuffer(colorAttachments[3]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::white);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
// Testing EXT_shader_framebuffer_fetch_non_coherent with multiple draw
TEST_P(FramebufferFetchNonCoherentES31, MultipleDraw)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent"));
constexpr char kVS[] =
"#version 310 es\n"
"in highp vec4 a_position;\n"
"\n"
"void main (void)\n"
"{\n"
" gl_Position = a_position;\n"
"}\n";
constexpr char kFS[] =
"#version 310 es\n"
"#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n"
"layout(noncoherent, location = 0) inout highp vec4 o_color;\n"
"\n"
"uniform highp vec4 u_color;\n"
"void main (void)\n"
"{\n"
" o_color += u_color;\n"
"}\n";
GLProgram program;
program.makeRaster(kVS, kFS);
glUseProgram(program);
ASSERT_GL_NO_ERROR();
GLFramebuffer framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
std::vector<GLColor> greenColor(kViewportWidth * kViewportHeight, GLColor::green);
GLTexture colorBufferTex;
glBindTexture(GL_TEXTURE_2D, colorBufferTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, greenColor.data());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTex, 0);
ASSERT_GL_NO_ERROR();
float color1[4] = {1.0f, 0.0f, 0.0f, 1.0f};
GLint colorLocation = glGetUniformLocation(program, "u_color");
glUniform4fv(colorLocation, 1, color1);
GLint positionLocation = glGetAttribLocation(program, "a_position");
render(positionLocation, GL_TRUE);
float color2[4] = {0.0f, 0.0f, 1.0f, 1.0f};
glUniform4fv(colorLocation, 1, color2);
render(positionLocation, GL_TRUE);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::white);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
// Testing EXT_shader_framebuffer_fetch_non_coherent with the order of non-fetch program and fetch
// program
TEST_P(FramebufferFetchNonCoherentES31, DrawNonFetchDrawFetch)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent"));
constexpr char kVS[] =
"#version 310 es\n"
"in highp vec4 a_position;\n"
"\n"
"void main (void)\n"
"{\n"
" gl_Position = a_position;\n"
"}\n";
constexpr char kFS1[] =
"#version 310 es\n"
"layout(location = 0) out highp vec4 o_color;\n"
"\n"
"uniform highp vec4 u_color;\n"
"void main (void)\n"
"{\n"
" o_color = u_color;\n"
"}\n";
constexpr char kFS2[] =
"#version 310 es\n"
"#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n"
"layout(noncoherent, location = 0) inout highp vec4 o_color;\n"
"\n"
"uniform highp vec4 u_color;\n"
"void main (void)\n"
"{\n"
" o_color += u_color;\n"
"}\n";
GLProgram programNonFetch, programFetch;
programNonFetch.makeRaster(kVS, kFS1);
glUseProgram(programNonFetch);
ASSERT_GL_NO_ERROR();
GLFramebuffer framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
std::vector<GLColor> greenColor(kViewportWidth * kViewportHeight, GLColor::green);
GLTexture colorBufferTex;
glBindTexture(GL_TEXTURE_2D, colorBufferTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, greenColor.data());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTex, 0);
ASSERT_GL_NO_ERROR();
float colorRed[4] = {1.0f, 0.0f, 0.0f, 1.0f};
GLint colorLocationNonFetch = glGetUniformLocation(programNonFetch, "u_color");
glUniform4fv(colorLocationNonFetch, 1, colorRed);
GLint positionLocationNonFetch = glGetAttribLocation(programNonFetch, "a_position");
render(positionLocationNonFetch, GL_FALSE);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
programFetch.makeRaster(kVS, kFS2);
glUseProgram(programFetch);
float colorGreen[4] = {0.0f, 1.0f, 0.0f, 1.0f};
GLint colorLocationFetch = glGetUniformLocation(programFetch, "u_color");
glUniform4fv(colorLocationFetch, 1, colorGreen);
GLint positionLocationFetch = glGetAttribLocation(programFetch, "a_position");
render(positionLocationFetch, GL_TRUE);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::yellow);
glUseProgram(programNonFetch);
glUniform4fv(colorLocationNonFetch, 1, colorRed);
render(positionLocationNonFetch, GL_FALSE);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
glUseProgram(programFetch);
glUniform4fv(colorLocationFetch, 1, colorGreen);
render(positionLocationFetch, GL_TRUE);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::yellow);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
// Testing EXT_shader_framebuffer_fetch_non_coherent with the order of fetch program and non-fetch
// program
TEST_P(FramebufferFetchNonCoherentES31, DrawFetchDrawNonFetch)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent"));
constexpr char kVS[] =
"#version 310 es\n"
"in highp vec4 a_position;\n"
"\n"
"void main (void)\n"
"{\n"
" gl_Position = a_position;\n"
"}\n";
constexpr char kFS1[] =
"#version 310 es\n"
"layout(location = 0) out highp vec4 o_color;\n"
"\n"
"uniform highp vec4 u_color;\n"
"void main (void)\n"
"{\n"
" o_color = u_color;\n"
"}\n";
constexpr char kFS2[] =
"#version 310 es\n"
"#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n"
"layout(noncoherent, location = 0) inout highp vec4 o_color;\n"
"\n"
"uniform highp vec4 u_color;\n"
"void main (void)\n"
"{\n"
" o_color += u_color;\n"
"}\n";
GLProgram programNonFetch, programFetch;
programFetch.makeRaster(kVS, kFS2);
glUseProgram(programFetch);
ASSERT_GL_NO_ERROR();
GLFramebuffer framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
std::vector<GLColor> greenColor(kViewportWidth * kViewportHeight, GLColor::green);
GLTexture colorBufferTex;
glBindTexture(GL_TEXTURE_2D, colorBufferTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, greenColor.data());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTex, 0);
ASSERT_GL_NO_ERROR();
float colorRed[4] = {1.0f, 0.0f, 0.0f, 1.0f};
GLint colorLocationFetch = glGetUniformLocation(programFetch, "u_color");
glUniform4fv(colorLocationFetch, 1, colorRed);
GLint positionLocationFetch = glGetAttribLocation(programFetch, "a_position");
render(positionLocationFetch, GL_TRUE);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::yellow);
programNonFetch.makeRaster(kVS, kFS1);
glUseProgram(programNonFetch);
GLint colorLocationNonFetch = glGetUniformLocation(programNonFetch, "u_color");
glUniform4fv(colorLocationNonFetch, 1, colorRed);
GLint positionLocationNonFetch = glGetAttribLocation(programNonFetch, "a_position");
render(positionLocationNonFetch, GL_FALSE);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
float colorGreen[4] = {0.0f, 1.0f, 0.0f, 1.0f};
glUseProgram(programFetch);
glUniform4fv(colorLocationFetch, 1, colorGreen);
render(positionLocationFetch, GL_TRUE);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::yellow);
glUseProgram(programNonFetch);
glUniform4fv(colorLocationNonFetch, 1, colorRed);
render(positionLocationNonFetch, GL_FALSE);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
// Testing EXT_shader_framebuffer_fetch_non_coherent with the order of non-fetch program and fetch
// program with different attachments
TEST_P(FramebufferFetchNonCoherentES31, DrawNonFetchDrawFetchWithDifferentAttachments)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent"));
constexpr char kVS[] =
"#version 310 es\n"
"in highp vec4 a_position;\n"
"\n"
"void main (void)\n"
"{\n"
" gl_Position = a_position;\n"
"}\n";
constexpr char kFS1[] =
"#version 310 es\n"
"layout(location = 0) out highp vec4 o_color;\n"
"\n"
"uniform highp vec4 u_color;\n"
"void main (void)\n"
"{\n"
" o_color = u_color;\n"
"}\n";
constexpr char kFS2[] =
"#version 310 es\n"
"#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n"
"layout(noncoherent, location = 0) inout highp vec4 o_color0;\n"
"layout(location = 1) out highp vec4 o_color1;\n"
"layout(noncoherent, location = 2) inout highp vec4 o_color2;\n"
"layout(location = 3) out highp vec4 o_color3;\n"
"uniform highp vec4 u_color;\n"
"\n"
"void main (void)\n"
"{\n"
" o_color0 += u_color;\n"
" o_color1 = u_color;\n"
" o_color2 += u_color;\n"
" o_color3 = u_color;\n"
"}\n";
GLProgram programNonFetch, programFetch1;
programNonFetch.makeRaster(kVS, kFS1);
glUseProgram(programNonFetch);
ASSERT_GL_NO_ERROR();
GLFramebuffer framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
std::vector<GLColor> greenColor(kViewportWidth * kViewportHeight, GLColor::green);
GLTexture colorTex;
glBindTexture(GL_TEXTURE_2D, colorTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, greenColor.data());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
ASSERT_GL_NO_ERROR();
float colorRed[4] = {1.0f, 0.0f, 0.0f, 1.0f};
GLint colorLocationNonFetch = glGetUniformLocation(programNonFetch, "u_color");
glUniform4fv(colorLocationNonFetch, 1, colorRed);
GLint positionLocationNonFetch = glGetAttribLocation(programNonFetch, "a_position");
render(positionLocationNonFetch, GL_FALSE);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
programFetch1.makeRaster(kVS, kFS2);
glUseProgram(programFetch1);
ASSERT_GL_NO_ERROR();
GLFramebuffer framebufferMRT1;
glBindFramebuffer(GL_FRAMEBUFFER, framebufferMRT1);
std::vector<GLColor> color1(kViewportWidth * kViewportHeight, GLColor::green);
std::vector<GLColor> color2(kViewportWidth * kViewportHeight, GLColor::blue);
GLTexture colorBufferTex1[kMaxColorBuffer];
GLenum colorAttachments[kMaxColorBuffer] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
glBindTexture(GL_TEXTURE_2D, colorBufferTex1[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color1.data());
glBindTexture(GL_TEXTURE_2D, colorBufferTex1[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color1.data());
glBindTexture(GL_TEXTURE_2D, colorBufferTex1[2]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color2.data());
glBindTexture(GL_TEXTURE_2D, colorBufferTex1[3]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color2.data());
glBindTexture(GL_TEXTURE_2D, 0);
for (unsigned int i = 0; i < kMaxColorBuffer; i++)
{
glFramebufferTexture2D(GL_FRAMEBUFFER, colorAttachments[i], GL_TEXTURE_2D,
colorBufferTex1[i], 0);
}
glDrawBuffers(kMaxColorBuffer, &colorAttachments[0]);
ASSERT_GL_NO_ERROR();
GLint colorLocation = glGetUniformLocation(programFetch1, "u_color");
glUniform4fv(colorLocation, 1, colorRed);
GLint positionLocation = glGetAttribLocation(programFetch1, "a_position");
render(positionLocation, GL_TRUE);
ASSERT_GL_NO_ERROR();
glReadBuffer(colorAttachments[0]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::yellow);
glReadBuffer(colorAttachments[1]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
glReadBuffer(colorAttachments[2]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::magenta);
glReadBuffer(colorAttachments[3]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
GLFramebuffer framebufferMRT2;
glBindFramebuffer(GL_FRAMEBUFFER, framebufferMRT2);
GLTexture colorBufferTex2[kMaxColorBuffer];
glBindTexture(GL_TEXTURE_2D, colorBufferTex2[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color2.data());
glBindTexture(GL_TEXTURE_2D, colorBufferTex2[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color2.data());
glBindTexture(GL_TEXTURE_2D, colorBufferTex2[2]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color1.data());
glBindTexture(GL_TEXTURE_2D, colorBufferTex2[3]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color1.data());
glBindTexture(GL_TEXTURE_2D, 0);
for (unsigned int i = 0; i < kMaxColorBuffer; i++)
{
glFramebufferTexture2D(GL_FRAMEBUFFER, colorAttachments[i], GL_TEXTURE_2D,
colorBufferTex2[i], 0);
}
glDrawBuffers(kMaxColorBuffer, &colorAttachments[0]);
ASSERT_GL_NO_ERROR();
glUniform4fv(colorLocation, 1, colorRed);
render(positionLocation, GL_TRUE);
ASSERT_GL_NO_ERROR();
glReadBuffer(colorAttachments[0]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::magenta);
glReadBuffer(colorAttachments[1]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
glReadBuffer(colorAttachments[2]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::yellow);
glReadBuffer(colorAttachments[3]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
// Testing EXT_shader_framebuffer_fetch_non_coherent with the order of non-fetch program and fetch
// with different programs
TEST_P(FramebufferFetchNonCoherentES31, DrawNonFetchDrawFetchWithDifferentPrograms)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent"));
constexpr char kVS[] =
"#version 310 es\n"
"in highp vec4 a_position;\n"
"\n"
"void main (void)\n"
"{\n"
" gl_Position = a_position;\n"
"}\n";
constexpr char kFS1[] =
"#version 310 es\n"
"layout(location = 0) out highp vec4 o_color;\n"
"\n"
"uniform highp vec4 u_color;\n"
"void main (void)\n"
"{\n"
" o_color = u_color;\n"
"}\n";
constexpr char kFS2[] =
"#version 310 es\n"
"#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n"
"layout(noncoherent, location = 0) inout highp vec4 o_color0;\n"
"layout(location = 1) out highp vec4 o_color1;\n"
"layout(noncoherent, location = 2) inout highp vec4 o_color2;\n"
"layout(location = 3) out highp vec4 o_color3;\n"
"uniform highp vec4 u_color;\n"
"\n"
"void main (void)\n"
"{\n"
" o_color0 += u_color;\n"
" o_color1 = u_color;\n"
" o_color2 += u_color;\n"
" o_color3 = u_color;\n"
"}\n";
constexpr char kFS3[] =
"#version 310 es\n"
"#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n"
"layout(noncoherent, location = 0) inout highp vec4 o_color0;\n"
"layout(location = 1) out highp vec4 o_color1;\n"
"layout(location = 2) out highp vec4 o_color2;\n"
"layout(noncoherent, location = 3) inout highp vec4 o_color3;\n"
"uniform highp vec4 u_color;\n"
"\n"
"void main (void)\n"
"{\n"
" o_color0 += u_color;\n"
" o_color1 = u_color;\n"
" o_color2 = u_color;\n"
" o_color3 += u_color;\n"
"}\n";
GLProgram programNonFetch, programFetch1, programFetch2;
programNonFetch.makeRaster(kVS, kFS1);
glUseProgram(programNonFetch);
ASSERT_GL_NO_ERROR();
GLFramebuffer framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
std::vector<GLColor> greenColor(kViewportWidth * kViewportHeight, GLColor::green);
GLTexture colorTex;
glBindTexture(GL_TEXTURE_2D, colorTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, greenColor.data());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
ASSERT_GL_NO_ERROR();
float colorRed[4] = {1.0f, 0.0f, 0.0f, 1.0f};
GLint colorLocationNonFetch = glGetUniformLocation(programNonFetch, "u_color");
glUniform4fv(colorLocationNonFetch, 1, colorRed);
GLint positionLocationNonFetch = glGetAttribLocation(programNonFetch, "a_position");
render(positionLocationNonFetch, GL_FALSE);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
programFetch1.makeRaster(kVS, kFS2);
glUseProgram(programFetch1);
ASSERT_GL_NO_ERROR();
GLFramebuffer framebufferMRT1;
glBindFramebuffer(GL_FRAMEBUFFER, framebufferMRT1);
std::vector<GLColor> color1(kViewportWidth * kViewportHeight, GLColor::green);
GLTexture colorBufferTex1[kMaxColorBuffer];
GLenum colorAttachments[kMaxColorBuffer] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
glBindTexture(GL_TEXTURE_2D, colorBufferTex1[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color1.data());
glBindTexture(GL_TEXTURE_2D, colorBufferTex1[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color1.data());
glBindTexture(GL_TEXTURE_2D, colorBufferTex1[2]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color1.data());
glBindTexture(GL_TEXTURE_2D, colorBufferTex1[3]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color1.data());
glBindTexture(GL_TEXTURE_2D, 0);
for (unsigned int i = 0; i < kMaxColorBuffer; i++)
{
glFramebufferTexture2D(GL_FRAMEBUFFER, colorAttachments[i], GL_TEXTURE_2D,
colorBufferTex1[i], 0);
}
glDrawBuffers(kMaxColorBuffer, &colorAttachments[0]);
ASSERT_GL_NO_ERROR();
GLint colorLocation = glGetUniformLocation(programFetch1, "u_color");
glUniform4fv(colorLocation, 1, colorRed);
GLint positionLocation = glGetAttribLocation(programFetch1, "a_position");
render(positionLocation, GL_TRUE);
ASSERT_GL_NO_ERROR();
glReadBuffer(colorAttachments[0]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::yellow);
glReadBuffer(colorAttachments[1]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
glReadBuffer(colorAttachments[2]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::yellow);
glReadBuffer(colorAttachments[3]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
programFetch2.makeRaster(kVS, kFS3);
glUseProgram(programFetch2);
ASSERT_GL_NO_ERROR();
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
GLint colorLocation1 = glGetUniformLocation(programFetch2, "u_color");
glUniform4fv(colorLocation1, 1, colorRed);
GLint positionLocation1 = glGetAttribLocation(programFetch2, "a_position");
render(positionLocation1, GL_TRUE);
ASSERT_GL_NO_ERROR();
glReadBuffer(colorAttachments[0]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::yellow);
glReadBuffer(colorAttachments[1]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
glReadBuffer(colorAttachments[2]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
glReadBuffer(colorAttachments[3]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::yellow);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
// Testing EXT_shader_framebuffer_fetch_non_coherent with the order of draw fetch, blit and draw
// fetch
TEST_P(FramebufferFetchNonCoherentES31, DrawFetchBlitDrawFetch)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent"));
constexpr char kVS[] =
"#version 310 es\n"
"in highp vec4 a_position;\n"
"\n"
"void main (void)\n"
"{\n"
" gl_Position = a_position;\n"
"}\n";
constexpr char kFS1[] =
"#version 310 es\n"
"#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n"
"layout(noncoherent, location = 0) inout highp vec4 o_color0;\n"
"layout(location = 1) out highp vec4 o_color1;\n"
"layout(noncoherent, location = 2) inout highp vec4 o_color2;\n"
"layout(location = 3) out highp vec4 o_color3;\n"
"uniform highp vec4 u_color;\n"
"\n"
"void main (void)\n"
"{\n"
" o_color0 += u_color;\n"
" o_color1 = u_color;\n"
" o_color2 += u_color;\n"
" o_color3 = u_color;\n"
"}\n";
GLProgram programFetch;
programFetch.makeRaster(kVS, kFS1);
glUseProgram(programFetch);
ASSERT_GL_NO_ERROR();
GLFramebuffer framebufferMRT1;
glBindFramebuffer(GL_FRAMEBUFFER, framebufferMRT1);
std::vector<GLColor> color1(kViewportWidth * kViewportHeight, GLColor::green);
std::vector<GLColor> color2(kViewportWidth * kViewportHeight, GLColor::blue);
GLTexture colorBufferTex1[kMaxColorBuffer];
GLenum colorAttachments[kMaxColorBuffer] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
glBindTexture(GL_TEXTURE_2D, colorBufferTex1[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color1.data());
glBindTexture(GL_TEXTURE_2D, colorBufferTex1[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color1.data());
glBindTexture(GL_TEXTURE_2D, colorBufferTex1[2]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color2.data());
glBindTexture(GL_TEXTURE_2D, colorBufferTex1[3]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color2.data());
glBindTexture(GL_TEXTURE_2D, 0);
for (unsigned int i = 0; i < kMaxColorBuffer; i++)
{
glFramebufferTexture2D(GL_FRAMEBUFFER, colorAttachments[i], GL_TEXTURE_2D,
colorBufferTex1[i], 0);
}
glDrawBuffers(kMaxColorBuffer, &colorAttachments[0]);
ASSERT_GL_NO_ERROR();
float colorRed[4] = {1.0f, 0.0f, 0.0f, 1.0f};
GLint colorLocation = glGetUniformLocation(programFetch, "u_color");
glUniform4fv(colorLocation, 1, colorRed);
GLint positionLocation = glGetAttribLocation(programFetch, "a_position");
render(positionLocation, GL_TRUE);
ASSERT_GL_NO_ERROR();
glReadBuffer(colorAttachments[0]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::yellow);
glReadBuffer(colorAttachments[1]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
glReadBuffer(colorAttachments[2]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::magenta);
glReadBuffer(colorAttachments[3]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
GLFramebuffer framebufferColor;
glBindFramebuffer(GL_FRAMEBUFFER, framebufferColor);
GLTexture colorTex;
glBindTexture(GL_TEXTURE_2D, colorTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, color2.data());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, framebufferColor);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, framebufferMRT1);
glBlitFramebuffer(0, 0, kViewportWidth, kViewportHeight, 0, 0, kViewportWidth, kViewportHeight,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
ASSERT_GL_NO_ERROR();
glBindFramebuffer(GL_FRAMEBUFFER, framebufferMRT1);
glReadBuffer(colorAttachments[0]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::blue);
glReadBuffer(colorAttachments[1]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::blue);
glReadBuffer(colorAttachments[2]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::blue);
glReadBuffer(colorAttachments[3]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::blue);
float colorGreen[4] = {0.0f, 1.0f, 0.0f, 1.0f};
glUniform4fv(colorLocation, 1, colorGreen);
render(positionLocation, GL_TRUE);
ASSERT_GL_NO_ERROR();
glReadBuffer(colorAttachments[0]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::cyan);
glReadBuffer(colorAttachments[1]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::green);
glReadBuffer(colorAttachments[2]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::cyan);
glReadBuffer(colorAttachments[3]);
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::green);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
// Testing EXT_shader_framebuffer_fetch_non_coherent with program pipeline
TEST_P(FramebufferFetchNonCoherentES31, ProgramPipeline)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent"));
const char kVS[] =
"#version 310 es\n"
"in highp vec4 a_position;\n"
"\n"
"void main (void)\n"
"{\n"
" gl_Position = a_position;\n"
"}\n";
constexpr char kFS1[] =
"#version 310 es\n"
"layout(location = 0) out highp vec4 o_color;\n"
"\n"
"uniform highp vec4 u_color;\n"
"void main (void)\n"
"{\n"
" o_color = u_color;\n"
"}\n";
constexpr char kFS2[] =
"#version 310 es\n"
"#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n"
"layout(noncoherent, location = 0) inout highp vec4 o_color;\n"
"\n"
"uniform highp vec4 u_color;\n"
"void main (void)\n"
"{\n"
" o_color += u_color;\n"
"}\n";
GLProgram programVert, programNonFetch, programFetch;
const char *sourceArray[3] = {kVS, kFS1, kFS2};
GLShader vertShader(GL_VERTEX_SHADER);
glShaderSource(vertShader, 1, &sourceArray[0], nullptr);
glCompileShader(vertShader);
glProgramParameteri(programVert, GL_PROGRAM_SEPARABLE, GL_TRUE);
glAttachShader(programVert, vertShader);
glLinkProgram(programVert);
ASSERT_GL_NO_ERROR();
GLShader fragShader1(GL_FRAGMENT_SHADER);
glShaderSource(fragShader1, 1, &sourceArray[1], nullptr);
glCompileShader(fragShader1);
glProgramParameteri(programNonFetch, GL_PROGRAM_SEPARABLE, GL_TRUE);
glAttachShader(programNonFetch, fragShader1);
glLinkProgram(programNonFetch);
ASSERT_GL_NO_ERROR();
GLShader fragShader2(GL_FRAGMENT_SHADER);
glShaderSource(fragShader2, 1, &sourceArray[2], nullptr);
glCompileShader(fragShader2);
glProgramParameteri(programFetch, GL_PROGRAM_SEPARABLE, GL_TRUE);
glAttachShader(programFetch, fragShader2);
glLinkProgram(programFetch);
ASSERT_GL_NO_ERROR();
GLProgramPipeline pipeline1, pipeline2, pipeline3, pipeline4;
glUseProgramStages(pipeline1, GL_VERTEX_SHADER_BIT, programVert);
glUseProgramStages(pipeline1, GL_FRAGMENT_SHADER_BIT, programNonFetch);
glBindProgramPipeline(pipeline1);
ASSERT_GL_NO_ERROR();
GLFramebuffer framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
std::vector<GLColor> greenColor(kViewportWidth * kViewportHeight, GLColor::green);
GLTexture colorBufferTex;
glBindTexture(GL_TEXTURE_2D, colorBufferTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kViewportWidth, kViewportHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, greenColor.data());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTex, 0);
ASSERT_GL_NO_ERROR();
glActiveShaderProgram(pipeline1, programNonFetch);
float colorRed[4] = {1.0f, 0.0f, 0.0f, 1.0f};
GLint colorLocationNonFetch = glGetUniformLocation(programNonFetch, "u_color");
glUniform4fv(colorLocationNonFetch, 1, colorRed);
ASSERT_GL_NO_ERROR();
glActiveShaderProgram(pipeline1, programVert);
GLint positionLocation = glGetAttribLocation(programVert, "a_position");
render(positionLocation, GL_FALSE);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
glUseProgramStages(pipeline2, GL_VERTEX_SHADER_BIT, programVert);
glUseProgramStages(pipeline2, GL_FRAGMENT_SHADER_BIT, programFetch);
glBindProgramPipeline(pipeline2);
ASSERT_GL_NO_ERROR();
glActiveShaderProgram(pipeline2, programFetch);
float colorGreen[4] = {0.0f, 1.0f, 0.0f, 1.0f};
GLint colorLocationFetch = glGetUniformLocation(programFetch, "u_color");
glUniform4fv(colorLocationFetch, 1, colorGreen);
render(positionLocation, GL_TRUE);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::yellow);
glUseProgramStages(pipeline3, GL_VERTEX_SHADER_BIT, programVert);
glUseProgramStages(pipeline3, GL_FRAGMENT_SHADER_BIT, programNonFetch);
glBindProgramPipeline(pipeline3);
ASSERT_GL_NO_ERROR();
glActiveShaderProgram(pipeline3, programNonFetch);
colorLocationNonFetch = glGetUniformLocation(programNonFetch, "u_color");
glUniform4fv(colorLocationNonFetch, 1, colorRed);
ASSERT_GL_NO_ERROR();
render(positionLocation, GL_FALSE);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::red);
glUseProgramStages(pipeline4, GL_VERTEX_SHADER_BIT, programVert);
glUseProgramStages(pipeline4, GL_FRAGMENT_SHADER_BIT, programFetch);
glBindProgramPipeline(pipeline4);
ASSERT_GL_NO_ERROR();
glActiveShaderProgram(pipeline4, programFetch);
colorLocationFetch = glGetUniformLocation(programFetch, "u_color");
glUniform4fv(colorLocationFetch, 1, colorGreen);
render(positionLocation, GL_TRUE);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(kViewportWidth / 2, kViewportHeight / 2, GLColor::yellow);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
ANGLE_INSTANTIATE_TEST_ES31(FramebufferFetchNonCoherentES31);
} // namespace angle
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