void VertexDataManager::prepareStaticBufferForAttribute(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue) const { gl::Buffer *buffer = attrib.buffer.get(); if (buffer) { BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer); // This will create the static buffer in the right circumstances StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBufferForAttribute(attrib); UNUSED_ASSERTION_VARIABLE(staticBuffer); // This check validates that a valid static vertex buffer was returned above ASSERT(!(staticBuffer && staticBuffer->getBufferSize() > 0 && !staticBuffer->lookupAttribute(attrib, NULL) && !staticBuffer->directStoragePossible(attrib, currentValue))); } }
gl::Error VertexDataManager::reserveSpaceForAttrib(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, GLsizei count, GLsizei instances) const { gl::Buffer *buffer = attrib.buffer.get(); BufferD3D *bufferImpl = buffer ? GetImplAs<BufferD3D>(buffer) : NULL; StaticVertexBufferInterface *staticBuffer = bufferImpl ? bufferImpl->getStaticVertexBufferForAttribute(attrib) : NULL; VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer); if (!vertexBuffer->directStoragePossible(attrib, currentValue)) { if (staticBuffer) { if (staticBuffer->getBufferSize() == 0) { int totalCount = ElementsInBuffer(attrib, bufferImpl->getSize()); gl::Error error = staticBuffer->reserveVertexSpace(attrib, totalCount, 0); if (error.isError()) { return error; } } } else { int totalCount = StreamingBufferElementCount(attrib, count, instances); ASSERT(!bufferImpl || ElementsInBuffer(attrib, bufferImpl->getSize()) >= totalCount); gl::Error error = mStreamingBuffer->reserveVertexSpace(attrib, totalCount, instances); if (error.isError()) { return error; } } } return gl::Error(GL_NO_ERROR); }
gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, TranslatedAttribute *translated, GLint start, GLsizei count, GLsizei instances) { gl::Buffer *buffer = attrib.buffer.get(); ASSERT(buffer || attrib.pointer); BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL; StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBufferForAttribute(attrib) : NULL; VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer); bool directStorage = vertexBuffer->directStoragePossible(attrib, currentValue); unsigned int streamOffset = 0; unsigned int outputElementSize = 0; // Instanced vertices do not apply the 'start' offset GLint firstVertexIndex = (instances > 0 && attrib.divisor > 0 ? 0 : start); if (directStorage) { outputElementSize = ComputeVertexAttributeStride(attrib); streamOffset = static_cast<unsigned int>(attrib.offset + outputElementSize * firstVertexIndex); } else if (staticBuffer) { gl::Error error = staticBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); if (error.isError()) { return error; } if (!staticBuffer->lookupAttribute(attrib, &streamOffset)) { // Convert the entire buffer int totalCount = ElementsInBuffer(attrib, storage->getSize()); int startIndex = attrib.offset / ComputeVertexAttributeStride(attrib); error = staticBuffer->storeVertexAttributes(attrib, currentValue, -startIndex, totalCount, 0, &streamOffset); // Each staticBuffer only contains the data for one attribute, so we know that it won't be modified again. // We can therefore safely unmap it here without hurting perf. staticBuffer->getVertexBuffer()->hintUnmapResource(); if (error.isError()) { return error; } } unsigned int firstElementOffset = (attrib.offset / ComputeVertexAttributeStride(attrib)) * outputElementSize; unsigned int startOffset = (instances == 0 || attrib.divisor == 0) ? firstVertexIndex * outputElementSize : 0; if (streamOffset + firstElementOffset + startOffset < streamOffset) { return gl::Error(GL_OUT_OF_MEMORY); } streamOffset += firstElementOffset + startOffset; } else { int totalCount = StreamingBufferElementCount(attrib, count, instances); gl::Error error = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); if (error.isError()) { return error; } error = mStreamingBuffer->storeVertexAttributes(attrib, currentValue, firstVertexIndex, totalCount, instances, &streamOffset); if (error.isError()) { return error; } } translated->storage = directStorage ? storage : NULL; translated->vertexBuffer = vertexBuffer->getVertexBuffer(); translated->serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial(); translated->divisor = attrib.divisor; translated->attribute = &attrib; translated->currentValueType = currentValue.Type; translated->stride = outputElementSize; translated->offset = streamOffset; return gl::Error(GL_NO_ERROR); }