Remove some useless allocations
parent
9e9bb8987f
commit
f7c2f7069e
|
@ -370,10 +370,9 @@ namespace contouring {
|
|||
const auto area_offset = glm::divide(std::get<0>(area.first).as_voxel());
|
||||
robin_hood::unordered_set<chunk_pos> done;
|
||||
for (const auto& occ: occlusion) {
|
||||
const geometry::Ray ray(start, occ, dist);
|
||||
std::vector<voxel_pos> points; //TODO: iterator
|
||||
ray.grid(points);
|
||||
for(auto& point: points) {
|
||||
geometry::Ray::iterator it(geometry::Ray(start, occ, dist));
|
||||
glm::llvec3 point;
|
||||
while (it.next(point)) {
|
||||
auto it = area.second.find(glm::lvec3(point) - area_offset);
|
||||
const auto buffer = solid ? it->second.first : it->second.second;
|
||||
if(it != area.second.end() && buffer != NULL && done.insert(it->first).second) {
|
||||
|
|
|
@ -61,9 +61,17 @@ int Client::connectionCallback(uint64_t stream_id, uint8_t* bytes, size_t length
|
|||
case picoquic_callback_stream_fin: {
|
||||
assert(stream_ctx::IsServerId(stream_id));
|
||||
auto stream_ctx = (in_stream_ctx *)v_stream_ctx;
|
||||
const auto is_fin = fin_or_event == picoquic_callback_stream_fin;
|
||||
|
||||
/* Data arrival on stream #x, maybe with fin mark */
|
||||
if (stream_ctx == NULL) { // New stream from server
|
||||
if (stream_ctx == NULL) {
|
||||
if (is_fin) { // Single frame packet
|
||||
if (length > 0) {
|
||||
onPacket(data::out_view(bytes, length), PacketFlags::TINY);
|
||||
}
|
||||
reset(stream_id);
|
||||
break;
|
||||
}
|
||||
// New long stream from server
|
||||
stream_ctx = receive(stream_id);
|
||||
}
|
||||
|
||||
|
@ -71,7 +79,7 @@ int Client::connectionCallback(uint64_t stream_id, uint8_t* bytes, size_t length
|
|||
stream_ctx->buffer.write(bytes, length);
|
||||
}
|
||||
|
||||
if (fin_or_event == picoquic_callback_stream_fin) {
|
||||
if (is_fin) {
|
||||
if (onPacket(data::out_view(stream_ctx->buffer.data.data(), stream_ctx->buffer.data.size()), PacketFlags::NONE)) {
|
||||
close(stream_ctx);
|
||||
} else {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include "../data/mem.hpp"
|
||||
#include "../utils/logger.hpp"
|
||||
|
||||
namespace data {
|
||||
|
@ -9,7 +9,9 @@ namespace data {
|
|||
class file_content: public std::vector<char> {
|
||||
public:
|
||||
// Read first
|
||||
file_content(const std::vector<std::string>& paths): std::vector<char>() {
|
||||
file_content(const std::vector<std::string>& paths, data::out_view prefix = data::out_view(nullptr, 0)):
|
||||
std::vector<char>(), prefix_size(prefix.size())
|
||||
{
|
||||
std::ifstream is = [&]() {
|
||||
for(auto& path: paths) {
|
||||
std::ifstream is(path, std::ios::in | std::ios::binary | std::ios::ate);
|
||||
|
@ -22,10 +24,18 @@ public:
|
|||
}();
|
||||
const auto end = is.tellg();
|
||||
is.seekg(0, std::ios::beg);
|
||||
resize(end - is.tellg());
|
||||
is.read(data(), size());
|
||||
resize(end - is.tellg() + prefix_size);
|
||||
memcpy(data(), prefix.ptr, prefix_size);
|
||||
is.read(data() + prefix_size, size());
|
||||
is.close();
|
||||
}
|
||||
|
||||
size_t prefix_size;
|
||||
|
||||
/// Data after prefix
|
||||
data::out_view content() const {
|
||||
return data::out_view((const uint8_t*)data() + prefix_size, size() - prefix_size);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
namespace data {
|
||||
|
|
|
@ -83,6 +83,55 @@ namespace geometry {
|
|||
}
|
||||
points.push_back(current);
|
||||
}
|
||||
/// Iterator implementation of grid
|
||||
struct iterator {
|
||||
enum class axis { X, Y, Z };
|
||||
|
||||
iterator(const Ray& r): current(r.from.as_voxel()),
|
||||
d(r.dir * r.dist), l(glm::abs(d)),
|
||||
dir((l.x >= l.y) && (l.x >= l.z) ? axis::X : ((l.y >= l.x) && (l.y >= l.z) ? axis::Y : axis::Z)),
|
||||
count(dir == axis::X ? l.x : (dir == axis::Y ? l.y : l.z)),
|
||||
inc(swap(glm::llvec3((d.x < 0) ? -1 : 1, (d.y < 0) ? -1 : 1, (d.z < 0) ? -1 : 1), dir)),
|
||||
delta(swap(l << 1ll, dir)), err_1(delta.y - count), err_2(delta.z - count) { }
|
||||
|
||||
static constexpr inline glm::llvec3 swap(const glm::llvec3& in, const axis dir) { return dir == axis::X ? in :
|
||||
(dir == axis::Y ? glm::llvec3(in.y, in.z, in.x) : glm::llvec3(in.z, in.x, in.y)); }
|
||||
|
||||
static constexpr inline long long& get(glm::llvec3& in, const axis dir, const axis target) {
|
||||
const axis v = (axis)(((int)dir + (int)target) % 3);
|
||||
return v == axis::X ? in.x : (v == axis::Y ? in.y : in.z);
|
||||
}
|
||||
|
||||
bool next(glm::llvec3& out) {
|
||||
if (count < 0)
|
||||
return false;
|
||||
|
||||
count--;
|
||||
out = current;
|
||||
if (err_1 > 0) {
|
||||
get(current, dir, axis::Y) += inc.y;
|
||||
err_1 -= delta.x;
|
||||
}
|
||||
if (err_2 > 0) {
|
||||
get(current, dir, axis::Z) += inc.z;
|
||||
err_2 -= delta.x;
|
||||
}
|
||||
err_1 += delta.y;
|
||||
err_2 += delta.z;
|
||||
get(current, dir, axis::X) += inc.x;
|
||||
return true;
|
||||
}
|
||||
|
||||
glm::llvec3 current;
|
||||
const glm::llvec3 d;
|
||||
const glm::llvec3 l;
|
||||
const axis dir;
|
||||
glm::llvec3::value_type count;
|
||||
const glm::llvec3 inc;
|
||||
const glm::llvec3 delta;
|
||||
int err_1;
|
||||
int err_2;
|
||||
};
|
||||
|
||||
IBox::ContainmentType intersect(const IBox& box) const {
|
||||
const glm::llvec3 start = from.as_voxel();
|
||||
|
|
|
@ -31,6 +31,7 @@ struct in_stream_ctx: stream_ctx {
|
|||
enum class PacketFlags {
|
||||
NONE = 0,
|
||||
DATAGRAM = 1 << 0,
|
||||
TINY = 1 << 1,
|
||||
};
|
||||
|
||||
/// Abstract QUIC context
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
namespace net {
|
||||
|
||||
//TODO: preallocate static data pool
|
||||
|
||||
/// Write allocated packets
|
||||
class PacketWriter final {
|
||||
public:
|
||||
PacketWriter(size_t size): buffer((uint8_t*)malloc(size), size) { }
|
||||
|
@ -27,6 +29,37 @@ public:
|
|||
write(&d, sizeof(d));
|
||||
}
|
||||
|
||||
struct varying_part {
|
||||
varying_part(data::in_view &buffer): buffer(buffer), visible_size(0) { }
|
||||
~varying_part() {
|
||||
buffer.siz = buffer.cur + visible_size;
|
||||
buffer.cur = buffer.siz;
|
||||
}
|
||||
|
||||
data::in_view &buffer;
|
||||
size_t visible_size;
|
||||
|
||||
constexpr size_t size() const { return visible_size; }
|
||||
void* data() { return buffer.writeTo(0); }
|
||||
void reserve(size_t target) {
|
||||
if (target >= buffer.siz - buffer.cur) {
|
||||
auto old = buffer.ptr;
|
||||
buffer.ptr = (uint8_t*)malloc(target);
|
||||
memcpy(buffer.ptr, old, buffer.siz);
|
||||
free(old);
|
||||
buffer.siz = target;
|
||||
}
|
||||
}
|
||||
void resize(size_t target) {
|
||||
reserve(target);
|
||||
visible_size = target;
|
||||
}
|
||||
};
|
||||
/// Only from resize, write, resize down
|
||||
varying_part varying() {
|
||||
return varying_part(buffer);
|
||||
}
|
||||
|
||||
bool isFull() const {
|
||||
return buffer.isDone();
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <zstd.h>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include "../data/mem.hpp"
|
||||
#include "logger.hpp"
|
||||
|
||||
namespace zstd {
|
||||
|
@ -73,6 +72,7 @@ namespace zstd {
|
|||
class dict_set {
|
||||
public:
|
||||
dict_set(const std::vector<char>& data) { load(data.data(), data.size()); }
|
||||
dict_set(const data::out_view& data) { load(data.data(), data.size()); }
|
||||
~dict_set() {
|
||||
ZSTD_freeCDict(c);
|
||||
ZSTD_freeDDict(d);
|
||||
|
|
|
@ -7,20 +7,19 @@ namespace world {
|
|||
|
||||
template<class Areas>
|
||||
Universe::ray_result Raycast(const geometry::Ray& ray, const Areas& areas) {
|
||||
//TODO: iterator
|
||||
//MAYBE: ray + offset to get float precision
|
||||
std::vector<voxel_pos> points;
|
||||
ray.grid(points);
|
||||
Universe::ray_result target;
|
||||
size_t dist = points.size();
|
||||
size_t dist = UINT32_MAX - 1;
|
||||
for(auto& area: areas) {
|
||||
if(ray.intersect(area.second->getBounding()) != geometry::IBox::ContainmentType::Disjoint) {
|
||||
const auto &offset = area.second->getOffset().as_voxel();
|
||||
const auto &chunks = area.second->getChunks();
|
||||
std::shared_ptr<world::Chunk> chunk = nullptr;
|
||||
chunk_pos chunk_vec(INT_MAX);
|
||||
for (size_t i = 0; i < dist; i++) {
|
||||
const auto pos = points[i] - offset;
|
||||
geometry::Ray::iterator it(ray);
|
||||
glm::llvec3 point;
|
||||
for (size_t i = 0; i < dist && it.next(point); i++) {
|
||||
const auto pos = point - offset;
|
||||
const chunk_pos cPos = glm::divide(pos);
|
||||
if(cPos != chunk_vec) {
|
||||
if (const auto it = chunks.find(cPos); it != chunks.end()) {
|
||||
|
|
|
@ -58,9 +58,17 @@ int Server::connectionCallback(Peer* peer, uint64_t stream_id, uint8_t* bytes, s
|
|||
case picoquic_callback_stream_fin: {
|
||||
assert(stream_ctx::IsClientId(stream_id));
|
||||
auto stream_ctx = (in_stream_ctx *)v_stream_ctx;
|
||||
const auto is_fin = fin_or_event == picoquic_callback_stream_fin;
|
||||
|
||||
/* Data arrival on stream #x, maybe with fin mark */
|
||||
if (stream_ctx == NULL) { // New stream from peer
|
||||
if (stream_ctx == NULL) {
|
||||
if (is_fin) { // Single frame packet
|
||||
if (length > 0) {
|
||||
onPacket(peer, data::out_view(bytes, length), PacketFlags::TINY);
|
||||
}
|
||||
peer->reset(stream_id);
|
||||
break;
|
||||
}
|
||||
// New long stream from server
|
||||
stream_ctx = peer->receive(stream_id);
|
||||
}
|
||||
|
||||
|
@ -68,7 +76,7 @@ int Server::connectionCallback(Peer* peer, uint64_t stream_id, uint8_t* bytes, s
|
|||
stream_ctx->buffer.write(bytes, length);
|
||||
}
|
||||
|
||||
if (fin_or_event == picoquic_callback_stream_fin) {
|
||||
if (is_fin) {
|
||||
if (onPacket(peer, data::out_view(stream_ctx->buffer.data.data(), stream_ctx->buffer.data.size()), PacketFlags::NONE)) {
|
||||
peer->close(stream_ctx);
|
||||
} else {
|
||||
|
|
|
@ -14,12 +14,14 @@
|
|||
using namespace world::server;
|
||||
|
||||
const auto AREAS_FILE = "/areas.idx";
|
||||
const auto COMPRESSION_PREFIX = (uint8_t)net::server_packet_type::COMPRESSION;
|
||||
|
||||
Universe::Universe(const Universe::options &options): host(options.connection,
|
||||
[&](net::server::Peer* peer) { return onConnect(peer); },
|
||||
[&](net::server::Peer* peer, bool is_app, uint16_t reason) { return onDisconnect(peer, is_app, reason); },
|
||||
[&](net::server::Peer* peer, const data::out_view &buf, net::PacketFlags flags) { return onPacket(peer, buf, flags); }
|
||||
), dict_content({options.folderPath + "/zstd.dict", "content/zstd.dict"}), dicts(dict_content), dict_write_ctx(dicts.make_writer())
|
||||
), dict_content({options.folderPath + "/zstd.dict", "content/zstd.dict"}, data::out_view(&COMPRESSION_PREFIX, sizeof(COMPRESSION_PREFIX))),
|
||||
dicts(dict_content.content()), dict_write_ctx(dicts.make_writer())
|
||||
{
|
||||
setOptions(options);
|
||||
folderPath = options.folderPath;
|
||||
|
@ -453,9 +455,7 @@ std::optional<uint16_t> Universe::onConnect(net::server::Peer* peer) {
|
|||
peer->send(net::PacketWriter::Of(net::server_packet_type::CAPABILITIES, loadDistance));
|
||||
|
||||
//TODO: lock while not received
|
||||
//MAYBE: add net::server_packet_type::COMPRESSION to dict_content: zero copy
|
||||
peer->send(net::PacketWriter::Of(net::server_packet_type::COMPRESSION, dict_content.data(), dict_content.size()), net::server::queue::CHUNK);
|
||||
|
||||
peer->send(data::out_buffer(data::out_view((uint8_t*)dict_content.data(), dict_content.size()), nullptr), net::server::queue::CHUNK);
|
||||
{
|
||||
auto player = findEntity(PLAYER_ENTITY_ID, client->instanceId);
|
||||
auto packet = net::PacketWriter(net::server_packet_type::TELEPORT, sizeof(size_t) + sizeof(voxel_pos));
|
||||
|
@ -582,12 +582,12 @@ data::out_buffer Universe::serializeChunk(area_<chunk_pos> id, const std::shared
|
|||
ZoneScopedN("Chunk");
|
||||
std::ostringstream out;
|
||||
data->write(out);
|
||||
std::vector<char> buffer;
|
||||
//FIXME: avoid buffer copy
|
||||
dict_write_ctx.compress(out.str(), buffer);
|
||||
auto packet = net::PacketWriter(net::server_packet_type::CHUNK, sizeof(id) + buffer.size());
|
||||
auto packet = net::PacketWriter(net::server_packet_type::CHUNK, sizeof(id));
|
||||
packet.write(id);
|
||||
packet.write(buffer.data(), buffer.size());
|
||||
{
|
||||
auto vec = packet.varying();
|
||||
dict_write_ctx.compress(out.str(), vec);
|
||||
}
|
||||
return packet.finish();
|
||||
}
|
||||
void Universe::broadcastMessage(const std::string& text) {
|
||||
|
|
Loading…
Reference in New Issue