diff options
Diffstat (limited to 'servers/rendering/rendering_device.cpp')
-rw-r--r-- | servers/rendering/rendering_device.cpp | 157 |
1 files changed, 147 insertions, 10 deletions
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 942d5631e4..e9fa38475e 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -946,6 +946,7 @@ RID RenderingDevice::texture_create_shared(const TextureView &p_view, RID p_with RDG::ResourceTracker *tracker = RDG::resource_tracker_create(); tracker->texture_driver_id = texture.shared_fallback->texture; + tracker->texture_size = Size2i(texture.width, texture.height); tracker->texture_subresources = texture.barrier_range(); tracker->texture_usage = alias_format.usage_bits; tracker->reference_count = 1; @@ -1125,6 +1126,7 @@ RID RenderingDevice::texture_create_shared_from_slice(const TextureView &p_view, RDG::ResourceTracker *tracker = RDG::resource_tracker_create(); tracker->texture_driver_id = texture.shared_fallback->texture; + tracker->texture_size = Size2i(texture.width, texture.height); tracker->texture_subresources = slice_range; tracker->texture_usage = slice_format.usage_bits; tracker->reference_count = 1; @@ -1260,8 +1262,6 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons write_ptr = driver->buffer_map(transfer_worker->staging_buffer); ERR_FAIL_NULL_V(write_ptr, ERR_CANT_CREATE); - write_ptr += staging_worker_offset; - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { // Transition the texture to the optimal layout. RDD::TextureBarrier tb; @@ -1303,11 +1303,12 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons if (copy_pass) { const uint8_t *read_ptr_mipmap_layer = read_ptr_mipmap + (tight_mip_size / depth) * z; - _copy_region_block_or_regular(read_ptr_mipmap_layer, write_ptr, 0, 0, width, width, height, block_w, block_h, pitch, pixel_size, block_size); - write_ptr += to_allocate; + uint64_t staging_buffer_offset = staging_worker_offset + staging_local_offset; + uint8_t *write_ptr_mipmap_layer = write_ptr + staging_buffer_offset; + _copy_region_block_or_regular(read_ptr_mipmap_layer, write_ptr_mipmap_layer, 0, 0, width, width, height, block_w, block_h, pitch, pixel_size, block_size); RDD::BufferTextureCopyRegion copy_region; - copy_region.buffer_offset = staging_worker_offset + staging_local_offset; + copy_region.buffer_offset = staging_buffer_offset; copy_region.texture_subresources.aspect = texture->read_aspect_flags; copy_region.texture_subresources.mipmap = mm_i; copy_region.texture_subresources.base_layer = p_layer; @@ -3758,6 +3759,15 @@ int RenderingDevice::screen_get_height(DisplayServer::WindowID p_screen) const { return context->surface_get_height(surface); } +int RenderingDevice::screen_get_pre_rotation_degrees(DisplayServer::WindowID p_screen) const { + _THREAD_SAFE_METHOD_ + + HashMap<DisplayServer::WindowID, RDD::SwapChainID>::ConstIterator it = screen_swap_chains.find(p_screen); + ERR_FAIL_COND_V_MSG(it == screen_swap_chains.end(), ERR_CANT_CREATE, "A swap chain was not created for the screen."); + + return driver->swap_chain_get_pre_rotation_degrees(it->value); +} + RenderingDevice::FramebufferFormatID RenderingDevice::screen_get_framebuffer_format(DisplayServer::WindowID p_screen) const { _THREAD_SAFE_METHOD_ @@ -4441,6 +4451,117 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint dl->state.draw_count++; } +void RenderingDevice::draw_list_draw_indirect(DrawListID p_list, bool p_use_indices, RID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride) { + ERR_RENDER_THREAD_GUARD(); + + DrawList *dl = _get_draw_list_ptr(p_list); + ERR_FAIL_NULL(dl); + + Buffer *buffer = storage_buffer_owner.get_or_null(p_buffer); + ERR_FAIL_NULL(buffer); + + ERR_FAIL_COND_MSG(!buffer->usage.has_flag(RDD::BUFFER_USAGE_INDIRECT_BIT), "Buffer provided was not created to do indirect dispatch."); + +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); +#endif + +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_MSG(!dl->validation.pipeline_active, + "No render pipeline was set before attempting to draw."); + if (dl->validation.pipeline_vertex_format != INVALID_ID) { + // Pipeline uses vertices, validate format. + ERR_FAIL_COND_MSG(dl->validation.vertex_format == INVALID_ID, + "No vertex array was bound, and render pipeline expects vertices."); + // Make sure format is right. + ERR_FAIL_COND_MSG(dl->validation.pipeline_vertex_format != dl->validation.vertex_format, + "The vertex format used to create the pipeline does not match the vertex format bound."); + } + + if (dl->validation.pipeline_push_constant_size > 0) { + // Using push constants, check that they were supplied. + ERR_FAIL_COND_MSG(!dl->validation.pipeline_push_constant_supplied, + "The shader in this pipeline requires a push constant to be set before drawing, but it's not present."); + } +#endif + +#ifdef DEBUG_ENABLED + for (uint32_t i = 0; i < dl->state.set_count; i++) { + if (dl->state.sets[i].pipeline_expected_format == 0) { + // Nothing expected by this pipeline. + continue; + } + + if (dl->state.sets[i].pipeline_expected_format != dl->state.sets[i].uniform_set_format) { + if (dl->state.sets[i].uniform_set_format == 0) { + ERR_FAIL_MSG(vformat("Uniforms were never supplied for set (%d) at the time of drawing, which are required by the pipeline.", i)); + } else if (uniform_set_owner.owns(dl->state.sets[i].uniform_set)) { + UniformSet *us = uniform_set_owner.get_or_null(dl->state.sets[i].uniform_set); + ERR_FAIL_MSG(vformat("Uniforms supplied for set (%d):\n%s\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(us->shader_id, us->shader_set), _shader_uniform_debug(dl->state.pipeline_shader))); + } else { + ERR_FAIL_MSG(vformat("Uniforms supplied for set (%s, which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(dl->state.pipeline_shader))); + } + } + } +#endif + + // Prepare descriptor sets if the API doesn't use pipeline barriers. + if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { + for (uint32_t i = 0; i < dl->state.set_count; i++) { + if (dl->state.sets[i].pipeline_expected_format == 0) { + // Nothing expected by this pipeline. + continue; + } + + draw_graph.add_draw_list_uniform_set_prepare_for_use(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i); + } + } + + // Bind descriptor sets. + for (uint32_t i = 0; i < dl->state.set_count; i++) { + if (dl->state.sets[i].pipeline_expected_format == 0) { + continue; // Nothing expected by this pipeline. + } + if (!dl->state.sets[i].bound) { + // All good, see if this requires re-binding. + draw_graph.add_draw_list_bind_uniform_set(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i); + + UniformSet *uniform_set = uniform_set_owner.get_or_null(dl->state.sets[i].uniform_set); + _uniform_set_update_shared(uniform_set); + + draw_graph.add_draw_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage); + + dl->state.sets[i].bound = true; + } + } + + if (p_use_indices) { +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_MSG(!dl->validation.index_array_count, + "Draw command requested indices, but no index buffer was set."); + + ERR_FAIL_COND_MSG(dl->validation.pipeline_uses_restart_indices != dl->validation.index_buffer_uses_restart_indices, + "The usage of restart indices in index buffer does not match the render primitive in the pipeline."); +#endif + + ERR_FAIL_COND_MSG(p_offset + 20 > buffer->size, "Offset provided (+20) is past the end of buffer."); + + draw_graph.add_draw_list_draw_indexed_indirect(buffer->driver_id, p_offset, p_draw_count, p_stride); + } else { + ERR_FAIL_COND_MSG(p_offset + 16 > buffer->size, "Offset provided (+16) is past the end of buffer."); + + draw_graph.add_draw_list_draw_indirect(buffer->driver_id, p_offset, p_draw_count, p_stride); + } + + dl->state.draw_count++; + + if (buffer->draw_tracker != nullptr) { + draw_graph.add_draw_list_usage(buffer->draw_tracker, RDG::RESOURCE_USAGE_INDIRECT_BUFFER_READ); + } + + _check_transfer_worker_buffer(buffer); +} + void RenderingDevice::draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) { ERR_RENDER_THREAD_GUARD(); @@ -5153,14 +5274,13 @@ void RenderingDevice::_wait_for_transfer_worker(TransferWorker *p_transfer_worke p_transfer_worker->operations_processed = p_transfer_worker->operations_submitted; } - if (!p_transfer_worker->texture_barriers.is_empty()) { - MutexLock transfer_worker_lock(transfer_worker_pool_mutex); - _flush_barriers_for_transfer_worker(p_transfer_worker); - } + _flush_barriers_for_transfer_worker(p_transfer_worker); } void RenderingDevice::_flush_barriers_for_transfer_worker(TransferWorker *p_transfer_worker) { + // Caller must have already acquired the mutex for the worker. if (!p_transfer_worker->texture_barriers.is_empty()) { + MutexLock transfer_worker_lock(transfer_worker_pool_texture_barriers_mutex); for (uint32_t i = 0; i < p_transfer_worker->texture_barriers.size(); i++) { transfer_worker_pool_texture_barriers.push_back(p_transfer_worker->texture_barriers[i]); } @@ -5233,8 +5353,11 @@ void RenderingDevice::_submit_transfer_workers(RDD::CommandBufferID p_draw_comma } } } +} - if (p_draw_command_buffer && !transfer_worker_pool_texture_barriers.is_empty()) { +void RenderingDevice::_submit_transfer_barriers(RDD::CommandBufferID p_draw_command_buffer) { + MutexLock transfer_worker_lock(transfer_worker_pool_texture_barriers_mutex); + if (!transfer_worker_pool_texture_barriers.is_empty()) { driver->command_pipeline_barrier(p_draw_command_buffer, RDD::PIPELINE_STAGE_COPY_BIT, RDD::PIPELINE_STAGE_ALL_COMMANDS_BIT, {}, {}, transfer_worker_pool_texture_barriers); transfer_worker_pool_texture_barriers.clear(); } @@ -5294,6 +5417,7 @@ bool RenderingDevice::_texture_make_mutable(Texture *p_texture, RID p_texture_id draw_tracker = RDG::resource_tracker_create(); draw_tracker->parent = owner_texture->draw_tracker; draw_tracker->texture_driver_id = p_texture->driver_id; + draw_tracker->texture_size = Size2i(p_texture->width, p_texture->height); draw_tracker->texture_subresources = p_texture->barrier_range(); draw_tracker->texture_usage = p_texture->usage_flags; draw_tracker->texture_slice_or_dirty_rect = p_texture->slice_rect; @@ -5316,6 +5440,7 @@ bool RenderingDevice::_texture_make_mutable(Texture *p_texture, RID p_texture_id // Regular texture. p_texture->draw_tracker = RDG::resource_tracker_create(); p_texture->draw_tracker->texture_driver_id = p_texture->driver_id; + p_texture->draw_tracker->texture_size = Size2i(p_texture->width, p_texture->height); p_texture->draw_tracker->texture_subresources = p_texture->barrier_range(); p_texture->draw_tracker->texture_usage = p_texture->usage_flags; p_texture->draw_tracker->reference_count = 1; @@ -5834,6 +5959,7 @@ void RenderingDevice::_end_frame() { // The command buffer must be copied into a stack variable as the driver workarounds can change the command buffer in use. RDD::CommandBufferID command_buffer = frames[frame].command_buffer; _submit_transfer_workers(command_buffer); + _submit_transfer_barriers(command_buffer); draw_graph.end(RENDER_GRAPH_REORDER, RENDER_GRAPH_FULL_BARRIERS, command_buffer, frames[frame].command_buffer_pool); driver->command_buffer_end(command_buffer); @@ -6553,6 +6679,12 @@ void RenderingDevice::finalize() { ERR_FAIL_COND(reverse_dependency_map.size()); } +void RenderingDevice::_set_max_fps(int p_max_fps) { + for (const KeyValue<DisplayServer::WindowID, RDD::SwapChainID> &it : screen_swap_chains) { + driver->swap_chain_set_max_fps(it.value, p_max_fps); + } +} + RenderingDevice *RenderingDevice::create_local_device() { RenderingDevice *rd = memnew(RenderingDevice); rd->initialize(context); @@ -6651,6 +6783,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_list_set_push_constant", "draw_list", "buffer", "size_bytes"), &RenderingDevice::_draw_list_set_push_constant); ClassDB::bind_method(D_METHOD("draw_list_draw", "draw_list", "use_indices", "instances", "procedural_vertex_count"), &RenderingDevice::draw_list_draw, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("draw_list_draw_indirect", "draw_list", "use_indices", "buffer", "offset", "draw_count", "stride"), &RenderingDevice::draw_list_draw_indirect, DEFVAL(0), DEFVAL(1), DEFVAL(0)); ClassDB::bind_method(D_METHOD("draw_list_enable_scissor", "draw_list", "rect"), &RenderingDevice::draw_list_enable_scissor, DEFVAL(Rect2())); ClassDB::bind_method(D_METHOD("draw_list_disable_scissor", "draw_list"), &RenderingDevice::draw_list_disable_scissor); @@ -7260,6 +7393,10 @@ void RenderingDevice::_bind_methods() { BIND_ENUM_CONSTANT(DEBUG_PASS); } +void RenderingDevice::make_current() { + render_thread_id = Thread::get_caller_id(); +} + RenderingDevice::~RenderingDevice() { finalize(); |