Commit b1580a27 by Hyunchang Kim Committed by Commit Bot

Vulkan: Set half float vertex format to valid in 2.0 context

- OES_vertex_half_float extension requires this patch - Add end2end tests to verify OES_vertex_half_float extension BUG=angleproject:3191 BUG=angleproject:3802 Test: angle_end2end_tests --gtest_filter=*VertexAttributeTest.HalfFloatClientMemoryPointer* 3DMark Icestorm GT1 Change-Id: Ia597021a5ae6b4853ee1199989ec3f9cc23c7fac Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1793354 Commit-Queue: Mohan Maiya <m.maiya@samsung.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 1439b6d5
......@@ -333,9 +333,10 @@ enum class VertexAttribType
Fixed = 12, // GLenum == 0x140C
MaxBasicType = 12,
UnsignedInt2101010 = 13, // GLenum == 0x8368
Int2101010 = 14, // GLenum == 0x8D9F
InvalidEnum = 15,
EnumCount = 15,
HalfFloatOES = 14, // GLenum == 0x8D61
Int2101010 = 15, // GLenum == 0x8D9F
InvalidEnum = 16,
EnumCount = 17,
};
template <>
......@@ -346,6 +347,8 @@ constexpr VertexAttribType FromGLenum<VertexAttribType>(GLenum from)
return static_cast<VertexAttribType>(packed);
if (from == GL_UNSIGNED_INT_2_10_10_10_REV)
return VertexAttribType::UnsignedInt2101010;
if (from == GL_HALF_FLOAT_OES)
return VertexAttribType::HalfFloatOES;
if (from == GL_INT_2_10_10_10_REV)
return VertexAttribType::Int2101010;
return VertexAttribType::InvalidEnum;
......@@ -356,6 +359,8 @@ constexpr GLenum ToGLenum(VertexAttribType from)
// This could be optimized using a constexpr table.
if (from == VertexAttribType::Int2101010)
return GL_INT_2_10_10_10_REV;
if (from == VertexAttribType::HalfFloatOES)
return GL_HALF_FLOAT_OES;
if (from == VertexAttribType::UnsignedInt2101010)
return GL_UNSIGNED_INT_2_10_10_10_REV;
return static_cast<GLenum>(from) + GL_BYTE;
......@@ -371,6 +376,7 @@ ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Float, GL_FLOAT);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, HalfFloat, GL_HALF_FLOAT);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Fixed, GL_FIXED);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Int2101010, GL_INT_2_10_10_10_REV);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, HalfFloatOES, GL_HALF_FLOAT_OES);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt2101010, GL_UNSIGNED_INT_2_10_10_10_REV);
std::ostream &operator<<(std::ostream &os, VertexAttribType value);
......
......@@ -9316,6 +9316,10 @@ void StateCache::updateTransformFeedbackActiveUnpaused(Context *context)
void StateCache::updateVertexAttribTypesValidation(Context *context)
{
VertexAttribTypeCase halfFloatValidity = (context->getExtensions().vertexHalfFloat)
? VertexAttribTypeCase::Valid
: VertexAttribTypeCase::Invalid;
if (context->getClientMajorVersion() <= 2)
{
mCachedVertexAttribTypesValidation = {{
......@@ -9325,6 +9329,7 @@ void StateCache::updateVertexAttribTypesValidation(Context *context)
{VertexAttribType::UnsignedShort, VertexAttribTypeCase::Valid},
{VertexAttribType::Float, VertexAttribTypeCase::Valid},
{VertexAttribType::Fixed, VertexAttribTypeCase::Valid},
{VertexAttribType::HalfFloatOES, halfFloatValidity},
}};
}
else
......@@ -9340,6 +9345,7 @@ void StateCache::updateVertexAttribTypesValidation(Context *context)
{VertexAttribType::HalfFloat, VertexAttribTypeCase::Valid},
{VertexAttribType::Fixed, VertexAttribTypeCase::Valid},
{VertexAttribType::Int2101010, VertexAttribTypeCase::ValidSize4Only},
{VertexAttribType::HalfFloatOES, halfFloatValidity},
{VertexAttribType::UnsignedInt2101010, VertexAttribTypeCase::ValidSize4Only},
}};
......
......@@ -1612,6 +1612,7 @@ angle::FormatID GetVertexFormatID(VertexAttribType type,
#endif
}
case VertexAttribType::HalfFloat:
case VertexAttribType::HalfFloatOES:
switch (components)
{
case 1:
......
......@@ -4,6 +4,7 @@
// found in the LICENSE file.
//
#include "anglebase/numerics/safe_conversions.h"
#include "common/mathutil.h"
#include "platform/FeaturesVk.h"
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
......@@ -22,6 +23,8 @@ GLsizei TypeStride(GLenum attribType)
return 1;
case GL_UNSIGNED_SHORT:
case GL_SHORT:
case GL_HALF_FLOAT:
case GL_HALF_FLOAT_OES:
return 2;
case GL_UNSIGNED_INT:
case GL_INT:
......@@ -124,7 +127,9 @@ class VertexAttributeTest : public ANGLETest
glEnableVertexAttribArray(mExpectedAttrib);
}
void checkPixels()
void checkPixels() { checkRGBPixels(true); }
void checkRGBPixels(bool checkAlpha)
{
GLint viewportSize[4];
glGetIntegerv(GL_VIEWPORT, viewportSize);
......@@ -135,10 +140,20 @@ class VertexAttributeTest : public ANGLETest
// We need to offset our checks from triangle edges to ensure we don't fall on a single tri
// Avoid making assumptions of drawQuad with four checks to check the four possible tri
// regions
EXPECT_PIXEL_EQ((midPixelX + viewportSize[0]) / 2, midPixelY, 255, 255, 255, 255);
EXPECT_PIXEL_EQ((midPixelX + viewportSize[2]) / 2, midPixelY, 255, 255, 255, 255);
EXPECT_PIXEL_EQ(midPixelX, (midPixelY + viewportSize[1]) / 2, 255, 255, 255, 255);
EXPECT_PIXEL_EQ(midPixelX, (midPixelY + viewportSize[3]) / 2, 255, 255, 255, 255);
if (checkAlpha)
{
EXPECT_PIXEL_EQ((midPixelX + viewportSize[0]) / 2, midPixelY, 255, 255, 255, 255);
EXPECT_PIXEL_EQ((midPixelX + viewportSize[2]) / 2, midPixelY, 255, 255, 255, 255);
EXPECT_PIXEL_EQ(midPixelX, (midPixelY + viewportSize[1]) / 2, 255, 255, 255, 255);
EXPECT_PIXEL_EQ(midPixelX, (midPixelY + viewportSize[3]) / 2, 255, 255, 255, 255);
}
else
{
EXPECT_PIXEL_RGB_EQUAL((midPixelX + viewportSize[0]) / 2, midPixelY, 255, 255, 255);
EXPECT_PIXEL_RGB_EQUAL((midPixelX + viewportSize[2]) / 2, midPixelY, 255, 255, 255);
EXPECT_PIXEL_RGB_EQUAL(midPixelX, (midPixelY + viewportSize[1]) / 2, 255, 255, 255);
EXPECT_PIXEL_RGB_EQUAL(midPixelX, (midPixelY + viewportSize[3]) / 2, 255, 255, 255);
}
}
void checkPixelsUnEqual()
......@@ -177,7 +192,16 @@ class VertexAttributeTest : public ANGLETest
if (checkPixelEqual)
{
checkPixels();
if ((test.type == GL_HALF_FLOAT || test.type == GL_HALF_FLOAT_OES) && IsVulkan() &&
typeSize == 3)
{ // We need a special case for RGB16F format on a Vulkan backend due to the fact
// that in such a usecase, we need to ignore the alpha channel.
checkRGBPixels(false);
}
else
{
checkPixels();
}
}
else
{
......@@ -420,6 +444,34 @@ TEST_P(VertexAttributeTest, ShortNormalized)
runTest(data);
}
// Verify that vertex data is updated correctly when using a float/half-float client memory pointer.
TEST_P(VertexAttributeTest, HalfFloatClientMemoryPointer)
{
std::array<GLhalf, kVertexCount> inputData;
std::array<GLfloat, kVertexCount> expectedData = {
{0.f, 1.5f, 2.3f, 3.2f, -1.8f, -2.2f, -3.9f, -4.f, 34.5f, 32.2f, -78.8f, -77.4f, -76.1f}};
for (size_t i = 0; i < kVertexCount; i++)
{
inputData[i] = gl::float32ToFloat16(expectedData[i]);
}
// If the extension is enabled run the test on all contexts
if (IsGLExtensionEnabled("GL_OES_vertex_half_float"))
{
TestData imediateData(GL_HALF_FLOAT_OES, GL_FALSE, Source::IMMEDIATE, inputData.data(),
expectedData.data());
runTest(imediateData);
}
// Otherwise run the test only if it is an ES3 context
else if (getClientMajorVersion() >= 3)
{
TestData imediateData(GL_HALF_FLOAT, GL_FALSE, Source::IMMEDIATE, inputData.data(),
expectedData.data());
runTest(imediateData);
}
}
// Verify that using the same client memory pointer in different format won't mess up the draw.
TEST_P(VertexAttributeTest, UsingDifferentFormatAndSameClientMemoryPointer)
{
......
......@@ -223,6 +223,17 @@ GLColor32F ReadColor32F(GLint x, GLint y);
EXPECT_EQ((a), pixel[3]); \
} while (0)
#define EXPECT_PIXEL_RGB_EQ_HELPER(x, y, r, g, b, ctype, format, type) \
do \
{ \
ctype pixel[4]; \
glReadPixels((x), (y), 1, 1, format, type, pixel); \
EXPECT_GL_NO_ERROR(); \
EXPECT_EQ((r), pixel[0]); \
EXPECT_EQ((g), pixel[1]); \
EXPECT_EQ((b), pixel[2]); \
} while (0)
#define EXPECT_PIXEL_NEAR(x, y, r, g, b, a, abs_error) \
EXPECT_PIXEL_NEAR_HELPER(x, y, r, g, b, a, abs_error, GLubyte, GL_RGBA, GL_UNSIGNED_BYTE)
......@@ -235,6 +246,9 @@ GLColor32F ReadColor32F(GLint x, GLint y);
#define EXPECT_PIXEL_8UI(x, y, r, g, b, a) \
EXPECT_PIXEL_EQ_HELPER(x, y, r, g, b, a, GLubyte, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE)
#define EXPECT_PIXEL_RGB_EQUAL(x, y, r, g, b) \
EXPECT_PIXEL_RGB_EQ_HELPER(x, y, r, g, b, GLubyte, GL_RGBA, GL_UNSIGNED_BYTE)
// TODO(jmadill): Figure out how we can use GLColor's nice printing with EXPECT_NEAR.
#define EXPECT_PIXEL_COLOR_NEAR(x, y, angleColor, abs_error) \
EXPECT_PIXEL_NEAR(x, y, angleColor.R, angleColor.G, angleColor.B, angleColor.A, abs_error)
......
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