blob: a6779f06e9969fc5c336d02fa896591edeb0c6ea [file] [log] [blame]
// Copyright 2019 The Amber Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/type_parser.h"
#include <cassert>
#include <cstdlib>
#include <string>
#include "src/make_unique.h"
namespace amber {
TypeParser::TypeParser() = default;
TypeParser::~TypeParser() = default;
std::unique_ptr<type::Type> TypeParser::Parse(const std::string& data) {
if (data.empty())
return nullptr;
// See if this is a custom glsl string format.
if (data.find('/', 0) != std::string::npos)
return ParseGlslFormat(data);
// Walk the string backwards. This means we'll know if it's pack and we'll
// know the mode before we get to a given named component.
size_t cur_pos = std::string::npos;
for (;;) {
size_t next_pos = data.rfind('_', cur_pos);
if (next_pos == std::string::npos) {
if (cur_pos != std::string::npos)
ProcessChunk(data.substr(0, cur_pos + 1));
break;
}
ProcessChunk(data.substr(next_pos + 1, cur_pos - next_pos));
cur_pos = next_pos - 1;
}
if (pieces_.empty())
return nullptr;
std::unique_ptr<type::Type> type = nullptr;
if (pack_size_ == 0 && pieces_.size() == 1 &&
pieces_[0].type == FormatComponentType::kR) {
type = MakeUnique<type::Number>(pieces_[0].mode, pieces_[0].num_bits);
} else {
type = MakeUnique<type::List>();
type->SetRowCount(static_cast<uint32_t>(pieces_.size()));
type->AsList()->SetPackSizeInBits(pack_size_);
for (const auto& piece : pieces_)
type->AsList()->AddMember(piece.type, piece.mode, piece.num_bits);
}
pack_size_ = 0;
mode_ = FormatMode::kSInt;
pieces_.clear();
return type;
}
void TypeParser::AddPiece(FormatComponentType type,
FormatMode mode,
uint8_t bits) {
pieces_.insert(pieces_.begin(), Pieces{type, mode, bits});
}
void TypeParser::ProcessChunk(const std::string& data) {
assert(data.size() > 0);
if (data[0] == 'P') {
if (data == "PACK8")
pack_size_ = 8;
else if (data == "PACK16")
pack_size_ = 16;
else if (data == "PACK32")
pack_size_ = 32;
else
assert(false);
return;
}
if (data[0] == 'U') {
if (data == "UINT")
mode_ = FormatMode::kUInt;
else if (data == "UNORM")
mode_ = FormatMode::kUNorm;
else if (data == "UFLOAT")
mode_ = FormatMode::kUFloat;
else if (data == "USCALED")
mode_ = FormatMode::kUScaled;
else
assert(false);
return;
}
if (data[0] == 'S') {
if (data == "SINT")
mode_ = FormatMode::kSInt;
else if (data == "SNORM")
mode_ = FormatMode::kSNorm;
else if (data == "SSCALED")
mode_ = FormatMode::kSScaled;
else if (data == "SFLOAT")
mode_ = FormatMode::kSFloat;
else if (data == "SRGB")
mode_ = FormatMode::kSRGB;
else if (data == "S8")
AddPiece(FormatComponentType::kS, mode_, 8);
else
assert(false);
return;
}
int32_t cur_pos = static_cast<int32_t>(data.size()) - 1;
for (;;) {
FormatComponentType type = FormatComponentType::kA;
while (cur_pos >= 0) {
if (data[static_cast<size_t>(cur_pos)] == 'X') {
type = FormatComponentType::kX;
break;
} else if (data[static_cast<size_t>(cur_pos)] == 'D') {
type = FormatComponentType::kD;
break;
} else if (data[static_cast<size_t>(cur_pos)] == 'R') {
type = FormatComponentType::kR;
break;
} else if (data[static_cast<size_t>(cur_pos)] == 'G') {
type = FormatComponentType::kG;
break;
} else if (data[static_cast<size_t>(cur_pos)] == 'B') {
type = FormatComponentType::kB;
break;
} else if (data[static_cast<size_t>(cur_pos)] == 'A') {
type = FormatComponentType::kA;
break;
}
--cur_pos;
}
assert(cur_pos >= 0);
char* next_str;
const char* str = data.c_str() + cur_pos + 1;
uint64_t val = static_cast<uint64_t>(std::strtol(str, &next_str, 10));
if (val > 0)
AddPiece(type, mode_, static_cast<uint8_t>(val));
if (cur_pos == 0)
break;
--cur_pos;
}
}
// static
FormatType TypeParser::NameToFormatType(const std::string& data) {
if (data == "A1R5G5B5_UNORM_PACK16")
return FormatType::kA1R5G5B5_UNORM_PACK16;
if (data == "A2B10G10R10_SINT_PACK32")
return FormatType::kA2B10G10R10_SINT_PACK32;
if (data == "A2B10G10R10_SNORM_PACK32")
return FormatType::kA2B10G10R10_SNORM_PACK32;
if (data == "A2B10G10R10_SSCALED_PACK32")
return FormatType::kA2B10G10R10_SSCALED_PACK32;
if (data == "A2B10G10R10_UINT_PACK32")
return FormatType::kA2B10G10R10_UINT_PACK32;
if (data == "A2B10G10R10_UNORM_PACK32")
return FormatType::kA2B10G10R10_UNORM_PACK32;
if (data == "A2B10G10R10_USCALED_PACK32")
return FormatType::kA2B10G10R10_USCALED_PACK32;
if (data == "A2R10G10B10_SINT_PACK32")
return FormatType::kA2R10G10B10_SINT_PACK32;
if (data == "A2R10G10B10_SNORM_PACK32")
return FormatType::kA2R10G10B10_SNORM_PACK32;
if (data == "A2R10G10B10_SSCALED_PACK32")
return FormatType::kA2R10G10B10_SSCALED_PACK32;
if (data == "A2R10G10B10_UINT_PACK32")
return FormatType::kA2R10G10B10_UINT_PACK32;
if (data == "A2R10G10B10_UNORM_PACK32")
return FormatType::kA2R10G10B10_UNORM_PACK32;
if (data == "A2R10G10B10_USCALED_PACK32")
return FormatType::kA2R10G10B10_USCALED_PACK32;
if (data == "A8B8G8R8_SINT_PACK32")
return FormatType::kA8B8G8R8_SINT_PACK32;
if (data == "A8B8G8R8_SNORM_PACK32")
return FormatType::kA8B8G8R8_SNORM_PACK32;
if (data == "A8B8G8R8_SRGB_PACK32")
return FormatType::kA8B8G8R8_SRGB_PACK32;
if (data == "A8B8G8R8_SSCALED_PACK32")
return FormatType::kA8B8G8R8_SSCALED_PACK32;
if (data == "A8B8G8R8_UINT_PACK32")
return FormatType::kA8B8G8R8_UINT_PACK32;
if (data == "A8B8G8R8_UNORM_PACK32")
return FormatType::kA8B8G8R8_UNORM_PACK32;
if (data == "A8B8G8R8_USCALED_PACK32")
return FormatType::kA8B8G8R8_USCALED_PACK32;
if (data == "B10G11R11_UFLOAT_PACK32")
return FormatType::kB10G11R11_UFLOAT_PACK32;
if (data == "B4G4R4A4_UNORM_PACK16")
return FormatType::kB4G4R4A4_UNORM_PACK16;
if (data == "B5G5R5A1_UNORM_PACK16")
return FormatType::kB5G5R5A1_UNORM_PACK16;
if (data == "B5G6R5_UNORM_PACK16")
return FormatType::kB5G6R5_UNORM_PACK16;
if (data == "B8G8R8A8_SINT")
return FormatType::kB8G8R8A8_SINT;
if (data == "B8G8R8A8_SNORM")
return FormatType::kB8G8R8A8_SNORM;
if (data == "B8G8R8A8_SRGB")
return FormatType::kB8G8R8A8_SRGB;
if (data == "B8G8R8A8_SSCALED")
return FormatType::kB8G8R8A8_SSCALED;
if (data == "B8G8R8A8_UINT")
return FormatType::kB8G8R8A8_UINT;
if (data == "B8G8R8A8_UNORM")
return FormatType::kB8G8R8A8_UNORM;
if (data == "B8G8R8A8_USCALED")
return FormatType::kB8G8R8A8_USCALED;
if (data == "B8G8R8_SINT")
return FormatType::kB8G8R8_SINT;
if (data == "B8G8R8_SNORM")
return FormatType::kB8G8R8_SNORM;
if (data == "B8G8R8_SRGB")
return FormatType::kB8G8R8_SRGB;
if (data == "B8G8R8_SSCALED")
return FormatType::kB8G8R8_SSCALED;
if (data == "B8G8R8_UINT")
return FormatType::kB8G8R8_UINT;
if (data == "B8G8R8_UNORM")
return FormatType::kB8G8R8_UNORM;
if (data == "B8G8R8_USCALED")
return FormatType::kB8G8R8_USCALED;
if (data == "D16_UNORM")
return FormatType::kD16_UNORM;
if (data == "D16_UNORM_S8_UINT")
return FormatType::kD16_UNORM_S8_UINT;
if (data == "D24_UNORM_S8_UINT")
return FormatType::kD24_UNORM_S8_UINT;
if (data == "D32_SFLOAT")
return FormatType::kD32_SFLOAT;
if (data == "D32_SFLOAT_S8_UINT")
return FormatType::kD32_SFLOAT_S8_UINT;
if (data == "R16G16B16A16_SFLOAT")
return FormatType::kR16G16B16A16_SFLOAT;
if (data == "R16G16B16A16_SINT")
return FormatType::kR16G16B16A16_SINT;
if (data == "R16G16B16A16_SNORM")
return FormatType::kR16G16B16A16_SNORM;
if (data == "R16G16B16A16_SSCALED")
return FormatType::kR16G16B16A16_SSCALED;
if (data == "R16G16B16A16_UINT")
return FormatType::kR16G16B16A16_UINT;
if (data == "R16G16B16A16_UNORM")
return FormatType::kR16G16B16A16_UNORM;
if (data == "R16G16B16A16_USCALED")
return FormatType::kR16G16B16A16_USCALED;
if (data == "R16G16B16_SFLOAT")
return FormatType::kR16G16B16_SFLOAT;
if (data == "R16G16B16_SINT")
return FormatType::kR16G16B16_SINT;
if (data == "R16G16B16_SNORM")
return FormatType::kR16G16B16_SNORM;
if (data == "R16G16B16_SSCALED")
return FormatType::kR16G16B16_SSCALED;
if (data == "R16G16B16_UINT")
return FormatType::kR16G16B16_UINT;
if (data == "R16G16B16_UNORM")
return FormatType::kR16G16B16_UNORM;
if (data == "R16G16B16_USCALED")
return FormatType::kR16G16B16_USCALED;
if (data == "R16G16_SFLOAT")
return FormatType::kR16G16_SFLOAT;
if (data == "R16G16_SINT")
return FormatType::kR16G16_SINT;
if (data == "R16G16_SNORM")
return FormatType::kR16G16_SNORM;
if (data == "R16G16_SSCALED")
return FormatType::kR16G16_SSCALED;
if (data == "R16G16_UINT")
return FormatType::kR16G16_UINT;
if (data == "R16G16_UNORM")
return FormatType::kR16G16_UNORM;
if (data == "R16G16_USCALED")
return FormatType::kR16G16_USCALED;
if (data == "R16_SFLOAT")
return FormatType::kR16_SFLOAT;
if (data == "R16_SINT")
return FormatType::kR16_SINT;
if (data == "R16_SNORM")
return FormatType::kR16_SNORM;
if (data == "R16_SSCALED")
return FormatType::kR16_SSCALED;
if (data == "R16_UINT")
return FormatType::kR16_UINT;
if (data == "R16_UNORM")
return FormatType::kR16_UNORM;
if (data == "R16_USCALED")
return FormatType::kR16_USCALED;
if (data == "R32G32B32A32_SFLOAT")
return FormatType::kR32G32B32A32_SFLOAT;
if (data == "R32G32B32A32_SINT")
return FormatType::kR32G32B32A32_SINT;
if (data == "R32G32B32A32_UINT")
return FormatType::kR32G32B32A32_UINT;
if (data == "R32G32B32_SFLOAT")
return FormatType::kR32G32B32_SFLOAT;
if (data == "R32G32B32_SINT")
return FormatType::kR32G32B32_SINT;
if (data == "R32G32B32_UINT")
return FormatType::kR32G32B32_UINT;
if (data == "R32G32_SFLOAT")
return FormatType::kR32G32_SFLOAT;
if (data == "R32G32_SINT")
return FormatType::kR32G32_SINT;
if (data == "R32G32_UINT")
return FormatType::kR32G32_UINT;
if (data == "R32_SFLOAT")
return FormatType::kR32_SFLOAT;
if (data == "R32_SINT")
return FormatType::kR32_SINT;
if (data == "R32_UINT")
return FormatType::kR32_UINT;
if (data == "R4G4B4A4_UNORM_PACK16")
return FormatType::kR4G4B4A4_UNORM_PACK16;
if (data == "R4G4_UNORM_PACK8")
return FormatType::kR4G4_UNORM_PACK8;
if (data == "R5G5B5A1_UNORM_PACK16")
return FormatType::kR5G5B5A1_UNORM_PACK16;
if (data == "R5G6B5_UNORM_PACK16")
return FormatType::kR5G6B5_UNORM_PACK16;
if (data == "R64G64B64A64_SFLOAT")
return FormatType::kR64G64B64A64_SFLOAT;
if (data == "R64G64B64A64_SINT")
return FormatType::kR64G64B64A64_SINT;
if (data == "R64G64B64A64_UINT")
return FormatType::kR64G64B64A64_UINT;
if (data == "R64G64B64_SFLOAT")
return FormatType::kR64G64B64_SFLOAT;
if (data == "R64G64B64_SINT")
return FormatType::kR64G64B64_SINT;
if (data == "R64G64B64_UINT")
return FormatType::kR64G64B64_UINT;
if (data == "R64G64_SFLOAT")
return FormatType::kR64G64_SFLOAT;
if (data == "R64G64_SINT")
return FormatType::kR64G64_SINT;
if (data == "R64G64_UINT")
return FormatType::kR64G64_UINT;
if (data == "R64_SFLOAT")
return FormatType::kR64_SFLOAT;
if (data == "R64_SINT")
return FormatType::kR64_SINT;
if (data == "R64_UINT")
return FormatType::kR64_UINT;
if (data == "R8G8B8A8_SINT")
return FormatType::kR8G8B8A8_SINT;
if (data == "R8G8B8A8_SNORM")
return FormatType::kR8G8B8A8_SNORM;
if (data == "R8G8B8A8_SRGB")
return FormatType::kR8G8B8A8_SRGB;
if (data == "R8G8B8A8_SSCALED")
return FormatType::kR8G8B8A8_SSCALED;
if (data == "R8G8B8A8_UINT")
return FormatType::kR8G8B8A8_UINT;
if (data == "R8G8B8A8_UNORM")
return FormatType::kR8G8B8A8_UNORM;
if (data == "R8G8B8A8_USCALED")
return FormatType::kR8G8B8A8_USCALED;
if (data == "R8G8B8_SINT")
return FormatType::kR8G8B8_SINT;
if (data == "R8G8B8_SNORM")
return FormatType::kR8G8B8_SNORM;
if (data == "R8G8B8_SRGB")
return FormatType::kR8G8B8_SRGB;
if (data == "R8G8B8_SSCALED")
return FormatType::kR8G8B8_SSCALED;
if (data == "R8G8B8_UINT")
return FormatType::kR8G8B8_UINT;
if (data == "R8G8B8_UNORM")
return FormatType::kR8G8B8_UNORM;
if (data == "R8G8B8_USCALED")
return FormatType::kR8G8B8_USCALED;
if (data == "R8G8_SINT")
return FormatType::kR8G8_SINT;
if (data == "R8G8_SNORM")
return FormatType::kR8G8_SNORM;
if (data == "R8G8_SRGB")
return FormatType::kR8G8_SRGB;
if (data == "R8G8_SSCALED")
return FormatType::kR8G8_SSCALED;
if (data == "R8G8_UINT")
return FormatType::kR8G8_UINT;
if (data == "R8G8_UNORM")
return FormatType::kR8G8_UNORM;
if (data == "R8G8_USCALED")
return FormatType::kR8G8_USCALED;
if (data == "R8_SINT")
return FormatType::kR8_SINT;
if (data == "R8_SNORM")
return FormatType::kR8_SNORM;
if (data == "R8_SRGB")
return FormatType::kR8_SRGB;
if (data == "R8_SSCALED")
return FormatType::kR8_SSCALED;
if (data == "R8_UINT")
return FormatType::kR8_UINT;
if (data == "R8_UNORM")
return FormatType::kR8_UNORM;
if (data == "R8_USCALED")
return FormatType::kR8_USCALED;
if (data == "S8_UINT")
return FormatType::kS8_UINT;
if (data == "X8_D24_UNORM_PACK32")
return FormatType::kX8_D24_UNORM_PACK32;
return FormatType::kUnknown;
}
std::unique_ptr<type::Type> TypeParser::ParseGlslFormat(
const std::string& fmt) {
size_t pos = fmt.find('/');
std::string gl_type = fmt.substr(0, pos);
std::string glsl_type = fmt.substr(pos + 1);
uint8_t bits = 0;
FormatMode mode = FormatMode::kUNorm;
static const struct {
const char* name;
uint8_t bits;
bool is_signed;
bool is_int;
} types[] = {
{"byte", 8, true, true}, {"ubyte", 8, false, true},
{"short", 16, true, true}, {"ushort", 16, false, true},
{"int", 32, true, true}, {"uint", 32, false, true},
{"half", 16, true, false}, {"float", 32, true, false},
{"double", 64, true, false},
};
for (auto& type : types) {
if (gl_type == std::string(type.name)) {
if (type.is_int)
mode = type.is_signed ? FormatMode::kSInt : FormatMode::kUInt;
else
mode = FormatMode::kSFloat;
bits = type.bits;
}
}
// Failed to find gl type.
if (mode == FormatMode::kUNorm)
return nullptr;
if (fmt.length() < 4)
return nullptr;
int8_t num_components = 0;
if (glsl_type == "float" || glsl_type == "double" || glsl_type == "int" ||
glsl_type == "uint") {
num_components = 1;
} else if (glsl_type.substr(0, 3) == "vec") {
num_components =
static_cast<int8_t>(strtol(glsl_type.c_str() + 3, nullptr, 10));
if (num_components < 2)
return nullptr;
} else if ((glsl_type[0] == 'd' || glsl_type[0] == 'i' ||
glsl_type[0] == 'u') &&
glsl_type.substr(1, 3) == "vec") {
num_components =
static_cast<int8_t>(strtol(glsl_type.c_str() + 4, nullptr, 10));
if (num_components < 2)
return nullptr;
}
if (num_components > 4)
return nullptr;
std::string new_name = "";
static const char* prefix = "RGBA";
for (int8_t i = 0; i < num_components; ++i)
new_name += prefix[i] + std::to_string(bits);
new_name += "_";
if (mode == FormatMode::kSInt)
new_name += "SINT";
else if (mode == FormatMode::kUInt)
new_name += "UINT";
else if (mode == FormatMode::kSFloat)
new_name += "SFLOAT";
return Parse(new_name);
}
} // namespace amber