diff --git a/CMakeLists.txt b/CMakeLists.txt index f36ccf4..414430e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ 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_EXTENSIONS OFF) diff --git a/kraken/KREngine-common.h b/kraken/KREngine-common.h index e134e24..3eb8d5e 100755 --- a/kraken/KREngine-common.h +++ b/kraken/KREngine-common.h @@ -120,9 +120,21 @@ using std::multimap; using std::stack; using std::queue; +#if defined(__x86_64__) || defined(_M_X64) + + #include + #define KRAKEN_ARCH_X86_64 1 + +#elif defined(__aarch64__) || defined(_M_ARM64) + + #include + #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 diff --git a/kraken/KRPipeline.cpp b/kraken/KRPipeline.cpp index ffafe8b..3e03373 100644 --- a/kraken/KRPipeline.cpp +++ b/kraken/KRPipeline.cpp @@ -117,13 +117,15 @@ KRPipeline::KRPipeline(KRContext& context, KrDeviceHandle deviceHandle, const KR const char* attribBaseName = VertexAttributeNames[(int)attrib.attribute]; int len = strlen(input_var.name); int baseNameLen = strlen(attribBaseName); + if (strncmp(attribBaseName, input_var.name, baseNameLen) != 0) { + continue; + } + if (len == baseNameLen) { - if (strcmp(attribBaseName, input_var.name) == 0) { - attribute_locations[i] = input_var.location; - } + attribute_locations[i] = input_var.location; break; } - if (len + 1 != baseNameLen) { + if (len != baseNameLen + 1) { continue; } char lastChar = input_var.name[len - 1]; diff --git a/kraken/nodes/KRCamera.cpp b/kraken/nodes/KRCamera.cpp index 75daff5..c45553a 100755 --- a/kraken/nodes/KRCamera.cpp +++ b/kraken/nodes/KRCamera.cpp @@ -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[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[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 #if KRENGINE_DEBUG_GPU_LABELS diff --git a/kraken/nodes/KRCamera.h b/kraken/nodes/KRCamera.h index ed03abd..23c3ec0 100755 --- a/kraken/nodes/KRCamera.h +++ b/kraken/nodes/KRCamera.h @@ -115,8 +115,8 @@ private: float x; float y; float z; - float u; - float v; + short u; + short v; } DebugTextVertexData; mimir::Block m_debug_text_vertices; diff --git a/kraken/resources/mesh/KRMesh.cpp b/kraken/resources/mesh/KRMesh.cpp index 030b299..02c483c 100755 --- a/kraken/resources/mesh/KRMesh.cpp +++ b/kraken/resources/mesh/KRMesh.cpp @@ -490,11 +490,7 @@ void KRMesh::renderSubmesh(VkCommandBuffer& commandBuffer, int iSubmesh, const K } else { assert(iVertex + cVertexes <= cBufferVertexes); - if (getIndexCount(0) == 0) { - vkCmdDraw(commandBuffer, cVertexes, 1, iVertex, 0); - } else { - vkCmdDrawIndexed(commandBuffer, cVertexes, 1, iVertex, 0, 0); - } + vkCmdDraw(commandBuffer, cVertexes, 1, iVertex, 0); m_pContext->getMeshManager()->log_draw_call(renderPass->getType(), object_name, material_name, cVertexes); cVertexes = 0; @@ -510,24 +506,17 @@ void KRMesh::LoadData(const KRMesh::mesh_info& mi, bool calculate_normals, bool releaseData(); // TODO, FINDME - These values should be passed as a parameter and set by GUI flags - bool use_short_vertexes = false; - bool use_short_normals = true; - bool use_short_tangents = true; - bool use_short_texcoord[8] = { false, false, false, false, false, false, false, false }; + bool use_f16_vertexes = false; + bool use_f16_normals = true; + bool use_f16_tangents = true; + bool use_f16_texcoord[8] = { false, false, false, false, false, false, false, false }; - if (use_short_vertexes) { - for (std::vector::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++) { - if (use_short_texcoord[set]) { + if (use_f16_texcoord[set]) { for (std::vector::const_iterator itr = mi.texcoord[set].begin(); itr != mi.texcoord[set].end(); itr++) { if (fabsf((*itr).x) > 1.0f || fabsf((*itr).y) > 1.0f) { - use_short_texcoord[set] = false; + use_f16_texcoord[set] = false; break; } } @@ -540,36 +529,33 @@ void KRMesh::LoadData(const KRMesh::mesh_info& mi, bool calculate_normals, bool if (mi.vertices.size()) { attribute->attribute = VertexAttribute::position; attribute->type = DataType::vec3; - if (use_short_vertexes) { + attribute->normalization = Normalization::none; + if (use_f16_vertexes) { attribute->component = ComponentType::float16; - attribute->normalization = Normalization::normalized; } else { attribute->component = ComponentType::float32; - attribute->normalization = Normalization::none; } attribute++; } if (mi.normals.size() || calculate_normals) { attribute->attribute = VertexAttribute::normal; attribute->type = DataType::vec3; - if (use_short_normals) { + attribute->normalization = Normalization::none; + if (use_f16_normals) { attribute->component = ComponentType::float16; - attribute->normalization = Normalization::normalized; } else { attribute->component = ComponentType::float32; - attribute->normalization = Normalization::none; } attribute++; } if (mi.tangents.size() || calculate_tangents) { attribute->attribute = VertexAttribute::tangent; attribute->type = DataType::vec3; - if (use_short_tangents) { + attribute->normalization = Normalization::none; + if (use_f16_tangents) { attribute->component = ComponentType::float16; - attribute->normalization = Normalization::normalized; } else { attribute->component = ComponentType::float32; - attribute->normalization = Normalization::none; } attribute++; } @@ -577,12 +563,11 @@ void KRMesh::LoadData(const KRMesh::mesh_info& mi, bool calculate_normals, bool if (mi.texcoord[set].size()) { attribute->attribute = VertexAttribute::texcoord; attribute->type = DataType::vec2; - if (use_short_texcoord[set]) { + attribute->normalization = Normalization::none; + if (use_f16_texcoord[set]) { attribute->component = ComponentType::float16; - attribute->normalization = Normalization::normalized; } else { attribute->component = ComponentType::float32; - attribute->normalization = Normalization::none; } attribute++; } @@ -978,8 +963,12 @@ constexpr void normalizeAttributeComponent(const Normalization norm, float val, case Normalization::none: case Normalization::scaled: { - float clampedFloat = std::clamp(val, minFloat, maxFloat); - *out = static_cast(clampedFloat); + if constexpr (std::is_same_v) { + *out = val; + } else { + float clampedFloat = std::clamp(val, minFloat, maxFloat); + *out = static_cast(clampedFloat); + } } break; case Normalization::normalized: @@ -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(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* 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); break; case ComponentType::float16: - normalizeAttributeComponent(attribute.normalization, val, (short*)componentAddress); + normalizeAttributeComponent_float16(attribute.normalization, val, (__uint16_t*)componentAddress); break; case ComponentType::float32: normalizeAttributeComponent(attribute.normalization, val, (float*)componentAddress); @@ -1080,7 +1174,7 @@ void readVertexAttributeComponent(const VertexAttributeInfo& attribute, const vo denormalizeAttributeComponent(attribute.normalization, *(__uint64_t*)componentAddress, out); break; case ComponentType::float16: - denormalizeAttributeComponent(attribute.normalization, *(short*)componentAddress, out); + denormalizeAttributeComponent_float16(attribute.normalization, *(__uint16_t*)componentAddress, out); break; case ComponentType::float32: denormalizeAttributeComponent(attribute.normalization, *(float*)componentAddress, out); diff --git a/tests/smoke/hello_cube/CMakeLists.txt b/tests/smoke/hello_cube/CMakeLists.txt index bf85052..3da0b1e 100644 --- a/tests/smoke/hello_cube/CMakeLists.txt +++ b/tests/smoke/hello_cube/CMakeLists.txt @@ -1,5 +1,5 @@ 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_EXTENSIONS OFF) diff --git a/tools/convert/CMakeLists.txt b/tools/convert/CMakeLists.txt index 14bc328..199ad53 100644 --- a/tools/convert/CMakeLists.txt +++ b/tools/convert/CMakeLists.txt @@ -1,5 +1,5 @@ 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_EXTENSIONS OFF)