int32_t write(bx::WriterI* _writer, const VertexDecl& _decl, bx::Error* _err) { BX_ERROR_SCOPE(_err); int32_t total = 0; uint8_t numAttrs = 0; for (uint32_t attr = 0; attr < Attrib::Count; ++attr) { numAttrs += UINT16_MAX == _decl.m_attributes[attr] ? 0 : 1; } total += bx::write(_writer, numAttrs, _err); total += bx::write(_writer, _decl.m_stride, _err); for (uint32_t attr = 0; attr < Attrib::Count; ++attr) { if (UINT16_MAX != _decl.m_attributes[attr]) { uint8_t num; AttribType::Enum type; bool normalized; bool asInt; _decl.decode(Attrib::Enum(attr), num, type, normalized, asInt); total += bx::write(_writer, _decl.m_offset[attr], _err); total += bx::write(_writer, s_attribToId[attr].id, _err); total += bx::write(_writer, num, _err); total += bx::write(_writer, s_attribTypeToId[type].id, _err); total += bx::write(_writer, normalized, _err); total += bx::write(_writer, asInt, _err); } } return total; }
void dump(const VertexDecl& _decl) { if (BX_ENABLED(BGFX_CONFIG_DEBUG) ) { dbgPrintf("vertexdecl %08x (%08x), stride %d\n" , _decl.m_hash , bx::hashMurmur2A(_decl.m_attributes) , _decl.m_stride ); for (uint32_t attr = 0; attr < Attrib::Count; ++attr) { if (UINT16_MAX != _decl.m_attributes[attr]) { uint8_t num; AttribType::Enum type; bool normalized; bool asInt; _decl.decode(Attrib::Enum(attr), num, type, normalized, asInt); dbgPrintf("\tattr %d - %s, num %d, type %d, norm %d, asint %d, offset %d\n" , attr , getAttribName(Attrib::Enum(attr) ) , num , type , normalized , asInt , _decl.m_offset[attr] ); } } } }
int32_t write(bx::WriterI* _writer, const VertexDecl& _decl) { int32_t total = 0; uint8_t numAttrs = 0; for (uint32_t attr = 0; attr < Attrib::Count; ++attr) { numAttrs += 0xff == _decl.m_attributes[attr] ? 0 : 1; } total += bx::write(_writer, numAttrs); total += bx::write(_writer, _decl.m_stride); for (uint32_t attr = 0; attr < Attrib::Count; ++attr) { if (0xff != _decl.m_attributes[attr]) { uint8_t num; AttribType::Enum type; bool normalized; bool asInt; _decl.decode(Attrib::Enum(attr), num, type, normalized, asInt); total += bx::write(_writer, _decl.m_offset[attr]); total += bx::write(_writer, s_attribToId[attr].id); total += bx::write(_writer, num); total += bx::write(_writer, s_attribTypeToId[type].id); total += bx::write(_writer, normalized); total += bx::write(_writer, asInt); } } return total; }
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 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 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; } } }