Home | History | Annotate | Download | only in libGLESv2
      1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //    http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 // VertexDataManager.h: Defines the VertexDataManager, a class that
     16 // runs the Buffer translation process.
     17 
     18 #include "VertexDataManager.h"
     19 
     20 #include "Buffer.h"
     21 #include "Program.h"
     22 #include "IndexDataManager.h"
     23 #include "common/debug.h"
     24 
     25 namespace
     26 {
     27 	enum {INITIAL_STREAM_BUFFER_SIZE = 1024 * 1024};
     28 }
     29 
     30 namespace es2
     31 {
     32 
     33 VertexDataManager::VertexDataManager(Context *context) : mContext(context)
     34 {
     35 	for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
     36 	{
     37 		mDirtyCurrentValue[i] = true;
     38 		mCurrentValueBuffer[i] = nullptr;
     39 	}
     40 
     41 	mStreamingBuffer = new StreamingVertexBuffer(INITIAL_STREAM_BUFFER_SIZE);
     42 
     43 	if(!mStreamingBuffer)
     44 	{
     45 		ERR("Failed to allocate the streaming vertex buffer.");
     46 	}
     47 }
     48 
     49 VertexDataManager::~VertexDataManager()
     50 {
     51 	delete mStreamingBuffer;
     52 
     53 	for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
     54 	{
     55 		delete mCurrentValueBuffer[i];
     56 	}
     57 }
     58 
     59 unsigned int VertexDataManager::writeAttributeData(StreamingVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute)
     60 {
     61 	Buffer *buffer = attribute.mBoundBuffer;
     62 
     63 	int inputStride = attribute.stride();
     64 	int elementSize = attribute.typeSize();
     65 	unsigned int streamOffset = 0;
     66 
     67 	char *output = nullptr;
     68 
     69 	if(vertexBuffer)
     70 	{
     71 		output = (char*)vertexBuffer->map(attribute, attribute.typeSize() * count, &streamOffset);
     72 	}
     73 
     74 	if(!output)
     75 	{
     76 		ERR("Failed to map vertex buffer.");
     77 		return ~0u;
     78 	}
     79 
     80 	const char *input = nullptr;
     81 
     82 	if(buffer)
     83 	{
     84 		input = static_cast<const char*>(buffer->data()) + attribute.mOffset;
     85 	}
     86 	else
     87 	{
     88 		input = static_cast<const char*>(attribute.mPointer);
     89 	}
     90 
     91 	input += inputStride * start;
     92 
     93 	if(inputStride == elementSize)
     94 	{
     95 		memcpy(output, input, count * inputStride);
     96 	}
     97 	else
     98 	{
     99 		for(int i = 0; i < count; i++)
    100 		{
    101 			memcpy(output, input, elementSize);
    102 			output += elementSize;
    103 			input += inputStride;
    104 		}
    105 	}
    106 
    107 	vertexBuffer->unmap();
    108 
    109 	return streamOffset;
    110 }
    111 
    112 GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instanceId)
    113 {
    114 	if(!mStreamingBuffer)
    115 	{
    116 		return GL_OUT_OF_MEMORY;
    117 	}
    118 
    119 	const VertexAttributeArray &attribs = mContext->getVertexArrayAttributes();
    120 	const VertexAttributeArray &currentAttribs = mContext->getCurrentVertexAttributes();
    121 	Program *program = mContext->getCurrentProgram();
    122 
    123 	// Determine the required storage size per used buffer
    124 	for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
    125 	{
    126 		const VertexAttribute &attrib = attribs[i].mArrayEnabled ? attribs[i] : currentAttribs[i];
    127 
    128 		if(program->getAttributeStream(i) != -1 && attrib.mArrayEnabled)
    129 		{
    130 			if(!attrib.mBoundBuffer)
    131 			{
    132 				const bool isInstanced = attrib.mDivisor > 0;
    133 				mStreamingBuffer->addRequiredSpace(attrib.typeSize() * (isInstanced ? 1 : count));
    134 			}
    135 		}
    136 	}
    137 
    138 	mStreamingBuffer->reserveRequiredSpace();
    139 
    140 	// Perform the vertex data translations
    141 	for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
    142 	{
    143 		if(program->getAttributeStream(i) != -1)
    144 		{
    145 			const VertexAttribute &attrib = attribs[i].mArrayEnabled ? attribs[i] : currentAttribs[i];
    146 
    147 			if(attrib.mArrayEnabled)
    148 			{
    149 				const bool isInstanced = attrib.mDivisor > 0;
    150 
    151 				// Instanced vertices do not apply the 'start' offset
    152 				GLint firstVertexIndex = isInstanced ? instanceId / attrib.mDivisor : start;
    153 
    154 				Buffer *buffer = attrib.mBoundBuffer;
    155 
    156 				if((!buffer && attrib.mPointer == nullptr) || (buffer && !buffer->data()))
    157 				{
    158 					// This is an application error that would normally result in a crash, but we catch it and return an error
    159 					ERR("An enabled vertex array has no buffer and no pointer.");
    160 					return GL_INVALID_OPERATION;
    161 				}
    162 
    163 				sw::Resource *staticBuffer = buffer ? buffer->getResource() : nullptr;
    164 
    165 				if(staticBuffer)
    166 				{
    167 					translated[i].vertexBuffer = staticBuffer;
    168 					translated[i].offset = firstVertexIndex * attrib.stride() + static_cast<int>(attrib.mOffset);
    169 					translated[i].stride = isInstanced ? 0 : attrib.stride();
    170 				}
    171 				else
    172 				{
    173 					unsigned int streamOffset = writeAttributeData(mStreamingBuffer, firstVertexIndex, isInstanced ? 1 : count, attrib);
    174 
    175 					if(streamOffset == ~0u)
    176 					{
    177 						return GL_OUT_OF_MEMORY;
    178 					}
    179 
    180 					translated[i].vertexBuffer = mStreamingBuffer->getResource();
    181 					translated[i].offset = streamOffset;
    182 					translated[i].stride = isInstanced ? 0 : attrib.typeSize();
    183 				}
    184 
    185 				switch(attrib.mType)
    186 				{
    187 				case GL_BYTE:           translated[i].type = sw::STREAMTYPE_SBYTE;  break;
    188 				case GL_UNSIGNED_BYTE:  translated[i].type = sw::STREAMTYPE_BYTE;   break;
    189 				case GL_SHORT:          translated[i].type = sw::STREAMTYPE_SHORT;  break;
    190 				case GL_UNSIGNED_SHORT: translated[i].type = sw::STREAMTYPE_USHORT; break;
    191 				case GL_INT:            translated[i].type = sw::STREAMTYPE_INT;    break;
    192 				case GL_UNSIGNED_INT:   translated[i].type = sw::STREAMTYPE_UINT;   break;
    193 				case GL_FIXED:          translated[i].type = sw::STREAMTYPE_FIXED;  break;
    194 				case GL_FLOAT:          translated[i].type = sw::STREAMTYPE_FLOAT;  break;
    195 				case GL_HALF_FLOAT:     translated[i].type = sw::STREAMTYPE_HALF;   break;
    196 				case GL_HALF_FLOAT_OES: translated[i].type = sw::STREAMTYPE_HALF;   break;
    197 				case GL_INT_2_10_10_10_REV:          translated[i].type = sw::STREAMTYPE_2_10_10_10_INT;  break;
    198 				case GL_UNSIGNED_INT_2_10_10_10_REV: translated[i].type = sw::STREAMTYPE_2_10_10_10_UINT; break;
    199 				default: UNREACHABLE(attrib.mType); translated[i].type = sw::STREAMTYPE_FLOAT;  break;
    200 				}
    201 
    202 				translated[i].count = attrib.mSize;
    203 				translated[i].normalized = attrib.mNormalized;
    204 			}
    205 			else
    206 			{
    207 				if(mDirtyCurrentValue[i])
    208 				{
    209 					delete mCurrentValueBuffer[i];
    210 					mCurrentValueBuffer[i] = new ConstantVertexBuffer(attrib.getCurrentValueBitsAsFloat(0), attrib.getCurrentValueBitsAsFloat(1), attrib.getCurrentValueBitsAsFloat(2), attrib.getCurrentValueBitsAsFloat(3));
    211 					mDirtyCurrentValue[i] = false;
    212 				}
    213 
    214 				translated[i].vertexBuffer = mCurrentValueBuffer[i]->getResource();
    215 
    216 				switch(attrib.currentValueType())
    217 				{
    218 				case GL_INT:
    219 					translated[i].type = sw::STREAMTYPE_INT;
    220 					break;
    221 				case GL_UNSIGNED_INT:
    222 					translated[i].type = sw::STREAMTYPE_UINT;
    223 					break;
    224 				default:
    225 					translated[i].type = sw::STREAMTYPE_FLOAT;
    226 					break;
    227 				}
    228 				translated[i].count = 4;
    229 				translated[i].stride = 0;
    230 				translated[i].offset = 0;
    231 				translated[i].normalized = false;
    232 			}
    233 		}
    234 	}
    235 
    236 	return GL_NO_ERROR;
    237 }
    238 
    239 VertexBuffer::VertexBuffer(unsigned int size) : mVertexBuffer(nullptr)
    240 {
    241 	if(size > 0)
    242 	{
    243 		mVertexBuffer = new sw::Resource(size + 1024);
    244 
    245 		if(!mVertexBuffer)
    246 		{
    247 			ERR("Out of memory allocating a vertex buffer of size %u.", size);
    248 		}
    249 	}
    250 }
    251 
    252 VertexBuffer::~VertexBuffer()
    253 {
    254 	if(mVertexBuffer)
    255 	{
    256 		mVertexBuffer->destruct();
    257 	}
    258 }
    259 
    260 void VertexBuffer::unmap()
    261 {
    262 	if(mVertexBuffer)
    263 	{
    264 		mVertexBuffer->unlock();
    265 	}
    266 }
    267 
    268 sw::Resource *VertexBuffer::getResource() const
    269 {
    270 	return mVertexBuffer;
    271 }
    272 
    273 ConstantVertexBuffer::ConstantVertexBuffer(float x, float y, float z, float w) : VertexBuffer(4 * sizeof(float))
    274 {
    275 	if(mVertexBuffer)
    276 	{
    277 		float *vector = (float*)mVertexBuffer->lock(sw::PUBLIC);
    278 
    279 		vector[0] = x;
    280 		vector[1] = y;
    281 		vector[2] = z;
    282 		vector[3] = w;
    283 
    284 		mVertexBuffer->unlock();
    285 	}
    286 }
    287 
    288 ConstantVertexBuffer::~ConstantVertexBuffer()
    289 {
    290 }
    291 
    292 StreamingVertexBuffer::StreamingVertexBuffer(unsigned int size) : VertexBuffer(size)
    293 {
    294 	mBufferSize = size;
    295 	mWritePosition = 0;
    296 	mRequiredSpace = 0;
    297 }
    298 
    299 StreamingVertexBuffer::~StreamingVertexBuffer()
    300 {
    301 }
    302 
    303 void StreamingVertexBuffer::addRequiredSpace(unsigned int requiredSpace)
    304 {
    305 	mRequiredSpace += requiredSpace;
    306 }
    307 
    308 void *StreamingVertexBuffer::map(const VertexAttribute &attribute, unsigned int requiredSpace, unsigned int *offset)
    309 {
    310 	void *mapPtr = nullptr;
    311 
    312 	if(mVertexBuffer)
    313 	{
    314 		// We can use a private lock because we never overwrite the content
    315 		mapPtr = (char*)mVertexBuffer->lock(sw::PRIVATE) + mWritePosition;
    316 
    317 		*offset = mWritePosition;
    318 		mWritePosition += requiredSpace;
    319 	}
    320 
    321 	return mapPtr;
    322 }
    323 
    324 void StreamingVertexBuffer::reserveRequiredSpace()
    325 {
    326 	if(mRequiredSpace > mBufferSize)
    327 	{
    328 		if(mVertexBuffer)
    329 		{
    330 			mVertexBuffer->destruct();
    331 			mVertexBuffer = 0;
    332 		}
    333 
    334 		mBufferSize = std::max(mRequiredSpace, 3 * mBufferSize / 2);   // 1.5 x mBufferSize is arbitrary and should be checked to see we don't have too many reallocations.
    335 
    336 		mVertexBuffer = new sw::Resource(mBufferSize);
    337 
    338 		if(!mVertexBuffer)
    339 		{
    340 			ERR("Out of memory allocating a vertex buffer of size %u.", mBufferSize);
    341 		}
    342 
    343 		mWritePosition = 0;
    344 	}
    345 	else if(mWritePosition + mRequiredSpace > mBufferSize)   // Recycle
    346 	{
    347 		if(mVertexBuffer)
    348 		{
    349 			mVertexBuffer->destruct();
    350 			mVertexBuffer = new sw::Resource(mBufferSize);
    351 		}
    352 
    353 		mWritePosition = 0;
    354 	}
    355 
    356 	mRequiredSpace = 0;
    357 }
    358 
    359 }
    360