void prepareDrawElementsEntry( RenderEngineGLIndirect::RenderGroupGLCache::DrawElementsListEntry *entry )
      {
        entry->m_indirectCommandsBuffer = nullptr;
        handleAssign( entry->m_indirectCommandsBuffer, BufferGL::create( dp::rix::core::BufferDescription() ) );
        entry->m_indirectCommandsBuffer->updateData( 0, &entry->m_indirectCommands[0], entry->m_indirectCommands.size() * sizeof(RenderEngineGLIndirect::RenderGroupGLCache::DrawElementsIndirectCommand) );

        entry->m_indirectEntriesBuffer = nullptr;
        handleAssign( entry->m_indirectEntriesBuffer, BufferGL::create( dp::rix::core::BufferDescription() ) );
        entry->m_indirectEntriesBuffer->updateData( 0, &entry->m_indirectEntries[0], entry->m_indirectEntries.size() * sizeof(RenderEngineGLIndirect::RenderGroupGLCache::IndirectEntry));

        entry->m_indirectPointersBuffer = nullptr;
        handleAssign( entry->m_indirectPointersBuffer, BufferGL::create( dp::rix::core::BufferDescription() ) );
        std::vector<GLuint64EXT> pointers;

        DP_ASSERT( entry->m_indirectEntriesBuffer->getBuffer() );
        dp::gl::BufferSharedPtr const& buffer = entry->m_indirectEntriesBuffer->getBuffer();
        GLuint64EXT base = buffer->getAddress();
        for ( size_t index = 0;index < entry->m_indirectEntries.size(); ++index )
        {
          pointers.push_back( base + index * sizeof(RenderEngineGLIndirect::RenderGroupGLCache::IndirectEntry) );
        }

        entry->m_indirectPointersBuffer->updateData( 0, &pointers[0], pointers.size() * sizeof(GLuint64EXT) );

        entry->m_indirectPointersBufferAddress = base;
        entry->m_indirectPointersBufferRange = buffer->getSize();

      }
Example #2
0
Value Interpreter::exec(const InstructionList &instructions, Bindings &bindings)
{
	Stack stack;
	ClosureValues closureValues;

	for(InstructionList::const_iterator it = instructions.begin() ; it != instructions.end() ; ++it)
	{
		Instruction::Type type = it->type();
		const Value &value = it->value();
		switch(type)
		{
		case Instruction::PUSH:
			if(settings_.trace)
			{				
				std::cout << "DEBUG: " << it->sourceLocation() << " push " << value << '\n';
			}
			stack.push_back(value);
			break;
		case Instruction::CALL:
			{
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " call " << value << '\n';
				}
				Value result = handleFunction(it->sourceLocation(), value, stack, bindings);
				stack.push_back(result);
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " return value " << result << '\n';
				}
			}
			break;
		case Instruction::JUMP:
			{
				int instructionsToSkip = getInstructionsToSkip(type, value);
				int remaining = instructions.end() - it;
				if(remaining < instructionsToSkip)
				{
					throw CompilerBug("insufficient instructions available to skip! (remaining: " + str(remaining) + " < instructionsToSkip: " + str(instructionsToSkip) + ")");
				}

				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " jumping back " << instructionsToSkip << '\n';
				}
				it += instructionsToSkip;
			}
			break;
		case Instruction::LOOP:
			{
				int instructionsToSkip = getInstructionsToSkip(type, value);
				int instructionsAvailable = instructions.size(); // Note: signed type is important!
				if(instructionsAvailable < instructionsToSkip)
				{
					throw CompilerBug("insufficient instructions available to loop! (instructionsToSkip: " + str(instructionsToSkip) + " > instructions.size(): " + str(instructions.size()) + ")");
				}

				if(settings_.trace)
				{				
					std::cout << "DEBUG: " << it->sourceLocation() << " looping back " << instructionsToSkip << " instructions\n";
				}
				it -= instructionsToSkip;
			}
			break;
		case Instruction::CLOSE:
			{
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " close " << value << '\n';
				}
				Value result = handleClose(value, stack, closureValues, bindings);
				stack.push_back(result);
			}
			break;
		case Instruction::COND_JUMP:
			{
				if(stack.empty())
				{
					throw CompilerBug("empty stack when testing conditional jump");
				}
				int instructionsToSkip = getInstructionsToSkip(type, value);
				int remaining = instructions.end() - it;
				if(remaining < instructionsToSkip)
				{
					throw CompilerBug("insufficient instructions available to skip! (remaining: " + str(remaining) + " < instructionsToSkip: " + str(instructionsToSkip) + ")");
				}

				Value top = pop(stack);
				if(settings_.trace)
				{				
					std::cout << "DEBUG: " << it->sourceLocation() << " jumping back " << instructionsToSkip << " if " << top << '\n';
				}

				if(top.isFalsey())
				{
					it += instructionsToSkip;
				}
			}
			break;
		case Instruction::REF_LOCAL:
			handleRef(Bindings::Local, value, stack, bindings);
			if(settings_.trace)
			{
				std::cout << "DEBUG: " << it->sourceLocation() << " local ref '" << value.string() << "' is " << stack.back() << '\n';
			}
			break;
		case Instruction::INIT_LOCAL:
			{
				const Value &intialisedValue = handleInit(Bindings::Local, value, stack, bindings);
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " local init '" << value.string() << "' to " << intialisedValue << '\n';
				}
			}
			break;
		case Instruction::ASSIGN_LOCAL:
			{
				const Value &assignedValue = handleAssign(Bindings::Local, value, stack, bindings);
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " local assign '" << value.string() << "' to " << assignedValue << '\n';
				}
			}
			break;
		case Instruction::REF_GLOBAL:
			handleRef(Bindings::Global, value, stack, bindings);
			if(settings_.trace)
			{
				std::cout << "DEBUG: " << it->sourceLocation() << " global ref '" << value.string() << "' is " << stack.back() << '\n';
			}
			break;
		case Instruction::INIT_GLOBAL:
			{
				const Value &intialisedValue = handleInit(Bindings::Global, value, stack, bindings);
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " global init '" << value.string() << "' to " << intialisedValue << '\n';
				}
			}
			break;
		case Instruction::ASSIGN_GLOBAL:
			{
				const Value &assignedValue = handleAssign(Bindings::Global, value, stack, bindings);
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " global assign '" << value.string() << "' to " << assignedValue << '\n';
				}
			}
			break;
		case Instruction::REF_CLOSURE:
			handleRef(Bindings::Closure, value, stack, bindings);
			if(settings_.trace)
			{
				std::cout << "DEBUG: " << it->sourceLocation() << " closure ref '" << value.string() << "' is " << stack.back() << '\n';
			}
			break;
		case Instruction::INIT_CLOSURE:
			{
				Identifier identifier = Identifier(value.string());
				Bindings::ValuePtr &binding = bindings.getPointer(identifier);
				closureValues.push_back(ClosedNameAndValue(identifier, binding));
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " closure init '" << value.string() << "' is " << *binding << '\n';
				}
			}
			break;
		case Instruction::ASSIGN_CLOSURE:
			{
				const Value &assignedValue = handleAssign(Bindings::Closure, value, stack, bindings);
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " closure assign '" << value.string() << "' to " << assignedValue << '\n';
				}
			}
			break;
		case Instruction::MEMBER_ACCESS:
			{
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " member access " << value << '\n';
				}
				assert(value.isString());
				const std::string &memberName = value.string();

				Value top = pop(stack);
				if(!top.isObject())
				{
					throw ExecutionError(it->sourceLocation(), "Member access instruction requires an object but got " + str(top));
				}
				const Value::Object &object = top.object();
				Value::Object::const_iterator memberIterator = object.find(memberName);
				if (memberIterator == object.end())
				{
					throw ExecutionError(it->sourceLocation(), "Unknown member name " + memberName + " for " + str(top));
				}
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " member access " << value.string() << "." << memberName << " was " << memberIterator->second << '\n';
				}
				stack.push_back(memberIterator->second);
			}
			break;
		default:
			throw CompilerBug("unhandled instruction type: " + str(type));
		}

		if (settings_.trace)
		{
			if (stack.empty())
			{
				std::cout << "Stack is empty\n";
			}
			else
			{
				std::cout << "Stack contains " << stack.size() << " entries:\n";
				int index = 0;
				for(Stack::const_iterator it = stack.begin() ; it != stack.end() ; ++it)
				{
					++index;
					std::cout << index << ":  " << *it << '\n';
				}
			}

			if (closureValues.empty())
			{
				std::cout << "closureValues is empty\n";
			}
			else
			{
				std::cout << "closureValues contains " << closureValues.size() << " entries:\n";
				int index = 0;
				for(const ClosedNameAndValue &closedValue: closureValues)
				{
					++index;
					std::cout << index << ":  " << closedValue.first << " -> " << *closedValue.second << " @ " << closedValue.second << '\n';
				}
			}
		}
	}
	
	return stack.empty() ? Value::nil() : pop(stack);
}