示例#1
0
Bool GpuBlockAllocator::blockHasEnoughSpace(U blockIdx, PtrSize size, U alignment) const
{
	ANKI_ASSERT(size > 0);

	const Block& block = m_blocks[blockIdx];

	PtrSize allocEnd = getAlignedRoundUp(alignment, block.m_offset) + size;
	PtrSize blockEnd = (blockIdx + 1) * m_blockSize;

	return allocEnd <= blockEnd;
}
示例#2
0
Error GpuBlockAllocator::allocate(PtrSize size, U alignment, PtrSize& outOffset)
{
	ANKI_ASSERT(isCreated());
	ANKI_ASSERT(size < m_blockSize);

	Block* block = nullptr;
	Error err = ErrorCode::NONE;

	LockGuard<Mutex> lock(m_mtx);

	if(m_currentBlock == MAX_U32 || !blockHasEnoughSpace(m_currentBlock, size, alignment))
	{
		// Need new block
		if(m_freeBlockCount > 0)
		{
			// Pop block from free
			U blockIdx = --m_freeBlockCount;

			block = &m_blocks[blockIdx];
			block->m_offset = blockIdx * m_blockSize;
			ANKI_ASSERT(block->m_allocationCount == 0);

			// Make it in-use
			m_currentBlock = blockIdx;
		}
	}

	if(block)
	{
		PtrSize outOffset = getAlignedRoundUp(alignment, block->m_offset);
		block->m_offset = outOffset + size;
		ANKI_ASSERT(block->m_offset <= (block - &m_blocks[0] + 1) * m_blockSize);

		++block->m_allocationCount;

		// Update the handle
		outOffset = outOffset;
	}
	else
	{
		err = ErrorCode::OUT_OF_MEMORY;
		outOffset = MAX_PTR_SIZE;
	}

	return err;
}
void CommandBufferPtr::updateDynamicUniforms(void* data, U32 originalSize)
{
	ANKI_ASSERT(data);
	ANKI_ASSERT(originalSize > 0);
	ANKI_ASSERT(originalSize <= 1024 * 4 && "Too high?");

	GlState& state =
		get().getManager().getImplementation().getRenderingThread().getState();

	const U uboSize = state.m_globalUboSize;
	const U subUboSize = GlState::MAX_UBO_SIZE;

	// Get offset in the contiguous buffer
	U size = getAlignedRoundUp(state.m_uniBuffOffsetAlignment, originalSize);
	U offset = state.m_globalUboCurrentOffset.fetchAdd(size);
	offset = offset % uboSize;

	while((offset % subUboSize) + size > subUboSize)
	{
		// Update area will fall between UBOs, need to start over
		offset = state.m_globalUboCurrentOffset.fetchAdd(size);
		offset = offset % uboSize;
	}

	ANKI_ASSERT(isAligned(state.m_uniBuffOffsetAlignment, offset));
	ANKI_ASSERT(offset + size <= uboSize);

	// Get actual UBO address to write
	U uboIdx = offset / subUboSize;
	U subUboOffset = offset % subUboSize;
	ANKI_ASSERT(isAligned(state.m_uniBuffOffsetAlignment, subUboOffset));

	U8* addressToWrite = state.m_globalUboAddresses[uboIdx] + subUboOffset;

	// Write
	memcpy(addressToWrite, data, originalSize);

	// Push bind command
	get().pushBackNewCommand<UpdateUniformsCommand>(
		state.m_globalUbos[uboIdx], subUboOffset, originalSize);
}