[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Public WebGL] TypedArray spec updates



On Thu, May 13, 2010 at 8:56 PM, Chris Marrin <cmarrin@apple.com> wrote:
>
> On May 12, 2010, at 4:23 PM, Kenneth Russell wrote:
>
> ...
>
> I still don't understand the DataArray API. I don't see why we need a
> separate view that is essentially an uberview, being able to view any offset
> as any type. That seems like overkill. It seems like it would be better if
> each view had a setter and getter that took an ArrayBuffer and a
> littleEndian flag. The flag would tell you the byte order of the data in the
> ArrayBuffer. Let's say I have some future version of XHR, which can give me
> data as an ArrayBuffer. Then I could do this:
>
>        function XHRDataReady(request)
>
>        {
>
>                var data = request.responseArrayBuffer; // New imaginary XHR
> API
>
>                var buffer = new ArrayBuffer(10 * 2 + 10 * 4); // enough
> space for 10 shorts and 10 floats
>
>                var shorts = new Int16Array(buffer, 0, 10);
>
>                var floats = new FloatArray(buffer, 10 * 2, 10);
>
>                shorts.setData(data, 0, 10, true); // Data I loaded with XHR
> is littleEndian
>
>                floats.setData(data, 10 * 2, 10, true);
>
>        }
>
> This would flip the order of the incoming data or not, as needed.
>
> With your API, would I use it like this:
>
>        function XHRDataReady(request)
>
>        {
>
>                var data = request.responseArrayBuffer; // New imaginary XHR
> API
>
>                var dataArray = new DataArray(data);
>
>                var buffer = new ArrayBuffer(10 * 2 + 10 * 4); // enough
> space for 10 shorts and 10 floats
>
>                var shorts = new Int16Array(buffer, 0, 10);
>
>                var floats = new FloatArray(buffer, 10 * 2, 10);
>
>                // Set the shorts
>
>                for (var i = 0; i < 10; ++i)
>
>                        shorts[i] = dataArray.getInt16(i * 2, true);
>
>                // Set the floats
>
>                for (var i = 0; i < 10; ++i)
>
>                        floats[i] = dataArray.getFloat(i * 4 + 10 * 2, true);
>
>        }
>
> First of all, I'm not sure passing 'true' is the right thing to do. I know
> my data is littleEndian, but don't I have to check to see if the data in the
> arrays needs to be littleEndian and then flip the flag if needed?
>
> Second of all, it seems like having the uber-view is more complicated than
> just putting the API on the existing views.
>
> The design constraints are:
>
> - Support unaligned loads / stores. This is a requirement to handle
> arbitrary file formats.
>
> The setData() method would handle unaligned data since you pass it a byte
> offset to the start of the data.
>
> - Support specified endianness rather than "native" endianness as in
> the TypedArrays. Most file formats are defined in terms of big-endian
> or little-endian values.
>
> This is where I'm confused. Your current spec seems to indicate that the
> littleEndian param will place data into the destination buffer in little or
> big endian form. I think the source data can be in a specified endianness,
> but the data in the views should always be in native endianness.
>
>
> - Do not slow down the fast path of the typed arrays.
>
> I'm not sure what that means,  but certainly the setData() method collapses
> to memcpy if the src and dest endianness match.
>
> The best way to achieve all of these goals is to provide an
> alternative view, decoupled from the typed arrays. Doing so avoids any
> conditionals in the fast path of the typed arrays, while still
> providing reasonably fast access via the new view's getters and
> setters, which can be implemented with a few machine instructions
> each.
>
> I'm not sure why that is. Only the setData() method would have to do
> endianness tests. The rest of the existing API would not change, nor would
> the implementation have to do any extra work because of endianness. It's
> true that it would be possible to read data with the wrong endianness into
> an ArrayBuffer and then map that onto some multi-byte view that would  then
> have incorrect data. But that will be possible no matter what.
> I don't think we need to generally deal with data in a view that is in the
> wrong endianness. So endian flipping wouldn't have to pervade the API calls.
> It's just setData() and getData() that have to worry about that, getting
> data into and out of the buffer.
>
> Your proposal above doesn't handle the unaligned data case.
>
> Since setData() is passed a byte offset it seems like it does handle the
> unaligned data case, doesn't it?
>
> Perhaps an example of the best way to use DataArray would help?
>
> I envision most users wrapping it into a stream-like interface,
> fetching individual data elements of various types and incrementing
> the byte offset of the stream. The proposal I originally sent out was
> of that form, though I agree based on your earlier feedback that
> lower-level functionality should be provided and this implemented in
> JavaScript.
>
> Right, my comments now have to do with the API now that I've had a chance to
> see it. Maybe we went over some showstopper problems with my approach, but I
> don't remember them. And I think a separate uber-view feels too heavyweight.

It's difficult to address your points above independently so let me
try to group the responses together.

The setData() mechanism would work similarly to Java's New I/O (NIO)
API for file reading and writing. Based on my experience with that
API, it has the following problems:
 - It is tedious to read elements at differing alignments throughout the file.
 - It is tedious to sequentially read or write elements of different
types. The file has to be viewed as or converted into many different
TypedArrays and different elements accessed from different arrays.
Element offsets have to be converted to byte offsets all over the
place.

The typed array views work well for bulk transmission of largely
homogeneous data with the platform's native endianness. For the cases
of reading and writing file formats, where the elements are
heterogeneous and defined with a specific endianness, it is much
simpler to read and write those elements directly rather than to first
extract or view a portion of the file into an array and then read one
or more elements from that array. This is true even if the individual
element access isn't quite as fast as it is for the typed arrays,
though the DataView's entry points can be optimized to only a few
machine instructions.

Note also that it doesn't make sense to always store the data in
native endianness as you suggest above. Consider the case of
constructing a TGA file to be uploaded to a web server. The entries in
the header are defined in little endian format, so no matter what the
byte order of the host machine, the transmission buffer must contain
little endian data. The primitives that are required are reading
elements with a specified endianness, for the case where you've
downloaded data from the network and are trying to parse it; and
writing elements with a specified endianness, for the case where
you're assembling data to write to the network. The DataView provides
this functionality and no more.

-Ken

-----------------------------------------------------------
You are currently subscribe to public_webgl@khronos.org.
To unsubscribe, send an email to majordomo@khronos.org with
the following command in the body of your email: