void vertexPack(const float _input[4], bool _inputNormalized, Attrib::Enum _attr, const VertexDecl& _decl, void* _data, uint32_t _index) { if (!_decl.has(_attr) ) { return; } uint32_t stride = _decl.getStride(); uint8_t* data = (uint8_t*)_data + _index*stride + _decl.getOffset(_attr); uint8_t num; AttribType::Enum type; bool normalized; bool asInt; _decl.decode(_attr, num, type, normalized, asInt); switch (type) { default: case AttribType::Uint8: { uint8_t* packed = (uint8_t*)data; if (_inputNormalized) { if (asInt) { switch (num) { default: *packed++ = uint8_t(*_input++ * 127.0f + 128.0f); BX_FALLTHROUGH; case 3: *packed++ = uint8_t(*_input++ * 127.0f + 128.0f); BX_FALLTHROUGH; case 2: *packed++ = uint8_t(*_input++ * 127.0f + 128.0f); BX_FALLTHROUGH; case 1: *packed++ = uint8_t(*_input++ * 127.0f + 128.0f); } } else { switch (num) { default: *packed++ = uint8_t(*_input++ * 255.0f); BX_FALLTHROUGH; case 3: *packed++ = uint8_t(*_input++ * 255.0f); BX_FALLTHROUGH; case 2: *packed++ = uint8_t(*_input++ * 255.0f); BX_FALLTHROUGH; case 1: *packed++ = uint8_t(*_input++ * 255.0f); } } } else { switch (num) { default: *packed++ = uint8_t(*_input++); BX_FALLTHROUGH; case 3: *packed++ = uint8_t(*_input++); BX_FALLTHROUGH; case 2: *packed++ = uint8_t(*_input++); BX_FALLTHROUGH; case 1: *packed++ = uint8_t(*_input++); } } } break; case AttribType::Uint10: { uint32_t packed = 0; if (_inputNormalized) { if (asInt) { switch (num) { default: BX_FALLTHROUGH; case 3: packed |= uint32_t(*_input++ * 511.0f + 512.0f); BX_FALLTHROUGH; case 2: packed <<= 10; packed |= uint32_t(*_input++ * 511.0f + 512.0f); BX_FALLTHROUGH; case 1: packed <<= 10; packed |= uint32_t(*_input++ * 511.0f + 512.0f); } } else { switch (num) { default: BX_FALLTHROUGH; case 3: packed |= uint32_t(*_input++ * 1023.0f); BX_FALLTHROUGH; case 2: packed <<= 10; packed |= uint32_t(*_input++ * 1023.0f); BX_FALLTHROUGH; case 1: packed <<= 10; packed |= uint32_t(*_input++ * 1023.0f); } } } else { switch (num) { default: BX_FALLTHROUGH; case 3: packed |= uint32_t(*_input++); BX_FALLTHROUGH; case 2: packed <<= 10; packed |= uint32_t(*_input++); BX_FALLTHROUGH; case 1: packed <<= 10; packed |= uint32_t(*_input++); } } *(uint32_t*)data = packed; } break; case AttribType::Int16: { int16_t* packed = (int16_t*)data; if (_inputNormalized) { if (asInt) { switch (num) { default: *packed++ = int16_t(*_input++ * 32767.0f); BX_FALLTHROUGH; case 3: *packed++ = int16_t(*_input++ * 32767.0f); BX_FALLTHROUGH; case 2: *packed++ = int16_t(*_input++ * 32767.0f); BX_FALLTHROUGH; case 1: *packed++ = int16_t(*_input++ * 32767.0f); } } else { switch (num) { default: *packed++ = int16_t(*_input++ * 65535.0f - 32768.0f); BX_FALLTHROUGH; case 3: *packed++ = int16_t(*_input++ * 65535.0f - 32768.0f); BX_FALLTHROUGH; case 2: *packed++ = int16_t(*_input++ * 65535.0f - 32768.0f); BX_FALLTHROUGH; case 1: *packed++ = int16_t(*_input++ * 65535.0f - 32768.0f); } } } else { switch (num) { default: *packed++ = int16_t(*_input++); BX_FALLTHROUGH; case 3: *packed++ = int16_t(*_input++); BX_FALLTHROUGH; case 2: *packed++ = int16_t(*_input++); BX_FALLTHROUGH; case 1: *packed++ = int16_t(*_input++); } } } break; case AttribType::Half: { uint16_t* packed = (uint16_t*)data; switch (num) { default: *packed++ = bx::halfFromFloat(*_input++); BX_FALLTHROUGH; case 3: *packed++ = bx::halfFromFloat(*_input++); BX_FALLTHROUGH; case 2: *packed++ = bx::halfFromFloat(*_input++); BX_FALLTHROUGH; case 1: *packed++ = bx::halfFromFloat(*_input++); } } break; case AttribType::Float: bx::memCopy(data, _input, num*sizeof(float) ); break; } }
void vertexUnpack(float _output[4], Attrib::Enum _attr, const VertexDecl& _decl, const void* _data, uint32_t _index) { if (!_decl.has(_attr) ) { bx::memSet(_output, 0, 4*sizeof(float) ); return; } uint32_t stride = _decl.getStride(); uint8_t* data = (uint8_t*)_data + _index*stride + _decl.getOffset(_attr); uint8_t num; AttribType::Enum type; bool normalized; bool asInt; _decl.decode(_attr, num, type, normalized, asInt); switch (type) { default: case AttribType::Uint8: { uint8_t* packed = (uint8_t*)data; if (asInt) { switch (num) { default: *_output++ = (float(*packed++) - 128.0f)*1.0f/127.0f; BX_FALLTHROUGH; case 3: *_output++ = (float(*packed++) - 128.0f)*1.0f/127.0f; BX_FALLTHROUGH; case 2: *_output++ = (float(*packed++) - 128.0f)*1.0f/127.0f; BX_FALLTHROUGH; case 1: *_output++ = (float(*packed++) - 128.0f)*1.0f/127.0f; } } else { switch (num) { default: *_output++ = float(*packed++)*1.0f/255.0f; BX_FALLTHROUGH; case 3: *_output++ = float(*packed++)*1.0f/255.0f; BX_FALLTHROUGH; case 2: *_output++ = float(*packed++)*1.0f/255.0f; BX_FALLTHROUGH; case 1: *_output++ = float(*packed++)*1.0f/255.0f; } } } break; case AttribType::Uint10: { uint32_t packed = *(uint32_t*)data; if (asInt) { switch (num) { default: BX_FALLTHROUGH; case 3: *_output++ = (float(packed & 0x3ff) - 512.0f)*1.0f/511.0f; packed >>= 10; BX_FALLTHROUGH; case 2: *_output++ = (float(packed & 0x3ff) - 512.0f)*1.0f/511.0f; packed >>= 10; BX_FALLTHROUGH; case 1: *_output++ = (float(packed & 0x3ff) - 512.0f)*1.0f/511.0f; } } else { switch (num) { default: BX_FALLTHROUGH; case 3: *_output++ = float(packed & 0x3ff)*1.0f/1023.0f; packed >>= 10; BX_FALLTHROUGH; case 2: *_output++ = float(packed & 0x3ff)*1.0f/1023.0f; packed >>= 10; BX_FALLTHROUGH; case 1: *_output++ = float(packed & 0x3ff)*1.0f/1023.0f; } } } break; case AttribType::Int16: { int16_t* packed = (int16_t*)data; if (asInt) { switch (num) { default: *_output++ = float(*packed++)*1.0f/32767.0f; BX_FALLTHROUGH; case 3: *_output++ = float(*packed++)*1.0f/32767.0f; BX_FALLTHROUGH; case 2: *_output++ = float(*packed++)*1.0f/32767.0f; BX_FALLTHROUGH; case 1: *_output++ = float(*packed++)*1.0f/32767.0f; } } else { switch (num) { default: *_output++ = (float(*packed++) + 32768.0f)*1.0f/65535.0f; BX_FALLTHROUGH; case 3: *_output++ = (float(*packed++) + 32768.0f)*1.0f/65535.0f; BX_FALLTHROUGH; case 2: *_output++ = (float(*packed++) + 32768.0f)*1.0f/65535.0f; BX_FALLTHROUGH; case 1: *_output++ = (float(*packed++) + 32768.0f)*1.0f/65535.0f; } } } break; case AttribType::Half: { uint16_t* packed = (uint16_t*)data; switch (num) { default: *_output++ = bx::halfToFloat(*packed++); BX_FALLTHROUGH; case 3: *_output++ = bx::halfToFloat(*packed++); BX_FALLTHROUGH; case 2: *_output++ = bx::halfToFloat(*packed++); BX_FALLTHROUGH; case 1: *_output++ = bx::halfToFloat(*packed++); } } break; case AttribType::Float: bx::memCopy(_output, data, num*sizeof(float) ); _output += num; break; }
void vertexConvert(const VertexDecl& _destDecl, void* _destData, const VertexDecl& _srcDecl, const void* _srcData, uint32_t _num) { if (_destDecl.m_hash == _srcDecl.m_hash) { memcpy(_destData, _srcData, _srcDecl.getSize(_num) ); return; } struct ConvertOp { enum Enum { Set, Copy, Convert, }; Attrib::Enum attr; Enum op; uint32_t src; uint32_t dest; uint32_t size; }; ConvertOp convertOp[Attrib::Count]; uint32_t numOps = 0; for (uint32_t ii = 0; ii < Attrib::Count; ++ii) { Attrib::Enum attr = (Attrib::Enum)ii; if (_destDecl.has(attr) ) { ConvertOp& cop = convertOp[numOps]; cop.attr = attr; cop.dest = _destDecl.getOffset(attr); uint8_t num; AttribType::Enum type; bool normalized; bool asInt; _destDecl.decode(attr, num, type, normalized, asInt); cop.size = (*s_attribTypeSize[0])[type][num-1]; if (_srcDecl.has(attr) ) { cop.src = _srcDecl.getOffset(attr); cop.op = _destDecl.m_attributes[attr] == _srcDecl.m_attributes[attr] ? ConvertOp::Copy : ConvertOp::Convert; } else { cop.op = ConvertOp::Set; } ++numOps; } } if (0 < numOps) { const uint8_t* src = (const uint8_t*)_srcData; uint32_t srcStride = _srcDecl.getStride(); uint8_t* dest = (uint8_t*)_destData; uint32_t destStride = _destDecl.getStride(); float unpacked[4]; for (uint32_t ii = 0; ii < _num; ++ii) { for (uint32_t jj = 0; jj < numOps; ++jj) { const ConvertOp& cop = convertOp[jj]; switch (cop.op) { case ConvertOp::Set: memset(dest + cop.dest, 0, cop.size); break; case ConvertOp::Copy: memcpy(dest + cop.dest, src + cop.src, cop.size); break; case ConvertOp::Convert: vertexUnpack(unpacked, cop.attr, _srcDecl, src); vertexPack(unpacked, true, cop.attr, _destDecl, dest); break; } } src += srcStride; dest += destStride; } } }