void PublicHubsFrame::updateList() { //CLockRedraw<> l_lock_draw(m_ctrlHubs); m_ctrlHubs.DeleteAllItems(); users = 0; visibleHubs = 0; double size = -1; FilterModes mode = NONE; int sel = ctrlFilterSel.GetCurSel(); bool doSizeCompare = parseFilter(mode, size); auto cnt = m_ctrlHubs.GetItemCount(); for (auto i = m_hubs.cbegin(); i != m_hubs.cend(); ++i) { if (matchFilter(*i, sel, doSizeCompare, mode, size)) { TStringList l; l.resize(COLUMN_LAST); l[COLUMN_NAME] = Text::toT(i->getName()); string l_description = i->getDescription(); boost::replace_all(l_description, ".px.", ""); l[COLUMN_DESCRIPTION] = Text::toT(l_description); l[COLUMN_USERS] = Util::toStringW(i->getUsers()); l[COLUMN_SERVER] = Text::toT(i->getServer()); l[COLUMN_COUNTRY] = Text::toT(i->getCountry()); // !SMT!-IP l[COLUMN_SHARED] = Util::formatBytesW(i->getShared()); l[COLUMN_MINSHARE] = Util::formatBytesW(i->getMinShare()); l[COLUMN_MINSLOTS] = Util::toStringW(i->getMinSlots()); l[COLUMN_MAXHUBS] = Util::toStringW(i->getMaxHubs()); l[COLUMN_MAXUSERS] = Util::toStringW(i->getMaxUsers()); l[COLUMN_RELIABILITY] = Util::toStringW(i->getReliability()); l[COLUMN_RATING] = Text::toT(i->getRating()); const auto l_country = i->getCountry(); dcassert(!l_country.empty()); const auto l_index_country = WinUtil::getFlagIndexByName(l_country.c_str()); //const auto l_index = m_ctrlHubs.insert(cnt++, l, l_index_country); // !SMT!-IP /* LVITEM lvItem = { 0 }; lvItem.mask = LVIF_IMAGE; lvItem.iItem = l_index; lvItem.iImage = isOnline(i->getServer()) ? 0 : 1; m_ctrlHubs.SetItem(&lvItem); */ visibleHubs++; users += i->getUsers(); } } m_ctrlHubs.resort(); updateStatus(); }
bool AFK_VapourCell::build3DList( unsigned int threadId, const AFK_KeyedCell& cell, AFK_3DList& list, const AFK_ShapeSizes& sSizes, AFK_VAPOUR_CELL_CACHE *cache) const { /* Add the local vapour to the list. */ list.extend<FeatureArray, CubeArray>(features, cubes); /* If this isn't the top level cell... */ if (cell.c.coord.v[3] < (sSizes.skeletonFlagGridDim * SHAPE_CELL_MAX_DISTANCE)) { /* Pull the parent cell from the cache, and * include its list too */ AFK_KeyedCell parentCell = cell.parent(sSizes.subdivisionFactor); auto parentVapourCellClaim = cache->getAndClaim(threadId, parentCell, AFK_CL_SHARED); if (parentVapourCellClaim.isValid()) return parentVapourCellClaim.getShared().build3DList(threadId, parentCell, list, sSizes, cache); else return false; } else return true; }
void AFK_LandscapeDisplayQueue::draw( unsigned int threadId, AFK_ShaderProgram *shaderProgram, AFK_Jigsaw *jigsaw, AFK_LANDSCAPE_CACHE *cache, const AFK_TerrainBaseTile *baseTile, const AFK_LandscapeSizes& lSizes) { /* First, check there's anything to draw at all ... */ #if COPY_TO_GL_CULLING bool allChecked = false; std::vector<bool> checked; checked.reserve(queue.size()); for (unsigned int i = 0; i < queue.size(); ++i) checked.push_back(false); do { allChecked = true; for (unsigned int i = 0; i < queue.size(); ++i) { if (checked[i]) continue; auto entry = cache->get(threadId, landscapeTiles[i]); if (entry) { auto claim = entry->claimable.claimInplace(threadId, AFK_CL_SHARED); if (claim.isValid()) { if (claim.getShared().realCellWithinYBounds(queue[i].cellCoord)) { /* I do want to draw this tile. */ culledQueue.push_back(queue[i]); } /* If I got here, the tile has been checked successfully. */ checked[i] = true; } else { /* want to retry */ allChecked = false; } } else { /* Ignore, this one shouldn't be drawn */ checked[i] = true; } } if (!allChecked) std::this_thread::yield(); /* Give things a chance */ } while (!allChecked); size_t instanceCount = culledQueue.size(); #else size_t instanceCount = queue.size(); #endif if (instanceCount == 0) return; /* Check I've initialised the various locations in the * shader program that I need */ if (!jigsawPiecePitchLocation) { jigsawPiecePitchLocation = glGetUniformLocation(shaderProgram->program, "JigsawPiecePitch"); jigsawYDispTexSamplerLocation = glGetUniformLocation(shaderProgram->program, "JigsawYDispTex"); jigsawColourTexSamplerLocation = glGetUniformLocation(shaderProgram->program, "JigsawColourTex"); jigsawNormalTexSamplerLocation = glGetUniformLocation(shaderProgram->program, "JigsawNormalTex"); displayTBOSamplerLocation = glGetUniformLocation(shaderProgram->program, "DisplayTBO"); } /* Fill out ye olde uniform variable with the jigsaw * piece pitch. */ Vec2<float> jigsawPiecePitchST = jigsaw->getPiecePitchST(); glUniform2fv(jigsawPiecePitchLocation, 1, &jigsawPiecePitchST.v[0]); /* The first texture is the jigsaw Y-displacement */ glActiveTexture(GL_TEXTURE0); jigsaw->bindTexture(0); glUniform1i(jigsawYDispTexSamplerLocation, 0); /* The second texture is the jigsaw colour */ glActiveTexture(GL_TEXTURE1); jigsaw->bindTexture(1); glUniform1i(jigsawColourTexSamplerLocation, 1); /* The third texture is the jigsaw normal */ glActiveTexture(GL_TEXTURE2); jigsaw->bindTexture(2); glUniform1i(jigsawNormalTexSamplerLocation, 2); /* The fourth texture is the landscape display texbuf, * which explains to the vertex shader which tile it's * drawing and where in the jigsaw to look. */ glActiveTexture(GL_TEXTURE3); if (!buf) glGenBuffers(1, &buf); glBindBuffer(GL_TEXTURE_BUFFER, buf); glBufferData( GL_TEXTURE_BUFFER, #if COPY_TO_GL_CULLING culledQueue.size() * sizeof(AFK_LandscapeDisplayUnit), &culledQueue[0], #else queue.size() * sizeof(AFK_LandscapeDisplayUnit), &queue[0], #endif GL_STREAM_DRAW); glTexBuffer( GL_TEXTURE_BUFFER, GL_RGBA32F, buf); AFK_GLCHK("landscape display queue texBuffer") glUniform1i(displayTBOSamplerLocation, 3); #if AFK_GL_DEBUG shaderProgram->Validate(); #endif baseTile->draw(instanceCount); glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_BUFFER, 0); }
bool AFK_World::generateClaimedWorldCell( AFK_WORLD_CACHE::Claim& claim, unsigned int threadId, const struct AFK_WorldWorkParam::World& param, const struct AFK_WorldWorkThreadLocal& threadLocal, AFK_WorldWorkQueue& queue) { const AFK_Cell& cell = param.cell; const Vec3<float>& viewerLocation = threadLocal.viewerLocation; const AFK_Camera& camera = threadLocal.camera; bool entirelyVisible = ((param.flags & AFK_WCG_FLAG_ENTIRELY_VISIBLE) != 0); bool renderTerrain = ((param.flags & AFK_WCG_FLAG_TERRAIN_RENDER) != 0); bool resume = ((param.flags & AFK_WCG_FLAG_RESUME) != 0); bool retval = true; AFK_WorldCell& worldCell = claim.get(); worldCell.bind(cell, minCellSize); /* Check for visibility. */ bool someVisible = entirelyVisible; bool allVisible = entirelyVisible; if (!entirelyVisible) worldCell.testVisibility(camera, someVisible, allVisible); if (!someVisible && !renderTerrain) { cellsInvisible.fetch_add(1); } else /* if (cell.coord.v[1] == 0) */ { bool needsResume = false; std::vector<AFK_Tile> missingTiles; /* We display geometry at a cell if its detail pitch is at the * target detail pitch, or if it's already the smallest * possible cell. * Note that the smallest possible cell is 2. I can't go to 1, * because it will preclude landscape half-tiles (which would * be at +/- 0.5). */ bool display = (cell.coord.v[3] == 2 || worldCell.testDetailPitch(threadLocal.detailPitch, camera, viewerLocation)); /* Find the tile where any landscape at this cell would be * homed */ AFK_Tile tile = afk_tile(cell); /* I'm going to want this in a moment. */ float landscapeTileUpperYBound = FLT_MAX; /* We always at least touch the landscape. Higher detailed * landscape tiles are dependent on lower detailed ones for their * terrain description. */ auto landscapeClaim = landscapeCache->insertAndClaim(threadId, tile, AFK_CL_BLOCK | AFK_CL_UPGRADE); if (landscapeClaim.isValid()) { landscapeTileUpperYBound = landscapeClaim.getShared().getYBoundUpper(); if (!landscapeClaim.getShared().hasTerrainDescriptor() || ((renderTerrain || display) && landscapeClaim.getShared().artworkState(landscapeJigsaws) != AFK_LANDSCAPE_TILE_HAS_ARTWORK)) { /* In order to generate this tile we need to upgrade * our claim if we can. */ if (landscapeClaim.upgrade()) { AFK_LandscapeTile& landscapeTile = landscapeClaim.get(); if (checkClaimedLandscapeTile(tile, landscapeTile, display)) needsResume = generateLandscapeArtwork(tile, landscapeTile, threadId, missingTiles); if (!needsResume && display) displayLandscapeTile(cell, tile, landscapeTile, threadId); } else { needsResume = true; } } else if (display) { displayLandscapeTile(cell, tile, landscapeClaim.getShared(), threadId); } } else { needsResume = true; } /* If I need a resume for the landscape tile, push it in */ if (needsResume) { /* Because I'm doing a resume, I need to account for it in the * remaining volume counter */ volumeLeftToEnumerate.fetch_add(CUBE(cell.coord.v[3])); AFK_WorldWorkQueue::WorkItem resumeItem; resumeItem.func = afk_generateWorldCells; resumeItem.param.world = param; resumeItem.param.world.flags |= AFK_WCG_FLAG_RESUME; if (param.dependency) param.dependency->retain(); /* If we have missing tiles, that resume needs to be a * dependency of those missing tiles: */ if (!missingTiles.empty()) { AFK_WorldWorkParam::Dependency *dep = new AFK_WorldWorkParam::Dependency(resumeItem); dep->retain(missingTiles.size()); for (auto m : missingTiles) { volumeLeftToEnumerate.fetch_add(CUBE(m.coord.v[2])); AFK_WorldWorkQueue::WorkItem missingItem; missingItem.func = afk_generateWorldCells; missingItem.param.world.cell = afk_cell(m, 0); missingItem.param.world.flags = AFK_WCG_FLAG_ENTIRELY_VISIBLE | AFK_WCG_FLAG_TERRAIN_RENDER; missingItem.param.world.dependency = dep; queue.push(missingItem); } tilesResumed.fetch_add(missingTiles.size()); } else { /* We enqueue the resume directly */ queue.push(resumeItem); } tilesResumed.fetch_add(1); } if (!resume && !renderTerrain) { /* Now that I've done all that, I can get to the * business of handling the entities within the cell. * Firstly, so long as it's above the landscape, give it * some starting entities if it hasn't got them * already. */ if (worldCell.getRealCoord().v[1] >= landscapeTileUpperYBound) { /* TODO: This RNG will make the same set of entities every * time the cell is re-displayed. This is fine for probably * static, landscape decoration type objects. But I'm also * going to want to have transient objects popping into * existence, and those should be done with a different, * long-period RNG that I retain (in thread local storage), * perhaps a Mersenne Twister. */ AFK_Boost_Taus88_RNG staticRng; staticRng.seed(cell.rngSeed()); int startingEntityCount = worldCell.getStartingEntitiesWanted( staticRng, entitySparseness); for (int e = 0; e < startingEntityCount; ++e) { int shapeKey = worldCell.getStartingEntityShapeKey(staticRng); generateStartingEntity(shapeKey, worldCell, threadId, staticRng); } } for (int eI = 0; eI < worldCell.getEntityCount(); ++eI) { AFK_Entity& e = worldCell.getEntityAt(eI); if (e.notProcessedYet(afk_core.computingFrame)) { /* Account for this shape in the volume left to enumerate */ volumeLeftToEnumerate.fetch_add(CUBE(SHAPE_CELL_MAX_DISTANCE)); /* Make sure everything I need in that shape * has been computed ... */ AFK_WorldWorkQueue::WorkItem shapeCellItem; shapeCellItem.func = afk_generateEntity; shapeCellItem.param.shape.cell = afk_keyedCell(afk_vec4<int64_t>( 0, 0, 0, SHAPE_CELL_MAX_DISTANCE), e.shapeKey); shapeCellItem.param.shape.transformation = e.getTransformation(); shapeCellItem.param.shape.flags = 0; #if AFK_SHAPE_ENUM_DEBUG shapeCellItem.param.shape.asedWorldCell = cell; shapeCellItem.param.shape.asedCounter = eI; AFK_DEBUG_PRINTL("ASED: Enqueued entity: worldCell=" << cell << ", entity counter=" << eI) #endif shapeCellItem.param.shape.dependency = nullptr; queue.push(shapeCellItem); entitiesQueued.fetch_add(1); } } } /* We don't need this any more */ claim.release(); /* If the terrain here was at too coarse a resolution to * be displayable, recurse through the subcells */ if (!display && !renderTerrain && someVisible && !resume) { /* I'm about to enumerate this cell's volume in subcells */ volumeLeftToEnumerate.fetch_add(CUBE(cell.coord.v[3])); size_t subcellsSize = CUBE(subdivisionFactor); AFK_Cell *subcells = new AFK_Cell[subcellsSize]; /* TODO avoid heap thrashing somehow. Maybe make it an iterator */ unsigned int subcellsCount = cell.subdivide(subcells, subcellsSize, subdivisionFactor); assert(subcellsCount == subcellsSize); for (unsigned int i = 0; i < subcellsCount; ++i) { AFK_WorldWorkQueue::WorkItem subcellItem; subcellItem.func = afk_generateWorldCells; subcellItem.param.world.cell = subcells[i]; subcellItem.param.world.flags = (allVisible ? AFK_WCG_FLAG_ENTIRELY_VISIBLE : 0); subcellItem.param.world.dependency = nullptr; queue.push(subcellItem); } delete[] subcells; } } return retval; }
int afk_testChainLink() { boost::random::random_device rdev; int64_t rngSeed = (static_cast<int64_t>(rdev()) | (static_cast<int64_t>(rdev())) << 32); const int iterations = 40000; const int maxChainLength = static_cast<int>(sqrt(iterations)); const int threads = 24; std::shared_ptr<AFK_BasicLinkFactory<AFK_ClaimableChainLinkTestLink> > linkFactory = std::make_shared<AFK_BasicLinkFactory<AFK_ClaimableChainLinkTestLink> >(); AFK_ChainLinkTestChain *testChain = new AFK_ChainLinkTestChain(linkFactory); std::deque<std::thread> workers; afk_clock::time_point startTime, endTime; startTime = afk_clock::now(); assert(threads < 31); for (int i = 0; i < threads; ++i) { workers.push_back(std::thread( afk_testChainLink_worker, i + 1, rngSeed, iterations, maxChainLength, testChain )); } for (auto workerIt = workers.begin(); workerIt != workers.end(); ++workerIt) { workerIt->join(); } endTime = afk_clock::now(); /* Verify that whole thing */ int index = 0; int fails = 0; testChain->foreach([&index, &fails](std::shared_ptr<AFK_ClaimableChainLinkTestLink> link) { //afk_out << "verify test chain link: index " << index << ": "; auto claim = link->claim(1, AFK_CL_SPIN); //afk_out << claim.getShared(); if (claim.getShared().verify(index)) { //afk_out << " (verify ok)" << std::endl; } else { //afk_out << " (verify FAILED)" << std::endl; ++fails; } ++index; }); afk_duration_mfl timeTaken = std::chrono::duration_cast<afk_duration_mfl>(endTime - startTime); afk_out << "Chain link test (" << iterations << " iterations, " << maxChainLength << " max chain length, " << threads << " threads) finished in " << timeTaken.count() << " millis" << std::endl; delete testChain; afk_out << "Chain link test finished with " << iterations << " iterations, " << fails << " fails." << std::endl; return fails; }
void setOther(Instance *other){getShared()->other=other;}
void setSelf(Instance *self){getShared()->self=self;}
Instance *getOther(){return getShared()->other;}
Instance *getSelf(){return getShared()->self;}