int StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances) { int attributeOffset = attrib.mOffset % attrib.stride(); VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attributeOffset, getWritePosition() }; mCache.push_back(element); return VertexBufferInterface::storeVertexAttributes(attrib, start, count, instances); }
static int ElementsInBuffer(const gl::VertexAttribute &attribute, unsigned int size) { // Size cannot be larger than a GLsizei if (size > static_cast<unsigned int>(std::numeric_limits<int>::max())) { size = static_cast<unsigned int>(std::numeric_limits<int>::max()); } GLsizei stride = attribute.stride(); return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride; }
bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue) const { gl::Buffer *buffer = attrib.mBoundBuffer.get(); BufferStorage *storage = buffer ? buffer->getStorage() : NULL; if (!storage || !storage->supportsDirectBinding()) { return false; } // Alignment restrictions: In D3D, vertex data must be aligned to // the format stride, or to a 4-byte boundary, whichever is smaller. // (Undocumented, and experimentally confirmed) size_t alignment = 4; bool requiresConversion = false; if (attrib.mType != GL_FLOAT) { gl::VertexFormat vertexFormat(attrib, currentValue.Type); unsigned int outputElementSize; getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); alignment = std::min<size_t>(outputElementSize, 4); requiresConversion = (mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) != 0; } bool isAligned = (static_cast<size_t>(attrib.stride()) % alignment == 0) && (static_cast<size_t>(attrib.mOffset) % alignment == 0); return !requiresConversion && isAligned; }
static bool directStoragePossible(VertexBufferInterface* vb, const gl::VertexAttribute& attrib) { gl::Buffer *buffer = attrib.mBoundBuffer.get(); BufferStorage *storage = buffer ? buffer->getStorage() : NULL; const bool isAligned = (attrib.stride() % 4 == 0) && (attrib.mOffset % 4 == 0); return storage && storage->supportsDirectBinding() && !vb->getVertexBuffer()->requiresConversion(attrib) && isAligned; }
int StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute) { for (unsigned int element = 0; element < mCache.size(); element++) { if (mCache[element].type == attribute.mType && mCache[element].size == attribute.mSize && mCache[element].stride == attribute.stride() && mCache[element].normalized == attribute.mNormalized) { if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride()) { return mCache[element].streamOffset; } } } return -1; }
bool StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset) { unsigned int streamOffset; if (VertexBufferInterface::storeVertexAttributes(attrib, currentValue, start, count, instances, &streamOffset)) { int attributeOffset = attrib.mOffset % attrib.stride(); VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attrib.mPureInteger, attributeOffset, streamOffset }; mCache.push_back(element); if (outStreamOffset) { *outStreamOffset = streamOffset; } return true; } else { return false; } }
bool VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, unsigned int offset) { if (mBuffer) { gl::Buffer *buffer = attrib.mBoundBuffer.get(); int inputStride = attrib.stride(); const VertexConverter &converter = getVertexConversion(attrib); ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); D3D11_MAPPED_SUBRESOURCE mappedResource; HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); if (FAILED(result)) { ERR("Vertex buffer map failed with error 0x%08x", result); return false; } char* output = reinterpret_cast<char*>(mappedResource.pData) + offset; const char *input = NULL; if (buffer) { BufferStorage *storage = buffer->getStorage(); input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.mOffset); } else { input = static_cast<const char*>(attrib.mPointer); } if (instances == 0 || attrib.mDivisor == 0) { input += inputStride * start; } converter.conversionFunc(input, inputStride, count, output); dxContext->Unmap(mBuffer, 0); return true; } else { ERR("Vertex buffer not initialized."); return false; } }
bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute, unsigned int *outStreamOffset) { for (unsigned int element = 0; element < mCache.size(); element++) { if (mCache[element].type == attribute.mType && mCache[element].size == attribute.mSize && mCache[element].stride == attribute.stride() && mCache[element].normalized == attribute.mNormalized && mCache[element].pureInteger == attribute.mPureInteger) { if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride()) { if (outStreamOffset) { *outStreamOffset = mCache[element].streamOffset; } return true; } } } return false; }
static int elementsInBuffer(const gl::VertexAttribute &attribute, int size) { int stride = attribute.stride(); return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride; }