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.
This commit is contained in:
Stephen White 2018-02-04 08:49:43 -05:00 committed by Corentin Wallez
parent 33dfd0a78f
commit 8d742d1375
7 changed files with 45 additions and 4 deletions

View File

@ -1222,7 +1222,9 @@
{"value": 0, "name": "float r32 g32 b32 a32"}, {"value": 0, "name": "float r32 g32 b32 a32"},
{"value": 1, "name": "float r32 g32 b32"}, {"value": 1, "name": "float r32 g32 b32"},
{"value": 2, "name": "float r32 g32"}, {"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": { "void": {

View File

@ -35,10 +35,12 @@ namespace backend {
uint32_t VertexFormatNumComponents(nxt::VertexFormat format) { uint32_t VertexFormatNumComponents(nxt::VertexFormat format) {
switch (format) { switch (format) {
case nxt::VertexFormat::FloatR32G32B32A32: case nxt::VertexFormat::FloatR32G32B32A32:
case nxt::VertexFormat::UnormR8G8B8A8:
return 4; return 4;
case nxt::VertexFormat::FloatR32G32B32: case nxt::VertexFormat::FloatR32G32B32:
return 3; return 3;
case nxt::VertexFormat::FloatR32G32: case nxt::VertexFormat::FloatR32G32:
case nxt::VertexFormat::UnormR8G8:
return 2; return 2;
case nxt::VertexFormat::FloatR32: case nxt::VertexFormat::FloatR32:
return 1; return 1;
@ -47,18 +49,25 @@ namespace backend {
} }
} }
size_t VertexFormatSize(nxt::VertexFormat format) { size_t VertexFormatComponentSize(nxt::VertexFormat format) {
switch (format) { switch (format) {
case nxt::VertexFormat::FloatR32G32B32A32: case nxt::VertexFormat::FloatR32G32B32A32:
case nxt::VertexFormat::FloatR32G32B32: case nxt::VertexFormat::FloatR32G32B32:
case nxt::VertexFormat::FloatR32G32: case nxt::VertexFormat::FloatR32G32:
case nxt::VertexFormat::FloatR32: 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: default:
UNREACHABLE(); UNREACHABLE();
} }
} }
size_t VertexFormatSize(nxt::VertexFormat format) {
return VertexFormatNumComponents(format) * VertexFormatComponentSize(format);
}
// InputStateBase // InputStateBase
InputStateBase::InputStateBase(InputStateBuilder* builder) { InputStateBase::InputStateBase(InputStateBuilder* builder) {

View File

@ -29,6 +29,7 @@ namespace backend {
size_t IndexFormatSize(nxt::IndexFormat format); size_t IndexFormatSize(nxt::IndexFormat format);
uint32_t VertexFormatNumComponents(nxt::VertexFormat format); uint32_t VertexFormatNumComponents(nxt::VertexFormat format);
size_t VertexFormatComponentSize(nxt::VertexFormat format);
size_t VertexFormatSize(nxt::VertexFormat format); size_t VertexFormatSize(nxt::VertexFormat format);
class InputStateBase : public RefCounted { class InputStateBase : public RefCounted {

View File

@ -28,6 +28,10 @@ namespace backend { namespace d3d12 {
return DXGI_FORMAT_R32G32_FLOAT; return DXGI_FORMAT_R32G32_FLOAT;
case nxt::VertexFormat::FloatR32: case nxt::VertexFormat::FloatR32:
return DXGI_FORMAT_R32_FLOAT; return DXGI_FORMAT_R32_FLOAT;
case nxt::VertexFormat::UnormR8G8B8A8:
return DXGI_FORMAT_R8G8B8A8_UNORM;
case nxt::VertexFormat::UnormR8G8:
return DXGI_FORMAT_R8G8_UNORM;
default: default:
UNREACHABLE(); UNREACHABLE();
} }

View File

@ -30,6 +30,10 @@ namespace backend { namespace metal {
return MTLVertexFormatFloat2; return MTLVertexFormatFloat2;
case nxt::VertexFormat::FloatR32: case nxt::VertexFormat::FloatR32:
return MTLVertexFormatFloat; return MTLVertexFormatFloat;
case nxt::VertexFormat::UnormR8G8B8A8:
return MTLVertexFormatUChar4Normalized;
case nxt::VertexFormat::UnormR8G8:
return MTLVertexFormatUChar2Normalized;
} }
} }

View File

@ -49,6 +49,24 @@ namespace backend { namespace opengl {
case nxt::VertexFormat::FloatR32G32: case nxt::VertexFormat::FloatR32G32:
case nxt::VertexFormat::FloatR32: case nxt::VertexFormat::FloatR32:
return GL_FLOAT; 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: default:
UNREACHABLE(); UNREACHABLE();
} }
@ -184,9 +202,10 @@ namespace backend { namespace opengl {
auto components = VertexFormatNumComponents(attribute.format); auto components = VertexFormatNumComponents(attribute.format);
auto formatType = VertexFormatType(attribute.format); auto formatType = VertexFormatType(attribute.format);
GLboolean normalized = VertexFormatIsNormalized(attribute.format);
glBindBuffer(GL_ARRAY_BUFFER, buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer);
glVertexAttribPointer( glVertexAttribPointer(
location, components, formatType, GL_FALSE, input.stride, location, components, formatType, normalized, input.stride,
reinterpret_cast<void*>( reinterpret_cast<void*>(
static_cast<intptr_t>(offset + attribute.offset))); static_cast<intptr_t>(offset + attribute.offset)));
} }

View File

@ -44,10 +44,12 @@ class InputStateTest : public NXTTest {
EXPECT_TRUE(component >= 0 && component < 4); EXPECT_TRUE(component >= 0 && component < 4);
switch (format) { switch (format) {
case VertexFormat::FloatR32G32B32A32: case VertexFormat::FloatR32G32B32A32:
case VertexFormat::UnormR8G8B8A8:
return component >= 4; return component >= 4;
case VertexFormat::FloatR32G32B32: case VertexFormat::FloatR32G32B32:
return component >= 3; return component >= 3;
case VertexFormat::FloatR32G32: case VertexFormat::FloatR32G32:
case VertexFormat::UnormR8G8:
return component >= 2; return component >= 2;
case VertexFormat::FloatR32: case VertexFormat::FloatR32:
return component >= 1; return component >= 1;