Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mobile Renderer makes Meshes unreadable/uneditable on Android #75599

Closed
qdeanc opened this issue Apr 2, 2023 · 2 comments · Fixed by #84852
Closed

Mobile Renderer makes Meshes unreadable/uneditable on Android #75599

qdeanc opened this issue Apr 2, 2023 · 2 comments · Fixed by #84852

Comments

@qdeanc
Copy link

qdeanc commented Apr 2, 2023

Godot version

4.0.1-stable

System information

Android 12, Mobile Renderer

Issue description

When retrieving Mesh data from a MeshInstance3D like so...

var mesh = self.get_mesh()
var mesh_array = mesh.surface_get_arrays(0)
var vertex_array = mesh_array[Mesh.ARRAY_VERTEX]
var index_array = mesh_array[Mesh.ARRAY_INDEX]

...the index_array contains vertex indices that are not within the vertex_array.

This issue does not occur in the Linux editor, but does occur on my Android build:
Android 12
arm64v8
sdk version 32.0.0
ndk version 23.2.8568313

Steps to reproduce

Download the minimal reproduction project, which contains an example ArrayMesh and GDScript script which has the code shown above. Build to Android using the 4.0.1 build template and test.

Minimal reproduction project

Array_Mesh_Test.zip

@qdeanc qdeanc changed the title ArrayMesh's ARRAY_INDEX array returns out-of-bounds vertex indexes on Android Mesh's ARRAY_INDEX array returns out-of-bounds vertex indexes on Android Apr 3, 2023
@qdeanc
Copy link
Author

qdeanc commented Apr 4, 2023

Some more info:

  • This bug happens when "Rendering Method.mobile" is set to "mobile" in the project settings. It does not happen when the "Rendering Method.mobile" is set to "gl_compatibility". "forward_plus" doesn't seem to render anything at all.

  • I tried modifying the custom mesh using the MeshDataTool, which failed and results in the mesh disappearing. So due to this bug, it seems that reading and modifying meshes is not possible on Android devices using the "mobile" renderer.

@qdeanc qdeanc changed the title Mesh's ARRAY_INDEX array returns out-of-bounds vertex indexes on Android Mobile Renderer makes Meshes unreadable/uneditable on Android Apr 4, 2023
@clayjohn clayjohn added this to the 4.x milestone Apr 11, 2023
@mbrlabs
Copy link
Contributor

mbrlabs commented Oct 7, 2023

I looked into this (latest master branch), but i hit a roadblock because my understanding of Vulkan is too limited unfortunately.

Godot reads the indices as raw byte buffers from the Vulkan API using the method below, but the returned values are sometimes bigger than the actual vertex count. They later get composed into 16/32 bit indices but they are wrong from the start i think.

Vector<uint8_t> RenderingDeviceVulkan::buffer_get_data(RID p_buffer, uint32_t p_offset, uint32_t p_size) {
_THREAD_SAFE_METHOD_
// It could be this buffer was just created.
VkPipelineShaderStageCreateFlags src_stage_mask = VK_PIPELINE_STAGE_TRANSFER_BIT;
VkAccessFlags src_access_mask = VK_ACCESS_TRANSFER_WRITE_BIT;
// Get the vulkan buffer and the potential stage/access possible.
Buffer *buffer = _get_buffer_from_owner(p_buffer, src_stage_mask, src_access_mask, BARRIER_MASK_ALL_BARRIERS);
if (!buffer) {
ERR_FAIL_V_MSG(Vector<uint8_t>(), "Buffer is either invalid or this type of buffer can't be retrieved. Only Index and Vertex buffers allow retrieving.");
}
// Make sure no one is using the buffer -- the "true" gets us to the same command buffer as below.
_buffer_memory_barrier(buffer->buffer, 0, buffer->size, src_stage_mask, VK_PIPELINE_STAGE_TRANSFER_BIT, src_access_mask, VK_ACCESS_TRANSFER_READ_BIT, true);
VkCommandBuffer command_buffer = frames[frame].draw_command_buffer;
// Size of buffer to retrieve.
if (!p_size) {
p_size = buffer->size;
} else {
ERR_FAIL_COND_V_MSG(p_size + p_offset > buffer->size, Vector<uint8_t>(),
"Size is larger than the buffer.");
}
Buffer tmp_buffer;
_buffer_allocate(&tmp_buffer, p_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST, VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT);
VkBufferCopy region;
region.srcOffset = p_offset;
region.dstOffset = 0;
region.size = p_size;
vkCmdCopyBuffer(command_buffer, buffer->buffer, tmp_buffer.buffer, 1, &region); // Dst buffer is in CPU, but I wonder if src buffer needs a barrier for this.
// Flush everything so memory can be safely mapped.
_flush(true);
void *buffer_mem;
VkResult vkerr = vmaMapMemory(allocator, tmp_buffer.allocation, &buffer_mem);
ERR_FAIL_COND_V_MSG(vkerr, Vector<uint8_t>(), "vmaMapMemory failed with error " + itos(vkerr) + ".");
Vector<uint8_t> buffer_data;
{
buffer_data.resize(p_size);
uint8_t *w = buffer_data.ptrw();
memcpy(w, buffer_mem, p_size);
}
vmaUnmapMemory(allocator, tmp_buffer.allocation);
_buffer_free(&tmp_buffer);
return buffer_data;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants