mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-15 22:13:24 +09:00
[Fix] (Magma): convert 32-bit int and packed 2_10_10_10 float attributes on the CPU
This commit is contained in:
@@ -160,6 +160,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
format = ToFloat32VertexFormat(attr.Size);
|
||||
conversion = VertexStreamConversion::Float64ToFloat32;
|
||||
}
|
||||
// GL_INT / GL_UNSIGNED_INT read as float (glVertexAttribFormat without the I suffix):
|
||||
// Vulkan has no 32-bit SCALED or NORM vertex format, so the stream is converted to
|
||||
// float32 on the CPU, normalized when the attribute asks for it.
|
||||
if (format == VK_FORMAT_UNDEFINED && !attr.IsInteger && !attr.IsLong && !attr.IsBgra &&
|
||||
(type == DataType::Int32 || type == DataType::Uint32)) {
|
||||
format = ToFloat32VertexFormat(attr.Size);
|
||||
conversion = VertexStreamConversion::ScaledIntegerToFloat32;
|
||||
}
|
||||
if (format == VK_FORMAT_UNDEFINED) { maskOut("format-map"); continue; }
|
||||
if (!SupportsVertexBufferFormat(format)) {
|
||||
if (!IsScaledIntegerVertexFormat(format)) { maskOut("native-format-feature", format); continue; }
|
||||
@@ -432,6 +440,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
case VK_FORMAT_R16G16B16_SSCALED:
|
||||
case VK_FORMAT_R16G16B16A16_USCALED:
|
||||
case VK_FORMAT_R16G16B16A16_SSCALED:
|
||||
// Packed 2_10_10_10 fetches are optional too (Adreno has neither SCALED form); the
|
||||
// converter decodes the fields itself, normalized or not.
|
||||
case VK_FORMAT_A2B10G10R10_USCALED_PACK32:
|
||||
case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:
|
||||
case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
|
||||
case VK_FORMAT_A2B10G10R10_SNORM_PACK32:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
||||
@@ -86,18 +86,51 @@
|
||||
return true;
|
||||
}
|
||||
output.resize(count * attr.Size * sizeof(Float));
|
||||
// GL 4.6 core 10.2.1 (equations 2.1 / 2.2) for a normalized fixed-point component; a
|
||||
// double is not fixed-point, so its normalized flag changes nothing.
|
||||
const Bool normalize = attr.Normalized && type != DataType::Float64;
|
||||
const auto convert = [&]<typename T>() {
|
||||
for (SizeT i = 0; i < count; ++i) {
|
||||
for (SizeT component = 0; component < attr.Size; ++component) {
|
||||
T value{};
|
||||
Memcpy(&value, source + i * stride + component * sizeof(T), sizeof(T));
|
||||
const Float converted = static_cast<Float>(value);
|
||||
Float converted = static_cast<Float>(value);
|
||||
if constexpr (std::is_integral_v<T>) {
|
||||
if (normalize) {
|
||||
constexpr double kMax = static_cast<double>(std::numeric_limits<T>::max());
|
||||
converted = static_cast<Float>(std::is_signed_v<T>
|
||||
? std::max(static_cast<double>(value) / kMax, -1.0)
|
||||
: static_cast<double>(value) / kMax);
|
||||
}
|
||||
}
|
||||
Memcpy(output.data() + (i * attr.Size + component) * sizeof(Float), &converted, sizeof(Float));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
switch (type) {
|
||||
case DataType::Uint2101010Rev:
|
||||
case DataType::Int2101010Rev: {
|
||||
// x, y, z in 10-bit fields from bit 0, w in the top 2 bits; GL 4.6 core 10.2.1.
|
||||
if (attr.Size != 4 || attr.IsBgra) return false;
|
||||
const Bool isSigned = type == DataType::Int2101010Rev;
|
||||
for (SizeT i = 0; i < count; ++i) {
|
||||
Uint32 word = 0;
|
||||
Memcpy(&word, source + i * stride, sizeof(word));
|
||||
for (Uint32 component = 0; component < 4; ++component) {
|
||||
const Uint32 bits = component < 3 ? 10u : 2u;
|
||||
const Uint32 field = (word >> (component * 10u)) & ((1u << bits) - 1u);
|
||||
const Int32 value = isSigned && (field >> (bits - 1u))
|
||||
? static_cast<Int32>(field) - static_cast<Int32>(1u << bits) : static_cast<Int32>(field);
|
||||
Float converted = static_cast<Float>(value);
|
||||
if (normalize)
|
||||
converted = isSigned ? std::max(converted / static_cast<Float>((1u << (bits - 1u)) - 1u), -1.0f)
|
||||
: converted / static_cast<Float>((1u << bits) - 1u);
|
||||
Memcpy(output.data() + (i * 4 + component) * sizeof(Float), &converted, sizeof(Float));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case DataType::Float64: return convert.template operator()<Double>();
|
||||
case DataType::Int8: return convert.template operator()<Int8>();
|
||||
case DataType::Uint8: return convert.template operator()<Uint8>();
|
||||
|
||||
Reference in New Issue
Block a user