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; Ref<Image> image;
image.instantiate(); image.instantiate();
image->create_from_data(sqri, sqri, false, Image::FORMAT_RGB8, bytes); image->create_from_data(sqri, sqri, false, Image::FORMAT_RGB8, bytes);
images.lookup_image = image; images.lookup = image;
} }
return images; return images;
@ -606,14 +606,14 @@ NormalMapTextures store_normalmap_data_to_textures(const NormalMapImages &data)
ZN_PROFILE_SCOPE_NAMED("Atlas texture"); ZN_PROFILE_SCOPE_NAMED("Atlas texture");
Ref<Texture2DArray> atlas; Ref<Texture2DArray> atlas;
atlas.instantiate(); 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); ZN_ASSERT_RETURN_V(err == OK, textures);
textures.atlas = atlas; textures.atlas = atlas;
} }
{ {
ZN_PROFILE_SCOPE_NAMED("Lookup image+texture"); 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; 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); Vector3i origin_in_voxels, unsigned int lod_index, bool octahedral_encoding);
struct NormalMapImages { struct NormalMapImages {
Vector<Ref<Image>> atlas_images; Vector<Ref<Image>> atlas;
Ref<Image> lookup_image; Ref<Image> lookup;
}; };
struct NormalMapTextures { 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. // 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); 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 } // namespace zylann::voxel
#endif // VOXEL_DISTANCE_NORMALMAPS_H #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()) { if (VoxelEngine::get_singleton().is_threaded_mesh_resource_building_enabled()) {
NormalMapTextures textures = store_normalmap_data_to_textures(images); NormalMapTextures textures = store_normalmap_data_to_textures(images);
virtual_textures->normalmap_atlas = textures.atlas; virtual_textures->normalmap_textures = textures;
virtual_textures->cell_lookup = textures.lookup;
} else { } else {
virtual_textures->normalmap_atlas_images = images.atlas_images; virtual_textures->normalmap_images = images;
virtual_textures->cell_lookup_image = images.lookup_image;
} }
virtual_textures->valid = true; virtual_textures->valid = true;

View File

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

View File

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

View File

@ -49,6 +49,7 @@ private:
VoxelMesher::Output _surfaces_output; VoxelMesher::Output _surfaces_output;
Ref<Mesh> _mesh; Ref<Mesh> _mesh;
std::vector<uint8_t> _mesh_material_indices; // Indexed by mesh surface 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, 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/progressive_task_runner.h"
#include "../util/tasks/threaded_task_runner.h" #include "../util/tasks/threaded_task_runner.h"
#include "../util/tasks/time_spread_task_runner.h" #include "../util/tasks/time_spread_task_runner.h"
#include "distance_normalmaps.h"
#include "priority_dependency.h" #include "priority_dependency.h"
namespace zylann::voxel { namespace zylann::voxel {
@ -38,6 +39,9 @@ public:
uint8_t lod; 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. // 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; 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 { struct BlockDataOutput {
@ -62,7 +66,7 @@ public:
}; };
struct BlockVirtualTextureOutput { struct BlockVirtualTextureOutput {
std::shared_ptr<VoxelMesher::VirtualTextureOutput> virtual_textures; std::shared_ptr<VirtualTextureOutput> virtual_textures;
Vector3i position; Vector3i position;
uint32_t lod_index; uint32_t lod_index;
}; };

View File

@ -46,18 +46,6 @@ public:
bool virtual_texture_hint = false; 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 Output {
struct Surface { struct Surface {
Array arrays; Array arrays;
@ -83,11 +71,6 @@ public:
// May be used to store extra information needed in shader to render the mesh properly // 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) // (currently used only by the cubes mesher when baking colors)
Ref<Image> atlas_image; 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); 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()); block->set_parent_transform(get_global_transform());
if (ob.surfaces.virtual_textures != nullptr && ob.surfaces.virtual_textures->valid) { if (ob.virtual_textures != nullptr && ob.virtual_textures->valid) {
apply_virtual_texture_update_to_block(*block, *ob.surfaces.virtual_textures, ob.lod); apply_virtual_texture_update_to_block(*block, *ob.virtual_textures, ob.lod);
} }
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
@ -1813,19 +1813,15 @@ void VoxelLodTerrain::apply_virtual_texture_update(VoxelEngine::BlockVirtualText
} }
void VoxelLodTerrain::apply_virtual_texture_update_to_block( 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_PROFILE_SCOPE();
ZN_ASSERT(ob.valid); ZN_ASSERT(ob.valid);
NormalMapTextures normalmap_textures; NormalMapTextures normalmap_textures = ob.normalmap_textures;
normalmap_textures.atlas = ob.normalmap_atlas;
normalmap_textures.lookup = ob.cell_lookup;
if (normalmap_textures.lookup.is_null()) { if (normalmap_textures.lookup.is_null()) {
// TODO When this code path is required, use a time-spread task to reduce stalls // TODO When this code path is required, use a time-spread task to reduce stalls
NormalMapImages normalmap_images; NormalMapImages normalmap_images = ob.normalmap_images;
normalmap_images.atlas_images = ob.normalmap_atlas_images;
normalmap_images.lookup_image = ob.cell_lookup_image;
normalmap_textures = store_normalmap_data_to_textures(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_data_block_response(VoxelEngine::BlockDataOutput &ob);
void apply_virtual_texture_update(VoxelEngine::BlockVirtualTextureOutput &ob); void apply_virtual_texture_update(VoxelEngine::BlockVirtualTextureOutput &ob);
void apply_virtual_texture_update_to_block( 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 start_updater();
void stop_updater(); void stop_updater();