| 1430 | } |
| 1431 | |
| 1432 | Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, RDD::TextureLayout p_dst_layout, bool p_immediate_flush) { |
| 1433 | Texture *texture = texture_owner.get_or_null(p_texture); |
| 1434 | ERR_FAIL_NULL_V(texture, ERR_INVALID_PARAMETER); |
| 1435 | |
| 1436 | if (texture->owner != RID()) { |
| 1437 | p_texture = texture->owner; |
| 1438 | texture = texture_owner.get_or_null(texture->owner); |
| 1439 | ERR_FAIL_NULL_V(texture, ERR_BUG); // This is a bug. |
| 1440 | } |
| 1441 | |
| 1442 | uint32_t layer_count = _texture_layer_count(texture); |
| 1443 | ERR_FAIL_COND_V(p_layer >= layer_count, ERR_INVALID_PARAMETER); |
| 1444 | |
| 1445 | uint32_t width, height; |
| 1446 | uint32_t tight_mip_size = get_image_format_required_size(texture->format, texture->width, texture->height, texture->depth, texture->mipmaps, &width, &height); |
| 1447 | uint32_t required_size = tight_mip_size; |
| 1448 | uint32_t required_align = _texture_alignment(texture); |
| 1449 | |
| 1450 | ERR_FAIL_COND_V_MSG(required_size != (uint32_t)p_data.size(), ERR_INVALID_PARAMETER, |
| 1451 | "Required size for texture update (" + itos(required_size) + ") does not match data supplied size (" + itos(p_data.size()) + ")."); |
| 1452 | |
| 1453 | uint32_t block_w, block_h; |
| 1454 | get_compressed_image_format_block_dimensions(texture->format, block_w, block_h); |
| 1455 | |
| 1456 | uint32_t pixel_size = get_image_format_pixel_size(texture->format); |
| 1457 | uint32_t pixel_rshift = get_compressed_image_format_pixel_rshift(texture->format); |
| 1458 | uint32_t block_size = get_compressed_image_format_block_byte_size(texture->format); |
| 1459 | |
| 1460 | // The algorithm operates on two passes, one to figure out the total size the staging buffer will require to allocate and another one where the copy is actually performed. |
| 1461 | uint32_t staging_worker_offset = 0; |
| 1462 | uint32_t staging_local_offset = 0; |
| 1463 | TransferWorker *transfer_worker = nullptr; |
| 1464 | const uint8_t *read_ptr = p_data.ptr(); |
| 1465 | uint8_t *write_ptr = nullptr; |
| 1466 | for (uint32_t pass = 0; pass < 2; pass++) { |
| 1467 | const bool copy_pass = (pass == 1); |
| 1468 | if (copy_pass) { |
| 1469 | transfer_worker = _acquire_transfer_worker(staging_local_offset, required_align, staging_worker_offset); |
| 1470 | texture->transfer_worker_index = transfer_worker->index; |
| 1471 | |
| 1472 | { |
| 1473 | MutexLock lock(transfer_worker->operations_mutex); |
| 1474 | texture->transfer_worker_operation = ++transfer_worker->operations_counter; |
| 1475 | } |
| 1476 | |
| 1477 | staging_local_offset = 0; |
| 1478 | |
| 1479 | write_ptr = driver->buffer_map(transfer_worker->staging_buffer); |
| 1480 | ERR_FAIL_NULL_V(write_ptr, ERR_CANT_CREATE); |
| 1481 | |
| 1482 | if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { |
| 1483 | // Transition the texture to the optimal layout. |
| 1484 | RDD::TextureBarrier tb; |
| 1485 | tb.texture = texture->driver_id; |
| 1486 | tb.dst_access = RDD::BARRIER_ACCESS_COPY_WRITE_BIT; |
| 1487 | tb.prev_layout = RDD::TEXTURE_LAYOUT_UNDEFINED; |
| 1488 | tb.next_layout = p_dst_layout; |
| 1489 | tb.subresources.aspect = texture->barrier_aspect_flags; |
nothing calls this directly
no test coverage detected