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 ...@@ -333,9 +333,10 @@ enum class VertexAttribType
Fixed = 12, // GLenum == 0x140C Fixed = 12, // GLenum == 0x140C
MaxBasicType = 12, MaxBasicType = 12,
UnsignedInt2101010 = 13, // GLenum == 0x8368 UnsignedInt2101010 = 13, // GLenum == 0x8368
Int2101010 = 14, // GLenum == 0x8D9F HalfFloatOES = 14, // GLenum == 0x8D61
InvalidEnum = 15, Int2101010 = 15, // GLenum == 0x8D9F
EnumCount = 15, InvalidEnum = 16,
EnumCount = 17,
}; };
template <> template <>
...@@ -346,6 +347,8 @@ constexpr VertexAttribType FromGLenum<VertexAttribType>(GLenum from) ...@@ -346,6 +347,8 @@ constexpr VertexAttribType FromGLenum<VertexAttribType>(GLenum from)
return static_cast<VertexAttribType>(packed); return static_cast<VertexAttribType>(packed);
if (from == GL_UNSIGNED_INT_2_10_10_10_REV) if (from == GL_UNSIGNED_INT_2_10_10_10_REV)
return VertexAttribType::UnsignedInt2101010; return VertexAttribType::UnsignedInt2101010;
if (from == GL_HALF_FLOAT_OES)
return VertexAttribType::HalfFloatOES;
if (from == GL_INT_2_10_10_10_REV) if (from == GL_INT_2_10_10_10_REV)
return VertexAttribType::Int2101010; return VertexAttribType::Int2101010;
return VertexAttribType::InvalidEnum; return VertexAttribType::InvalidEnum;
...@@ -356,6 +359,8 @@ constexpr GLenum ToGLenum(VertexAttribType from) ...@@ -356,6 +359,8 @@ constexpr GLenum ToGLenum(VertexAttribType from)
// This could be optimized using a constexpr table. // This could be optimized using a constexpr table.
if (from == VertexAttribType::Int2101010) if (from == VertexAttribType::Int2101010)
return GL_INT_2_10_10_10_REV; return GL_INT_2_10_10_10_REV;
if (from == VertexAttribType::HalfFloatOES)
return GL_HALF_FLOAT_OES;
if (from == VertexAttribType::UnsignedInt2101010) if (from == VertexAttribType::UnsignedInt2101010)
return GL_UNSIGNED_INT_2_10_10_10_REV; return GL_UNSIGNED_INT_2_10_10_10_REV;
return static_cast<GLenum>(from) + GL_BYTE; return static_cast<GLenum>(from) + GL_BYTE;
...@@ -371,6 +376,7 @@ ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Float, GL_FLOAT); ...@@ -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, HalfFloat, GL_HALF_FLOAT);
ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, Fixed, GL_FIXED); 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, 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); ANGLE_VALIDATE_PACKED_ENUM(VertexAttribType, UnsignedInt2101010, GL_UNSIGNED_INT_2_10_10_10_REV);
std::ostream &operator<<(std::ostream &os, VertexAttribType value); std::ostream &operator<<(std::ostream &os, VertexAttribType value);
......
...@@ -9316,6 +9316,10 @@ void StateCache::updateTransformFeedbackActiveUnpaused(Context *context) ...@@ -9316,6 +9316,10 @@ void StateCache::updateTransformFeedbackActiveUnpaused(Context *context)
void StateCache::updateVertexAttribTypesValidation(Context *context) void StateCache::updateVertexAttribTypesValidation(Context *context)
{ {
VertexAttribTypeCase halfFloatValidity = (context->getExtensions().vertexHalfFloat)
? VertexAttribTypeCase::Valid
: VertexAttribTypeCase::Invalid;
if (context->getClientMajorVersion() <= 2) if (context->getClientMajorVersion() <= 2)
{ {
mCachedVertexAttribTypesValidation = {{ mCachedVertexAttribTypesValidation = {{
...@@ -9325,6 +9329,7 @@ void StateCache::updateVertexAttribTypesValidation(Context *context) ...@@ -9325,6 +9329,7 @@ void StateCache::updateVertexAttribTypesValidation(Context *context)
{VertexAttribType::UnsignedShort, VertexAttribTypeCase::Valid}, {VertexAttribType::UnsignedShort, VertexAttribTypeCase::Valid},
{VertexAttribType::Float, VertexAttribTypeCase::Valid}, {VertexAttribType::Float, VertexAttribTypeCase::Valid},
{VertexAttribType::Fixed, VertexAttribTypeCase::Valid}, {VertexAttribType::Fixed, VertexAttribTypeCase::Valid},
{VertexAttribType::HalfFloatOES, halfFloatValidity},
}}; }};
} }
else else
...@@ -9340,6 +9345,7 @@ void StateCache::updateVertexAttribTypesValidation(Context *context) ...@@ -9340,6 +9345,7 @@ void StateCache::updateVertexAttribTypesValidation(Context *context)
{VertexAttribType::HalfFloat, VertexAttribTypeCase::Valid}, {VertexAttribType::HalfFloat, VertexAttribTypeCase::Valid},
{VertexAttribType::Fixed, VertexAttribTypeCase::Valid}, {VertexAttribType::Fixed, VertexAttribTypeCase::Valid},
{VertexAttribType::Int2101010, VertexAttribTypeCase::ValidSize4Only}, {VertexAttribType::Int2101010, VertexAttribTypeCase::ValidSize4Only},
{VertexAttribType::HalfFloatOES, halfFloatValidity},
{VertexAttribType::UnsignedInt2101010, VertexAttribTypeCase::ValidSize4Only}, {VertexAttribType::UnsignedInt2101010, VertexAttribTypeCase::ValidSize4Only},
}}; }};
......
...@@ -1612,6 +1612,7 @@ angle::FormatID GetVertexFormatID(VertexAttribType type, ...@@ -1612,6 +1612,7 @@ angle::FormatID GetVertexFormatID(VertexAttribType type,
#endif #endif
} }
case VertexAttribType::HalfFloat: case VertexAttribType::HalfFloat:
case VertexAttribType::HalfFloatOES:
switch (components) switch (components)
{ {
case 1: case 1:
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
// found in the LICENSE file. // found in the LICENSE file.
// //
#include "anglebase/numerics/safe_conversions.h" #include "anglebase/numerics/safe_conversions.h"
#include "common/mathutil.h"
#include "platform/FeaturesVk.h" #include "platform/FeaturesVk.h"
#include "test_utils/ANGLETest.h" #include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h" #include "test_utils/gl_raii.h"
...@@ -22,6 +23,8 @@ GLsizei TypeStride(GLenum attribType) ...@@ -22,6 +23,8 @@ GLsizei TypeStride(GLenum attribType)
return 1; return 1;
case GL_UNSIGNED_SHORT: case GL_UNSIGNED_SHORT:
case GL_SHORT: case GL_SHORT:
case GL_HALF_FLOAT:
case GL_HALF_FLOAT_OES:
return 2; return 2;
case GL_UNSIGNED_INT: case GL_UNSIGNED_INT:
case GL_INT: case GL_INT:
...@@ -124,7 +127,9 @@ class VertexAttributeTest : public ANGLETest ...@@ -124,7 +127,9 @@ class VertexAttributeTest : public ANGLETest
glEnableVertexAttribArray(mExpectedAttrib); glEnableVertexAttribArray(mExpectedAttrib);
} }
void checkPixels() void checkPixels() { checkRGBPixels(true); }
void checkRGBPixels(bool checkAlpha)
{ {
GLint viewportSize[4]; GLint viewportSize[4];
glGetIntegerv(GL_VIEWPORT, viewportSize); glGetIntegerv(GL_VIEWPORT, viewportSize);
...@@ -135,10 +140,20 @@ class VertexAttributeTest : public ANGLETest ...@@ -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 // 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 // Avoid making assumptions of drawQuad with four checks to check the four possible tri
// regions // regions
EXPECT_PIXEL_EQ((midPixelX + viewportSize[0]) / 2, midPixelY, 255, 255, 255, 255); if (checkAlpha)
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 + viewportSize[0]) / 2, midPixelY, 255, 255, 255, 255);
EXPECT_PIXEL_EQ(midPixelX, (midPixelY + viewportSize[3]) / 2, 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() void checkPixelsUnEqual()
...@@ -177,7 +192,16 @@ class VertexAttributeTest : public ANGLETest ...@@ -177,7 +192,16 @@ class VertexAttributeTest : public ANGLETest
if (checkPixelEqual) 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 else
{ {
...@@ -420,6 +444,34 @@ TEST_P(VertexAttributeTest, ShortNormalized) ...@@ -420,6 +444,34 @@ TEST_P(VertexAttributeTest, ShortNormalized)
runTest(data); 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. // Verify that using the same client memory pointer in different format won't mess up the draw.
TEST_P(VertexAttributeTest, UsingDifferentFormatAndSameClientMemoryPointer) TEST_P(VertexAttributeTest, UsingDifferentFormatAndSameClientMemoryPointer)
{ {
......
...@@ -223,6 +223,17 @@ GLColor32F ReadColor32F(GLint x, GLint y); ...@@ -223,6 +223,17 @@ GLColor32F ReadColor32F(GLint x, GLint y);
EXPECT_EQ((a), pixel[3]); \ EXPECT_EQ((a), pixel[3]); \
} while (0) } 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) \ #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) 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); ...@@ -235,6 +246,9 @@ GLColor32F ReadColor32F(GLint x, GLint y);
#define EXPECT_PIXEL_8UI(x, y, r, g, b, a) \ #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) 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. // 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) \ #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) 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