Fix more bugs with VertexDataLayout driven buffer parsing and generation.
Bump to C++23 standard.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required (VERSION 3.16)
|
cmake_minimum_required (VERSION 3.16)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
|||||||
@@ -120,9 +120,21 @@ using std::multimap;
|
|||||||
using std::stack;
|
using std::stack;
|
||||||
using std::queue;
|
using std::queue;
|
||||||
|
|
||||||
|
#if defined(__x86_64__) || defined(_M_X64)
|
||||||
|
|
||||||
|
#include <immintrin.h>
|
||||||
|
#define KRAKEN_ARCH_X86_64 1
|
||||||
|
|
||||||
|
#elif defined(__aarch64__) || defined(_M_ARM64)
|
||||||
|
|
||||||
|
#include <arm_neon.h>
|
||||||
|
#define KRAKEN_ARCH_ARM64
|
||||||
|
#define KRAKEN_USE_ARM_NEON
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static_assert(false, "CPU Architecture not implemented.");
|
||||||
|
|
||||||
#if !defined(__i386__) && defined(__arm__)
|
|
||||||
#define KRAKEN_USE_ARM_NEON
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -117,13 +117,15 @@ KRPipeline::KRPipeline(KRContext& context, KrDeviceHandle deviceHandle, const KR
|
|||||||
const char* attribBaseName = VertexAttributeNames[(int)attrib.attribute];
|
const char* attribBaseName = VertexAttributeNames[(int)attrib.attribute];
|
||||||
int len = strlen(input_var.name);
|
int len = strlen(input_var.name);
|
||||||
int baseNameLen = strlen(attribBaseName);
|
int baseNameLen = strlen(attribBaseName);
|
||||||
if (len == baseNameLen) {
|
if (strncmp(attribBaseName, input_var.name, baseNameLen) != 0) {
|
||||||
if (strcmp(attribBaseName, input_var.name) == 0) {
|
continue;
|
||||||
attribute_locations[i] = input_var.location;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (len == baseNameLen) {
|
||||||
|
attribute_locations[i] = input_var.location;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (len + 1 != baseNameLen) {
|
if (len != baseNameLen + 1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
char lastChar = input_var.name[len - 1];
|
char lastChar = input_var.name[len - 1];
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ KRCamera::KRCamera(KRScene& scene, std::string name)
|
|||||||
m_debug_text_vbo_layout.offsets[0] = offsetof(DebugTextVertexData, x);
|
m_debug_text_vbo_layout.offsets[0] = offsetof(DebugTextVertexData, x);
|
||||||
m_debug_text_vbo_layout.offsets[1] = offsetof(DebugTextVertexData, u);
|
m_debug_text_vbo_layout.offsets[1] = offsetof(DebugTextVertexData, u);
|
||||||
m_debug_text_vbo_layout.attributes[0] = { ComponentType::float32, DataType::vec3, Normalization::none, VertexAttribute::position };
|
m_debug_text_vbo_layout.attributes[0] = { ComponentType::float32, DataType::vec3, Normalization::none, VertexAttribute::position };
|
||||||
m_debug_text_vbo_layout.attributes[1] = { ComponentType::float32, DataType::vec2, Normalization::none, VertexAttribute::texcoord };
|
m_debug_text_vbo_layout.attributes[1] = { ComponentType::float16, DataType::vec2, Normalization::none, VertexAttribute::texcoord };
|
||||||
|
|
||||||
m_debug_text_vbo_data.init(m_pContext->getMeshManager(), &m_debug_text_vertices, nullptr, &m_debug_text_vbo_layout, true, KRMeshManager::KRVBOData::IMMEDIATE
|
m_debug_text_vbo_data.init(m_pContext->getMeshManager(), &m_debug_text_vertices, nullptr, &m_debug_text_vbo_layout, true, KRMeshManager::KRVBOData::IMMEDIATE
|
||||||
#if KRENGINE_DEBUG_GPU_LABELS
|
#if KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
|||||||
@@ -115,8 +115,8 @@ private:
|
|||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
float z;
|
float z;
|
||||||
float u;
|
short u;
|
||||||
float v;
|
short v;
|
||||||
} DebugTextVertexData;
|
} DebugTextVertexData;
|
||||||
|
|
||||||
mimir::Block m_debug_text_vertices;
|
mimir::Block m_debug_text_vertices;
|
||||||
|
|||||||
@@ -490,11 +490,7 @@ void KRMesh::renderSubmesh(VkCommandBuffer& commandBuffer, int iSubmesh, const K
|
|||||||
} else {
|
} else {
|
||||||
assert(iVertex + cVertexes <= cBufferVertexes);
|
assert(iVertex + cVertexes <= cBufferVertexes);
|
||||||
|
|
||||||
if (getIndexCount(0) == 0) {
|
|
||||||
vkCmdDraw(commandBuffer, cVertexes, 1, iVertex, 0);
|
vkCmdDraw(commandBuffer, cVertexes, 1, iVertex, 0);
|
||||||
} else {
|
|
||||||
vkCmdDrawIndexed(commandBuffer, cVertexes, 1, iVertex, 0, 0);
|
|
||||||
}
|
|
||||||
m_pContext->getMeshManager()->log_draw_call(renderPass->getType(), object_name, material_name, cVertexes);
|
m_pContext->getMeshManager()->log_draw_call(renderPass->getType(), object_name, material_name, cVertexes);
|
||||||
|
|
||||||
cVertexes = 0;
|
cVertexes = 0;
|
||||||
@@ -510,24 +506,17 @@ void KRMesh::LoadData(const KRMesh::mesh_info& mi, bool calculate_normals, bool
|
|||||||
releaseData();
|
releaseData();
|
||||||
|
|
||||||
// TODO, FINDME - These values should be passed as a parameter and set by GUI flags
|
// TODO, FINDME - These values should be passed as a parameter and set by GUI flags
|
||||||
bool use_short_vertexes = false;
|
bool use_f16_vertexes = false;
|
||||||
bool use_short_normals = true;
|
bool use_f16_normals = true;
|
||||||
bool use_short_tangents = true;
|
bool use_f16_tangents = true;
|
||||||
bool use_short_texcoord[8] = { false, false, false, false, false, false, false, false };
|
bool use_f16_texcoord[8] = { false, false, false, false, false, false, false, false };
|
||||||
|
|
||||||
if (use_short_vertexes) {
|
|
||||||
for (std::vector<Vector3>::const_iterator itr = mi.vertices.begin(); itr != mi.vertices.end(); itr++) {
|
|
||||||
if (fabsf((*itr).x) > 1.0f || fabsf((*itr).y) > 1.0f || fabsf((*itr).z) > 1.0f) {
|
|
||||||
use_short_vertexes = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int set = 0; set < 8; set++) {
|
for (int set = 0; set < 8; set++) {
|
||||||
if (use_short_texcoord[set]) {
|
if (use_f16_texcoord[set]) {
|
||||||
for (std::vector<Vector2>::const_iterator itr = mi.texcoord[set].begin(); itr != mi.texcoord[set].end(); itr++) {
|
for (std::vector<Vector2>::const_iterator itr = mi.texcoord[set].begin(); itr != mi.texcoord[set].end(); itr++) {
|
||||||
if (fabsf((*itr).x) > 1.0f || fabsf((*itr).y) > 1.0f) {
|
if (fabsf((*itr).x) > 1.0f || fabsf((*itr).y) > 1.0f) {
|
||||||
use_short_texcoord[set] = false;
|
use_f16_texcoord[set] = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -540,36 +529,33 @@ void KRMesh::LoadData(const KRMesh::mesh_info& mi, bool calculate_normals, bool
|
|||||||
if (mi.vertices.size()) {
|
if (mi.vertices.size()) {
|
||||||
attribute->attribute = VertexAttribute::position;
|
attribute->attribute = VertexAttribute::position;
|
||||||
attribute->type = DataType::vec3;
|
attribute->type = DataType::vec3;
|
||||||
if (use_short_vertexes) {
|
attribute->normalization = Normalization::none;
|
||||||
|
if (use_f16_vertexes) {
|
||||||
attribute->component = ComponentType::float16;
|
attribute->component = ComponentType::float16;
|
||||||
attribute->normalization = Normalization::normalized;
|
|
||||||
} else {
|
} else {
|
||||||
attribute->component = ComponentType::float32;
|
attribute->component = ComponentType::float32;
|
||||||
attribute->normalization = Normalization::none;
|
|
||||||
}
|
}
|
||||||
attribute++;
|
attribute++;
|
||||||
}
|
}
|
||||||
if (mi.normals.size() || calculate_normals) {
|
if (mi.normals.size() || calculate_normals) {
|
||||||
attribute->attribute = VertexAttribute::normal;
|
attribute->attribute = VertexAttribute::normal;
|
||||||
attribute->type = DataType::vec3;
|
attribute->type = DataType::vec3;
|
||||||
if (use_short_normals) {
|
attribute->normalization = Normalization::none;
|
||||||
|
if (use_f16_normals) {
|
||||||
attribute->component = ComponentType::float16;
|
attribute->component = ComponentType::float16;
|
||||||
attribute->normalization = Normalization::normalized;
|
|
||||||
} else {
|
} else {
|
||||||
attribute->component = ComponentType::float32;
|
attribute->component = ComponentType::float32;
|
||||||
attribute->normalization = Normalization::none;
|
|
||||||
}
|
}
|
||||||
attribute++;
|
attribute++;
|
||||||
}
|
}
|
||||||
if (mi.tangents.size() || calculate_tangents) {
|
if (mi.tangents.size() || calculate_tangents) {
|
||||||
attribute->attribute = VertexAttribute::tangent;
|
attribute->attribute = VertexAttribute::tangent;
|
||||||
attribute->type = DataType::vec3;
|
attribute->type = DataType::vec3;
|
||||||
if (use_short_tangents) {
|
attribute->normalization = Normalization::none;
|
||||||
|
if (use_f16_tangents) {
|
||||||
attribute->component = ComponentType::float16;
|
attribute->component = ComponentType::float16;
|
||||||
attribute->normalization = Normalization::normalized;
|
|
||||||
} else {
|
} else {
|
||||||
attribute->component = ComponentType::float32;
|
attribute->component = ComponentType::float32;
|
||||||
attribute->normalization = Normalization::none;
|
|
||||||
}
|
}
|
||||||
attribute++;
|
attribute++;
|
||||||
}
|
}
|
||||||
@@ -577,12 +563,11 @@ void KRMesh::LoadData(const KRMesh::mesh_info& mi, bool calculate_normals, bool
|
|||||||
if (mi.texcoord[set].size()) {
|
if (mi.texcoord[set].size()) {
|
||||||
attribute->attribute = VertexAttribute::texcoord;
|
attribute->attribute = VertexAttribute::texcoord;
|
||||||
attribute->type = DataType::vec2;
|
attribute->type = DataType::vec2;
|
||||||
if (use_short_texcoord[set]) {
|
attribute->normalization = Normalization::none;
|
||||||
|
if (use_f16_texcoord[set]) {
|
||||||
attribute->component = ComponentType::float16;
|
attribute->component = ComponentType::float16;
|
||||||
attribute->normalization = Normalization::normalized;
|
|
||||||
} else {
|
} else {
|
||||||
attribute->component = ComponentType::float32;
|
attribute->component = ComponentType::float32;
|
||||||
attribute->normalization = Normalization::none;
|
|
||||||
}
|
}
|
||||||
attribute++;
|
attribute++;
|
||||||
}
|
}
|
||||||
@@ -978,9 +963,13 @@ constexpr void normalizeAttributeComponent(const Normalization norm, float val,
|
|||||||
case Normalization::none:
|
case Normalization::none:
|
||||||
case Normalization::scaled:
|
case Normalization::scaled:
|
||||||
{
|
{
|
||||||
|
if constexpr (std::is_same_v<T, float>) {
|
||||||
|
*out = val;
|
||||||
|
} else {
|
||||||
float clampedFloat = std::clamp(val, minFloat, maxFloat);
|
float clampedFloat = std::clamp(val, minFloat, maxFloat);
|
||||||
*out = static_cast<T>(clampedFloat);
|
*out = static_cast<T>(clampedFloat);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Normalization::normalized:
|
case Normalization::normalized:
|
||||||
if constexpr (std::is_signed_v<T>) {
|
if constexpr (std::is_signed_v<T>) {
|
||||||
@@ -1007,6 +996,111 @@ constexpr void normalizeAttributeComponent(const Normalization norm, float val,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(KRAKEN_ARCH_X86_64)
|
||||||
|
uint16_t floatToHalf(float val)
|
||||||
|
{
|
||||||
|
__m128 simdFloat = _mm_set_ss(val);
|
||||||
|
__m128i simdHalf = _mm_cvtps_ph(simdFloat, _MM_FROUND_TO_NEAREST_INT);
|
||||||
|
return _mm_cvtsi128_si32(simdHalf) & 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
float halfToFloat(uint16_t val)
|
||||||
|
{
|
||||||
|
__m128i simdHalf = _mm_cvtsi32_si128(val);
|
||||||
|
__m128 simdFloat = _mm_cvtph_ps(simdHalf);
|
||||||
|
return _mm_cvtss_f32(simdFloat);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(KRAKEN_ARCH_ARM64)
|
||||||
|
uint16_t floatToHalf(float val)
|
||||||
|
{
|
||||||
|
__fp16 h = static_cast<__fp16>(val);
|
||||||
|
uint16_t bits;
|
||||||
|
std::memcpy(&bits, &h, 2);
|
||||||
|
return bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Half to Float
|
||||||
|
float halfToFloat(uint16_t val)
|
||||||
|
{
|
||||||
|
__fp16 h;
|
||||||
|
std::memcpy(&h, &val, 2);
|
||||||
|
return static_cast<float>(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
uint16_t floatToHalf(float val)
|
||||||
|
{
|
||||||
|
uint32_t f32Bits;
|
||||||
|
std::memcpy(&f32Bits, &val, sizeof(float));
|
||||||
|
|
||||||
|
uint32_t sign = (f32Bits >> 16) & 0x8000;
|
||||||
|
int32_t exponent = ((f32Bits >> 23) & 0xFF) - 127;
|
||||||
|
uint32_t mantissa = f32Bits & 0x007FFFFF;
|
||||||
|
|
||||||
|
if (exponent <= -15) {
|
||||||
|
if (exponent < -24) return sign;
|
||||||
|
mantissa |= 0x00800000;
|
||||||
|
return sign | (mantissa >> (-14 - exponent));
|
||||||
|
}
|
||||||
|
if (exponent > 15) return sign | 0x7C00;
|
||||||
|
|
||||||
|
return sign | ((exponent + 15) << 10) | (mantissa >> 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
float halfToFloat(uint16_t val)
|
||||||
|
{
|
||||||
|
uint32_t sign = (val & 0x8000) << 16;
|
||||||
|
uint32_t exponent = (val & 0x7C00) >> 10;
|
||||||
|
uint32_t mantissa = val & 0x03FF;
|
||||||
|
uint32_t f32Bits = 0;
|
||||||
|
|
||||||
|
if (exponent == 0) {
|
||||||
|
if (mantissa != 0) {
|
||||||
|
while ((mantissa & 0x0400) == 0) {
|
||||||
|
mantissa <<= 1;
|
||||||
|
exponent--;
|
||||||
|
}
|
||||||
|
exponent++;
|
||||||
|
mantissa &= 0x03FF;
|
||||||
|
f32Bits = sign | ((exponent + 112) << 23) | (mantissa << 13);
|
||||||
|
} else {
|
||||||
|
f32Bits = sign;
|
||||||
|
}
|
||||||
|
} else if (exponent == 31) {
|
||||||
|
f32Bits = sign | 0x7F800000 | (mantissa << 13);
|
||||||
|
} else {
|
||||||
|
f32Bits = sign | ((exponent + 112) << 23) | (mantissa << 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
float result;
|
||||||
|
std::memcpy(&result, &f32Bits, sizeof(float));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// IEEE 754 Half precision specialization
|
||||||
|
constexpr void normalizeAttributeComponent_float16(const Normalization norm, float val, uint16_t* out)
|
||||||
|
{
|
||||||
|
assert(norm == Normalization::none);
|
||||||
|
|
||||||
|
constexpr float minFloat = -65504.0f;
|
||||||
|
constexpr float maxFloat = 65504.0f;
|
||||||
|
|
||||||
|
float clampedFloat = std::clamp(val, minFloat, maxFloat);
|
||||||
|
*out = floatToHalf(clampedFloat);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IEEE 754 Half precision specialization
|
||||||
|
constexpr void denormalizeAttributeComponent_float16(const Normalization norm, uint16_t val, float* out)
|
||||||
|
{
|
||||||
|
assert(norm == Normalization::none);
|
||||||
|
|
||||||
|
*out = halfToFloat(val);
|
||||||
|
}
|
||||||
|
|
||||||
void writeVertexAttributeComponent(const VertexAttributeInfo& attribute, void* address, int componentIndex, float val)
|
void writeVertexAttributeComponent(const VertexAttributeInfo& attribute, void* address, int componentIndex, float val)
|
||||||
{
|
{
|
||||||
void* componentAddress = (uint8_t*)address + ComponentSize[(int)attribute.component] * componentIndex;
|
void* componentAddress = (uint8_t*)address + ComponentSize[(int)attribute.component] * componentIndex;
|
||||||
@@ -1038,7 +1132,7 @@ void writeVertexAttributeComponent(const VertexAttributeInfo& attribute, void* a
|
|||||||
normalizeAttributeComponent(attribute.normalization, val, (__uint64_t*)componentAddress);
|
normalizeAttributeComponent(attribute.normalization, val, (__uint64_t*)componentAddress);
|
||||||
break;
|
break;
|
||||||
case ComponentType::float16:
|
case ComponentType::float16:
|
||||||
normalizeAttributeComponent(attribute.normalization, val, (short*)componentAddress);
|
normalizeAttributeComponent_float16(attribute.normalization, val, (__uint16_t*)componentAddress);
|
||||||
break;
|
break;
|
||||||
case ComponentType::float32:
|
case ComponentType::float32:
|
||||||
normalizeAttributeComponent(attribute.normalization, val, (float*)componentAddress);
|
normalizeAttributeComponent(attribute.normalization, val, (float*)componentAddress);
|
||||||
@@ -1080,7 +1174,7 @@ void readVertexAttributeComponent(const VertexAttributeInfo& attribute, const vo
|
|||||||
denormalizeAttributeComponent(attribute.normalization, *(__uint64_t*)componentAddress, out);
|
denormalizeAttributeComponent(attribute.normalization, *(__uint64_t*)componentAddress, out);
|
||||||
break;
|
break;
|
||||||
case ComponentType::float16:
|
case ComponentType::float16:
|
||||||
denormalizeAttributeComponent(attribute.normalization, *(short*)componentAddress, out);
|
denormalizeAttributeComponent_float16(attribute.normalization, *(__uint16_t*)componentAddress, out);
|
||||||
break;
|
break;
|
||||||
case ComponentType::float32:
|
case ComponentType::float32:
|
||||||
denormalizeAttributeComponent(attribute.normalization, *(float*)componentAddress, out);
|
denormalizeAttributeComponent(attribute.normalization, *(float*)componentAddress, out);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
cmake_minimum_required (VERSION 3.16)
|
cmake_minimum_required (VERSION 3.16)
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
cmake_minimum_required (VERSION 3.16)
|
cmake_minimum_required (VERSION 3.16)
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user