From 8d742d1375e48638ec210fc18005b5b218170b22 Mon Sep 17 00:00:00 2001 From: Stephen White Date: Sun, 4 Feb 2018 08:49:43 -0500 Subject: [PATCH] Implement unorm_rgba8 and unorm_rg8 vertex formats. Backend support implemented in GL, Metal and D3D12. Support for unorm values in the GL backend requires a utility function to indicate if the format's components are normalized. Note that unorm_r8 is only supported on more recent MacOS SDKs (10.13), so it's omitted for now. --- next.json | 4 +++- src/backend/InputState.cpp | 13 +++++++++++-- src/backend/InputState.h | 1 + src/backend/d3d12/InputStateD3D12.cpp | 4 ++++ src/backend/metal/InputStateMTL.mm | 4 ++++ src/backend/opengl/CommandBufferGL.cpp | 21 ++++++++++++++++++++- src/tests/end2end/InputStateTests.cpp | 2 ++ 7 files changed, 45 insertions(+), 4 deletions(-) diff --git a/next.json b/next.json index 47917ef251..2f1cf9690b 100644 --- a/next.json +++ b/next.json @@ -1222,7 +1222,9 @@ {"value": 0, "name": "float r32 g32 b32 a32"}, {"value": 1, "name": "float r32 g32 b32"}, {"value": 2, "name": "float r32 g32"}, - {"value": 3, "name": "float r32"} + {"value": 3, "name": "float r32"}, + {"value": 4, "name": "unorm r8 g8 b8 a8"}, + {"value": 5, "name": "unorm r8 g8"} ] }, "void": { diff --git a/src/backend/InputState.cpp b/src/backend/InputState.cpp index 7180c90142..4e0b31b34f 100644 --- a/src/backend/InputState.cpp +++ b/src/backend/InputState.cpp @@ -35,10 +35,12 @@ namespace backend { uint32_t VertexFormatNumComponents(nxt::VertexFormat format) { switch (format) { case nxt::VertexFormat::FloatR32G32B32A32: + case nxt::VertexFormat::UnormR8G8B8A8: return 4; case nxt::VertexFormat::FloatR32G32B32: return 3; case nxt::VertexFormat::FloatR32G32: + case nxt::VertexFormat::UnormR8G8: return 2; case nxt::VertexFormat::FloatR32: return 1; @@ -47,18 +49,25 @@ namespace backend { } } - size_t VertexFormatSize(nxt::VertexFormat format) { + size_t VertexFormatComponentSize(nxt::VertexFormat format) { switch (format) { case nxt::VertexFormat::FloatR32G32B32A32: case nxt::VertexFormat::FloatR32G32B32: case nxt::VertexFormat::FloatR32G32: case nxt::VertexFormat::FloatR32: - return VertexFormatNumComponents(format) * sizeof(float); + return sizeof(float); + case nxt::VertexFormat::UnormR8G8B8A8: + case nxt::VertexFormat::UnormR8G8: + return sizeof(uint8_t); default: UNREACHABLE(); } } + size_t VertexFormatSize(nxt::VertexFormat format) { + return VertexFormatNumComponents(format) * VertexFormatComponentSize(format); + } + // InputStateBase InputStateBase::InputStateBase(InputStateBuilder* builder) { diff --git a/src/backend/InputState.h b/src/backend/InputState.h index 7a62b4ffbd..ca69b904ae 100644 --- a/src/backend/InputState.h +++ b/src/backend/InputState.h @@ -29,6 +29,7 @@ namespace backend { size_t IndexFormatSize(nxt::IndexFormat format); uint32_t VertexFormatNumComponents(nxt::VertexFormat format); + size_t VertexFormatComponentSize(nxt::VertexFormat format); size_t VertexFormatSize(nxt::VertexFormat format); class InputStateBase : public RefCounted { diff --git a/src/backend/d3d12/InputStateD3D12.cpp b/src/backend/d3d12/InputStateD3D12.cpp index 4b005fd0af..0d5d9f4c82 100644 --- a/src/backend/d3d12/InputStateD3D12.cpp +++ b/src/backend/d3d12/InputStateD3D12.cpp @@ -28,6 +28,10 @@ namespace backend { namespace d3d12 { return DXGI_FORMAT_R32G32_FLOAT; case nxt::VertexFormat::FloatR32: return DXGI_FORMAT_R32_FLOAT; + case nxt::VertexFormat::UnormR8G8B8A8: + return DXGI_FORMAT_R8G8B8A8_UNORM; + case nxt::VertexFormat::UnormR8G8: + return DXGI_FORMAT_R8G8_UNORM; default: UNREACHABLE(); } diff --git a/src/backend/metal/InputStateMTL.mm b/src/backend/metal/InputStateMTL.mm index 27cf220f00..061903dec2 100644 --- a/src/backend/metal/InputStateMTL.mm +++ b/src/backend/metal/InputStateMTL.mm @@ -30,6 +30,10 @@ namespace backend { namespace metal { return MTLVertexFormatFloat2; case nxt::VertexFormat::FloatR32: return MTLVertexFormatFloat; + case nxt::VertexFormat::UnormR8G8B8A8: + return MTLVertexFormatUChar4Normalized; + case nxt::VertexFormat::UnormR8G8: + return MTLVertexFormatUChar2Normalized; } } diff --git a/src/backend/opengl/CommandBufferGL.cpp b/src/backend/opengl/CommandBufferGL.cpp index 8e879ac83e..5f361d29bd 100644 --- a/src/backend/opengl/CommandBufferGL.cpp +++ b/src/backend/opengl/CommandBufferGL.cpp @@ -49,6 +49,24 @@ namespace backend { namespace opengl { case nxt::VertexFormat::FloatR32G32: case nxt::VertexFormat::FloatR32: return GL_FLOAT; + case nxt::VertexFormat::UnormR8G8B8A8: + case nxt::VertexFormat::UnormR8G8: + return GL_UNSIGNED_BYTE; + default: + UNREACHABLE(); + } + } + + GLboolean VertexFormatIsNormalized(nxt::VertexFormat format) { + switch (format) { + case nxt::VertexFormat::FloatR32G32B32A32: + case nxt::VertexFormat::FloatR32G32B32: + case nxt::VertexFormat::FloatR32G32: + case nxt::VertexFormat::FloatR32: + return GL_FALSE; + case nxt::VertexFormat::UnormR8G8B8A8: + case nxt::VertexFormat::UnormR8G8: + return GL_TRUE; default: UNREACHABLE(); } @@ -184,9 +202,10 @@ namespace backend { namespace opengl { auto components = VertexFormatNumComponents(attribute.format); auto formatType = VertexFormatType(attribute.format); + GLboolean normalized = VertexFormatIsNormalized(attribute.format); glBindBuffer(GL_ARRAY_BUFFER, buffer); glVertexAttribPointer( - location, components, formatType, GL_FALSE, input.stride, + location, components, formatType, normalized, input.stride, reinterpret_cast( static_cast(offset + attribute.offset))); } diff --git a/src/tests/end2end/InputStateTests.cpp b/src/tests/end2end/InputStateTests.cpp index 088e0dd12d..dc5762abed 100644 --- a/src/tests/end2end/InputStateTests.cpp +++ b/src/tests/end2end/InputStateTests.cpp @@ -44,10 +44,12 @@ class InputStateTest : public NXTTest { EXPECT_TRUE(component >= 0 && component < 4); switch (format) { case VertexFormat::FloatR32G32B32A32: + case VertexFormat::UnormR8G8B8A8: return component >= 4; case VertexFormat::FloatR32G32B32: return component >= 3; case VertexFormat::FloatR32G32: + case VertexFormat::UnormR8G8: return component >= 2; case VertexFormat::FloatR32: return component >= 1;