Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e60149d2 authored by Alex Sakhartchouk's avatar Alex Sakhartchouk
Browse files

Expand RS vector3 types to vector4.

BUG=5609007

The underlying LLVM implementation for vector3 types does this implicitly. If
RS does not adjust its implementation, we will always be misaligned for any
subsequent data after a vector3 type. We previously inserted padding into the
reflected layers from llvm-rs-cc (hence the skip padding part of this change).
We can safely ignore the padding now that the Java/native code is updated to
use the expanded size. The compiler will also need modification to ensure that
we don't mistakenly skip over any end-of-struct padding.

Fixing the 3 component vector padding problem.

Change-Id: If68af42287deb8f4b28addcd19a9fa314656be44
parent 7b95eba9
Loading
Loading
Loading
Loading
+21 −1
Original line number Diff line number Diff line
@@ -690,7 +690,11 @@ public class Element extends BaseObj {
        if ((dt != DataType.UNSIGNED_5_6_5) &&
            (dt != DataType.UNSIGNED_4_4_4_4) &&
            (dt != DataType.UNSIGNED_5_5_5_1)) {
            if (size == 3) {
                mSize = dt.mSize * 4;
            } else {
                mSize = dt.mSize * size;
            }
        } else {
            mSize = dt.mSize;
        }
@@ -885,6 +889,7 @@ public class Element extends BaseObj {
        String[] mElementNames;
        int[] mArraySizes;
        int mCount;
        int mSkipPadding;

        /**
         * Create a builder object.
@@ -910,6 +915,21 @@ public class Element extends BaseObj {
            if (arraySize < 1) {
                throw new RSIllegalArgumentException("Array size cannot be less than 1.");
            }

            // Skip padding fields after a vector 3 type.
            if (mSkipPadding != 0) {
                if (name.startsWith("#padding_")) {
                    mSkipPadding = 0;
                    return this;
                }
            }

            if (element.mVectorSize == 3) {
                mSkipPadding = 1;
            } else {
                mSkipPadding = 0;
            }

            if(mCount == mElements.length) {
                Element[] e = new Element[mCount + 8];
                String[] s = new String[mCount + 8];
+12 −11
Original line number Diff line number Diff line
@@ -514,6 +514,7 @@ public class Mesh extends BaseObj {
    public static class TriangleMeshBuilder {
        float mVtxData[];
        int mVtxCount;
        int mMaxIndex;
        short mIndexData[];
        int mIndexCount;
        RenderScript mRS;
@@ -548,6 +549,7 @@ public class Mesh extends BaseObj {
        public TriangleMeshBuilder(RenderScript rs, int vtxSize, int flags) {
            mRS = rs;
            mVtxCount = 0;
            mMaxIndex = 0;
            mIndexCount = 0;
            mVtxData = new float[128];
            mIndexData = new short[128];
@@ -581,11 +583,13 @@ public class Mesh extends BaseObj {
                mVtxData[mVtxCount++] = mT0;
            }
            if ((mFlags & NORMAL) != 0) {
                makeSpace(3);
                makeSpace(4);
                mVtxData[mVtxCount++] = mNX;
                mVtxData[mVtxCount++] = mNY;
                mVtxData[mVtxCount++] = mNZ;
                mVtxData[mVtxCount++] = 0.0f;
            }
            mMaxIndex ++;
        }

        /**
@@ -622,10 +626,11 @@ public class Mesh extends BaseObj {
            if (mVtxSize != 3) {
                throw new IllegalStateException("add mistmatch with declared components.");
            }
            makeSpace(3);
            makeSpace(4);
            mVtxData[mVtxCount++] = x;
            mVtxData[mVtxCount++] = y;
            mVtxData[mVtxCount++] = z;
            mVtxData[mVtxCount++] = 1.0f;
            latch();
            return this;
        }
@@ -697,9 +702,9 @@ public class Mesh extends BaseObj {
        * @return this
        **/
        public TriangleMeshBuilder addTriangle(int idx1, int idx2, int idx3) {
            if((idx1 >= mVtxCount) || (idx1 < 0) ||
               (idx2 >= mVtxCount) || (idx2 < 0) ||
               (idx3 >= mVtxCount) || (idx3 < 0)) {
            if((idx1 >= mMaxIndex) || (idx1 < 0) ||
               (idx2 >= mMaxIndex) || (idx2 < 0) ||
               (idx3 >= mMaxIndex) || (idx3 < 0)) {
               throw new IllegalStateException("Index provided greater than vertex count.");
            }
            if ((mIndexCount + 3) >= mIndexData.length) {
@@ -729,20 +734,16 @@ public class Mesh extends BaseObj {
        **/
        public Mesh create(boolean uploadToBufferObject) {
            Element.Builder b = new Element.Builder(mRS);
            int floatCount = mVtxSize;
            b.add(Element.createVector(mRS,
                                       Element.DataType.FLOAT_32,
                                       mVtxSize), "position");
            if ((mFlags & COLOR) != 0) {
                floatCount += 4;
                b.add(Element.F32_4(mRS), "color");
            }
            if ((mFlags & TEXTURE_0) != 0) {
                floatCount += 2;
                b.add(Element.F32_2(mRS), "texture0");
            }
            if ((mFlags & NORMAL) != 0) {
                floatCount += 3;
                b.add(Element.F32_3(mRS), "normal");
            }
            mElement = b.create();
@@ -753,12 +754,12 @@ public class Mesh extends BaseObj {
            }

            Builder smb = new Builder(mRS, usage);
            smb.addVertexType(mElement, mVtxCount / floatCount);
            smb.addVertexType(mElement, mMaxIndex);
            smb.addIndexSetType(Element.U16(mRS), mIndexCount, Primitive.TRIANGLE);

            Mesh sm = smb.create();

            sm.getVertexAllocation(0).copy1DRangeFromUnchecked(0, mVtxCount / floatCount, mVtxData);
            sm.getVertexAllocation(0).copy1DRangeFromUnchecked(0, mMaxIndex, mVtxData);
            if(uploadToBufferObject) {
                if (uploadToBufferObject) {
                    sm.getVertexAllocation(0).syncAll(Allocation.USAGE_SCRIPT);
+100 −10
Original line number Diff line number Diff line
@@ -195,6 +195,81 @@ void Allocation::dumpLOGV(const char *prefix) const {
         prefix, getPtr(), mHal.state.usageFlags, mHal.state.mipmapControl);
}

uint32_t Allocation::getPackedSize() const {
    uint32_t numItems = mHal.state.type->getSizeBytes() / mHal.state.type->getElementSizeBytes();
    return numItems * mHal.state.type->getElement()->getSizeBytesUnpadded();
}

void Allocation::writePackedData(const Type *type,
                                 uint8_t *dst, const uint8_t *src, bool dstPadded) {
    const Element *elem = type->getElement();
    uint32_t unpaddedBytes = elem->getSizeBytesUnpadded();
    uint32_t paddedBytes = elem->getSizeBytes();
    uint32_t numItems = type->getSizeBytes() / paddedBytes;

    uint32_t srcInc = !dstPadded ? paddedBytes : unpaddedBytes;
    uint32_t dstInc =  dstPadded ? paddedBytes : unpaddedBytes;

    // no sub-elements
    uint32_t fieldCount = elem->getFieldCount();
    if (fieldCount == 0) {
        for (uint32_t i = 0; i < numItems; i ++) {
            memcpy(dst, src, unpaddedBytes);
            src += srcInc;
            dst += dstInc;
        }
        return;
    }

    // Cache offsets
    uint32_t *offsetsPadded = new uint32_t[fieldCount];
    uint32_t *offsetsUnpadded = new uint32_t[fieldCount];
    uint32_t *sizeUnpadded = new uint32_t[fieldCount];

    for (uint32_t i = 0; i < fieldCount; i++) {
        offsetsPadded[i] = elem->getFieldOffsetBytes(i);
        offsetsUnpadded[i] = elem->getFieldOffsetBytesUnpadded(i);
        sizeUnpadded[i] = elem->getField(i)->getSizeBytesUnpadded();
    }

    uint32_t *srcOffsets = !dstPadded ? offsetsPadded : offsetsUnpadded;
    uint32_t *dstOffsets =  dstPadded ? offsetsPadded : offsetsUnpadded;

    // complex elements, need to copy subelem after subelem
    for (uint32_t i = 0; i < numItems; i ++) {
        for (uint32_t fI = 0; fI < fieldCount; fI++) {
            memcpy(dst + dstOffsets[fI], src + srcOffsets[fI], sizeUnpadded[fI]);
        }
        src += srcInc;
        dst += dstInc;
    }

    delete[] offsetsPadded;
    delete[] offsetsUnpadded;
    delete[] sizeUnpadded;
}

void Allocation::unpackVec3Allocation(const void *data, uint32_t dataSize) {
    const uint8_t *src = (const uint8_t*)data;
    uint8_t *dst = (uint8_t*)getPtr();

    writePackedData(getType(), dst, src, true);
}

void Allocation::packVec3Allocation(OStream *stream) const {
    uint32_t paddedBytes = getType()->getElement()->getSizeBytes();
    uint32_t unpaddedBytes = getType()->getElement()->getSizeBytesUnpadded();
    uint32_t numItems = mHal.state.type->getSizeBytes() / paddedBytes;

    const uint8_t *src = (const uint8_t*)getPtr();
    uint8_t *dst = new uint8_t[numItems * unpaddedBytes];

    writePackedData(getType(), dst, src, false);
    stream->addByteArray(dst, getPackedSize());

    delete[] dst;
}

void Allocation::serialize(OStream *stream) const {
    // Need to identify ourselves
    stream->addU32((uint32_t)getClassId());
@@ -207,10 +282,17 @@ void Allocation::serialize(OStream *stream) const {
    mHal.state.type->serialize(stream);

    uint32_t dataSize = mHal.state.type->getSizeBytes();
    // 3 element vectors are padded to 4 in memory, but padding isn't serialized
    uint32_t packedSize = getPackedSize();
    // Write how much data we are storing
    stream->addU32(dataSize);
    stream->addU32(packedSize);
    if (dataSize == packedSize) {
        // Now write the data
        stream->addByteArray(getPtr(), dataSize);
    } else {
        // Now write the data
        packVec3Allocation(stream);
    }
}

Allocation *Allocation::createFromStream(Context *rsc, IStream *stream) {
@@ -230,22 +312,30 @@ Allocation *Allocation::createFromStream(Context *rsc, IStream *stream) {
    }
    type->compute();

    Allocation *alloc = Allocation::createAllocation(rsc, type, RS_ALLOCATION_USAGE_SCRIPT);
    type->decUserRef();

    // Number of bytes we wrote out for this allocation
    uint32_t dataSize = stream->loadU32();
    if (dataSize != type->getSizeBytes()) {
    // 3 element vectors are padded to 4 in memory, but padding isn't serialized
    uint32_t packedSize = alloc->getPackedSize();
    if (dataSize != type->getSizeBytes() &&
        dataSize != packedSize) {
        LOGE("failed to read allocation because numbytes written is not the same loaded type wants\n");
        ObjectBase::checkDelete(alloc);
        ObjectBase::checkDelete(type);
        return NULL;
    }

    Allocation *alloc = Allocation::createAllocation(rsc, type, RS_ALLOCATION_USAGE_SCRIPT);
    alloc->setName(name.string(), name.size());
    type->decUserRef();

    if (dataSize == type->getSizeBytes()) {
        uint32_t count = dataSize / type->getElementSizeBytes();

        // Read in all of our allocation data
        alloc->data(rsc, 0, 0, count, stream->getPtr() + stream->getPos(), dataSize);
    } else {
        alloc->unpackVec3Allocation(stream->getPtr() + stream->getPos(), dataSize);
    }
    stream->reset(stream->getPos() + dataSize);

    return alloc;
+5 −0
Original line number Diff line number Diff line
@@ -135,6 +135,11 @@ protected:
private:
    void freeChildrenUnlocked();
    Allocation(Context *rsc, const Type *, uint32_t usages, RsAllocationMipmapControl mc);

    uint32_t getPackedSize() const;
    static void writePackedData(const Type *type, uint8_t *dst, const uint8_t *src, bool dstPadded);
    void unpackVec3Allocation(const void *data, uint32_t dataSize);
    void packVec3Allocation(OStream *stream) const;
};

}
+2 −1
Original line number Diff line number Diff line
@@ -169,7 +169,8 @@ void Component::set(RsDataType dt, RsDataKind dk, bool norm, uint32_t vecSize) {
        break;
    }

    mBits = mTypeBits * mVectorSize;
    mBitsUnpadded = mTypeBits * mVectorSize;
    mBits = mTypeBits * rsHigherPow2(mVectorSize);
}

bool Component::isReference() const {
Loading