Fix more bugs with VertexDataLayout driven buffer parsing and generation.

Bump to C++23 standard.
This commit is contained in:
2026-06-16 00:37:54 -07:00
parent 130fb5cbe8
commit 64ce0be790
8 changed files with 154 additions and 46 deletions

View File

@@ -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)

View File

@@ -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)
#if !defined(__i386__) && defined(__arm__) #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 #define KRAKEN_USE_ARM_NEON
#else
static_assert(false, "CPU Architecture not implemented.");
#endif #endif

View File

@@ -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];

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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)

View File

@@ -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)