First version wof space working with Transaction & Collection

This commit is contained in:
Sam Gateau 2018-03-13 01:45:21 -07:00
parent 1af139a4d4
commit a2993c7cdb
11 changed files with 229 additions and 121 deletions

View file

@ -56,7 +56,7 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext,
return;
}
std::vector<workload::Space::Proxy> proxies(space->getNumAllocatedProxies());
workload::Proxy::Vector proxies(space->getNumAllocatedProxies());
space->copyProxyValues(proxies.data(), (uint32_t)proxies.size());
workload::Views views(space->getNumViews());
@ -130,9 +130,9 @@ void GameWorkloadRenderItem::showViews(bool show) {
}
void GameWorkloadRenderItem::setAllProxies(const std::vector<workload::Space::Proxy>& proxies) {
void GameWorkloadRenderItem::setAllProxies(const workload::Proxy::Vector& proxies) {
_myOwnProxies = proxies;
static const uint32_t sizeOfProxy = sizeof(workload::Space::Proxy);
static const uint32_t sizeOfProxy = sizeof(workload::Proxy);
if (!_allProxiesBuffer) {
_allProxiesBuffer = std::make_shared<gpu::Buffer>(sizeOfProxy);
}

View file

@ -63,7 +63,7 @@ public:
void showProxies(bool show);
void showViews(bool show);
void setAllProxies(const std::vector<workload::Space::Proxy>& proxies);
void setAllProxies(const workload::Proxy::Vector& proxies);
void setAllViews(const workload::Views& views);
render::ItemKey getKey() const;
@ -71,7 +71,7 @@ public:
protected:
render::Item::Bound _bound;
std::vector<workload::Space::Proxy> _myOwnProxies;
workload::Proxy::Vector _myOwnProxies;
gpu::BufferPointer _allProxiesBuffer;
uint32_t _numAllProxies{ 0 };

View file

@ -281,8 +281,11 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r
}
if (entity->getSpaceIndex() == -1) {
std::unique_lock<std::mutex> lock(_spaceLock);
workload::Space::Sphere sphere(entity->getWorldPosition(), entity->getBoundingRadius());
int32_t spaceIndex = _space->createProxy(sphere);
auto spaceIndex = _space->allocateID();
workload::Sphere sphere(entity->getWorldPosition(), entity->getBoundingRadius());
workload::Transaction transaction;
transaction.reset(spaceIndex, sphere);
_space->enqueueTransaction(transaction);
entity->setSpaceIndex(spaceIndex);
connect(entity.get(), &EntityItem::spaceUpdate, this, &EntityTreeRenderer::handleSpaceUpdate, Qt::QueuedConnection);
}
@ -427,17 +430,19 @@ void EntityTreeRenderer::update(bool simulate) {
scene->enqueueTransaction(transaction);
}
}
workload::Transaction spaceTransaction;
{ // update proxies in the workload::Space
std::unique_lock<std::mutex> lock(_spaceLock);
_space->updateProxies(_spaceUpdates);
spaceTransaction.update(_spaceUpdates);
_spaceUpdates.clear();
}
{
std::vector<int32_t> staleProxies;
tree->swapStaleProxies(staleProxies);
spaceTransaction.remove(staleProxies);
{
std::unique_lock<std::mutex> lock(_spaceLock);
_space->deleteProxies(staleProxies);
_space->enqueueTransaction(spaceTransaction);
}
}
@ -458,7 +463,7 @@ void EntityTreeRenderer::update(bool simulate) {
void EntityTreeRenderer::handleSpaceUpdate(std::pair<int32_t, glm::vec4> proxyUpdate) {
std::unique_lock<std::mutex> lock(_spaceLock);
_spaceUpdates.push_back(proxyUpdate);
_spaceUpdates.emplace_back(proxyUpdate.first, proxyUpdate.second);
}
bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QVector<EntityItemID>* entitiesContainingAvatar) {

View file

@ -270,7 +270,7 @@ private:
mutable std::mutex _spaceLock;
workload::SpacePointer _space{ new workload::Space() };
std::vector<workload::Space::ProxyUpdate> _spaceUpdates;
workload::Transaction::Updates _spaceUpdates;
};

View file

@ -29,6 +29,7 @@ namespace workload {
using JobModel = Task::ModelI<EngineBuilder, Inputs>;
void build(JobModel& model, const Varying& in, Varying& out) {
model.addJob<SetupViews>("setupViews", in);
model.addJob<PerformSpaceTransaction>("updateSpace");
const auto regionChanges = model.addJob<RegionTracker>("regionTracker");
model.addJob<RegionState>("regionState", regionChanges);
@ -38,5 +39,15 @@ namespace workload {
Engine::Engine(const WorkloadContextPointer& context) : Task("Engine", EngineBuilder::JobModel::create()),
_context(context) {
}
void PerformSpaceTransaction::configure(const Config& config) {
}
void PerformSpaceTransaction::run(const WorkloadContextPointer& context) {
context->_space->enqueueFrame();
context->_space->processTransactionQueue();
}
} // namespace workload

View file

@ -50,6 +50,24 @@ namespace workload {
};
using EnginePointer = std::shared_ptr<Engine>;
class PerformSpaceTransactionConfig : public Job::Config {
Q_OBJECT
public:
signals :
void dirty();
protected:
};
class PerformSpaceTransaction {
public:
using Config = PerformSpaceTransactionConfig;
using JobModel = Job::Model<PerformSpaceTransaction, Config>;
void configure(const Config& config);
void run(const WorkloadContextPointer& context);
protected:
};
} // namespace workload
#endif // hifi_workload_Space_h

View file

@ -21,10 +21,12 @@ public:
Proxy(const Sphere& s) : sphere(s) {}
Sphere sphere;
uint8_t region{ Region::UNKNOWN };
uint8_t prevRegion{ Region::UNKNOWN };
uint8_t region{ Region::INVALID };
uint8_t prevRegion{ Region::INVALID };
uint16_t _padding;
uint32_t _paddings[3];
using Vector = std::vector<Proxy>;
};

View file

@ -20,11 +20,80 @@
using namespace workload;
void Space::clear() {
_proxies.clear();
_freeIndices.clear();
Space::Space() : Collection() {
}
void Space::processTransactionFrame(const Transaction& transaction) {
std::unique_lock<std::mutex> lock(_proxiesMutex);
// Here we should be able to check the value of last ProxyID allocated
// and allocate new proxies accordingly
ProxyID maxID = _IDAllocator.getNumAllocatedIndices();
if (maxID > _proxies.size()) {
_proxies.resize(maxID + 100); // allocate the maxId and more
}
// Now we know for sure that we have enough items in the array to
// capture anything coming from the transaction
// resets and potential NEW items
processResets(transaction._resetItems);
// Update the numItemsAtomic counter AFTER the reset changes went through
// _numAllocatedItems.exchange(maxID);
// updates
processUpdates(transaction._updatedItems);
// removes
processRemoves(transaction._removedItems);
// Update the numItemsAtomic counter AFTER the pending changes went through
// _numAllocatedItems.exchange(maxID);
}
void Space::processResets(const Transaction::Resets& transactions) {
for (auto& reset : transactions) {
// Access the true item
auto ProxyID = std::get<0>(reset);
auto& item = _proxies[ProxyID];
// Reset the item with a new payload
item.sphere = (std::get<1>(reset));
item.prevRegion = item.region = Region::UNKNOWN;
}
}
void Space::processRemoves(const Transaction::Removes& transactions) {
for (auto removedID : transactions) {
_IDAllocator.freeIndex(removedID);
// Access the true item
auto& item = _proxies[removedID];
// Kill it
item.prevRegion = item.region = Region::INVALID;
}
}
void Space::processUpdates(const Transaction::Updates& transactions) {
for (auto& update : transactions) {
auto updateID = std::get<0>(update);
if (updateID == INVALID_PROXY_ID) {
continue;
}
// Access the true item
auto& item = _proxies[updateID];
// Update the item
// item.update(std::get<1>(update));
item.sphere = (std::get<1>(update));
item.prevRegion = item.region = Region::UNKNOWN;
}
}
/*
int32_t Space::createProxy(const Space::Sphere& newSphere) {
if (_freeIndices.empty()) {
_proxies.emplace_back(Space::Proxy(newSphere));
@ -37,32 +106,25 @@ int32_t Space::createProxy(const Space::Sphere& newSphere) {
_proxies[index].prevRegion = Region::UNKNOWN;
return index;
}
}
}*/
/*
void Space::deleteProxies(const std::vector<int32_t>& deadIndices) {
for (uint32_t i = 0; i < deadIndices.size(); ++i) {
deleteProxy(deadIndices[i]);
}
}
void Space::updateProxies(const std::vector<ProxyUpdate>& changedProxies) {
*/
/*void Space::updateProxies(const std::vector<ProxyUpdate>& changedProxies) {
for (uint32_t i = 0; i < changedProxies.size(); ++i) {
int32_t proxyId = changedProxies[i].first;
if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) {
updateProxy(changedProxies[i].first, changedProxies[i].second);
}
}
}
void Space::setViews(const Views& views) {
_views = views;
}
void Space::copyViews(std::vector<View>& copy) const {
copy = _views;
}
}*/
void Space::categorizeAndGetChanges(std::vector<Space::Change>& changes) {
std::unique_lock<std::mutex> lock(_proxiesMutex);
uint32_t numProxies = (uint32_t)_proxies.size();
uint32_t numViews = (uint32_t)_views.size();
for (uint32_t i = 0; i < numProxies; ++i) {
@ -92,7 +154,7 @@ void Space::categorizeAndGetChanges(std::vector<Space::Change>& changes) {
}
// private
void Space::deleteProxy(int32_t proxyId) {
/*void Space::deleteProxy(int32_t proxyId) {
if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) {
if (proxyId == (int32_t)_proxies.size() - 1) {
// remove proxy on back
@ -110,9 +172,10 @@ void Space::deleteProxy(int32_t proxyId) {
_freeIndices.push_back(proxyId);
}
}
}
}*/
uint32_t Space::copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const {
std::unique_lock<std::mutex> lock(_proxiesMutex);
auto numCopied = std::min(numDestProxies, (uint32_t)_proxies.size());
memcpy(proxies, _proxies.data(), numCopied * sizeof(Proxy));
return numCopied;
@ -120,9 +183,24 @@ uint32_t Space::copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const {
// private
void Space::updateProxy(int32_t proxyId, const Space::Sphere& newSphere) {
/*void Space::updateProxy(int32_t proxyId, const Space::Sphere& newSphere) {
if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) {
_proxies[proxyId].sphere = newSphere;
}
}*/
void Space::clear() {
std::unique_lock<std::mutex> lock(_proxiesMutex);
_IDAllocator.clear();
_proxies.clear();
_views.clear();
}
void Space::setViews(const Views& views) {
_views = views;
}
void Space::copyViews(std::vector<View>& copy) const {
copy = _views;
}

View file

@ -23,7 +23,7 @@
namespace workload {
class Space {
class Space : public Collection {
public:
using ProxyUpdate = std::pair<int32_t, Sphere>;
@ -35,55 +35,40 @@ public:
uint8_t prevRegion { 0 };
};
Space() {}
Space();
// This call is thread safe, can be called from anywhere to allocate a new ID
ProxyID allocateID();
// Check that the ID is valid and allocated for this space, this a threadsafe call
bool isAllocatedID(const ProxyID& id) const;
// THis is the total number of allocated proxies, this a threadsafe call
Index getNumAllocatedProxies() const { return _numAllocatedProxies.load(); }
// Enqueue transaction to the space
void enqueueTransaction(const Transaction& transaction);
// Enqueue transaction to the space
void enqueueTransaction(Transaction&& transaction);
// Enqueue end of frame transactions boundary
uint32_t enqueueFrame();
// Process the pending transactions queued
void processTransactionQueue();
void setViews(const std::vector<View>& views);
void setViews(const Views& views);
uint32_t getNumViews() const { return (uint32_t)(_views.size()); }
void copyViews(std::vector<View>& copy) const;
uint32_t getNumObjects() const { return (uint32_t)(_proxies.size() - _freeIndices.size()); }
uint32_t getNumAllocatedProxies() const { return (uint32_t)(_proxies.size()); }
uint32_t getNumObjects() const { return _IDAllocator.getNumLiveIndices(); } // (uint32_t)(_proxies.size() - _freeIndices.size()); }
uint32_t getNumAllocatedProxies() const { return (uint32_t)(_IDAllocator.getNumAllocatedIndices()); }
void categorizeAndGetChanges(std::vector<Change>& changes);
uint32_t copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const;
void clear();
private:
virtual void processTransactionFrame(const Transaction& transaction);
void processResets(const Transaction::Resets& transactions);
void processRemoves(const Transaction::Removes& transactions);
void processUpdates(const Transaction::Updates& transactions);
void clear();
int32_t createProxy(const Sphere& sphere);
void deleteProxies(const IndexVector& deadIndices);
void updateProxies(const std::vector<ProxyUpdate>& changedProxies);
// int32_t createProxy(const Sphere& sphere);
// void deleteProxies(const IndexVector& deadIndices);
// void updateProxies(const std::vector<ProxyUpdate>& changedProxies);
void deleteProxy(int32_t proxyId);
void updateProxy(int32_t proxyId, const Sphere& sphere);
// void deleteProxy(int32_t proxyId);
// void updateProxy(int32_t proxyId, const Sphere& sphere);
// The database of proxies is protected for editing by a mutex
mutable std::mutex _proxiesMutex;
Proxy::Vector _proxies;
std::vector<Proxy> _proxies;
Views _views;
IndexVector _freeIndices;
};
using SpacePointer = std::shared_ptr<Space>;

View file

@ -13,21 +13,16 @@
using namespace workload;
void Transaction::resetItem(ItemID id, PayloadPointer& payload) {
if (payload) {
_resetItems.emplace_back(Reset{ id, payload });
} else {
qCDebug(renderlogging) << "WARNING: Transaction::resetItem with a null payload!";
removeItem(id);
}
void Transaction::reset(ProxyID id, const ProxyPayload& payload) {
_resetItems.emplace_back(Reset{ id, payload });
}
void Transaction::removeItem(ItemID id) {
void Transaction::remove(ProxyID id) {
_removedItems.emplace_back(id);
}
void Transaction::updateItem(ItemID id, const UpdateFunctorPointer& functor) {
_updatedItems.emplace_back(id, functor);
void Transaction::update(ProxyID id, const ProxyPayload& payload) {
_updatedItems.emplace_back(id, payload);
}
void Transaction::reserve(const std::vector<Transaction>& transactionContainer) {
@ -77,6 +72,18 @@ void copyElements(T& target, const T& source) {
}
void Transaction::reset(const Resets& resets) {
copyElements(_resetItems, resets);
}
void Transaction::remove(const Removes& removes) {
copyElements(_removedItems, removes);
}
void Transaction::update(const Updates& updates) {
copyElements(_updatedItems, updates);
}
void Transaction::merge(Transaction&& transaction) {
moveElements(_resetItems, transaction._resetItems);
moveElements(_removedItems, transaction._removedItems);
@ -99,23 +106,22 @@ void Transaction::clear() {
Collection::Collection() {
_items.push_back(Item()); // add the itemID #0 to nothing
//_items.push_back(Item()); // add the ProxyID #0 to nothing
}
Collection::~Collection() {
qCDebug(renderlogging) << "Scene::~Scene()";
}
ItemID Collection::allocateID() {
// Just increment and return the proevious value initialized at 0
return _IDAllocator.fetch_add(1);
ProxyID Collection::allocateID() {
// Just increment and return the previous value initialized at 0
return _IDAllocator.allocateIndex();
}
bool Collection::isAllocatedID(const ItemID& id) const {
return Item::isValidID(id) && (id < _numAllocatedItems.load());
bool Collection::isAllocatedID(const ProxyID& id) const {
return _IDAllocator.checkIndex(id);
}
/// Enqueue change batch to the scene
/// Enqueue change batch to the Collection
void Collection::enqueueTransaction(const Transaction& transaction) {
std::unique_lock<std::mutex> lock(_transactionQueueMutex);
_transactionQueue.emplace_back(transaction);
@ -127,7 +133,6 @@ void Collection::enqueueTransaction(Transaction&& transaction) {
}
uint32_t Collection::enqueueFrame() {
PROFILE_RANGE(render, __FUNCTION__);
TransactionQueue localTransactionQueue;
{
std::unique_lock<std::mutex> lock(_transactionQueueMutex);
@ -146,8 +151,6 @@ uint32_t Collection::enqueueFrame() {
void Collection::processTransactionQueue() {
PROFILE_RANGE(render, __FUNCTION__);
static TransactionFrames queuedFrames;
{
// capture the queued frames and clear the queue
@ -163,13 +166,12 @@ void Collection::processTransactionQueue() {
queuedFrames.clear();
}
void Collection::processTransactionFrame(const Transaction& transaction) {
PROFILE_RANGE(render, __FUNCTION__);
{
//void Collection::processTransactionFrame(const Transaction& transaction) {
/**
std::unique_lock<std::mutex> lock(_itemsMutex);
// Here we should be able to check the value of last ItemID allocated
// Here we should be able to check the value of last ProxyID allocated
// and allocate new items accordingly
ItemID maxID = _IDAllocator.load();
ProxyID maxID = _IDAllocator.getNumAllocatedIndices();
if (maxID > _items.size()) {
_items.resize(maxID + 100); // allocate the maxId and more
}
@ -195,32 +197,32 @@ void Collection::processTransactionFrame(const Transaction& transaction) {
// Update the numItemsAtomic counter AFTER the pending changes went through
_numAllocatedItems.exchange(maxID);
}
}
}*/
//}
void Collection::resetItems(const Transaction::Resets& transactions) {
for (auto& reset : transactions) {
//void Collection::resetItems(const Transaction::Resets& transactions) {
/* for (auto& reset : transactions) {
// Access the true item
auto itemId = std::get<0>(reset);
auto& item = _items[itemId];
auto ProxyID = std::get<0>(reset);
auto& item = _items[ProxyID];
// Reset the item with a new payload
item.resetPayload(std::get<1>(reset));
}
}
}*/
//}
void Collection::removeItems(const Transaction::Removes& transactions) {
for (auto removedID : transactions) {
//void Collection::removeItems(const Transaction::Removes& transactions) {
/* for (auto removedID : transactions) {
// Access the true item
auto& item = _items[removedID];
// Kill it
item.kill();
}
}
}*/
//}
void Collection::updateItems(const Transaction::Updates& transactions) {
for (auto& update : transactions) {
//void Collection::updateItems(const Transaction::Updates& transactions) {
/* for (auto& update : transactions) {
auto updateID = std::get<0>(update);
if (updateID == Item::INVALID_ITEM_ID) {
continue;
@ -231,5 +233,5 @@ void Collection::updateItems(const Transaction::Updates& transactions) {
// Update the item
item.update(std::get<1>(update));
}
}
}*/
//}

View file

@ -38,7 +38,7 @@ namespace workload {
Index _nextNewIndex{ 0 };
bool checkIndex(Index index) const { return ((index >= 0) && (index < _nextNewIndex)); }
Index getNumIndices() const { return _nextNewIndex - (Index)_freeIndices.size(); }
Index getNumLiveIndices() const { return _nextNewIndex - (Index)_freeIndices.size(); }
Index getNumFreeIndices() const { return (Index)_freeIndices.size(); }
Index getNumAllocatedIndices() const { return _nextNewIndex; }
@ -64,6 +64,7 @@ namespace workload {
void freeIndex(Index index) {
if (checkIndex(index)) {
_freeIndices.push_back(index);
//std::sort(_freeIndices.begin(), _freeIndices.end());
}
}
@ -79,7 +80,7 @@ namespace workload {
using IndexVector = indexed_container::Indices;
using ProxyID = Index;
const ProxyID INVALID_PROXY_ID{ indexed_container ::INVALID_INDEX };
// Transaction is the mechanism to make any change to the Space.
// Whenever a new proxy need to be reset,
@ -94,16 +95,27 @@ class Transaction {
public:
using ProxyPayload = Sphere;
using Reset = std::tuple<ProxyID, ProxyPayload>;
using Remove = ProxyID;
using Update = std::tuple<ProxyID, ProxyPayload>;
using Resets = std::vector<Reset>;
using Removes = std::vector<Remove>;
using Updates = std::vector<Update>;
Transaction() {}
~Transaction() {}
// Proxy transactions
void reset(ProxyID id, const ProxyPayload& sphere);
void reset(const Resets& resets);
void remove(ProxyID id);
void remove(const Removes& removes);
bool hasRemovals() const { return !_removedItems.empty(); }
void update(ProxyID id, const ProxyPayload& sphere);
void update(const Updates& updates);
void reserve(const std::vector<Transaction>& transactionContainer);
void merge(const std::vector<Transaction>& transactionContainer);
void merge(std::vector<Transaction>&& transactionContainer);
@ -113,13 +125,6 @@ public:
protected:
using Reset = std::tuple<ProxyID, ProxyPayload>;
using Remove = ProxyID;
using Update = std::tuple<ProxyID, ProxyPayload>;
using Resets = std::vector<Reset>;
using Removes = std::vector<Remove>;
using Updates = std::vector<Update>;
Resets _resetItems;
Removes _removedItems;
@ -129,6 +134,8 @@ typedef std::vector<Transaction> TransactionQueue;
class Collection {
public:
Collection();
~Collection();
// This call is thread safe, can be called from anywhere to allocate a new ID
ProxyID allocateID();
@ -149,7 +156,7 @@ public:
uint32_t enqueueFrame();
// Process the pending transactions queued
void processTransactionQueue();
virtual void processTransactionQueue();
protected:
@ -168,7 +175,7 @@ protected:
uint32_t _transactionFrameNumber{ 0 };
// Process one transaction frame
void processTransactionFrame(const Transaction& transaction);
virtual void processTransactionFrame(const Transaction& transaction) = 0;
};
} // namespace workload