mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Test] (MG_IntegrationTest/Scenarios, MG_Test/Backend): run every narrow case
- the client-memory case runs on every arm, as the client array scenario does - a capture program meets both signednesses in one capture without a relink - a relink that turns an ivec4 input into uvec4 starts over - the recreated program and array must reuse their names - the ESSL check counts the width declarations
This commit is contained in:
@@ -27,7 +27,6 @@
|
||||
// cannot look it says so and the value checks still run.
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
@@ -37,7 +36,6 @@
|
||||
#include "../Harness/HeadlessGL.h"
|
||||
#include "../Harness/IntegerAttributeTypePeek.h"
|
||||
#include "../Harness/ScenarioFixture.h"
|
||||
#include "../Harness/SplitRuntimePeek.h"
|
||||
|
||||
#ifdef GLAPI
|
||||
#undef GLAPI
|
||||
@@ -613,8 +611,9 @@ void main()
|
||||
m_programs.push_back(uintProgram);
|
||||
const GLuint signedArray = MakeByteArray(kBytes, GL_BYTE);
|
||||
ASSERT_EQ(glGetError(), GL_NO_ERROR) << "second pair setup";
|
||||
RecordProperty("program_name_reused", uintProgram == intProgram ? 1 : 0);
|
||||
RecordProperty("vertex_array_name_reused", signedArray == unsignedArray ? 1 : 0);
|
||||
// The case is about the reused names; a fresh name would check nothing it is for.
|
||||
EXPECT_EQ(uintProgram, intProgram) << "the program name was not reused";
|
||||
EXPECT_EQ(signedArray, unsignedArray) << "the vertex array name was not reused";
|
||||
EXPECT_EQ(Capture(uintProgram, signedArray, 4), kBytesAsSigned) << "the second pair";
|
||||
EXPECT_EQ(glGetError(), GL_NO_ERROR);
|
||||
ExpectDriverArraysFitTheirInputs();
|
||||
@@ -687,20 +686,10 @@ void main()
|
||||
ExpectDriverArraysFitTheirInputs();
|
||||
}
|
||||
|
||||
// An array in the application's own memory. Only a library-hosted backend reads client
|
||||
// memory at the draw, and only relaxed semantics allow such an array, so the case stops
|
||||
// before its first draw anywhere else.
|
||||
// An array in the application's own memory, as ClientVertexArrayScenario draws one on
|
||||
// every arm.
|
||||
TEST_F(NarrowIntegerAttributeScenario, AClientMemoryArrayIsCorrected) {
|
||||
if (!Ready()) GTEST_SKIP();
|
||||
const std::string transport = SplitLane::MarkerValue("MOBILEGL_TRANSPORT");
|
||||
if (PeekSplitRuntime().transportResolved || (!transport.empty() && transport != "monolith"))
|
||||
GTEST_SKIP() << "client-memory arrays are drawn only with the backend in this library";
|
||||
GLint profile = 0;
|
||||
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile);
|
||||
if ((profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0 &&
|
||||
AmbientQuirkFromEnvironment("MOBILEGL_RELAXED_SEMANTICS") != AmbientQuirk::On) {
|
||||
GTEST_SKIP() << "a core profile without relaxed semantics has no client-memory arrays";
|
||||
}
|
||||
std::string log;
|
||||
const GLuint program = BuildCaptureProgram(kSingleInputVertexSource, {"captured"}, &log);
|
||||
ASSERT_NE(program, 0u) << log;
|
||||
@@ -818,5 +807,70 @@ void main()
|
||||
EXPECT_EQ(glGetError(), GL_NO_ERROR);
|
||||
ExpectDriverArraysFitTheirInputs();
|
||||
}
|
||||
|
||||
// A capture program's first draws, matching data then the other signedness, inside one
|
||||
// capture: the program has to be built for both before the capture opens, since nothing
|
||||
// may relink it while it captures.
|
||||
TEST_F(NarrowIntegerAttributeScenario, ACaptureProgramMeetsBothSignednessesInOneCapture) {
|
||||
if (!Ready()) GTEST_SKIP();
|
||||
const long linksBefore = LinksSoFar();
|
||||
std::string log;
|
||||
const GLuint program = BuildCaptureProgram(kSingleInputVertexSource, {"captured"}, &log);
|
||||
ASSERT_NE(program, 0u) << log;
|
||||
m_programs.push_back(program);
|
||||
const GLuint signedArray = MakeByteArray(kBytes, GL_BYTE);
|
||||
const GLuint unsignedArray = MakeByteArray(kLightBytes, GL_UNSIGNED_BYTE);
|
||||
ASSERT_EQ(glGetError(), GL_NO_ERROR) << "vertex array setup";
|
||||
|
||||
std::vector<GLuint> expected = kBytesAsSigned;
|
||||
expected.insert(expected.end(), kLightWords.begin(), kLightWords.end());
|
||||
EXPECT_EQ(Capture(program, signedArray, 8,
|
||||
[unsignedArray] {
|
||||
glDrawArrays(GL_POINTS, 0, 1);
|
||||
glBindVertexArray(unsignedArray);
|
||||
glDrawArrays(GL_POINTS, 0, 1);
|
||||
}),
|
||||
expected);
|
||||
if (linksBefore >= 0) EXPECT_LE(LinksSoFar(), linksBefore + 1) << "the program was relinked";
|
||||
EXPECT_EQ(glGetError(), GL_NO_ERROR);
|
||||
ExpectDriverArraysFitTheirInputs();
|
||||
}
|
||||
|
||||
// The application relinks the same program object with its input at location 0 turned
|
||||
// from ivec4 into uvec4: what was known about the old link's inputs no longer holds.
|
||||
TEST_F(NarrowIntegerAttributeScenario, ARelinkThatChangesTheInputsSignednessStartsOver) {
|
||||
if (!Ready()) GTEST_SKIP();
|
||||
std::string log;
|
||||
const GLuint program = BuildCaptureProgram(kSingleInputVertexSource, {"captured"}, &log);
|
||||
ASSERT_NE(program, 0u) << log;
|
||||
m_programs.push_back(program);
|
||||
const GLuint unsignedArray = MakeByteArray(kLightBytes, GL_UNSIGNED_BYTE);
|
||||
const GLuint signedArray = MakeByteArray(kBytes, GL_BYTE);
|
||||
ASSERT_EQ(glGetError(), GL_NO_ERROR) << "vertex array setup";
|
||||
EXPECT_EQ(Capture(program, unsignedArray, 4), kLightWords) << "the ivec4 link";
|
||||
|
||||
GLuint attached[4] = {};
|
||||
GLsizei attachedCount = 0;
|
||||
glGetAttachedShaders(program, 4, &attachedCount, attached);
|
||||
for (GLsizei i = 0; i < attachedCount; ++i)
|
||||
glDetachShader(program, attached[i]);
|
||||
const GLuint vertexShader = CompileShader(GL_VERTEX_SHADER, kSingleUintInputVertexSource, &log);
|
||||
ASSERT_NE(vertexShader, 0u) << log;
|
||||
const GLuint fragmentShader = CompileShader(GL_FRAGMENT_SHADER, kFragmentSource, &log);
|
||||
ASSERT_NE(fragmentShader, 0u) << log;
|
||||
glAttachShader(program, vertexShader);
|
||||
glAttachShader(program, fragmentShader);
|
||||
glLinkProgram(program);
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
GLint status = GL_FALSE;
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &status);
|
||||
ASSERT_EQ(status, GL_TRUE);
|
||||
|
||||
EXPECT_EQ(Capture(program, signedArray, 4), kBytesAsSigned) << "the uvec4 link, GL_BYTE data";
|
||||
EXPECT_EQ(Capture(program, unsignedArray, 4), kLightWords) << "the uvec4 link, matching data";
|
||||
EXPECT_EQ(glGetError(), GL_NO_ERROR);
|
||||
ExpectDriverArraysFitTheirInputs();
|
||||
}
|
||||
} // namespace
|
||||
} // namespace MGITest
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
// takes: the array-input split, the RuntimeWidths pass, ESSL 3.00 emission and the uniform
|
||||
// promotion. The two widths have to come out as `uniform highp uint` (anything else is read
|
||||
// uninitialised or at too low a precision) and the result has to be ESSL 3.00 a compiler accepts.
|
||||
// The emission here uses plain ESSL 3.00 options, not the build's whole pass chain; the
|
||||
// integration lanes run that chain (NarrowIntegerAttributeScenario).
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
@@ -93,6 +95,17 @@ void main() { color = vec4(a) + vec4(b); }
|
||||
return result != nullptr ? String(result) : String{};
|
||||
}
|
||||
|
||||
// Declarations of `name` as a uint, whatever their qualifiers or initialiser.
|
||||
SizeT CountUintDeclarations(const String& source, const char* name) {
|
||||
SizeT count = 0;
|
||||
for (const char* suffix : {";", " ="}) {
|
||||
const String declaration = String("uint ") + name + suffix;
|
||||
for (SizeT pos = source.find(declaration); pos != String::npos; pos = source.find(declaration, pos + 1))
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
String CompileErrorAsEssl300Vertex(const String& source) {
|
||||
glslang::TShader shader(EShLangVertex);
|
||||
const char* strings[] = {source.c_str()};
|
||||
@@ -121,7 +134,7 @@ TEST(NarrowIntegerEssl, ArmedVertexStageDeclaresBothWidthsAsHighpUniformsInValid
|
||||
for (const char* name : {kNarrowIntegerWidths8GlobalName, kNarrowIntegerWidths16GlobalName}) {
|
||||
EXPECT_NE(essl.find(String("uniform highp uint ") + name + ";"), String::npos) << name << "\n" << essl;
|
||||
// Exactly one declaration, and it is the uniform.
|
||||
EXPECT_EQ(essl.find(String("uint ") + name), essl.find(String("highp uint ") + name) + 6) << essl;
|
||||
EXPECT_EQ(CountUintDeclarations(essl, name), 1u) << name << "\n" << essl;
|
||||
}
|
||||
for (const char* bitfield : {"bitfieldExtract", "bitfieldInsert"})
|
||||
EXPECT_EQ(essl.find(bitfield), String::npos) << essl;
|
||||
|
||||
Reference in New Issue
Block a user