Moved VirtualTextureOutput out of VoxelMesher

This commit is contained in:
Marc Gilleron 2022-08-14 22:34:27 +01:00
parent 92b3c25292
commit 5943b1d549
10 changed files with 33 additions and 43 deletions

View File

@ -554,7 +554,7 @@ NormalMapImages store_normalmap_data_to_images(
}
}
images.atlas_images = tile_images;
images.atlas = tile_images;
}
{
@ -590,7 +590,7 @@ NormalMapImages store_normalmap_data_to_images(
Ref<Image> image;
image.instantiate();
image->create_from_data(sqri, sqri, false, Image::FORMAT_RGB8, bytes);
images.lookup_image = image;
images.lookup = image;
}
return images;
@ -606,14 +606,14 @@ NormalMapTextures store_normalmap_data_to_textures(const NormalMapImages &data)
ZN_PROFILE_SCOPE_NAMED("Atlas texture");
Ref<Texture2DArray> atlas;
atlas.instantiate();
const Error err = atlas->create_from_images(data.atlas_images);
const Error err = atlas->create_from_images(data.atlas);
ZN_ASSERT_RETURN_V(err == OK, textures);
textures.atlas = atlas;
}
{
ZN_PROFILE_SCOPE_NAMED("Lookup image+texture");
Ref<ImageTexture> lookup = ImageTexture::create_from_image(data.lookup_image);
Ref<ImageTexture> lookup = ImageTexture::create_from_image(data.lookup);
textures.lookup = lookup;
}

View File

@ -85,8 +85,8 @@ void compute_normalmap(ICellIterator &cell_iterator, Span<const Vector3f> mesh_v
Vector3i origin_in_voxels, unsigned int lod_index, bool octahedral_encoding);
struct NormalMapImages {
Vector<Ref<Image>> atlas_images;
Ref<Image> lookup_image;
Vector<Ref<Image>> atlas;
Ref<Image> lookup;
};
struct NormalMapTextures {
@ -101,6 +101,15 @@ NormalMapImages store_normalmap_data_to_images(
// This may not be allowed to run in a different thread than the main thread if the renderer is not using Vulkan.
NormalMapTextures store_normalmap_data_to_textures(const NormalMapImages &data);
struct VirtualTextureOutput {
// Normalmap atlas used for smooth voxels.
// If textures can't be created from threads, images are returned instead.
NormalMapImages normalmap_images;
NormalMapTextures normalmap_textures;
// Can be false if textures are computed asynchronously. Will become true when it's done (and not change after).
std::atomic_bool valid;
};
} // namespace zylann::voxel
#endif // VOXEL_DISTANCE_NORMALMAPS_H

View File

@ -27,11 +27,9 @@ void GenerateDistanceNormalmapTask::run(ThreadedTaskContext ctx) {
if (VoxelEngine::get_singleton().is_threaded_mesh_resource_building_enabled()) {
NormalMapTextures textures = store_normalmap_data_to_textures(images);
virtual_textures->normalmap_atlas = textures.atlas;
virtual_textures->cell_lookup = textures.lookup;
virtual_textures->normalmap_textures = textures;
} else {
virtual_textures->normalmap_atlas_images = images.atlas_images;
virtual_textures->cell_lookup_image = images.lookup_image;
virtual_textures->normalmap_images = images;
}
virtual_textures->valid = true;

View File

@ -30,7 +30,7 @@ public:
NormalMapSettings virtual_texture_settings;
// Output (to be assigned so it can be populated)
std::shared_ptr<VoxelMesher::VirtualTextureOutput> virtual_textures;
std::shared_ptr<VirtualTextureOutput> virtual_textures;
// Identification
Vector3i block_position;

View File

@ -326,13 +326,11 @@ void MeshBlockTask::run(zylann::ThreadedTaskContext ctx) {
const Vector3i block_size =
voxels.get_size() - Vector3iUtil::create(mesher->get_minimum_padding() + mesher->get_maximum_padding());
ZN_ASSERT(_surfaces_output.virtual_textures == nullptr);
std::shared_ptr<VoxelMesher::VirtualTextureOutput> virtual_textures =
make_shared_instance<VoxelMesher::VirtualTextureOutput>();
std::shared_ptr<VirtualTextureOutput> virtual_textures = make_shared_instance<VirtualTextureOutput>();
virtual_textures->valid = false;
// This is stored here in case virtual texture rendering completes before the output of the current task gets
// dequeued in the main thread, since it runs in a separate asynchronous task
_surfaces_output.virtual_textures = virtual_textures;
_virtual_textures = virtual_textures;
GenerateDistanceNormalmapTask *nm_task = ZN_NEW(GenerateDistanceNormalmapTask);
nm_task->cell_iterator = std::move(cell_iterator);
@ -397,6 +395,7 @@ void MeshBlockTask::apply_result() {
o.mesh = _mesh;
o.mesh_material_indices = std::move(_mesh_material_indices);
o.has_mesh_resource = _has_mesh_resource;
o.virtual_textures = _virtual_textures;
VoxelEngine::VolumeCallbacks callbacks = VoxelEngine::get_singleton().get_volume_callbacks(volume_id);
ERR_FAIL_COND(callbacks.mesh_output_callback == nullptr);

View File

@ -49,6 +49,7 @@ private:
VoxelMesher::Output _surfaces_output;
Ref<Mesh> _mesh;
std::vector<uint8_t> _mesh_material_indices; // Indexed by mesh surface
std::shared_ptr<VirtualTextureOutput> _virtual_textures;
};
Ref<ArrayMesh> build_mesh(Span<const VoxelMesher::Output::Surface> surfaces, Mesh::PrimitiveType primitive, int flags,

View File

@ -9,6 +9,7 @@
#include "../util/tasks/progressive_task_runner.h"
#include "../util/tasks/threaded_task_runner.h"
#include "../util/tasks/time_spread_task_runner.h"
#include "distance_normalmaps.h"
#include "priority_dependency.h"
namespace zylann::voxel {
@ -38,6 +39,9 @@ public:
uint8_t lod;
// Tells if the mesh resource was built as part of the task. If not, you need to build it on the main thread.
bool has_mesh_resource;
// Can be null. Attached to meshing output so it is tracked more easily, because it is baked asynchronously
// starting from the mesh task, and it might complete earlier or later than the mesh.
std::shared_ptr<VirtualTextureOutput> virtual_textures;
};
struct BlockDataOutput {
@ -62,7 +66,7 @@ public:
};
struct BlockVirtualTextureOutput {
std::shared_ptr<VoxelMesher::VirtualTextureOutput> virtual_textures;
std::shared_ptr<VirtualTextureOutput> virtual_textures;
Vector3i position;
uint32_t lod_index;
};

View File

@ -46,18 +46,6 @@ public:
bool virtual_texture_hint = false;
};
// TODO Might move out of meshers because it is baked (mostly) independtly from meshers.
struct VirtualTextureOutput {
// Normalmap atlas used for smooth voxels.
// If textures can't be created from threads, images are returned instead.
Ref<Texture2DArray> normalmap_atlas;
Vector<Ref<Image>> normalmap_atlas_images;
Ref<Texture2D> cell_lookup;
Ref<Image> cell_lookup_image;
// Can be false if textures are computed asynchronously. Will become true when it's done (and not change after).
std::atomic_bool valid;
};
struct Output {
struct Surface {
Array arrays;
@ -83,11 +71,6 @@ public:
// May be used to store extra information needed in shader to render the mesh properly
// (currently used only by the cubes mesher when baking colors)
Ref<Image> atlas_image;
// Can be null. Attached to meshing output so it is tracked more easily, because it is baked asynchronously and
// it might complete earlier or later than the mesh.
// TODO Might be moved to meshing task output instead, meshers don't actually use this field.
std::shared_ptr<VirtualTextureOutput> virtual_textures;
};
static bool is_mesh_empty(const std::vector<Output::Surface> &surfaces);

View File

@ -1781,8 +1781,8 @@ void VoxelLodTerrain::apply_mesh_update(VoxelEngine::BlockMeshOutput &ob) {
block->set_parent_transform(get_global_transform());
if (ob.surfaces.virtual_textures != nullptr && ob.surfaces.virtual_textures->valid) {
apply_virtual_texture_update_to_block(*block, *ob.surfaces.virtual_textures, ob.lod);
if (ob.virtual_textures != nullptr && ob.virtual_textures->valid) {
apply_virtual_texture_update_to_block(*block, *ob.virtual_textures, ob.lod);
}
#ifdef TOOLS_ENABLED
@ -1813,19 +1813,15 @@ void VoxelLodTerrain::apply_virtual_texture_update(VoxelEngine::BlockVirtualText
}
void VoxelLodTerrain::apply_virtual_texture_update_to_block(
VoxelMeshBlockVLT &block, VoxelMesher::VirtualTextureOutput &ob, unsigned int lod_index) {
VoxelMeshBlockVLT &block, VirtualTextureOutput &ob, unsigned int lod_index) {
ZN_PROFILE_SCOPE();
ZN_ASSERT(ob.valid);
NormalMapTextures normalmap_textures;
normalmap_textures.atlas = ob.normalmap_atlas;
normalmap_textures.lookup = ob.cell_lookup;
NormalMapTextures normalmap_textures = ob.normalmap_textures;
if (normalmap_textures.lookup.is_null()) {
// TODO When this code path is required, use a time-spread task to reduce stalls
NormalMapImages normalmap_images;
normalmap_images.atlas_images = ob.normalmap_atlas_images;
normalmap_images.lookup_image = ob.cell_lookup_image;
NormalMapImages normalmap_images = ob.normalmap_images;
normalmap_textures = store_normalmap_data_to_textures(normalmap_images);
}

View File

@ -282,7 +282,7 @@ private:
void apply_data_block_response(VoxelEngine::BlockDataOutput &ob);
void apply_virtual_texture_update(VoxelEngine::BlockVirtualTextureOutput &ob);
void apply_virtual_texture_update_to_block(
VoxelMeshBlockVLT &block, VoxelMesher::VirtualTextureOutput &ob, unsigned int lod_index);
VoxelMeshBlockVLT &block, VirtualTextureOutput &ob, unsigned int lod_index);
void start_updater();
void stop_updater();