gl::Error VertexDataManager::storeDynamicAttribs( std::vector<TranslatedAttribute> *translatedAttribs, const gl::AttributesMask &dynamicAttribsMask, GLint start, GLsizei count, GLsizei instances) { // Reserve the required space for the dynamic buffers. for (auto attribIndex : angle::IterateBitSet(dynamicAttribsMask)) { const auto &dynamicAttrib = (*translatedAttribs)[attribIndex]; gl::Error error = reserveSpaceForAttrib(dynamicAttrib, count, instances); if (error.isError()) { return error; } } // Store dynamic attributes for (auto attribIndex : angle::IterateBitSet(dynamicAttribsMask)) { auto *dynamicAttrib = &(*translatedAttribs)[attribIndex]; gl::Error error = storeDynamicAttrib(dynamicAttrib, start, count, instances); if (error.isError()) { unmapStreamingBuffer(); return error; } } unmapStreamingBuffer(); // Promote static usage of dynamic buffers. for (auto attribIndex : angle::IterateBitSet(dynamicAttribsMask)) { auto *dynamicAttrib = &(*translatedAttribs)[attribIndex]; gl::Buffer *buffer = dynamicAttrib->attribute->buffer.get(); if (buffer) { BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer); size_t typeSize = ComputeVertexAttributeTypeSize(*dynamicAttrib->attribute); bufferD3D->promoteStaticUsage(count * static_cast<int>(typeSize)); } } return gl::Error(GL_NO_ERROR); }
angle::Result VertexDataManager::storeDynamicAttribs( const gl::Context *context, std::vector<TranslatedAttribute> *translatedAttribs, const gl::AttributesMask &dynamicAttribsMask, GLint start, size_t count, GLsizei instances) { // Instantiating this class will ensure the streaming buffer is never left mapped. class StreamingBufferUnmapper final : NonCopyable { public: StreamingBufferUnmapper(StreamingVertexBufferInterface *streamingBuffer) : mStreamingBuffer(streamingBuffer) { ASSERT(mStreamingBuffer); } ~StreamingBufferUnmapper() { mStreamingBuffer->getVertexBuffer()->hintUnmapResource(); } private: StreamingVertexBufferInterface *mStreamingBuffer; }; // Will trigger unmapping on return. StreamingBufferUnmapper localUnmapper(&mStreamingBuffer); // Reserve the required space for the dynamic buffers. for (auto attribIndex : dynamicAttribsMask) { const auto &dynamicAttrib = (*translatedAttribs)[attribIndex]; ANGLE_TRY(reserveSpaceForAttrib(context, dynamicAttrib, start, count, instances)); } // Store dynamic attributes for (auto attribIndex : dynamicAttribsMask) { auto *dynamicAttrib = &(*translatedAttribs)[attribIndex]; ANGLE_TRY(storeDynamicAttrib(context, dynamicAttrib, start, count, instances)); } return angle::Result::Continue(); }