Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 471b8d4

Browse files
jdarpinianCommit Bot
authored andcommitted
WebGL, D3D: Forbid multiple TF outputs in one buffer
Implementing a WebGL spec change: KhronosGroup/WebGL#2658 Fixes WebGL 2 conformance test: conformance2/transform_feedback/same-buffer-two-binding-points.html Also applying the change to D3D backends because they can't support multiple transform feedback outputs in one buffer. Bug: chromium:866089 Change-Id: I8d7eda14225c13efb7ca1ed974239332be4e79a6 Reviewed-on: https://chromium-review.googlesource.com/c/1347749 Commit-Queue: James Darpinian <jdarpinian@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org>
1 parent 5552cdf commit 471b8d4

File tree

8 files changed

+55
-5
lines changed

8 files changed

+55
-5
lines changed

src/libANGLE/Buffer.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,11 @@ bool Buffer::isBoundForTransformFeedbackAndOtherUse() const
268268
mState.mBindingCount - mState.mTransformFeedbackGenericBindingCount;
269269
}
270270

271+
bool Buffer::isDoubleBoundForTransformFeedback() const
272+
{
273+
return mState.mTransformFeedbackIndexedBindingCount > 1;
274+
}
275+
271276
void Buffer::onTFBindingChanged(const Context *context, bool bound, bool indexed)
272277
{
273278
ASSERT(bound || mState.mBindingCount > 0);

src/libANGLE/Buffer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ class Buffer final : public RefCountObject,
123123

124124
bool isBound() const;
125125
bool isBoundForTransformFeedbackAndOtherUse() const;
126+
bool isDoubleBoundForTransformFeedback() const;
126127
void onTFBindingChanged(const Context *context, bool bound, bool indexed);
127128
void onNonTFBindingChanged(int incr) { mState.mBindingCount += incr; }
128129

src/libANGLE/Caps.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,8 @@ Limitations::Limitations()
286286
noSeparateStencilRefsAndMasks(false),
287287
shadersRequireIndexedLoopValidation(false),
288288
noSimultaneousConstantColorAndAlphaBlendFunc(false),
289-
noFlexibleVaryingPacking(false)
289+
noFlexibleVaryingPacking(false),
290+
noDoubleBoundTransformFeedbackBuffers(false)
290291
{
291292
}
292293

src/libANGLE/Caps.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,9 @@ struct Limitations
506506

507507
// D3D9 does not support flexible varying register packing.
508508
bool noFlexibleVaryingPacking;
509+
510+
// D3D does not support having multiple transform feedback outputs go to the same buffer.
511+
bool noDoubleBoundTransformFeedbackBuffers;
509512
};
510513

511514
struct TypePrecision

src/libANGLE/ErrorStrings.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ constexpr const char *kErrorDestinationTextureTooSmall = "Destination texture to
104104
constexpr const char *kErrorDimensionsMustBePow2 = "Texture dimensions must be power-of-two.";
105105
constexpr const char *kErrorDispatchIndirectBufferNotBound =
106106
"Dispatch indirect buffer must be bound.";
107+
constexpr const char *kErrorDoubleBoundTransformFeedbackBuffer =
108+
"Transform feedback has a buffer bound to multiple outputs.";
107109
constexpr const char *kErrorDrawIndirectBufferNotBound = "Draw indirect buffer must be bound.";
108110
constexpr const char *kErrorDrawBufferTypeMismatch =
109111
"Fragment shader output type does not match the bound framebuffer attachment type.";

src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,6 +1654,9 @@ void GenerateCaps(ID3D11Device *device,
16541654
// D3D11 cannot support constant color and alpha blend funcs together
16551655
limitations->noSimultaneousConstantColorAndAlphaBlendFunc = true;
16561656

1657+
// D3D11 does not support multiple transform feedback outputs writing to the same buffer.
1658+
limitations->noDoubleBoundTransformFeedbackBuffers = true;
1659+
16571660
#ifdef ANGLE_ENABLE_WINDOWS_STORE
16581661
// Setting a non-zero divisor on attribute zero doesn't work on certain Windows Phone 8-era
16591662
// devices. We should prevent developers from doing this on ALL Windows Store devices. This will

src/libANGLE/validationES3.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2472,11 +2472,22 @@ bool ValidateBeginTransformFeedback(Context *context, PrimitiveMode primitiveMod
24722472
for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
24732473
{
24742474
const auto &buffer = transformFeedback->getIndexedBuffer(i);
2475-
if (buffer.get() && buffer->isMapped())
2475+
if (buffer.get())
24762476
{
2477-
context->validationError(GL_INVALID_OPERATION,
2478-
"Transform feedback has a mapped buffer.");
2479-
return false;
2477+
if (buffer->isMapped())
2478+
{
2479+
context->validationError(GL_INVALID_OPERATION,
2480+
"Transform feedback has a mapped buffer.");
2481+
return false;
2482+
}
2483+
if ((context->getLimitations().noDoubleBoundTransformFeedbackBuffers ||
2484+
context->getExtensions().webglCompatibility) &&
2485+
buffer->isDoubleBoundForTransformFeedback())
2486+
{
2487+
context->validationError(GL_INVALID_OPERATION,
2488+
kErrorDoubleBoundTransformFeedbackBuffer);
2489+
return false;
2490+
}
24802491
}
24812492
}
24822493

src/tests/gl_tests/WebGLCompatibilityTest.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4254,6 +4254,30 @@ TEST_P(WebGL2CompatibilityTest, TransformFeedbackCheckNullDeref)
42544254
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
42554255
}
42564256

4257+
// We should forbid two transform feedback outputs going to the same buffer.
4258+
TEST_P(WebGL2CompatibilityTest, TransformFeedbackDoubleBinding)
4259+
{
4260+
constexpr char kVS[] =
4261+
R"(attribute float a; varying float b; varying float c; void main() { b = a; c = a; })";
4262+
constexpr char kFS[] = R"(void main(){})";
4263+
ANGLE_GL_PROGRAM(program, kVS, kFS);
4264+
static const char *varyings[] = {"b", "c"};
4265+
glTransformFeedbackVaryings(program, 2, varyings, GL_SEPARATE_ATTRIBS);
4266+
glLinkProgram(program);
4267+
glUseProgram(program);
4268+
ASSERT_GL_NO_ERROR();
4269+
4270+
// Bind the transform feedback varyings to non-overlapping regions of the same buffer.
4271+
GLBuffer buffer;
4272+
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer, 0, 4);
4273+
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 1, buffer, 4, 4);
4274+
glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 8, nullptr, GL_STATIC_DRAW);
4275+
ASSERT_GL_NO_ERROR();
4276+
// Two varyings bound to the same buffer should be an error.
4277+
glBeginTransformFeedback(GL_POINTS);
4278+
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
4279+
}
4280+
42574281
// Check the return type of a given parameter upon getting the active uniforms.
42584282
TEST_P(WebGL2CompatibilityTest, UniformVariablesReturnTypes)
42594283
{

0 commit comments

Comments
 (0)