зеркало из https://github.com/AvaloniaUI/angle.git
Vulkan: Workaround ARM bug with stencil write mask
Bug: angleproject:7556 Change-Id: I0aa17c178071cc15d8ee15f700b0c4932819c72a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3821367 Reviewed-by: Ian Elliott <ianelliott@google.com> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Cody Northrop <cnorthrop@google.com>
This commit is contained in:
Родитель
dc82ff15ee
Коммит
493b5aff70
|
@ -26,7 +26,7 @@
|
|||
|
||||
// Version number for shader translation API.
|
||||
// It is incremented every time the API changes.
|
||||
#define ANGLE_SH_VERSION 300
|
||||
#define ANGLE_SH_VERSION 301
|
||||
|
||||
enum ShShaderSpec
|
||||
{
|
||||
|
@ -805,6 +805,7 @@ unsigned int GetImage2DRegisterIndex(const ShHandle handle);
|
|||
// handle: Specifies the compiler
|
||||
const std::set<std::string> *GetUsedImage2DFunctionNames(const ShHandle handle);
|
||||
|
||||
bool HasDiscardInFragmentShader(const ShHandle handle);
|
||||
bool HasValidGeometryShaderInputPrimitiveType(const ShHandle handle);
|
||||
bool HasValidGeometryShaderOutputPrimitiveType(const ShHandle handle);
|
||||
bool HasValidGeometryShaderMaxVertices(const ShHandle handle);
|
||||
|
|
|
@ -670,6 +670,12 @@ struct FeaturesVk : FeatureSetBase
|
|||
"VkDevice supports VK_ANDROID_render_to_external_format and VK_EXT_ycbcr_attachment",
|
||||
&members,
|
||||
};
|
||||
|
||||
FeatureInfo useNonZeroStencilWriteMaskStaticState = {
|
||||
"useNonZeroStencilWriteMaskStaticState", FeatureCategory::VulkanWorkarounds,
|
||||
"Work around a driver bug where 0 in stencil write mask static state would make the"
|
||||
"corresponding dynamic state malfunction in the presence of discard or alpha to coverage",
|
||||
&members, "http://anglebug.com/7556"};
|
||||
};
|
||||
|
||||
inline FeaturesVk::FeaturesVk() = default;
|
||||
|
|
|
@ -900,6 +900,15 @@
|
|||
"description": [
|
||||
"VkDevice supports VK_ANDROID_render_to_external_format and VK_EXT_ycbcr_attachment"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "use_non_zero_stencil_write_mask_static_state",
|
||||
"category": "Workarounds",
|
||||
"description": [
|
||||
"Work around a driver bug where 0 in stencil write mask static state would make the",
|
||||
"corresponding dynamic state malfunction in the presence of discard or alpha to coverage"
|
||||
],
|
||||
"issue": "http://anglebug.com/7556"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"include/platform/FeaturesMtl_autogen.h":
|
||||
"6b6d49c35bc9246361f8dac0a5445a02",
|
||||
"include/platform/FeaturesVk_autogen.h":
|
||||
"ab5ace9dfe770836cc0532cb44a0d689",
|
||||
"858c952c9988cfdb448ebf5ac24d3433",
|
||||
"include/platform/FrontendFeatures_autogen.h":
|
||||
"1781e4fa6efb552bca2ce5a5164eb374",
|
||||
"include/platform/d3d_features.json":
|
||||
|
@ -20,9 +20,9 @@
|
|||
"include/platform/mtl_features.json":
|
||||
"1fabfe4d5c2eb3683a5b567ab60ad83c",
|
||||
"include/platform/vk_features.json":
|
||||
"712395bb25e2492ea13fba1c8131f481",
|
||||
"584d2949c0cc9e59f479748e583af9ef",
|
||||
"util/angle_features_autogen.cpp":
|
||||
"adf8f4a7e32d3229aa42bb7a96842d5b",
|
||||
"e5742cc5b6a78cfed2345067f2a247b2",
|
||||
"util/angle_features_autogen.h":
|
||||
"92d40c02e5b2741b33bcc88aa759cfde"
|
||||
"9bbae74bf2e9816ebe2f9002dd8f2fd2"
|
||||
}
|
|
@ -553,6 +553,8 @@ void TCompiler::setASTMetadata(const TParseContext &parseContext)
|
|||
|
||||
mEarlyFragmentTestsSpecified = parseContext.isEarlyFragmentTestsSpecified();
|
||||
|
||||
mHasDiscard = parseContext.hasDiscard();
|
||||
|
||||
mEnablesPerSampleShading = parseContext.isSampleQualifierSpecified();
|
||||
|
||||
mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared();
|
||||
|
|
|
@ -112,6 +112,7 @@ class TCompiler : public TShHandleBase
|
|||
TInfoSink &getInfoSink() { return mInfoSink; }
|
||||
|
||||
bool isEarlyFragmentTestsSpecified() const { return mEarlyFragmentTestsSpecified; }
|
||||
bool hasDiscard() const { return mHasDiscard; }
|
||||
bool enablesPerSampleShading() const { return mEnablesPerSampleShading; }
|
||||
SpecConstUsageBits getSpecConstUsageBits() const { return mSpecConstUsageBits; }
|
||||
|
||||
|
@ -317,9 +318,12 @@ class TCompiler : public TShHandleBase
|
|||
TDiagnostics mDiagnostics;
|
||||
const char *mSourcePath; // Path of source file or NULL
|
||||
|
||||
// fragment shader early fragment tests
|
||||
// Fragment shader early fragment tests
|
||||
bool mEarlyFragmentTestsSpecified;
|
||||
|
||||
// Fragment shader has the discard instruction
|
||||
bool mHasDiscard;
|
||||
|
||||
// Whether per-sample shading is enabled by the shader. In OpenGL, this keyword should
|
||||
// implicitly trigger per-sample shading without the API enabling it.
|
||||
bool mEnablesPerSampleShading;
|
||||
|
|
|
@ -210,6 +210,7 @@ TParseContext::TParseContext(TSymbolTable &symt,
|
|||
mChecksPrecisionErrors(checksPrecErrors),
|
||||
mFragmentPrecisionHighOnESSL1(false),
|
||||
mEarlyFragmentTestsSpecified(false),
|
||||
mHasDiscard(false),
|
||||
mSampleQualifierSpecified(false),
|
||||
mDefaultUniformMatrixPacking(EmpColumnMajor),
|
||||
mDefaultUniformBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
|
||||
|
@ -6810,6 +6811,7 @@ TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
|
|||
{
|
||||
errorIfPLSDeclared(loc, PLSIllegalOperations::Discard);
|
||||
}
|
||||
mHasDiscard = true;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
|
|
@ -76,6 +76,7 @@ class TParseContext : angle::NonCopyable
|
|||
}
|
||||
|
||||
bool isEarlyFragmentTestsSpecified() const { return mEarlyFragmentTestsSpecified; }
|
||||
bool hasDiscard() const { return mHasDiscard; }
|
||||
bool isSampleQualifierSpecified() const { return mSampleQualifierSpecified; }
|
||||
|
||||
void setLoopNestingLevel(int loopNestintLevel) { mLoopNestingLevel = loopNestintLevel; }
|
||||
|
@ -731,8 +732,9 @@ class TParseContext : angle::NonCopyable
|
|||
// without precision, explicit or implicit.
|
||||
bool mFragmentPrecisionHighOnESSL1; // true if highp precision is supported when compiling
|
||||
// ESSL1.
|
||||
bool mEarlyFragmentTestsSpecified; // true if layout(early_fragment_tests) in; is specified.
|
||||
bool mSampleQualifierSpecified; // true if the |sample| qualifier is used
|
||||
bool mEarlyFragmentTestsSpecified; // true if |layout(early_fragment_tests) in| is specified.
|
||||
bool mHasDiscard; // true if |discard| is encountered in the shader.
|
||||
bool mSampleQualifierSpecified; // true if the |sample| qualifier is used.
|
||||
TLayoutMatrixPacking mDefaultUniformMatrixPacking;
|
||||
TLayoutBlockStorage mDefaultUniformBlockStorage;
|
||||
TLayoutMatrixPacking mDefaultBufferMatrixPacking;
|
||||
|
|
|
@ -736,6 +736,17 @@ const std::set<std::string> *GetUsedImage2DFunctionNames(const ShHandle handle)
|
|||
#endif // ANGLE_ENABLE_HLSL
|
||||
}
|
||||
|
||||
bool HasDiscardInFragmentShader(const ShHandle handle)
|
||||
{
|
||||
ASSERT(handle);
|
||||
|
||||
TShHandleBase *base = static_cast<TShHandleBase *>(handle);
|
||||
TCompiler *compiler = base->getAsCompiler();
|
||||
ASSERT(compiler);
|
||||
|
||||
return compiler->getShaderType() == GL_FRAGMENT_SHADER && compiler->hasDiscard();
|
||||
}
|
||||
|
||||
bool HasValidGeometryShaderInputPrimitiveType(const ShHandle handle)
|
||||
{
|
||||
ASSERT(handle);
|
||||
|
|
|
@ -1347,6 +1347,7 @@ angle::Result Program::linkImpl(const Context *context)
|
|||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
mState.mExecutable->mHasDiscard = fragmentShader->hasDiscard();
|
||||
mState.mExecutable->mEnablesPerSampleShading =
|
||||
fragmentShader->enablesPerSampleShading();
|
||||
mState.mExecutable->mAdvancedBlendEquations =
|
||||
|
|
|
@ -196,6 +196,7 @@ ProgramExecutable::ProgramExecutable()
|
|||
mImageUniformRange(0, 0),
|
||||
mAtomicCounterUniformRange(0, 0),
|
||||
mFragmentInoutRange(0, 0),
|
||||
mHasDiscard(false),
|
||||
mEnablesPerSampleShading(false),
|
||||
// [GL_EXT_geometry_shader] Table 20.22
|
||||
mGeometryShaderInputPrimitiveType(PrimitiveMode::Triangles),
|
||||
|
@ -244,6 +245,7 @@ ProgramExecutable::ProgramExecutable(const ProgramExecutable &other)
|
|||
mAtomicCounterBuffers(other.mAtomicCounterBuffers),
|
||||
mShaderStorageBlocks(other.mShaderStorageBlocks),
|
||||
mFragmentInoutRange(other.mFragmentInoutRange),
|
||||
mHasDiscard(other.mHasDiscard),
|
||||
mEnablesPerSampleShading(other.mEnablesPerSampleShading),
|
||||
mAdvancedBlendEquations(other.mAdvancedBlendEquations)
|
||||
{
|
||||
|
@ -293,6 +295,7 @@ void ProgramExecutable::reset(bool clearInfoLog)
|
|||
mAtomicCounterUniformRange = RangeUI(0, 0);
|
||||
|
||||
mFragmentInoutRange = RangeUI(0, 0);
|
||||
mHasDiscard = false;
|
||||
mEnablesPerSampleShading = false;
|
||||
mAdvancedBlendEquations.reset();
|
||||
|
||||
|
@ -325,6 +328,7 @@ void ProgramExecutable::load(bool isSeparable, gl::BinaryInputStream *stream)
|
|||
unsigned int fragmentInoutRangeHigh = stream->readInt<uint32_t>();
|
||||
mFragmentInoutRange = RangeUI(fragmentInoutRangeLow, fragmentInoutRangeHigh);
|
||||
|
||||
mHasDiscard = stream->readBool();
|
||||
mEnablesPerSampleShading = stream->readBool();
|
||||
|
||||
static_assert(sizeof(mAdvancedBlendEquations.bits()) == sizeof(uint32_t));
|
||||
|
@ -557,6 +561,7 @@ void ProgramExecutable::save(bool isSeparable, gl::BinaryOutputStream *stream) c
|
|||
stream->writeInt(mFragmentInoutRange.low());
|
||||
stream->writeInt(mFragmentInoutRange.high());
|
||||
|
||||
stream->writeBool(mHasDiscard);
|
||||
stream->writeBool(mEnablesPerSampleShading);
|
||||
stream->writeInt(mAdvancedBlendEquations.bits());
|
||||
|
||||
|
|
|
@ -231,6 +231,7 @@ class ProgramExecutable final : public angle::Subject
|
|||
const RangeUI &getImageUniformRange() const { return mImageUniformRange; }
|
||||
const RangeUI &getAtomicCounterUniformRange() const { return mAtomicCounterUniformRange; }
|
||||
const RangeUI &getFragmentInoutRange() const { return mFragmentInoutRange; }
|
||||
bool hasDiscard() const { return mHasDiscard; }
|
||||
bool enablesPerSampleShading() const { return mEnablesPerSampleShading; }
|
||||
BlendEquationBitSet getAdvancedBlendEquations() const { return mAdvancedBlendEquations; }
|
||||
const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
|
||||
|
@ -472,6 +473,7 @@ class ProgramExecutable final : public angle::Subject
|
|||
std::vector<InterfaceBlock> mShaderStorageBlocks;
|
||||
|
||||
RangeUI mFragmentInoutRange;
|
||||
bool mHasDiscard;
|
||||
bool mEnablesPerSampleShading;
|
||||
|
||||
// KHR_blend_equation_advanced supported equation list
|
||||
|
|
|
@ -371,6 +371,7 @@ void ProgramPipeline::updateFragmentInoutRangeAndEnablesPerSampleShading()
|
|||
|
||||
const ProgramExecutable &fragmentExecutable = fragmentProgram->getExecutable();
|
||||
mState.mExecutable->mFragmentInoutRange = fragmentExecutable.mFragmentInoutRange;
|
||||
mState.mExecutable->mHasDiscard = fragmentExecutable.mHasDiscard;
|
||||
mState.mExecutable->mEnablesPerSampleShading = fragmentExecutable.mEnablesPerSampleShading;
|
||||
}
|
||||
|
||||
|
|
|
@ -343,6 +343,7 @@ void Shader::compile(const Context *context)
|
|||
mState.mTessGenVertexOrder = 0;
|
||||
mState.mTessGenPointMode = 0;
|
||||
mState.mAdvancedBlendEquations.reset();
|
||||
mState.mHasDiscard = false;
|
||||
mState.mEnablesPerSampleShading = false;
|
||||
mState.mSpecConstUsageBits.reset();
|
||||
|
||||
|
@ -544,6 +545,7 @@ void Shader::resolveCompile()
|
|||
std::sort(mState.mInputVaryings.begin(), mState.mInputVaryings.end(), CompareShaderVar);
|
||||
mState.mActiveOutputVariables =
|
||||
GetActiveShaderVariables(sh::GetOutputVariables(compilerHandle));
|
||||
mState.mHasDiscard = sh::HasDiscardInFragmentShader(compilerHandle);
|
||||
mState.mEnablesPerSampleShading = sh::EnablesPerSampleShading(compilerHandle);
|
||||
mState.mAdvancedBlendEquations =
|
||||
BlendEquationBitSet(sh::GetAdvancedBlendEquations(compilerHandle));
|
||||
|
|
|
@ -91,6 +91,7 @@ class ShaderState final : angle::NonCopyable
|
|||
|
||||
const sh::WorkGroupSize &getLocalSize() const { return mLocalSize; }
|
||||
|
||||
bool hasDiscard() const { return mHasDiscard; }
|
||||
bool enablesPerSampleShading() const { return mEnablesPerSampleShading; }
|
||||
rx::SpecConstUsageBits getSpecConstUsageBits() const { return mSpecConstUsageBits; }
|
||||
|
||||
|
@ -134,6 +135,7 @@ class ShaderState final : angle::NonCopyable
|
|||
std::vector<sh::ShaderVariable> mActiveAttributes;
|
||||
std::vector<sh::ShaderVariable> mActiveOutputVariables;
|
||||
|
||||
bool mHasDiscard;
|
||||
bool mEnablesPerSampleShading;
|
||||
BlendEquationBitSet mAdvancedBlendEquations;
|
||||
rx::SpecConstUsageBits mSpecConstUsageBits;
|
||||
|
@ -200,6 +202,7 @@ class Shader final : angle::NonCopyable, public LabeledObject
|
|||
unsigned int getRefCount() const;
|
||||
bool isFlaggedForDeletion() const;
|
||||
void flagForDeletion();
|
||||
bool hasDiscard() const { return mState.mHasDiscard; }
|
||||
bool enablesPerSampleShading() const { return mState.mEnablesPerSampleShading; }
|
||||
BlendEquationBitSet getAdvancedBlendEquations() const { return mState.mAdvancedBlendEquations; }
|
||||
rx::SpecConstUsageBits getSpecConstUsageBits() const { return mState.mSpecConstUsageBits; }
|
||||
|
|
|
@ -920,8 +920,11 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
|
|||
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_LINE_WIDTH);
|
||||
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_POLYGON_OFFSET);
|
||||
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_BLEND_COLOR);
|
||||
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
|
||||
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK);
|
||||
if (!getFeatures().useNonZeroStencilWriteMaskStaticState.enabled)
|
||||
{
|
||||
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
|
||||
mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK);
|
||||
}
|
||||
|
||||
// Dynamic state in VK_EXT_extended_dynamic_state:
|
||||
if (getFeatures().supportsExtendedDynamicState.enabled)
|
||||
|
@ -4626,6 +4629,24 @@ void ContextVk::updateDither()
|
|||
}
|
||||
}
|
||||
|
||||
void ContextVk::updateStencilWriteWorkaround()
|
||||
{
|
||||
if (!getFeatures().useNonZeroStencilWriteMaskStaticState.enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// On certain drivers, having a stencil write mask of 0 in static state enables optimizations
|
||||
// that make the interaction of the stencil write mask dynamic state with discard and alpha to
|
||||
// coverage broken. When the program has discard, or when alpha to coverage is enabled, these
|
||||
// optimizations are disabled by specifying a non-zero static state for stencil write mask.
|
||||
const bool programHasDiscard = mState.getProgramExecutable()->hasDiscard();
|
||||
const bool isAlphaToCoverageEnabled = mState.isSampleAlphaToCoverageEnabled();
|
||||
|
||||
mGraphicsPipelineDesc->updateNonZeroStencilWriteMaskWorkaround(
|
||||
&mGraphicsPipelineTransition, programHasDiscard || isAlphaToCoverageEnabled);
|
||||
}
|
||||
|
||||
angle::Result ContextVk::invalidateProgramExecutableHelper(const gl::Context *context)
|
||||
{
|
||||
const gl::State &glState = context->getState();
|
||||
|
@ -4661,6 +4682,8 @@ angle::Result ContextVk::invalidateProgramExecutableHelper(const gl::Context *co
|
|||
// masked, so update their access.
|
||||
onColorAccessChange();
|
||||
}
|
||||
|
||||
updateStencilWriteWorkaround();
|
||||
}
|
||||
|
||||
return angle::Result::Continue;
|
||||
|
@ -4729,6 +4752,8 @@ angle::Result ContextVk::syncState(const gl::Context *context,
|
|||
case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
|
||||
mGraphicsPipelineDesc->updateAlphaToCoverageEnable(
|
||||
&mGraphicsPipelineTransition, glState.isSampleAlphaToCoverageEnabled());
|
||||
updateStencilWriteWorkaround();
|
||||
|
||||
static_assert(gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE >
|
||||
gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED,
|
||||
"Dirty bit order");
|
||||
|
|
|
@ -1277,6 +1277,16 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
|
|||
|
||||
void updateDither();
|
||||
|
||||
// When the useNonZeroStencilWriteMaskStaticState workaround is enabled, the static state for
|
||||
// stencil should be non-zero despite the state being dynamic. This is done when:
|
||||
//
|
||||
// - The shader includes discard, or
|
||||
// - Alpha-to-coverage is enabled.
|
||||
//
|
||||
// An alternative could have been to set the static state unconditionally to non-zero. This is
|
||||
// avoided however, as on the affected driver that would disable certain optimizations.
|
||||
void updateStencilWriteWorkaround();
|
||||
|
||||
SpecConstUsageBits getCurrentProgramSpecConstUsageBits() const;
|
||||
void updateGraphicsPipelineDescWithSpecConstUsageBits(SpecConstUsageBits usageBits);
|
||||
|
||||
|
|
|
@ -3671,6 +3671,11 @@ void RendererVk::initFeatures(DisplayVk *displayVk,
|
|||
!isARM && !isPowerVR && !isQualcommProprietary &&
|
||||
!(IsLinux() && isIntel) && !(IsChromeOS() && isSwiftShader));
|
||||
|
||||
// On ARM, dynamic state for stencil write mask doesn't work correctly in the presence of
|
||||
// discard or alpha to coverage, if the static state provided when creating the pipeline has a
|
||||
// value of 0.
|
||||
ANGLE_FEATURE_CONDITION(&mFeatures, useNonZeroStencilWriteMaskStaticState, isARM);
|
||||
|
||||
// On ARM, per-sample shading is not enabled despite the presence of a Sample decoration. As a
|
||||
// workaround, per-sample shading is inferred by ANGLE and explicitly enabled by the API.
|
||||
ANGLE_FEATURE_CONDITION(&mFeatures, explicitlyEnablePerSampleShading, isARM);
|
||||
|
|
|
@ -257,14 +257,20 @@ void UnpackDepthStencilResolveAttachmentDesc(VkAttachmentDescription *desc,
|
|||
desc->finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
}
|
||||
|
||||
void UnpackStencilState(const PackedStencilOpState &packedState, VkStencilOpState *stateOut)
|
||||
void UnpackStencilState(const PackedStencilOpState &packedState,
|
||||
VkStencilOpState *stateOut,
|
||||
bool writeMaskWorkaround)
|
||||
{
|
||||
// Any non-zero value works for the purposes of the useNonZeroStencilWriteMaskStaticState driver
|
||||
// bug workaround.
|
||||
constexpr uint32_t kNonZeroWriteMaskForWorkaround = 1;
|
||||
|
||||
stateOut->failOp = static_cast<VkStencilOp>(packedState.ops.fail);
|
||||
stateOut->passOp = static_cast<VkStencilOp>(packedState.ops.pass);
|
||||
stateOut->depthFailOp = static_cast<VkStencilOp>(packedState.ops.depthFail);
|
||||
stateOut->compareOp = static_cast<VkCompareOp>(packedState.ops.compare);
|
||||
stateOut->compareMask = 0;
|
||||
stateOut->writeMask = 0;
|
||||
stateOut->writeMask = writeMaskWorkaround ? kNonZeroWriteMaskForWorkaround : 0;
|
||||
stateOut->reference = 0;
|
||||
}
|
||||
|
||||
|
@ -1637,7 +1643,7 @@ void UnpackPipelineState(const vk::GraphicsPipelineDesc &state, UnpackedPipeline
|
|||
const PackedInputAssemblyAndRasterizationStateInfo &inputAndRaster =
|
||||
state.getInputAssemblyAndRasterizationStateInfoForLog();
|
||||
const PackedColorBlendStateInfo &colorBlend = state.getColorBlendStateInfoForLog();
|
||||
const PackedDither &dither = state.getDitherForLog();
|
||||
const PackedDitherAndWorkarounds &dither = state.getDitherForLog();
|
||||
const PackedDynamicState &dynamicState = state.getDynamicStateForLog();
|
||||
|
||||
valuesOut->fill(0);
|
||||
|
@ -2669,8 +2675,9 @@ void GraphicsPipelineDesc::initDefaults(const ContextVk *contextVk)
|
|||
&mColorBlendStateInfo.attachments[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS],
|
||||
blendAttachmentState);
|
||||
|
||||
mDither.emulatedDitherControl = 0;
|
||||
mDither.unused = 0;
|
||||
mDitherAndWorkarounds.emulatedDitherControl = 0;
|
||||
mDitherAndWorkarounds.nonZeroStencilWriteMaskWorkaround = 0;
|
||||
mDitherAndWorkarounds.unused = 0;
|
||||
|
||||
SetBitField(mDynamicState.ds1And2.cullMode, VK_CULL_MODE_NONE);
|
||||
SetBitField(mDynamicState.ds1And2.frontFace, VK_FRONT_FACE_COUNTER_CLOCKWISE);
|
||||
|
@ -3032,8 +3039,10 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
|
|||
depthStencilState.depthBoundsTestEnable =
|
||||
static_cast<VkBool32>(inputAndRaster.misc.depthBoundsTest);
|
||||
depthStencilState.stencilTestEnable = static_cast<VkBool32>(mDynamicState.ds1And2.stencilTest);
|
||||
UnpackStencilState(mDynamicState.ds1.front, &depthStencilState.front);
|
||||
UnpackStencilState(mDynamicState.ds1.back, &depthStencilState.back);
|
||||
UnpackStencilState(mDynamicState.ds1.front, &depthStencilState.front,
|
||||
mDitherAndWorkarounds.nonZeroStencilWriteMaskWorkaround);
|
||||
UnpackStencilState(mDynamicState.ds1.back, &depthStencilState.back,
|
||||
mDitherAndWorkarounds.nonZeroStencilWriteMaskWorkaround);
|
||||
depthStencilState.minDepthBounds = 0;
|
||||
depthStencilState.maxDepthBounds = 0;
|
||||
|
||||
|
@ -3703,10 +3712,18 @@ void GraphicsPipelineDesc::updateEmulatedDitherControl(GraphicsPipelineTransitio
|
|||
uint16_t value)
|
||||
{
|
||||
// Make sure we don't waste time resetting this to zero in the common no-dither case.
|
||||
ASSERT(value != 0 || mDither.emulatedDitherControl != 0);
|
||||
ASSERT(value != 0 || mDitherAndWorkarounds.emulatedDitherControl != 0);
|
||||
|
||||
mDither.emulatedDitherControl = value;
|
||||
transition->set(ANGLE_GET_TRANSITION_BIT(mDither, emulatedDitherControl));
|
||||
mDitherAndWorkarounds.emulatedDitherControl = value;
|
||||
transition->set(ANGLE_GET_TRANSITION_BIT(mDitherAndWorkarounds, emulatedDitherControl));
|
||||
}
|
||||
|
||||
void GraphicsPipelineDesc::updateNonZeroStencilWriteMaskWorkaround(
|
||||
GraphicsPipelineTransitionBits *transition,
|
||||
bool enabled)
|
||||
{
|
||||
mDitherAndWorkarounds.nonZeroStencilWriteMaskWorkaround = enabled;
|
||||
transition->set(ANGLE_GET_TRANSITION_BIT(mDitherAndWorkarounds, emulatedDitherControl));
|
||||
}
|
||||
|
||||
void GraphicsPipelineDesc::updateRenderPassDesc(GraphicsPipelineTransitionBits *transition,
|
||||
|
|
|
@ -468,12 +468,13 @@ struct PackedColorBlendStateInfo final
|
|||
constexpr size_t kPackedColorBlendStateSize = sizeof(PackedColorBlendStateInfo);
|
||||
static_assert(kPackedColorBlendStateSize == 36, "Size check failed");
|
||||
|
||||
struct PackedDither final
|
||||
struct PackedDitherAndWorkarounds final
|
||||
{
|
||||
static_assert(gl::IMPLEMENTATION_MAX_DRAW_BUFFERS <= 8,
|
||||
"2 bits per draw buffer is needed for dither emulation");
|
||||
uint16_t emulatedDitherControl;
|
||||
uint16_t unused;
|
||||
uint16_t nonZeroStencilWriteMaskWorkaround : 1;
|
||||
uint16_t unused : 15;
|
||||
};
|
||||
|
||||
// State that is dynamic in VK_EXT_extended_dynamic_state and 2. These are placed at the end of the
|
||||
|
@ -537,7 +538,7 @@ static_assert(kPackedDynamicStateSize == 40, "Size check failed");
|
|||
constexpr size_t kGraphicsPipelineDescSumOfSizes =
|
||||
kVertexInputAttributesSize + kRenderPassDescSize +
|
||||
kPackedInputAssemblyAndRasterizationStateSize + kPackedColorBlendStateSize +
|
||||
sizeof(PackedDither) + kPackedDynamicStateSize;
|
||||
sizeof(PackedDitherAndWorkarounds) + kPackedDynamicStateSize;
|
||||
|
||||
// Number of dirty bits in the dirty bit set.
|
||||
constexpr size_t kGraphicsPipelineDirtyBitBytes = 4;
|
||||
|
@ -720,7 +721,13 @@ class GraphicsPipelineDesc final
|
|||
}
|
||||
|
||||
void updateEmulatedDitherControl(GraphicsPipelineTransitionBits *transition, uint16_t value);
|
||||
uint32_t getEmulatedDitherControl() const { return mDither.emulatedDitherControl; }
|
||||
uint32_t getEmulatedDitherControl() const
|
||||
{
|
||||
return mDitherAndWorkarounds.emulatedDitherControl;
|
||||
}
|
||||
|
||||
void updateNonZeroStencilWriteMaskWorkaround(GraphicsPipelineTransitionBits *transition,
|
||||
bool enabled);
|
||||
|
||||
void setSupportsDynamicStateForTest(bool supports)
|
||||
{
|
||||
|
@ -740,7 +747,7 @@ class GraphicsPipelineDesc final
|
|||
{
|
||||
return mColorBlendStateInfo;
|
||||
}
|
||||
const PackedDither &getDitherForLog() const { return mDither; }
|
||||
const PackedDitherAndWorkarounds &getDitherForLog() const { return mDitherAndWorkarounds; }
|
||||
const PackedDynamicState &getDynamicStateForLog() const { return mDynamicState; }
|
||||
|
||||
private:
|
||||
|
@ -750,7 +757,7 @@ class GraphicsPipelineDesc final
|
|||
RenderPassDesc mRenderPassDesc;
|
||||
PackedInputAssemblyAndRasterizationStateInfo mInputAssemblyAndRasterizationStateInfo;
|
||||
PackedColorBlendStateInfo mColorBlendStateInfo;
|
||||
PackedDither mDither;
|
||||
PackedDitherAndWorkarounds mDitherAndWorkarounds;
|
||||
PackedDynamicState mDynamicState;
|
||||
};
|
||||
|
||||
|
|
|
@ -538,7 +538,6 @@
|
|||
7158 PIXEL6 VULKAN : ImageTestES3.SourceAHBMipTarget2DMip/* = SKIP
|
||||
7158 PIXEL6 VULKAN : ImageTestES3.SourceAHBMipTarget2DMipGenerateMipmap/* = SKIP
|
||||
7279 PIXEL6 VULKAN : PixelLocalStorageTest.EarlyFragmentTests/ES3_1_Vulkan_EmulatePixelLocalStorage* = SKIP
|
||||
7556 PIXEL6 VULKAN : StateChangeTestES3.StencilWriteMaskVsDiscard/* = SKIP
|
||||
|
||||
// ARM drivers cannot support xfb emulation because they lack support for the
|
||||
// vertexPipelineStoresAndAtomics Vulkan feature. The tests that force-enable this feature are
|
||||
|
|
|
@ -285,6 +285,7 @@ constexpr PackedEnumMap<Feature, const char *> kFeatureNames = {{
|
|||
{Feature::UploadTextureDataInChunks, "uploadTextureDataInChunks"},
|
||||
{Feature::UseInstancedPointSpriteEmulation, "useInstancedPointSpriteEmulation"},
|
||||
{Feature::UseMultipleDescriptorsForExternalFormats, "useMultipleDescriptorsForExternalFormats"},
|
||||
{Feature::UseNonZeroStencilWriteMaskStaticState, "useNonZeroStencilWriteMaskStaticState"},
|
||||
{Feature::UseSystemMemoryForConstantBuffers, "useSystemMemoryForConstantBuffers"},
|
||||
{Feature::UseUnusedBlocksWithStandardOrSharedLayout,
|
||||
"useUnusedBlocksWithStandardOrSharedLayout"},
|
||||
|
|
|
@ -266,6 +266,7 @@ enum class Feature
|
|||
UploadTextureDataInChunks,
|
||||
UseInstancedPointSpriteEmulation,
|
||||
UseMultipleDescriptorsForExternalFormats,
|
||||
UseNonZeroStencilWriteMaskStaticState,
|
||||
UseSystemMemoryForConstantBuffers,
|
||||
UseUnusedBlocksWithStandardOrSharedLayout,
|
||||
VertexIDDoesNotIncludeBaseVertex,
|
||||
|
|
Загрузка…
Ссылка в новой задаче