Finish splitting functionality of the Vulkan and D3D12 backends into RenderingDeviceDriver.

This commit is contained in:
Dario 2023-12-19 14:57:56 -03:00
parent f317cc713a
commit 73eff10c76
74 changed files with 5723 additions and 5953 deletions

View file

@ -1470,6 +1470,8 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF_BASIC("gui/common/snap_controls_to_pixels", true);
GLOBAL_DEF_BASIC("gui/fonts/dynamic_fonts/use_oversampling", true);
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/vsync/frame_queue_size", PROPERTY_HINT_RANGE, "2,3,1"), 2);
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/vsync/swapchain_image_count", PROPERTY_HINT_RANGE, "2,4,1"), 3);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/rendering_device/staging_buffer/block_size_kb", PROPERTY_HINT_RANGE, "4,2048,1,or_greater"), 256);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/rendering_device/staging_buffer/max_size_mb", PROPERTY_HINT_RANGE, "1,1024,1,or_greater"), 128);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/rendering_device/staging_buffer/texture_upload_region_size_px", PROPERTY_HINT_RANGE, "1,256,1,or_greater"), 64);

View file

@ -2698,6 +2698,20 @@
</member>
<member name="rendering/rendering_device/staging_buffer/texture_upload_region_size_px" type="int" setter="" getter="" default="64">
</member>
<member name="rendering/rendering_device/vsync/frame_queue_size" type="int" setter="" getter="" default="2">
The number of frames to track on the CPU side before stalling to wait for the GPU.
Try the [url=https://darksylinc.github.io/vsync_simulator/]V-Sync Simulator[/url], an interactive interface that simulates presentation to better understand how it is affected by different variables under various conditions.
[b]Note:[/b] This property is only read when the project starts. There is currently no way to change this value at run-time.
</member>
<member name="rendering/rendering_device/vsync/swapchain_image_count" type="int" setter="" getter="" default="3">
The number of images the swapchain will consist of (back buffers + front buffer).
[code]2[/code] corresponds to double-buffering and [code]3[/code] to triple-buffering.
Double-buffering may give you the lowest lag/latency but if V-Sync is on and the system can't render at 60 fps, the framerate will go down in multiples of it (e.g. 30 fps, 15, 7.5, etc.). Triple buffering gives you higher framerate (specially if the system can't reach a constant 60 fps) at the cost of up to 1 frame of latency, with [constant DisplayServer.VSYNC_ENABLED] (FIFO).
Use double-buffering with [constant DisplayServer.VSYNC_ENABLED]. Triple-buffering is a must if you plan on using [constant DisplayServer.VSYNC_MAILBOX] mode.
Try the [url=https://darksylinc.github.io/vsync_simulator/]V-Sync Simulator[/url], an interactive interface that simulates presentation to better understand how it is affected by different variables under various conditions.
[b]Note:[/b] This property is only read when the project starts. There is currently no way to change this value at run-time.
[b]Note:[/b] Some platforms may restrict the actual value.
</member>
<member name="rendering/rendering_device/vulkan/max_descriptors_per_pool" type="int" setter="" getter="" default="64">
</member>
<member name="rendering/scaling_3d/fsr_sharpness" type="float" setter="" getter="" default="0.2">

View file

@ -590,8 +590,9 @@
</method>
<method name="screen_get_framebuffer_format" qualifiers="const">
<return type="int" />
<param index="0" name="screen" type="int" default="0" />
<description>
Returns the screen's framebuffer format.
Returns the framebuffer format of the given screen.
[b]Note:[/b] Only the main [RenderingDevice] returned by [method RenderingServer.get_rendering_device] has a format. If called on a local [RenderingDevice], this method prints an error and returns [constant INVALID_ID].
</description>
</method>

File diff suppressed because it is too large Load diff

View file

@ -1,261 +0,0 @@
/**************************************************************************/
/* d3d12_context.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef D3D12_CONTEXT_H
#define D3D12_CONTEXT_H
#include "core/error/error_list.h"
#include "core/os/mutex.h"
#include "core/string/ustring.h"
#include "core/templates/rid_owner.h"
#include "rendering_device_driver_d3d12.h"
#include "servers/display_server.h"
#include "servers/rendering/renderer_rd/api_context_rd.h"
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wswitch"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
#if defined(AS)
#undef AS
#endif
#include "d3dx12.h"
#include <dxgi1_6.h>
#include <wrl/client.h>
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
using Microsoft::WRL::ComPtr;
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
class D3D12Context : public ApiContextRD {
public:
struct DeviceLimits {
uint64_t max_srvs_per_shader_stage;
uint64_t max_cbvs_per_shader_stage;
uint64_t max_samplers_across_all_stages;
uint64_t max_uavs_across_all_stages;
uint64_t timestamp_frequency;
};
struct SubgroupCapabilities {
uint32_t size;
bool wave_ops_supported;
uint32_t supported_stages_flags_rd() const;
uint32_t supported_operations_flags_rd() const;
};
struct VRSCapabilities {
bool draw_call_supported; // We can specify our fragment rate on a draw call level.
bool primitive_supported; // We can specify our fragment rate on each drawcall.
bool primitive_in_multiviewport;
bool ss_image_supported; // We can provide a density map attachment on our framebuffer.
uint32_t ss_image_tile_size;
bool additional_rates_supported;
};
struct ShaderCapabilities {
D3D_SHADER_MODEL shader_model;
bool native_16bit_ops;
};
struct StorageBufferCapabilities {
bool storage_buffer_16_bit_access_is_supported;
};
struct FormatCapabilities {
bool relaxed_casting_supported;
};
private:
enum {
FRAME_LAG = 2,
IMAGE_COUNT = FRAME_LAG + 1,
};
ComPtr<ID3D12DeviceFactory> device_factory;
ComPtr<IDXGIFactory2> dxgi_factory;
ComPtr<IDXGIAdapter> gpu;
DeviceLimits gpu_limits = {};
struct DeviceBasics {
ComPtr<ID3D12Device> device;
ComPtr<ID3D12CommandQueue> queue;
ComPtr<ID3D12Fence> fence;
HANDLE fence_event = nullptr;
UINT64 fence_value = 0;
RenderingDeviceDriverD3D12 *driver = nullptr;
} md; // 'Main device', as opposed to local device.
uint32_t feature_level = 0; // Major * 10 + minor.
bool tearing_supported = false;
SubgroupCapabilities subgroup_capabilities;
RDD::MultiviewCapabilities multiview_capabilities;
VRSCapabilities vrs_capabilities;
ShaderCapabilities shader_capabilities;
StorageBufferCapabilities storage_buffer_capabilities;
FormatCapabilities format_capabilities;
String adapter_vendor;
String adapter_name;
RenderingDevice::DeviceType adapter_type = {};
String pipeline_cache_id;
bool buffers_prepared = false;
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
uint32_t frame = 0;
ComPtr<ID3D12Fence> frame_fence;
HANDLE frame_fence_event = nullptr;
struct Window {
HWND hwnd = nullptr;
ComPtr<IDXGISwapChain3> swapchain;
UINT swapchain_flags = 0;
UINT sync_interval = 1;
UINT present_flags = 0;
ComPtr<ID3D12Resource> render_targets[IMAGE_COUNT];
uint32_t current_buffer = 0;
int width = 0;
int height = 0;
DisplayServer::VSyncMode vsync_mode = DisplayServer::VSYNC_ENABLED;
RenderingDeviceDriverD3D12::RenderPassInfo render_pass;
RenderingDeviceDriverD3D12::FramebufferInfo framebuffers[IMAGE_COUNT];
};
struct LocalDevice : public DeviceBasics {
bool waiting = false;
HANDLE fence_event = nullptr;
UINT64 fence_value = 0;
};
RID_Owner<LocalDevice, true> local_device_owner;
HashMap<DisplayServer::WindowID, Window> windows;
// Commands.
LocalVector<ID3D12CommandList *> command_list_queue;
uint32_t command_list_count = 1;
static void STDMETHODCALLTYPE _debug_message_func(
D3D12_MESSAGE_CATEGORY p_category,
D3D12_MESSAGE_SEVERITY p_severity,
D3D12_MESSAGE_ID p_id,
LPCSTR p_description,
void *p_context);
Error _initialize_debug_layers();
void _init_device_factory();
Error _select_adapter(int &r_index);
void _dump_adapter_info(int p_index);
Error _create_device(DeviceBasics &r_basics);
Error _get_device_limits();
Error _check_capabilities();
Error _update_swap_chain(Window *window);
void _wait_for_idle_queue(ID3D12CommandQueue *p_queue);
protected:
virtual bool _use_validation_layers();
public:
virtual const char *get_api_name() const override final { return "D3D12"; };
virtual RenderingDevice::Capabilities get_device_capabilities() const override final;
const SubgroupCapabilities &get_subgroup_capabilities() const { return subgroup_capabilities; };
virtual const RDD::MultiviewCapabilities &get_multiview_capabilities() const override final { return multiview_capabilities; };
const VRSCapabilities &get_vrs_capabilities() const { return vrs_capabilities; };
const ShaderCapabilities &get_shader_capabilities() const { return shader_capabilities; };
const StorageBufferCapabilities &get_storage_buffer_capabilities() const { return storage_buffer_capabilities; };
const FormatCapabilities &get_format_capabilities() const { return format_capabilities; };
ID3D12Device *get_device();
IDXGIAdapter *get_adapter();
virtual int get_swapchain_image_count() const override final;
struct WindowPlatformData {
HWND window;
};
virtual Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) override final;
virtual void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height) override final;
virtual int window_get_width(DisplayServer::WindowID p_window = 0) override final;
virtual int window_get_height(DisplayServer::WindowID p_window = 0) override final;
virtual bool window_is_valid_swapchain(DisplayServer::WindowID p_window = 0) override final;
virtual void window_destroy(DisplayServer::WindowID p_window_id) override final;
virtual RDD::RenderPassID window_get_render_pass(DisplayServer::WindowID p_window = 0) override final;
virtual RDD::FramebufferID window_get_framebuffer(DisplayServer::WindowID p_window = 0) override final;
virtual RID local_device_create() override final;
virtual void local_device_push_command_buffers(RID p_local_device, const RDD::CommandBufferID *p_buffers, int p_count) override final;
virtual void local_device_sync(RID p_local_device) override final;
virtual void local_device_free(RID p_local_device) override final;
DXGI_FORMAT get_screen_format() const;
const DeviceLimits &get_device_limits() const;
virtual void set_setup_buffer(RDD::CommandBufferID p_command_buffer) override final;
virtual void append_command_buffer(RDD::CommandBufferID p_command_buffer) override final;
void resize_notify();
virtual void flush(bool p_flush_setup = false, bool p_flush_pending = false, bool p_sync = true) override final;
virtual Error prepare_buffers(RDD::CommandBufferID p_command_buffer) override final;
virtual void postpare_buffers(RDD::CommandBufferID p_command_buffer) override final;
virtual Error swap_buffers() override final;
virtual Error initialize() override final;
void set_object_name(ID3D12Object *p_object, String p_object_name);
virtual String get_device_vendor_name() const override final;
virtual String get_device_name() const override final;
virtual RDD::DeviceType get_device_type() const override final;
virtual String get_device_api_version() const override final;
virtual String get_device_pipeline_cache_uuid() const override final;
virtual void set_vsync_mode(DisplayServer::WindowID p_window, DisplayServer::VSyncMode p_mode) override final;
virtual DisplayServer::VSyncMode get_vsync_mode(DisplayServer::WindowID p_window = 0) const override final;
virtual RenderingDeviceDriver *get_driver(RID p_local_device = RID()) override final;
virtual bool is_debug_utils_enabled() const override final;
D3D12Context();
virtual ~D3D12Context();
};
#endif // D3D12_CONTEXT_H

View file

@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "d3d12_context.h"
#include "rendering_context_driver_d3d12.h"
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push

View file

@ -0,0 +1,313 @@
/**************************************************************************/
/* rendering_context_driver_d3d12.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "rendering_context_driver_d3d12.h"
#include "core/config/engine.h"
#include "core/config/project_settings.h"
#include "core/string/ustring.h"
#include "core/templates/local_vector.h"
#include "core/version.h"
#include "servers/rendering/rendering_device.h"
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wswitch"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif
#include "dxcapi.h"
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
#if !defined(_MSC_VER)
#include <guiddef.h>
#include <dxguids.h>
#endif
// Note: symbols are not available in MinGW and old MSVC import libraries.
const CLSID CLSID_D3D12DeviceFactoryGodot = __uuidof(ID3D12DeviceFactory);
const CLSID CLSID_D3D12DebugGodot = __uuidof(ID3D12Debug);
const CLSID CLSID_D3D12SDKConfigurationGodot = __uuidof(ID3D12SDKConfiguration);
extern "C" {
char godot_nir_arch_name[32];
}
#ifdef PIX_ENABLED
#if defined(__GNUC__)
#define _MSC_VER 1800
#endif
#define USE_PIX
#include "WinPixEventRuntime/pix3.h"
#if defined(__GNUC__)
#undef _MSC_VER
#endif
#endif
RenderingContextDriverD3D12::RenderingContextDriverD3D12() {
CharString cs = Engine::get_singleton()->get_architecture_name().ascii();
memcpy(godot_nir_arch_name, (const char *)cs.get_data(), cs.size());
}
RenderingContextDriverD3D12::~RenderingContextDriverD3D12() {
}
Error RenderingContextDriverD3D12::_init_device_factory() {
uint32_t agility_sdk_version = GLOBAL_GET("rendering/rendering_device/d3d12/agility_sdk_version");
String agility_sdk_path = String(".\\") + Engine::get_singleton()->get_architecture_name();
// Note: symbol is not available in MinGW import library.
PFN_D3D12_GET_INTERFACE d3d_D3D12GetInterface = (PFN_D3D12_GET_INTERFACE)GetProcAddress(LoadLibraryW(L"D3D12.dll"), "D3D12GetInterface");
if (d3d_D3D12GetInterface == nullptr) {
// FIXME: Is it intended for this to silently return when it fails to find the symbol?
return OK;
}
ID3D12SDKConfiguration *sdk_config = nullptr;
if (SUCCEEDED(d3d_D3D12GetInterface(CLSID_D3D12SDKConfigurationGodot, IID_PPV_ARGS(&sdk_config)))) {
ID3D12SDKConfiguration1 *sdk_config1 = nullptr;
if (SUCCEEDED(sdk_config->QueryInterface(&sdk_config1))) {
if (SUCCEEDED(sdk_config1->CreateDeviceFactory(agility_sdk_version, agility_sdk_path.ascii().get_data(), IID_PPV_ARGS(device_factory.GetAddressOf())))) {
d3d_D3D12GetInterface(CLSID_D3D12DeviceFactoryGodot, IID_PPV_ARGS(device_factory.GetAddressOf()));
} else if (SUCCEEDED(sdk_config1->CreateDeviceFactory(agility_sdk_version, ".\\", IID_PPV_ARGS(device_factory.GetAddressOf())))) {
d3d_D3D12GetInterface(CLSID_D3D12DeviceFactoryGodot, IID_PPV_ARGS(device_factory.GetAddressOf()));
}
sdk_config1->Release();
}
sdk_config->Release();
}
return OK;
}
Error RenderingContextDriverD3D12::_initialize_debug_layers() {
ComPtr<ID3D12Debug> debug_controller;
HRESULT res;
if (device_factory) {
res = device_factory->GetConfigurationInterface(CLSID_D3D12DebugGodot, IID_PPV_ARGS(&debug_controller));
} else {
res = D3D12GetDebugInterface(IID_PPV_ARGS(&debug_controller));
}
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_QUERY_FAILED);
debug_controller->EnableDebugLayer();
return OK;
}
Error RenderingContextDriverD3D12::_initialize_devices() {
const UINT dxgi_factory_flags = use_validation_layers() ? DXGI_CREATE_FACTORY_DEBUG : 0;
HRESULT res = CreateDXGIFactory2(dxgi_factory_flags, IID_PPV_ARGS(&dxgi_factory));
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE);
// Enumerate all possible adapters.
LocalVector<IDXGIAdapter1 *> adapters;
IDXGIAdapter1 *adapter = nullptr;
do {
adapter = create_adapter(adapters.size());
if (adapter != nullptr) {
adapters.push_back(adapter);
}
} while (adapter != nullptr);
ERR_FAIL_COND_V_MSG(adapters.is_empty(), ERR_CANT_CREATE, "Adapters enumeration reported zero accessible devices.");
// Fill the device descriptions with the adapters.
driver_devices.resize(adapters.size());
for (uint32_t i = 0; i < adapters.size(); ++i) {
DXGI_ADAPTER_DESC1 desc = {};
adapters[i]->GetDesc1(&desc);
Device &device = driver_devices[i];
device.name = desc.Description;
device.vendor = Vendor(desc.VendorId);
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
device.type = DEVICE_TYPE_CPU;
} else {
const bool has_dedicated_vram = desc.DedicatedVideoMemory > 0;
device.type = has_dedicated_vram ? DEVICE_TYPE_DISCRETE_GPU : DEVICE_TYPE_INTEGRATED_GPU;
}
}
// Release all created adapters.
for (uint32_t i = 0; i < adapters.size(); ++i) {
adapters[i]->Release();
}
ComPtr<IDXGIFactory5> factory_5;
dxgi_factory.As(&factory_5);
if (factory_5 != nullptr) {
// The type is important as in general, sizeof(bool) != sizeof(BOOL).
BOOL feature_supported = FALSE;
res = factory_5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &feature_supported, sizeof(feature_supported));
if (SUCCEEDED(res)) {
tearing_supported = feature_supported;
} else {
ERR_PRINT("CheckFeatureSupport failed with error " + vformat("0x%08ux", (uint64_t)res) + ".");
}
}
return OK;
}
bool RenderingContextDriverD3D12::use_validation_layers() const {
return Engine::get_singleton()->is_validation_layers_enabled();
}
Error RenderingContextDriverD3D12::initialize() {
Error err = _init_device_factory();
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
if (use_validation_layers()) {
err = _initialize_debug_layers();
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
}
err = _initialize_devices();
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
return OK;
}
const RenderingContextDriver::Device &RenderingContextDriverD3D12::device_get(uint32_t p_device_index) const {
DEV_ASSERT(p_device_index < driver_devices.size());
return driver_devices[p_device_index];
}
uint32_t RenderingContextDriverD3D12::device_get_count() const {
return driver_devices.size();
}
bool RenderingContextDriverD3D12::device_supports_present(uint32_t p_device_index, SurfaceID p_surface) const {
// All devices should support presenting to any surface.
return true;
}
RenderingDeviceDriver *RenderingContextDriverD3D12::driver_create() {
return memnew(RenderingDeviceDriverD3D12(this));
}
void RenderingContextDriverD3D12::driver_free(RenderingDeviceDriver *p_driver) {
memdelete(p_driver);
}
RenderingContextDriver::SurfaceID RenderingContextDriverD3D12::surface_create(const void *p_platform_data) {
const WindowPlatformData *wpd = (const WindowPlatformData *)(p_platform_data);
Surface *surface = memnew(Surface);
surface->hwnd = wpd->window;
return SurfaceID(surface);
}
void RenderingContextDriverD3D12::surface_set_size(SurfaceID p_surface, uint32_t p_width, uint32_t p_height) {
Surface *surface = (Surface *)(p_surface);
surface->width = p_width;
surface->height = p_height;
surface->needs_resize = true;
}
void RenderingContextDriverD3D12::surface_set_vsync_mode(SurfaceID p_surface, DisplayServer::VSyncMode p_vsync_mode) {
Surface *surface = (Surface *)(p_surface);
surface->vsync_mode = p_vsync_mode;
surface->needs_resize = true;
}
DisplayServer::VSyncMode RenderingContextDriverD3D12::surface_get_vsync_mode(SurfaceID p_surface) const {
Surface *surface = (Surface *)(p_surface);
return surface->vsync_mode;
}
uint32_t RenderingContextDriverD3D12::surface_get_width(SurfaceID p_surface) const {
Surface *surface = (Surface *)(p_surface);
return surface->width;
}
uint32_t RenderingContextDriverD3D12::surface_get_height(SurfaceID p_surface) const {
Surface *surface = (Surface *)(p_surface);
return surface->height;
}
void RenderingContextDriverD3D12::surface_set_needs_resize(SurfaceID p_surface, bool p_needs_resize) {
Surface *surface = (Surface *)(p_surface);
surface->needs_resize = p_needs_resize;
}
bool RenderingContextDriverD3D12::surface_get_needs_resize(SurfaceID p_surface) const {
Surface *surface = (Surface *)(p_surface);
return surface->needs_resize;
}
void RenderingContextDriverD3D12::surface_destroy(SurfaceID p_surface) {
Surface *surface = (Surface *)(p_surface);
memdelete(surface);
}
bool RenderingContextDriverD3D12::is_debug_utils_enabled() const {
#ifdef PIX_ENABLED
return true;
#else
return false;
#endif
}
IDXGIAdapter1 *RenderingContextDriverD3D12::create_adapter(uint32_t p_adapter_index) const {
ComPtr<IDXGIFactory6> factory_6;
dxgi_factory.As(&factory_6);
// TODO: Use IDXCoreAdapterList, which gives more comprehensive information.
IDXGIAdapter1 *adapter = nullptr;
if (factory_6) {
if (factory_6->EnumAdapterByGpuPreference(p_adapter_index, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, IID_PPV_ARGS(&adapter)) == DXGI_ERROR_NOT_FOUND) {
return nullptr;
}
} else {
if (dxgi_factory->EnumAdapters1(p_adapter_index, &adapter) == DXGI_ERROR_NOT_FOUND) {
return nullptr;
}
}
return adapter;
}
ID3D12DeviceFactory *RenderingContextDriverD3D12::device_factory_get() const {
return device_factory.Get();
}
IDXGIFactory2 *RenderingContextDriverD3D12::dxgi_factory_get() const {
return dxgi_factory.Get();
}
bool RenderingContextDriverD3D12::get_tearing_supported() const {
return tearing_supported;
}

View file

@ -0,0 +1,120 @@
/**************************************************************************/
/* rendering_context_driver_d3d12.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RENDERING_CONTEXT_DRIVER_D3D12_H
#define RENDERING_CONTEXT_DRIVER_D3D12_H
#include "core/error/error_list.h"
#include "core/os/mutex.h"
#include "core/string/ustring.h"
#include "core/templates/rid_owner.h"
#include "rendering_device_driver_d3d12.h"
#include "servers/display_server.h"
#include "servers/rendering/rendering_context_driver.h"
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wswitch"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
#if defined(AS)
#undef AS
#endif
#include "d3dx12.h"
#include <dxgi1_6.h>
#include <wrl/client.h>
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
using Microsoft::WRL::ComPtr;
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
class RenderingContextDriverD3D12 : public RenderingContextDriver {
ComPtr<ID3D12DeviceFactory> device_factory;
ComPtr<IDXGIFactory2> dxgi_factory;
TightLocalVector<Device> driver_devices;
bool tearing_supported = false;
Error _init_device_factory();
Error _initialize_debug_layers();
Error _initialize_devices();
public:
virtual Error initialize() override;
virtual const Device &device_get(uint32_t p_device_index) const override;
virtual uint32_t device_get_count() const override;
virtual bool device_supports_present(uint32_t p_device_index, SurfaceID p_surface) const override;
virtual RenderingDeviceDriver *driver_create() override;
virtual void driver_free(RenderingDeviceDriver *p_driver) override;
virtual SurfaceID surface_create(const void *p_platform_data) override;
virtual void surface_set_size(SurfaceID p_surface, uint32_t p_width, uint32_t p_height) override;
virtual void surface_set_vsync_mode(SurfaceID p_surface, DisplayServer::VSyncMode p_vsync_mode) override;
virtual DisplayServer::VSyncMode surface_get_vsync_mode(SurfaceID p_surface) const override;
virtual uint32_t surface_get_width(SurfaceID p_surface) const override;
virtual uint32_t surface_get_height(SurfaceID p_surface) const override;
virtual void surface_set_needs_resize(SurfaceID p_surface, bool p_needs_resize) override;
virtual bool surface_get_needs_resize(SurfaceID p_surface) const override;
virtual void surface_destroy(SurfaceID p_surface) override;
virtual bool is_debug_utils_enabled() const override;
// Platform-specific data for the Windows embedded in this driver.
struct WindowPlatformData {
HWND window;
};
// D3D12-only methods.
struct Surface {
HWND hwnd = NULL;
uint32_t width = 0;
uint32_t height = 0;
DisplayServer::VSyncMode vsync_mode = DisplayServer::VSYNC_ENABLED;
bool needs_resize = false;
};
IDXGIAdapter1 *create_adapter(uint32_t p_adapter_index) const;
ID3D12DeviceFactory *device_factory_get() const;
IDXGIFactory2 *dxgi_factory_get() const;
bool get_tearing_supported() const;
bool use_validation_layers() const;
RenderingContextDriverD3D12();
virtual ~RenderingContextDriverD3D12() override;
};
#endif // RENDERING_CONTEXT_DRIVER_D3D12_H

File diff suppressed because it is too large Load diff

View file

@ -65,14 +65,11 @@ using Microsoft::WRL::ComPtr;
#define D3D12_BITCODE_OFFSETS_NUM_STAGES 3
struct dxil_validator;
class D3D12Context;
class RenderingContextDriverD3D12;
// Design principles:
// - D3D12 structs are zero-initialized and fields not requiring a non-zero value are omitted (except in cases where expresivity reasons apply).
class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
friend class D3D12Context; // For FramebufferInfo, RenderPassInfo and CommandBufferInfo.
/*****************/
/**** GENERIC ****/
/*****************/
@ -86,8 +83,58 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
static const D3D12Format RD_TO_D3D12_FORMAT[RDD::DATA_FORMAT_MAX];
D3D12Context *context = nullptr;
ID3D12Device *device = nullptr; // Owned by the context.
struct DeviceLimits {
uint64_t max_srvs_per_shader_stage = 0;
uint64_t max_cbvs_per_shader_stage = 0;
uint64_t max_samplers_across_all_stages = 0;
uint64_t max_uavs_across_all_stages = 0;
uint64_t timestamp_frequency = 0;
};
struct SubgroupCapabilities {
uint32_t size = 0;
bool wave_ops_supported = false;
uint32_t supported_stages_flags_rd() const;
uint32_t supported_operations_flags_rd() const;
};
struct VRSCapabilities {
bool draw_call_supported = false; // We can specify our fragment rate on a draw call level.
bool primitive_supported = false; // We can specify our fragment rate on each drawcall.
bool primitive_in_multiviewport = false;
bool ss_image_supported = false; // We can provide a density map attachment on our framebuffer.
uint32_t ss_image_tile_size = 0;
bool additional_rates_supported = false;
};
struct ShaderCapabilities {
D3D_SHADER_MODEL shader_model = (D3D_SHADER_MODEL)0;
bool native_16bit_ops = false;
};
struct StorageBufferCapabilities {
bool storage_buffer_16_bit_access_is_supported = false;
};
struct FormatCapabilities {
bool relaxed_casting_supported = false;
};
RenderingContextDriverD3D12 *context_driver = nullptr;
RenderingContextDriver::Device context_device;
ComPtr<IDXGIAdapter> adapter;
DXGI_ADAPTER_DESC adapter_desc;
ComPtr<ID3D12Device> device;
DeviceLimits device_limits;
RDD::Capabilities device_capabilities;
uint32_t feature_level = 0; // Major * 10 + minor.
SubgroupCapabilities subgroup_capabilities;
RDD::MultiviewCapabilities multiview_capabilities;
VRSCapabilities vrs_capabilities;
ShaderCapabilities shader_capabilities;
StorageBufferCapabilities storage_buffer_capabilities;
FormatCapabilities format_capabilities;
String pipeline_cache_id;
class DescriptorsHeap {
D3D12_DESCRIPTOR_HEAP_DESC desc = {};
@ -127,6 +174,19 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
ComPtr<ID3D12CommandSignature> dispatch;
} indirect_cmd_signatures;
static void STDMETHODCALLTYPE _debug_message_func(D3D12_MESSAGE_CATEGORY p_category, D3D12_MESSAGE_SEVERITY p_severity, D3D12_MESSAGE_ID p_id, LPCSTR p_description, void *p_context);
void _set_object_name(ID3D12Object *p_object, String p_object_name);
Error _initialize_device();
Error _check_capabilities();
Error _get_device_limits();
Error _initialize_allocator();
Error _initialize_frames(uint32_t p_frame_count);
Error _initialize_command_signatures();
public:
Error initialize(uint32_t p_device_index, uint32_t p_frame_count) override final;
private:
/****************/
/**** MEMORY ****/
/****************/
@ -183,7 +243,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
uint64_t subres_mask[MAX_SUBRESOURCES / 64] = {};
} groups[MAX_GROUPS];
uint8_t groups_count = 0;
static const D3D12_RESOURCE_STATES DELETED_GROUP = D3D12_RESOURCE_STATE_COMMON;
static const D3D12_RESOURCE_STATES DELETED_GROUP = D3D12_RESOURCE_STATES(0xFFFFFFFFU);
};
PagedAllocator<HashMapElement<ResourceInfo::States *, BarrierRequest>> res_barriers_requests_allocator;
HashMap<ResourceInfo::States *, BarrierRequest, HashMapHasherDefault, HashMapComparatorDefault<ResourceInfo::States *>, decltype(res_barriers_requests_allocator)> res_barriers_requests;
@ -307,13 +367,65 @@ public:
VectorView<RDD::BufferBarrier> p_buffer_barriers,
VectorView<RDD::TextureBarrier> p_texture_barriers) override final;
/*************************/
/**** COMMAND BUFFERS ****/
/*************************/
private:
/****************/
/**** FENCES ****/
/****************/
struct FenceInfo {
ComPtr<ID3D12Fence> d3d_fence = nullptr;
HANDLE event_handle = NULL;
UINT64 fence_value = 0;
};
public:
virtual FenceID fence_create() override;
virtual Error fence_wait(FenceID p_fence) override;
virtual void fence_free(FenceID p_fence) override;
private:
/********************/
/**** SEMAPHORES ****/
/********************/
struct SemaphoreInfo {
ComPtr<ID3D12Fence> d3d_fence = nullptr;
UINT64 fence_value = 0;
};
virtual SemaphoreID semaphore_create() override;
virtual void semaphore_free(SemaphoreID p_semaphore) override;
/******************/
/**** COMMANDS ****/
/******************/
// ----- QUEUE FAMILY -----
virtual CommandQueueFamilyID command_queue_family_get(BitField<CommandQueueFamilyBits> p_cmd_queue_family_bits, RenderingContextDriver::SurfaceID p_surface = 0) override;
private:
// ----- QUEUE -----
struct CommandQueueInfo {
ComPtr<ID3D12CommandQueue> d3d_queue;
};
public:
virtual CommandQueueID command_queue_create(CommandQueueFamilyID p_cmd_queue_family, bool p_identify_as_main_queue = false) override;
virtual Error command_queue_execute(CommandQueueID p_cmd_queue, VectorView<CommandBufferID> p_cmd_buffers, VectorView<SemaphoreID> p_wait_semaphores, VectorView<SemaphoreID> p_signal_semaphores, FenceID p_signal_fence) override;
virtual Error command_queue_present(CommandQueueID p_cmd_queue, VectorView<SwapChainID> p_swap_chains, VectorView<SemaphoreID> p_wait_semaphores) override;
virtual void command_queue_free(CommandQueueID p_cmd_queue) override;
private:
// ----- POOL -----
struct CommandPoolInfo {
CommandQueueFamilyID queue_family;
CommandBufferType buffer_type = COMMAND_BUFFER_TYPE_PRIMARY;
};
virtual CommandPoolID command_pool_create(CommandBufferType p_cmd_buffer_type) override final;
public:
virtual CommandPoolID command_pool_create(CommandQueueFamilyID p_cmd_queue_family, CommandBufferType p_cmd_buffer_type) override final;
virtual void command_pool_free(CommandPoolID p_cmd_pool) override final;
// ----- BUFFER -----
@ -347,17 +459,45 @@ private:
uint32_t compute_root_signature_crc = 0;
RenderPassState render_pass_state;
bool descriptor_heaps_set = false;
};
RBMap<CommandPoolID, LocalVector<CommandBufferInfo *>> pools_command_buffers;
CommandPoolID last_command_pool_id;
public:
virtual CommandBufferID command_buffer_create(CommandBufferType p_cmd_buffer_type, CommandPoolID p_cmd_pool) override final;
virtual CommandBufferID command_buffer_create(CommandPoolID p_cmd_pool) override final;
virtual bool command_buffer_begin(CommandBufferID p_cmd_buffer) override final;
virtual bool command_buffer_begin_secondary(CommandBufferID p_cmd_buffer, RenderPassID p_render_pass, uint32_t p_subpass, FramebufferID p_framebuffer) override final;
virtual void command_buffer_end(CommandBufferID p_cmd_buffer) override final;
virtual void command_buffer_execute_secondary(CommandBufferID p_cmd_buffer, VectorView<CommandBufferID> p_secondary_cmd_buffers) override final;
private:
/********************/
/**** SWAP CHAIN ****/
/********************/
struct SwapChain {
ComPtr<IDXGISwapChain3> d3d_swap_chain;
RenderingContextDriver::SurfaceID surface = RenderingContextDriver::SurfaceID();
UINT present_flags = 0;
UINT sync_interval = 1;
UINT creation_flags = 0;
RenderPassID render_pass;
TightLocalVector<ID3D12Resource *> render_targets;
TightLocalVector<TextureInfo> render_targets_info;
TightLocalVector<FramebufferID> framebuffers;
RDD::DataFormat data_format = DATA_FORMAT_MAX;
};
void _swap_chain_release(SwapChain *p_swap_chain);
void _swap_chain_release_buffers(SwapChain *p_swap_chain);
public:
virtual SwapChainID swap_chain_create(RenderingContextDriver::SurfaceID p_surface) override;
virtual Error swap_chain_resize(CommandQueueID p_cmd_queue, SwapChainID p_swap_chain, uint32_t p_desired_framebuffer_count) override;
virtual FramebufferID swap_chain_acquire_framebuffer(CommandQueueID p_cmd_queue, SwapChainID p_swap_chain, bool &r_resize_required) override;
virtual RenderPassID swap_chain_get_render_pass(SwapChainID p_swap_chain) override;
virtual DataFormat swap_chain_get_format(SwapChainID p_swap_chain) override;
virtual void swap_chain_free(SwapChainID p_swap_chain) override;
/*********************/
/**** FRAMEBUFFER ****/
/*********************/
@ -376,6 +516,8 @@ private:
D3D12_RENDER_TARGET_VIEW_DESC _make_rtv_for_texture(const TextureInfo *p_texture_info, uint32_t p_mipmap_offset, uint32_t p_layer_offset, uint32_t p_layers, bool p_add_bases = true);
D3D12_DEPTH_STENCIL_VIEW_DESC _make_dsv_for_texture(const TextureInfo *p_texture_info);
FramebufferID _framebuffer_create(RenderPassID p_render_pass, VectorView<TextureID> p_attachments, uint32_t p_width, uint32_t p_height, bool p_is_screen);
public:
virtual FramebufferID framebuffer_create(RenderPassID p_render_pass, VectorView<TextureID> p_attachments, uint32_t p_width, uint32_t p_height) override final;
virtual void framebuffer_free(FramebufferID p_framebuffer) override final;
@ -602,6 +744,7 @@ public:
virtual void command_uniform_set_prepare_for_use(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index) override final;
private:
void _command_check_descriptor_sets(CommandBufferID p_cmd_buffer);
void _command_bind_uniform_set(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index, bool p_for_compute);
public:
@ -777,12 +920,6 @@ public:
virtual void command_begin_label(CommandBufferID p_cmd_buffer, const char *p_label_name, const Color &p_color) override final;
virtual void command_end_label(CommandBufferID p_cmd_buffer) override final;
/****************/
/**** SCREEN ****/
/****************/
virtual DataFormat screen_get_format() override final;
/********************/
/**** SUBMISSION ****/
/********************/
@ -821,7 +958,7 @@ private:
bool segment_begun = false;
public:
virtual void begin_segment(CommandBufferID p_cmd_buffer, uint32_t p_frame_index, uint32_t p_frames_drawn) override final;
virtual void begin_segment(uint32_t p_frame_index, uint32_t p_frames_drawn) override final;
virtual void end_segment() override final;
/**************/
@ -835,6 +972,10 @@ public:
virtual uint64_t api_trait_get(ApiTrait p_trait) override final;
virtual bool has_feature(Features p_feature) override final;
virtual const MultiviewCapabilities &get_multiview_capabilities() override final;
virtual String get_api_name() const override final;
virtual String get_api_version() const override final;
virtual String get_pipeline_cache_uuid() const override final;
virtual const Capabilities &get_capabilities() const override final;
private:
/*********************/
@ -858,7 +999,7 @@ private:
/******************/
public:
RenderingDeviceDriverD3D12(D3D12Context *p_context, ID3D12Device *p_device, uint32_t p_frame_count);
RenderingDeviceDriverD3D12(RenderingContextDriverD3D12 *p_context_driver);
virtual ~RenderingDeviceDriverD3D12();
};

View file

@ -356,9 +356,6 @@ RasterizerGLES3::RasterizerGLES3() {
RasterizerGLES3::~RasterizerGLES3() {
}
void RasterizerGLES3::prepare_for_blitting_render_targets() {
}
void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect, uint32_t p_layer, bool p_first) {
GLES3::RenderTarget *rt = GLES3::TextureStorage::get_singleton()->get_render_target(p_render_target);

View file

@ -90,7 +90,6 @@ public:
void initialize();
void begin_frame(double frame_step);
void prepare_for_blitting_render_targets();
void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount);
void end_viewport(bool p_swap_buffers);

View file

@ -0,0 +1,686 @@
/**************************************************************************/
/* rendering_context_driver_vulkan.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifdef VULKAN_ENABLED
#include "rendering_context_driver_vulkan.h"
#include "vk_enum_string_helper.h"
#include "core/config/project_settings.h"
#include "core/version.h"
#include "rendering_device_driver_vulkan.h"
#include "vulkan_hooks.h"
RenderingContextDriverVulkan::RenderingContextDriverVulkan() {
// Empty constructor.
}
RenderingContextDriverVulkan::~RenderingContextDriverVulkan() {
if (debug_messenger != VK_NULL_HANDLE && functions.DestroyDebugUtilsMessengerEXT != nullptr) {
functions.DestroyDebugUtilsMessengerEXT(instance, debug_messenger, nullptr);
}
if (debug_report != VK_NULL_HANDLE && functions.DestroyDebugReportCallbackEXT != nullptr) {
functions.DestroyDebugReportCallbackEXT(instance, debug_report, nullptr);
}
if (instance != VK_NULL_HANDLE) {
vkDestroyInstance(instance, nullptr);
}
}
Error RenderingContextDriverVulkan::_initialize_vulkan_version() {
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkApplicationInfo.html#_description
// For Vulkan 1.0 vkEnumerateInstanceVersion is not available, including not in the loader we compile against on Android.
typedef VkResult(VKAPI_PTR * _vkEnumerateInstanceVersion)(uint32_t *);
_vkEnumerateInstanceVersion func = (_vkEnumerateInstanceVersion)vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion");
if (func != nullptr) {
uint32_t api_version;
VkResult res = func(&api_version);
if (res == VK_SUCCESS) {
instance_api_version = api_version;
} else {
// According to the documentation this shouldn't fail with anything except a memory allocation error
// in which case we're in deep trouble anyway.
ERR_FAIL_V(ERR_CANT_CREATE);
}
} else {
print_line("vkEnumerateInstanceVersion not available, assuming Vulkan 1.0.");
instance_api_version = VK_API_VERSION_1_0;
}
return OK;
}
void RenderingContextDriverVulkan::_register_requested_instance_extension(const CharString &p_extension_name, bool p_required) {
ERR_FAIL_COND(requested_instance_extensions.has(p_extension_name));
requested_instance_extensions[p_extension_name] = p_required;
}
Error RenderingContextDriverVulkan::_initialize_instance_extensions() {
enabled_instance_extension_names.clear();
// The surface extension and the platform-specific surface extension are core requirements.
_register_requested_instance_extension(VK_KHR_SURFACE_EXTENSION_NAME, true);
if (_get_platform_surface_extension()) {
_register_requested_instance_extension(_get_platform_surface_extension(), true);
}
if (_use_validation_layers()) {
_register_requested_instance_extension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, false);
}
// This extension allows us to use the properties2 features to query additional device capabilities.
_register_requested_instance_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, false);
// Only enable debug utils in verbose mode or DEV_ENABLED.
// End users would get spammed with messages of varying verbosity due to the
// mess that thirdparty layers/extensions and drivers seem to leave in their
// wake, making the Windows registry a bottomless pit of broken layer JSON.
#ifdef DEV_ENABLED
bool want_debug_utils = true;
#else
bool want_debug_utils = OS::get_singleton()->is_stdout_verbose();
#endif
if (want_debug_utils) {
_register_requested_instance_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, false);
}
// Load instance extensions that are available.
uint32_t instance_extension_count = 0;
VkResult err = vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, nullptr);
ERR_FAIL_COND_V(err != VK_SUCCESS && err != VK_INCOMPLETE, ERR_CANT_CREATE);
ERR_FAIL_COND_V_MSG(instance_extension_count == 0, ERR_CANT_CREATE, "No instance extensions were found.");
TightLocalVector<VkExtensionProperties> instance_extensions;
instance_extensions.resize(instance_extension_count);
err = vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, instance_extensions.ptr());
if (err != VK_SUCCESS && err != VK_INCOMPLETE) {
ERR_FAIL_V(ERR_CANT_CREATE);
}
#ifdef DEV_ENABLED
for (uint32_t i = 0; i < instance_extension_count; i++) {
print_verbose(String("VULKAN: Found instance extension ") + String::utf8(instance_extensions[i].extensionName) + String("."));
}
#endif
// Enable all extensions that are supported and requested.
for (uint32_t i = 0; i < instance_extension_count; i++) {
CharString extension_name(instance_extensions[i].extensionName);
if (requested_instance_extensions.has(extension_name)) {
enabled_instance_extension_names.insert(extension_name);
}
}
// Now check our requested extensions.
for (KeyValue<CharString, bool> &requested_extension : requested_instance_extensions) {
if (!enabled_instance_extension_names.has(requested_extension.key)) {
if (requested_extension.value) {
ERR_FAIL_V_MSG(ERR_BUG, String("Required extension ") + String::utf8(requested_extension.key) + String(" not found."));
} else {
print_verbose(String("Optional extension ") + String::utf8(requested_extension.key) + String(" not found."));
}
}
}
return OK;
}
Error RenderingContextDriverVulkan::_find_validation_layers(TightLocalVector<const char *> &r_layer_names) const {
r_layer_names.clear();
uint32_t instance_layer_count = 0;
VkResult err = vkEnumerateInstanceLayerProperties(&instance_layer_count, nullptr);
ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);
if (instance_layer_count > 0) {
TightLocalVector<VkLayerProperties> layer_properties;
layer_properties.resize(instance_layer_count);
err = vkEnumerateInstanceLayerProperties(&instance_layer_count, layer_properties.ptr());
ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);
// Preferred set of validation layers.
const std::initializer_list<const char *> preferred = { "VK_LAYER_KHRONOS_validation" };
// Alternative (deprecated, removed in SDK 1.1.126.0) set of validation layers.
const std::initializer_list<const char *> lunarg = { "VK_LAYER_LUNARG_standard_validation" };
// Alternative (deprecated, removed in SDK 1.1.121.1) set of validation layers.
const std::initializer_list<const char *> google = { "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation", "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation", "VK_LAYER_GOOGLE_unique_objects" };
// Verify all the layers of the list are present.
for (const std::initializer_list<const char *> &list : { preferred, lunarg, google }) {
bool layers_found = false;
for (const char *layer_name : list) {
layers_found = false;
for (const VkLayerProperties &properties : layer_properties) {
if (!strcmp(properties.layerName, layer_name)) {
layers_found = true;
break;
}
}
if (!layers_found) {
break;
}
}
if (layers_found) {
r_layer_names.reserve(list.size());
for (const char *layer_name : list) {
r_layer_names.push_back(layer_name);
}
break;
}
}
}
return OK;
}
VKAPI_ATTR VkBool32 VKAPI_CALL RenderingContextDriverVulkan::_debug_messenger_callback(VkDebugUtilsMessageSeverityFlagBitsEXT p_message_severity, VkDebugUtilsMessageTypeFlagsEXT p_message_type, const VkDebugUtilsMessengerCallbackDataEXT *p_callback_data, void *p_user_data) {
// This error needs to be ignored because the AMD allocator will mix up memory types on IGP processors.
if (strstr(p_callback_data->pMessage, "Mapping an image with layout") != nullptr && strstr(p_callback_data->pMessage, "can result in undefined behavior if this memory is used by the device") != nullptr) {
return VK_FALSE;
}
// This needs to be ignored because Validator is wrong here.
if (strstr(p_callback_data->pMessage, "Invalid SPIR-V binary version 1.3") != nullptr) {
return VK_FALSE;
}
// This needs to be ignored because Validator is wrong here.
if (strstr(p_callback_data->pMessage, "Shader requires flag") != nullptr) {
return VK_FALSE;
}
// This needs to be ignored because Validator is wrong here.
if (strstr(p_callback_data->pMessage, "SPIR-V module not valid: Pointer operand") != nullptr && strstr(p_callback_data->pMessage, "must be a memory object") != nullptr) {
return VK_FALSE;
}
if (p_callback_data->pMessageIdName && strstr(p_callback_data->pMessageIdName, "UNASSIGNED-CoreValidation-DrawState-ClearCmdBeforeDraw") != nullptr) {
return VK_FALSE;
}
String type_string;
switch (p_message_type) {
case (VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT):
type_string = "GENERAL";
break;
case (VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT):
type_string = "VALIDATION";
break;
case (VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT):
type_string = "PERFORMANCE";
break;
case (VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT):
type_string = "VALIDATION|PERFORMANCE";
break;
}
String objects_string;
if (p_callback_data->objectCount > 0) {
objects_string = "\n\tObjects - " + String::num_int64(p_callback_data->objectCount);
for (uint32_t object = 0; object < p_callback_data->objectCount; ++object) {
objects_string +=
"\n\t\tObject[" + String::num_int64(object) + "]" +
" - " + string_VkObjectType(p_callback_data->pObjects[object].objectType) +
", Handle " + String::num_int64(p_callback_data->pObjects[object].objectHandle);
if (p_callback_data->pObjects[object].pObjectName != nullptr && strlen(p_callback_data->pObjects[object].pObjectName) > 0) {
objects_string += ", Name \"" + String(p_callback_data->pObjects[object].pObjectName) + "\"";
}
}
}
String labels_string;
if (p_callback_data->cmdBufLabelCount > 0) {
labels_string = "\n\tCommand Buffer Labels - " + String::num_int64(p_callback_data->cmdBufLabelCount);
for (uint32_t cmd_buf_label = 0; cmd_buf_label < p_callback_data->cmdBufLabelCount; ++cmd_buf_label) {
labels_string +=
"\n\t\tLabel[" + String::num_int64(cmd_buf_label) + "]" +
" - " + p_callback_data->pCmdBufLabels[cmd_buf_label].pLabelName +
"{ ";
for (int color_idx = 0; color_idx < 4; ++color_idx) {
labels_string += String::num(p_callback_data->pCmdBufLabels[cmd_buf_label].color[color_idx]);
if (color_idx < 3) {
labels_string += ", ";
}
}
labels_string += " }";
}
}
String error_message(type_string +
" - Message Id Number: " + String::num_int64(p_callback_data->messageIdNumber) +
" | Message Id Name: " + p_callback_data->pMessageIdName +
"\n\t" + p_callback_data->pMessage +
objects_string + labels_string);
// Convert VK severity to our own log macros.
switch (p_message_severity) {
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
print_verbose(error_message);
break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
print_line(error_message);
break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
WARN_PRINT(error_message);
break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
ERR_PRINT(error_message);
CRASH_COND_MSG(Engine::get_singleton()->is_abort_on_gpu_errors_enabled(), "Crashing, because abort on GPU errors is enabled.");
break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT:
break; // Shouldn't happen, only handling to make compilers happy.
}
return VK_FALSE;
}
VKAPI_ATTR VkBool32 VKAPI_CALL RenderingContextDriverVulkan::_debug_report_callback(VkDebugReportFlagsEXT p_flags, VkDebugReportObjectTypeEXT p_object_type, uint64_t p_object, size_t p_location, int32_t p_message_code, const char *p_layer_prefix, const char *p_message, void *p_user_data) {
String debug_message = String("Vulkan Debug Report: object - ") + String::num_int64(p_object) + "\n" + p_message;
switch (p_flags) {
case VK_DEBUG_REPORT_DEBUG_BIT_EXT:
case VK_DEBUG_REPORT_INFORMATION_BIT_EXT:
print_line(debug_message);
break;
case VK_DEBUG_REPORT_WARNING_BIT_EXT:
case VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT:
WARN_PRINT(debug_message);
break;
case VK_DEBUG_REPORT_ERROR_BIT_EXT:
ERR_PRINT(debug_message);
break;
}
return VK_FALSE;
}
Error RenderingContextDriverVulkan::_initialize_instance() {
Error err;
TightLocalVector<const char *> enabled_extension_names;
enabled_extension_names.reserve(enabled_instance_extension_names.size());
for (const CharString &extension_name : enabled_instance_extension_names) {
enabled_extension_names.push_back(extension_name.ptr());
}
// We'll set application version to the Vulkan version we're developing against, even if our instance is based on an older Vulkan
// version, devices can still support newer versions of Vulkan. The exception is when we're on Vulkan 1.0, we should not set this
// to anything but 1.0. Note that this value is only used by validation layers to warn us about version issues.
uint32_t application_api_version = instance_api_version == VK_API_VERSION_1_0 ? VK_API_VERSION_1_0 : VK_API_VERSION_1_2;
CharString cs = GLOBAL_GET("application/config/name").operator String().utf8();
VkApplicationInfo app_info = {};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.pApplicationName = cs.get_data();
app_info.pEngineName = VERSION_NAME;
app_info.engineVersion = VK_MAKE_VERSION(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
app_info.apiVersion = application_api_version;
TightLocalVector<const char *> enabled_layer_names;
if (_use_validation_layers()) {
err = _find_validation_layers(enabled_layer_names);
ERR_FAIL_COND_V(err != OK, err);
}
VkInstanceCreateInfo instance_info = {};
instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instance_info.pApplicationInfo = &app_info;
instance_info.enabledExtensionCount = enabled_extension_names.size();
instance_info.ppEnabledExtensionNames = enabled_extension_names.ptr();
instance_info.enabledLayerCount = enabled_layer_names.size();
instance_info.ppEnabledLayerNames = enabled_layer_names.ptr();
// This is info for a temp callback to use during CreateInstance. After the instance is created, we use the instance-based function to register the final callback.
VkDebugUtilsMessengerCreateInfoEXT debug_messenger_create_info = {};
VkDebugReportCallbackCreateInfoEXT debug_report_callback_create_info = {};
const bool has_debug_utils_extension = enabled_instance_extension_names.has(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
const bool has_debug_report_extension = enabled_instance_extension_names.has(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
if (has_debug_utils_extension) {
debug_messenger_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
debug_messenger_create_info.pNext = nullptr;
debug_messenger_create_info.flags = 0;
debug_messenger_create_info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
debug_messenger_create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
debug_messenger_create_info.pfnUserCallback = _debug_messenger_callback;
debug_messenger_create_info.pUserData = this;
instance_info.pNext = &debug_messenger_create_info;
} else if (has_debug_report_extension) {
debug_report_callback_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
debug_report_callback_create_info.flags = VK_DEBUG_REPORT_INFORMATION_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT | VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_DEBUG_BIT_EXT;
debug_report_callback_create_info.pfnCallback = _debug_report_callback;
debug_report_callback_create_info.pUserData = this;
instance_info.pNext = &debug_report_callback_create_info;
}
err = _create_vulkan_instance(&instance_info, &instance);
ERR_FAIL_COND_V(err != OK, err);
#ifdef USE_VOLK
volkLoadInstance(instance);
#endif
// Physical device.
if (enabled_instance_extension_names.has(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
functions.GetPhysicalDeviceFeatures2 = PFN_vkGetPhysicalDeviceFeatures2(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2"));
functions.GetPhysicalDeviceProperties2 = PFN_vkGetPhysicalDeviceProperties2(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2"));
// In Vulkan 1.0, the functions might be accessible under their original extension names.
if (functions.GetPhysicalDeviceFeatures2 == nullptr) {
functions.GetPhysicalDeviceFeatures2 = PFN_vkGetPhysicalDeviceFeatures2(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2KHR"));
}
if (functions.GetPhysicalDeviceProperties2 == nullptr) {
functions.GetPhysicalDeviceProperties2 = PFN_vkGetPhysicalDeviceProperties2(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2KHR"));
}
}
// Device.
functions.GetDeviceProcAddr = PFN_vkGetDeviceProcAddr(vkGetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
// Surfaces.
functions.GetPhysicalDeviceSurfaceSupportKHR = PFN_vkGetPhysicalDeviceSurfaceSupportKHR(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceSupportKHR"));
functions.GetPhysicalDeviceSurfaceFormatsKHR = PFN_vkGetPhysicalDeviceSurfaceFormatsKHR(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR"));
functions.GetPhysicalDeviceSurfaceCapabilitiesKHR = PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
functions.GetPhysicalDeviceSurfacePresentModesKHR = PFN_vkGetPhysicalDeviceSurfacePresentModesKHR(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR"));
// Debug utils and report.
if (has_debug_utils_extension) {
// Setup VK_EXT_debug_utils function pointers always (we use them for debug labels and names).
functions.CreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
functions.DestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
functions.CmdBeginDebugUtilsLabelEXT = (PFN_vkCmdBeginDebugUtilsLabelEXT)vkGetInstanceProcAddr(instance, "vkCmdBeginDebugUtilsLabelEXT");
functions.CmdEndDebugUtilsLabelEXT = (PFN_vkCmdEndDebugUtilsLabelEXT)vkGetInstanceProcAddr(instance, "vkCmdEndDebugUtilsLabelEXT");
functions.SetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT)vkGetInstanceProcAddr(instance, "vkSetDebugUtilsObjectNameEXT");
if (!functions.debug_util_functions_available()) {
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "GetProcAddr: Failed to init VK_EXT_debug_utils\nGetProcAddr: Failure");
}
VkResult res = functions.CreateDebugUtilsMessengerEXT(instance, &debug_messenger_create_info, nullptr, &debug_messenger);
switch (res) {
case VK_SUCCESS:
break;
case VK_ERROR_OUT_OF_HOST_MEMORY:
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "CreateDebugUtilsMessengerEXT: out of host memory\nCreateDebugUtilsMessengerEXT Failure");
break;
default:
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "CreateDebugUtilsMessengerEXT: unknown failure\nCreateDebugUtilsMessengerEXT Failure");
break;
}
} else if (has_debug_report_extension) {
functions.CreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT");
functions.DebugReportMessageEXT = (PFN_vkDebugReportMessageEXT)vkGetInstanceProcAddr(instance, "vkDebugReportMessageEXT");
functions.DestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT");
if (!functions.debug_report_functions_available()) {
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "GetProcAddr: Failed to init VK_EXT_debug_report\nGetProcAddr: Failure");
}
VkResult res = functions.CreateDebugReportCallbackEXT(instance, &debug_report_callback_create_info, nullptr, &debug_report);
switch (res) {
case VK_SUCCESS:
break;
case VK_ERROR_OUT_OF_HOST_MEMORY:
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "CreateDebugReportCallbackEXT: out of host memory\nCreateDebugReportCallbackEXT Failure");
break;
default:
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "CreateDebugReportCallbackEXT: unknown failure\nCreateDebugReportCallbackEXT Failure");
break;
}
}
return OK;
}
Error RenderingContextDriverVulkan::_initialize_devices() {
if (VulkanHooks::get_singleton() != nullptr) {
VkPhysicalDevice physical_device;
bool device_retrieved = VulkanHooks::get_singleton()->get_physical_device(&physical_device);
ERR_FAIL_COND_V(!device_retrieved, ERR_CANT_CREATE);
// When a hook is active, pretend the device returned by the hook is the only device available.
driver_devices.resize(1);
physical_devices.resize(1);
device_queue_families.resize(1);
physical_devices[0] = physical_device;
} else {
uint32_t physical_device_count = 0;
VkResult err = vkEnumeratePhysicalDevices(instance, &physical_device_count, nullptr);
ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);
ERR_FAIL_COND_V_MSG(physical_device_count == 0, ERR_CANT_CREATE, "vkEnumeratePhysicalDevices reported zero accessible devices.\n\nDo you have a compatible Vulkan installable client driver (ICD) installed?\nvkEnumeratePhysicalDevices Failure.");
driver_devices.resize(physical_device_count);
physical_devices.resize(physical_device_count);
device_queue_families.resize(physical_device_count);
err = vkEnumeratePhysicalDevices(instance, &physical_device_count, physical_devices.ptr());
ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);
}
// Fill the list of driver devices with the properties from the physical devices.
for (uint32_t i = 0; i < physical_devices.size(); i++) {
VkPhysicalDeviceProperties props;
vkGetPhysicalDeviceProperties(physical_devices[i], &props);
Device &driver_device = driver_devices[i];
driver_device.name = String::utf8(props.deviceName);
driver_device.vendor = Vendor(props.vendorID);
driver_device.type = DeviceType(props.deviceType);
uint32_t queue_family_properties_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &queue_family_properties_count, nullptr);
if (queue_family_properties_count > 0) {
device_queue_families[i].properties.resize(queue_family_properties_count);
vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &queue_family_properties_count, device_queue_families[i].properties.ptr());
}
}
return OK;
}
bool RenderingContextDriverVulkan::_use_validation_layers() const {
return Engine::get_singleton()->is_validation_layers_enabled();
}
Error RenderingContextDriverVulkan::_create_vulkan_instance(const VkInstanceCreateInfo *p_create_info, VkInstance *r_instance) {
if (VulkanHooks::get_singleton() != nullptr) {
return VulkanHooks::get_singleton()->create_vulkan_instance(p_create_info, r_instance) ? OK : ERR_CANT_CREATE;
} else {
VkResult err = vkCreateInstance(p_create_info, nullptr, r_instance);
ERR_FAIL_COND_V_MSG(err == VK_ERROR_INCOMPATIBLE_DRIVER, ERR_CANT_CREATE,
"Cannot find a compatible Vulkan installable client driver (ICD).\n\n"
"vkCreateInstance Failure");
ERR_FAIL_COND_V_MSG(err == VK_ERROR_EXTENSION_NOT_PRESENT, ERR_CANT_CREATE,
"Cannot find a specified extension library.\n"
"Make sure your layers path is set appropriately.\n"
"vkCreateInstance Failure");
ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE,
"vkCreateInstance failed.\n\n"
"Do you have a compatible Vulkan installable client driver (ICD) installed?\n"
"Please look at the Getting Started guide for additional information.\n"
"vkCreateInstance Failure");
}
return OK;
}
Error RenderingContextDriverVulkan::initialize() {
Error err;
#ifdef USE_VOLK
if (volkInitialize() != VK_SUCCESS) {
return FAILED;
}
#endif
err = _initialize_vulkan_version();
ERR_FAIL_COND_V(err != OK, err);
err = _initialize_instance_extensions();
ERR_FAIL_COND_V(err != OK, err);
err = _initialize_instance();
ERR_FAIL_COND_V(err != OK, err);
err = _initialize_devices();
ERR_FAIL_COND_V(err != OK, err);
return OK;
}
const RenderingContextDriver::Device &RenderingContextDriverVulkan::device_get(uint32_t p_device_index) const {
DEV_ASSERT(p_device_index < driver_devices.size());
return driver_devices[p_device_index];
}
uint32_t RenderingContextDriverVulkan::device_get_count() const {
return driver_devices.size();
}
bool RenderingContextDriverVulkan::device_supports_present(uint32_t p_device_index, SurfaceID p_surface) const {
DEV_ASSERT(p_device_index < physical_devices.size());
// Check if any of the queues supported by the device supports presenting to the window's surface.
const VkPhysicalDevice physical_device = physical_devices[p_device_index];
const DeviceQueueFamilies &queue_families = device_queue_families[p_device_index];
for (uint32_t i = 0; i < queue_families.properties.size(); i++) {
if ((queue_families.properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) && queue_family_supports_present(physical_device, i, p_surface)) {
return true;
}
}
return false;
}
RenderingDeviceDriver *RenderingContextDriverVulkan::driver_create() {
return memnew(RenderingDeviceDriverVulkan(this));
}
void RenderingContextDriverVulkan::driver_free(RenderingDeviceDriver *p_driver) {
memdelete(p_driver);
}
RenderingContextDriver::SurfaceID RenderingContextDriverVulkan::surface_create(const void *p_platform_data) {
DEV_ASSERT(false && "Surface creation should not be called on the platform-agnostic version of the driver.");
return SurfaceID();
}
void RenderingContextDriverVulkan::surface_set_size(SurfaceID p_surface, uint32_t p_width, uint32_t p_height) {
Surface *surface = (Surface *)(p_surface);
surface->width = p_width;
surface->height = p_height;
surface->needs_resize = true;
}
void RenderingContextDriverVulkan::surface_set_vsync_mode(SurfaceID p_surface, DisplayServer::VSyncMode p_vsync_mode) {
Surface *surface = (Surface *)(p_surface);
surface->vsync_mode = p_vsync_mode;
surface->needs_resize = true;
}
DisplayServer::VSyncMode RenderingContextDriverVulkan::surface_get_vsync_mode(SurfaceID p_surface) const {
Surface *surface = (Surface *)(p_surface);
return surface->vsync_mode;
}
uint32_t RenderingContextDriverVulkan::surface_get_width(SurfaceID p_surface) const {
Surface *surface = (Surface *)(p_surface);
return surface->width;
}
uint32_t RenderingContextDriverVulkan::surface_get_height(SurfaceID p_surface) const {
Surface *surface = (Surface *)(p_surface);
return surface->height;
}
void RenderingContextDriverVulkan::surface_set_needs_resize(SurfaceID p_surface, bool p_needs_resize) {
Surface *surface = (Surface *)(p_surface);
surface->needs_resize = p_needs_resize;
}
bool RenderingContextDriverVulkan::surface_get_needs_resize(SurfaceID p_surface) const {
Surface *surface = (Surface *)(p_surface);
return surface->needs_resize;
}
void RenderingContextDriverVulkan::surface_destroy(SurfaceID p_surface) {
Surface *surface = (Surface *)(p_surface);
vkDestroySurfaceKHR(instance, surface->vk_surface, nullptr);
memdelete(surface);
}
bool RenderingContextDriverVulkan::is_debug_utils_enabled() const {
return enabled_instance_extension_names.has(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
}
VkInstance RenderingContextDriverVulkan::instance_get() const {
return instance;
}
VkPhysicalDevice RenderingContextDriverVulkan::physical_device_get(uint32_t p_device_index) const {
DEV_ASSERT(p_device_index < physical_devices.size());
return physical_devices[p_device_index];
}
uint32_t RenderingContextDriverVulkan::queue_family_get_count(uint32_t p_device_index) const {
DEV_ASSERT(p_device_index < physical_devices.size());
return device_queue_families[p_device_index].properties.size();
}
VkQueueFamilyProperties RenderingContextDriverVulkan::queue_family_get(uint32_t p_device_index, uint32_t p_queue_family_index) const {
DEV_ASSERT(p_device_index < physical_devices.size());
DEV_ASSERT(p_queue_family_index < queue_family_get_count(p_device_index));
return device_queue_families[p_device_index].properties[p_queue_family_index];
}
bool RenderingContextDriverVulkan::queue_family_supports_present(VkPhysicalDevice p_physical_device, uint32_t p_queue_family_index, SurfaceID p_surface) const {
DEV_ASSERT(p_physical_device != VK_NULL_HANDLE);
DEV_ASSERT(p_surface != 0);
Surface *surface = (Surface *)(p_surface);
VkBool32 present_supported = false;
VkResult err = vkGetPhysicalDeviceSurfaceSupportKHR(p_physical_device, p_queue_family_index, surface->vk_surface, &present_supported);
return err == VK_SUCCESS && present_supported;
}
const RenderingContextDriverVulkan::Functions &RenderingContextDriverVulkan::functions_get() const {
return functions;
}
#endif // VULKAN_ENABLED

View file

@ -0,0 +1,161 @@
/**************************************************************************/
/* rendering_context_driver_vulkan.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RENDERING_CONTEXT_DRIVER_VULKAN_H
#define RENDERING_CONTEXT_DRIVER_VULKAN_H
#ifdef VULKAN_ENABLED
#include "servers/rendering/rendering_context_driver.h"
#ifdef USE_VOLK
#include <volk.h>
#else
#include <vulkan/vulkan.h>
#endif
class RenderingContextDriverVulkan : public RenderingContextDriver {
public:
struct Functions {
// Physical device.
PFN_vkGetPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2 = nullptr;
PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2 = nullptr;
// Device.
PFN_vkGetDeviceProcAddr GetDeviceProcAddr = nullptr;
// Surfaces.
PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR = nullptr;
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR = nullptr;
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GetPhysicalDeviceSurfaceCapabilitiesKHR = nullptr;
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR = nullptr;
// Debug utils.
PFN_vkCreateDebugUtilsMessengerEXT CreateDebugUtilsMessengerEXT = nullptr;
PFN_vkDestroyDebugUtilsMessengerEXT DestroyDebugUtilsMessengerEXT = nullptr;
PFN_vkCmdBeginDebugUtilsLabelEXT CmdBeginDebugUtilsLabelEXT = nullptr;
PFN_vkCmdEndDebugUtilsLabelEXT CmdEndDebugUtilsLabelEXT = nullptr;
PFN_vkSetDebugUtilsObjectNameEXT SetDebugUtilsObjectNameEXT = nullptr;
bool debug_util_functions_available() const {
return CreateDebugUtilsMessengerEXT != nullptr &&
DestroyDebugUtilsMessengerEXT != nullptr &&
CmdBeginDebugUtilsLabelEXT != nullptr &&
CmdEndDebugUtilsLabelEXT != nullptr &&
SetDebugUtilsObjectNameEXT != nullptr;
}
// Debug report.
PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT = nullptr;
PFN_vkDebugReportMessageEXT DebugReportMessageEXT = nullptr;
PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT = nullptr;
bool debug_report_functions_available() const {
return CreateDebugReportCallbackEXT != nullptr &&
DebugReportMessageEXT != nullptr &&
DestroyDebugReportCallbackEXT != nullptr;
}
};
private:
struct DeviceQueueFamilies {
TightLocalVector<VkQueueFamilyProperties> properties;
};
VkInstance instance = VK_NULL_HANDLE;
uint32_t instance_api_version = VK_API_VERSION_1_0;
HashMap<CharString, bool> requested_instance_extensions;
HashSet<CharString> enabled_instance_extension_names;
TightLocalVector<Device> driver_devices;
TightLocalVector<VkPhysicalDevice> physical_devices;
TightLocalVector<DeviceQueueFamilies> device_queue_families;
VkDebugUtilsMessengerEXT debug_messenger = VK_NULL_HANDLE;
VkDebugReportCallbackEXT debug_report = VK_NULL_HANDLE;
Functions functions;
Error _initialize_vulkan_version();
void _register_requested_instance_extension(const CharString &p_extension_name, bool p_required);
Error _initialize_instance_extensions();
Error _initialize_instance();
Error _initialize_devices();
// Static callbacks.
static VKAPI_ATTR VkBool32 VKAPI_CALL _debug_messenger_callback(VkDebugUtilsMessageSeverityFlagBitsEXT p_message_severity, VkDebugUtilsMessageTypeFlagsEXT p_message_type, const VkDebugUtilsMessengerCallbackDataEXT *p_callback_data, void *p_user_data);
static VKAPI_ATTR VkBool32 VKAPI_CALL _debug_report_callback(VkDebugReportFlagsEXT p_flags, VkDebugReportObjectTypeEXT p_object_type, uint64_t p_object, size_t p_location, int32_t p_message_code, const char *p_layer_prefix, const char *p_message, void *p_user_data);
protected:
Error _find_validation_layers(TightLocalVector<const char *> &r_layer_names) const;
// Can be overridden by platform-specific drivers.
virtual const char *_get_platform_surface_extension() const { return nullptr; }
virtual bool _use_validation_layers() const;
virtual Error _create_vulkan_instance(const VkInstanceCreateInfo *p_create_info, VkInstance *r_instance);
public:
virtual Error initialize() override;
virtual const Device &device_get(uint32_t p_device_index) const override;
virtual uint32_t device_get_count() const override;
virtual bool device_supports_present(uint32_t p_device_index, SurfaceID p_surface) const override;
virtual RenderingDeviceDriver *driver_create() override;
virtual void driver_free(RenderingDeviceDriver *p_driver) override;
virtual SurfaceID surface_create(const void *p_platform_data) override;
virtual void surface_set_size(SurfaceID p_surface, uint32_t p_width, uint32_t p_height) override;
virtual void surface_set_vsync_mode(SurfaceID p_surface, DisplayServer::VSyncMode p_vsync_mode) override;
virtual DisplayServer::VSyncMode surface_get_vsync_mode(SurfaceID p_surface) const override;
virtual uint32_t surface_get_width(SurfaceID p_surface) const override;
virtual uint32_t surface_get_height(SurfaceID p_surface) const override;
virtual void surface_set_needs_resize(SurfaceID p_surface, bool p_needs_resize) override;
virtual bool surface_get_needs_resize(SurfaceID p_surface) const override;
virtual void surface_destroy(SurfaceID p_surface) override;
virtual bool is_debug_utils_enabled() const override;
// Vulkan-only methods.
struct Surface {
VkSurfaceKHR vk_surface = VK_NULL_HANDLE;
uint32_t width = 0;
uint32_t height = 0;
DisplayServer::VSyncMode vsync_mode = DisplayServer::VSYNC_ENABLED;
bool needs_resize = false;
};
VkInstance instance_get() const;
VkPhysicalDevice physical_device_get(uint32_t p_device_index) const;
uint32_t queue_family_get_count(uint32_t p_device_index) const;
VkQueueFamilyProperties queue_family_get(uint32_t p_device_index, uint32_t p_queue_family_index) const;
bool queue_family_supports_present(VkPhysicalDevice p_physical_device, uint32_t p_queue_family_index, SurfaceID p_surface) const;
const Functions &functions_get() const;
RenderingContextDriverVulkan();
virtual ~RenderingContextDriverVulkan() override;
};
#endif // VULKAN_ENABLED
#endif // RENDERING_CONTEXT_DRIVER_VULKAN_H

File diff suppressed because it is too large Load diff

View file

@ -33,6 +33,7 @@
#include "core/templates/hash_map.h"
#include "core/templates/paged_allocator.h"
#include "drivers/vulkan/rendering_context_driver_vulkan.h"
#include "servers/rendering/rendering_device_driver.h"
#ifdef DEBUG_ENABLED
@ -48,8 +49,6 @@
#include <vulkan/vulkan.h>
#endif
class VulkanContext;
// Design principles:
// - Vulkan structs are zero-initialized and fields not requiring a non-zero value are omitted (except in cases where expresivity reasons apply).
class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
@ -57,9 +56,99 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
/**** GENERIC ****/
/*****************/
VulkanContext *context = nullptr;
VkDevice vk_device = VK_NULL_HANDLE; // Owned by the context.
struct CommandQueue;
struct SwapChain;
struct Queue {
VkQueue queue = VK_NULL_HANDLE;
uint32_t virtual_count = 0;
BinaryMutex submit_mutex;
};
struct SubgroupCapabilities {
uint32_t size = 0;
uint32_t min_size = 0;
uint32_t max_size = 0;
VkShaderStageFlags supported_stages = 0;
VkSubgroupFeatureFlags supported_operations = 0;
VkBool32 quad_operations_in_all_stages = false;
bool size_control_is_supported = false;
uint32_t supported_stages_flags_rd() const;
String supported_stages_desc() const;
uint32_t supported_operations_flags_rd() const;
String supported_operations_desc() const;
};
struct VRSCapabilities {
bool pipeline_vrs_supported = false; // We can specify our fragment rate on a pipeline level.
bool primitive_vrs_supported = false; // We can specify our fragment rate on each drawcall.
bool attachment_vrs_supported = false; // We can provide a density map attachment on our framebuffer.
Size2i min_texel_size;
Size2i max_texel_size;
Size2i texel_size; // The texel size we'll use
};
struct ShaderCapabilities {
bool shader_float16_is_supported = false;
bool shader_int8_is_supported = false;
};
struct StorageBufferCapabilities {
bool storage_buffer_16_bit_access_is_supported = false;
bool uniform_and_storage_buffer_16_bit_access_is_supported = false;
bool storage_push_constant_16_is_supported = false;
bool storage_input_output_16 = false;
};
struct DeviceFunctions {
PFN_vkCreateSwapchainKHR CreateSwapchainKHR = nullptr;
PFN_vkDestroySwapchainKHR DestroySwapchainKHR = nullptr;
PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR = nullptr;
PFN_vkAcquireNextImageKHR AcquireNextImageKHR = nullptr;
PFN_vkQueuePresentKHR QueuePresentKHR = nullptr;
PFN_vkCreateRenderPass2KHR CreateRenderPass2KHR = nullptr;
};
VkDevice vk_device = VK_NULL_HANDLE;
RenderingContextDriverVulkan *context_driver = nullptr;
RenderingContextDriver::Device context_device = {};
VkPhysicalDevice physical_device = VK_NULL_HANDLE;
VkPhysicalDeviceProperties physical_device_properties = {};
VkPhysicalDeviceFeatures physical_device_features = {};
VkPhysicalDeviceFeatures requested_device_features = {};
HashMap<CharString, bool> requested_device_extensions;
HashSet<CharString> enabled_device_extension_names;
TightLocalVector<TightLocalVector<Queue>> queue_families;
TightLocalVector<VkQueueFamilyProperties> queue_family_properties;
RDD::Capabilities device_capabilities;
SubgroupCapabilities subgroup_capabilities;
MultiviewCapabilities multiview_capabilities;
VRSCapabilities vrs_capabilities;
ShaderCapabilities shader_capabilities;
StorageBufferCapabilities storage_buffer_capabilities;
bool pipeline_cache_control_support = false;
DeviceFunctions device_functions;
void _register_requested_device_extension(const CharString &p_extension_name, bool p_required);
Error _initialize_device_extensions();
Error _check_device_features();
Error _check_device_capabilities();
Error _add_queue_create_info(LocalVector<VkDeviceQueueCreateInfo> &r_queue_create_info);
Error _initialize_device(const LocalVector<VkDeviceQueueCreateInfo> &p_queue_create_info);
Error _initialize_allocator();
Error _initialize_pipeline_cache();
VkResult _create_render_pass(VkDevice p_device, const VkRenderPassCreateInfo2 *p_create_info, const VkAllocationCallbacks *p_allocator, VkRenderPass *p_render_pass);
bool _release_image_semaphore(CommandQueue *p_command_queue, uint32_t p_semaphore_index, bool p_release_on_swap_chain);
bool _recreate_image_semaphore(CommandQueue *p_command_queue, uint32_t p_semaphore_index, bool p_release_on_swap_chain);
void _set_object_name(VkObjectType p_object_type, uint64_t p_object_handle, String p_object_name);
public:
Error initialize(uint32_t p_device_index, uint32_t p_frame_count) override final;
private:
/****************/
/**** MEMORY ****/
/****************/
@ -154,32 +243,104 @@ public:
VectorView<BufferBarrier> p_buffer_barriers,
VectorView<TextureBarrier> p_texture_barriers) override final;
/*************************/
/**** COMMAND BUFFERS ****/
/*************************/
private:
#ifdef DEBUG_ENABLED
// Vulkan doesn't need to know if the command buffers created in a pool
// will be primary or secondary, but RDD works like that, so we will enforce.
/****************/
/**** FENCES ****/
/****************/
HashSet<CommandPoolID> secondary_cmd_pools;
HashSet<CommandBufferID> secondary_cmd_buffers;
#endif
private:
struct Fence {
VkFence vk_fence = VK_NULL_HANDLE;
CommandQueue *queue_signaled_from = nullptr;
};
public:
virtual FenceID fence_create() override final;
virtual Error fence_wait(FenceID p_fence) override final;
virtual void fence_free(FenceID p_fence) override final;
/********************/
/**** SEMAPHORES ****/
/********************/
virtual SemaphoreID semaphore_create() override final;
virtual void semaphore_free(SemaphoreID p_semaphore) override final;
/******************/
/**** COMMANDS ****/
/******************/
// ----- QUEUE FAMILY -----
virtual CommandQueueFamilyID command_queue_family_get(BitField<CommandQueueFamilyBits> p_cmd_queue_family_bits, RenderingContextDriver::SurfaceID p_surface = 0) override final;
// ----- QUEUE -----
private:
struct CommandQueue {
LocalVector<VkSemaphore> image_semaphores;
LocalVector<SwapChain *> image_semaphores_swap_chains;
LocalVector<uint32_t> pending_semaphores_for_execute;
LocalVector<uint32_t> pending_semaphores_for_fence;
LocalVector<uint32_t> free_image_semaphores;
LocalVector<Pair<Fence *, uint32_t>> image_semaphores_for_fences;
uint32_t queue_family = 0;
uint32_t queue_index = 0;
};
public:
virtual CommandQueueID command_queue_create(CommandQueueFamilyID p_cmd_queue_family, bool p_identify_as_main_queue = false) override final;
virtual Error command_queue_execute(CommandQueueID p_cmd_queue, VectorView<CommandBufferID> p_cmd_buffers, VectorView<SemaphoreID> p_wait_semaphores, VectorView<SemaphoreID> p_signal_semaphores, FenceID p_signal_fence) override final;
virtual Error command_queue_present(CommandQueueID p_cmd_queue, VectorView<SwapChainID> p_swap_chains, VectorView<SemaphoreID> p_wait_semaphores) override final;
virtual void command_queue_free(CommandQueueID p_cmd_queue) override final;
private:
// ----- POOL -----
virtual CommandPoolID command_pool_create(CommandBufferType p_cmd_buffer_type) override final;
struct CommandPool {
VkCommandPool vk_command_pool = VK_NULL_HANDLE;
CommandBufferType buffer_type = COMMAND_BUFFER_TYPE_PRIMARY;
};
public:
virtual CommandPoolID command_pool_create(CommandQueueFamilyID p_cmd_queue_family, CommandBufferType p_cmd_buffer_type) override final;
virtual void command_pool_free(CommandPoolID p_cmd_pool) override final;
// ----- BUFFER -----
virtual CommandBufferID command_buffer_create(CommandBufferType p_cmd_buffer_type, CommandPoolID p_cmd_pool) override final;
virtual CommandBufferID command_buffer_create(CommandPoolID p_cmd_pool) override final;
virtual bool command_buffer_begin(CommandBufferID p_cmd_buffer) override final;
virtual bool command_buffer_begin_secondary(CommandBufferID p_cmd_buffer, RenderPassID p_render_pass, uint32_t p_subpass, FramebufferID p_framebuffer) override final;
virtual void command_buffer_end(CommandBufferID p_cmd_buffer) override final;
virtual void command_buffer_execute_secondary(CommandBufferID p_cmd_buffer, VectorView<CommandBufferID> p_secondary_cmd_buffers) override final;
/********************/
/**** SWAP CHAIN ****/
/********************/
private:
struct SwapChain {
VkSwapchainKHR vk_swapchain = VK_NULL_HANDLE;
RenderingContextDriver::SurfaceID surface = RenderingContextDriver::SurfaceID();
VkFormat format = VK_FORMAT_UNDEFINED;
VkColorSpaceKHR color_space = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
TightLocalVector<VkImage> images;
TightLocalVector<VkImageView> image_views;
TightLocalVector<FramebufferID> framebuffers;
LocalVector<CommandQueue *> command_queues_acquired;
LocalVector<uint32_t> command_queues_acquired_semaphores;
RenderPassID render_pass;
uint32_t image_index = 0;
};
void _swap_chain_release(SwapChain *p_swap_chain);
public:
virtual SwapChainID swap_chain_create(RenderingContextDriver::SurfaceID p_surface) override final;
virtual Error swap_chain_resize(CommandQueueID p_cmd_queue, SwapChainID p_swap_chain, uint32_t p_desired_framebuffer_count) override final;
virtual FramebufferID swap_chain_acquire_framebuffer(CommandQueueID p_cmd_queue, SwapChainID p_swap_chain, bool &r_resize_required) override final;
virtual RenderPassID swap_chain_get_render_pass(SwapChainID p_swap_chain) override final;
virtual DataFormat swap_chain_get_format(SwapChainID p_swap_chain) override final;
virtual void swap_chain_free(SwapChainID p_swap_chain) override final;
/*********************/
/**** FRAMEBUFFER ****/
/*********************/
@ -329,6 +490,7 @@ private:
static int caching_instance_count;
PipelineCache pipelines_cache;
String pipeline_cache_id;
public:
virtual void pipeline_free(PipelineID p_pipeline) override final;
@ -439,25 +601,17 @@ public:
virtual void command_begin_label(CommandBufferID p_cmd_buffer, const char *p_label_name, const Color &p_color) override final;
virtual void command_end_label(CommandBufferID p_cmd_buffer) override final;
/****************/
/**** SCREEN ****/
/****************/
virtual DataFormat screen_get_format() override final;
/********************/
/**** SUBMISSION ****/
/********************/
virtual void begin_segment(CommandBufferID p_cmd_buffer, uint32_t p_frame_index, uint32_t p_frames_drawn) override final;
virtual void begin_segment(uint32_t p_frame_index, uint32_t p_frames_drawn) override final;
virtual void end_segment() override final;
/**************/
/**** MISC ****/
/**************/
VkPhysicalDeviceLimits limits = {};
virtual void set_object_name(ObjectType p_type, ID p_driver_id, const String &p_name) override final;
virtual uint64_t get_resource_native_handle(DriverResource p_type, ID p_driver_id) override final;
virtual uint64_t get_total_memory_used() override final;
@ -465,6 +619,10 @@ public:
virtual uint64_t api_trait_get(ApiTrait p_trait) override final;
virtual bool has_feature(Features p_feature) override final;
virtual const MultiviewCapabilities &get_multiview_capabilities() override final;
virtual String get_api_name() const override final;
virtual String get_api_version() const override final;
virtual String get_pipeline_cache_uuid() const override final;
virtual const Capabilities &get_capabilities() const override final;
private:
/*********************/
@ -482,7 +640,7 @@ private:
/******************/
public:
RenderingDeviceDriverVulkan(VulkanContext *p_context, VkDevice p_vk_device);
RenderingDeviceDriverVulkan(RenderingContextDriverVulkan *p_context_driver);
virtual ~RenderingDeviceDriverVulkan();
};

File diff suppressed because it is too large Load diff

View file

@ -1,348 +0,0 @@
/**************************************************************************/
/* vulkan_context.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef VULKAN_CONTEXT_H
#define VULKAN_CONTEXT_H
#include "core/error/error_list.h"
#include "core/os/mutex.h"
#include "core/string/ustring.h"
#include "core/templates/hash_map.h"
#include "core/templates/rb_map.h"
#include "core/templates/rid_owner.h"
#include "rendering_device_driver_vulkan.h"
#include "servers/display_server.h"
#include "servers/rendering/renderer_rd/api_context_rd.h"
#ifdef USE_VOLK
#include <volk.h>
#else
#include <vulkan/vulkan.h>
#endif
#include "vulkan_hooks.h"
class VulkanContext : public ApiContextRD {
public:
struct SubgroupCapabilities {
uint32_t size;
uint32_t min_size;
uint32_t max_size;
VkShaderStageFlags supportedStages;
VkSubgroupFeatureFlags supportedOperations;
VkBool32 quadOperationsInAllStages;
bool size_control_is_supported;
uint32_t supported_stages_flags_rd() const;
String supported_stages_desc() const;
uint32_t supported_operations_flags_rd() const;
String supported_operations_desc() const;
};
struct VRSCapabilities {
bool pipeline_vrs_supported; // We can specify our fragment rate on a pipeline level.
bool primitive_vrs_supported; // We can specify our fragment rate on each drawcall.
bool attachment_vrs_supported; // We can provide a density map attachment on our framebuffer.
Size2i min_texel_size;
Size2i max_texel_size;
Size2i texel_size; // The texel size we'll use
};
struct ShaderCapabilities {
bool shader_float16_is_supported;
bool shader_int8_is_supported;
};
struct StorageBufferCapabilities {
bool storage_buffer_16_bit_access_is_supported;
bool uniform_and_storage_buffer_16_bit_access_is_supported;
bool storage_push_constant_16_is_supported;
bool storage_input_output_16;
};
private:
enum {
MAX_EXTENSIONS = 128,
MAX_LAYERS = 64,
FRAME_LAG = 2
};
static VulkanHooks *vulkan_hooks;
VkInstance inst = VK_NULL_HANDLE;
VkPhysicalDevice gpu = VK_NULL_HANDLE;
VkPhysicalDeviceProperties gpu_props;
uint32_t queue_family_count = 0;
VkQueueFamilyProperties *queue_props = nullptr;
VkDevice device = VK_NULL_HANDLE;
bool device_initialized = false;
bool inst_initialized = false;
uint32_t instance_api_version = VK_API_VERSION_1_0;
SubgroupCapabilities subgroup_capabilities;
RDD::MultiviewCapabilities multiview_capabilities;
VRSCapabilities vrs_capabilities;
ShaderCapabilities shader_capabilities;
StorageBufferCapabilities storage_buffer_capabilities;
bool pipeline_cache_control_support = false;
String device_vendor;
String device_name;
VkPhysicalDeviceType device_type;
String pipeline_cache_id;
uint32_t device_api_version = 0;
bool buffers_prepared = false;
// Present queue.
bool queues_initialized = false;
uint32_t graphics_queue_family_index = UINT32_MAX;
uint32_t present_queue_family_index = UINT32_MAX;
bool separate_present_queue = false;
VkQueue graphics_queue = VK_NULL_HANDLE;
VkQueue present_queue = VK_NULL_HANDLE;
VkColorSpaceKHR color_space;
VkFormat format;
VkSemaphore draw_complete_semaphores[FRAME_LAG];
VkSemaphore image_ownership_semaphores[FRAME_LAG];
int frame_index = 0;
VkFence fences[FRAME_LAG];
VkPhysicalDeviceMemoryProperties memory_properties;
VkPhysicalDeviceFeatures physical_device_features;
typedef struct {
VkImage image;
VkCommandBuffer graphics_to_present_cmd;
VkImageView view;
VkFramebuffer framebuffer;
} SwapchainImageResources;
struct Window {
VkSurfaceKHR surface = VK_NULL_HANDLE;
VkSwapchainKHR swapchain = VK_NULL_HANDLE;
SwapchainImageResources *swapchain_image_resources = VK_NULL_HANDLE;
VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
VkSemaphore image_acquired_semaphores[FRAME_LAG];
bool semaphore_acquired = false;
uint32_t current_buffer = 0;
int width = 0;
int height = 0;
DisplayServer::VSyncMode vsync_mode = DisplayServer::VSYNC_ENABLED;
VkCommandPool present_cmd_pool = VK_NULL_HANDLE; // For separate present queue.
VkRenderPass render_pass = VK_NULL_HANDLE;
};
struct LocalDevice {
bool waiting = false;
VkDevice device = VK_NULL_HANDLE;
VkQueue queue = VK_NULL_HANDLE;
RenderingDeviceDriverVulkan *driver = nullptr;
};
RID_Owner<LocalDevice, true> local_device_owner;
RenderingDeviceDriverVulkan *driver = nullptr;
HashMap<DisplayServer::WindowID, Window> windows;
uint32_t swapchainImageCount = 0;
// Commands.
bool prepared = false;
LocalVector<VkCommandBuffer> command_buffer_queue;
uint32_t command_buffer_count = 1;
// Extensions.
static bool instance_extensions_initialized;
static HashMap<CharString, bool> requested_instance_extensions;
HashSet<CharString> enabled_instance_extension_names;
static bool device_extensions_initialized;
static HashMap<CharString, bool> requested_device_extensions;
HashSet<CharString> enabled_device_extension_names;
bool VK_KHR_incremental_present_enabled = true;
bool VK_GOOGLE_display_timing_enabled = true;
PFN_vkCreateDebugUtilsMessengerEXT CreateDebugUtilsMessengerEXT = nullptr;
PFN_vkDestroyDebugUtilsMessengerEXT DestroyDebugUtilsMessengerEXT = nullptr;
PFN_vkSubmitDebugUtilsMessageEXT SubmitDebugUtilsMessageEXT = nullptr;
PFN_vkCmdBeginDebugUtilsLabelEXT CmdBeginDebugUtilsLabelEXT = nullptr;
PFN_vkCmdEndDebugUtilsLabelEXT CmdEndDebugUtilsLabelEXT = nullptr;
PFN_vkCmdInsertDebugUtilsLabelEXT CmdInsertDebugUtilsLabelEXT = nullptr;
PFN_vkSetDebugUtilsObjectNameEXT SetDebugUtilsObjectNameEXT = nullptr;
PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT = nullptr;
PFN_vkDebugReportMessageEXT DebugReportMessageEXT = nullptr;
PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT = nullptr;
PFN_vkGetPhysicalDeviceSurfaceSupportKHR fpGetPhysicalDeviceSurfaceSupportKHR = nullptr;
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR fpGetPhysicalDeviceSurfaceCapabilitiesKHR = nullptr;
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR fpGetPhysicalDeviceSurfaceFormatsKHR = nullptr;
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR fpGetPhysicalDeviceSurfacePresentModesKHR = nullptr;
PFN_vkCreateSwapchainKHR fpCreateSwapchainKHR = nullptr;
PFN_vkDestroySwapchainKHR fpDestroySwapchainKHR = nullptr;
PFN_vkGetSwapchainImagesKHR fpGetSwapchainImagesKHR = nullptr;
PFN_vkAcquireNextImageKHR fpAcquireNextImageKHR = nullptr;
PFN_vkQueuePresentKHR fpQueuePresentKHR = nullptr;
PFN_vkGetRefreshCycleDurationGOOGLE fpGetRefreshCycleDurationGOOGLE = nullptr;
PFN_vkGetPastPresentationTimingGOOGLE fpGetPastPresentationTimingGOOGLE = nullptr;
PFN_vkCreateRenderPass2KHR fpCreateRenderPass2KHR = nullptr;
VkDebugUtilsMessengerEXT dbg_messenger = VK_NULL_HANDLE;
VkDebugReportCallbackEXT dbg_debug_report = VK_NULL_HANDLE;
Error _obtain_vulkan_version();
Error _initialize_instance_extensions();
Error _initialize_device_extensions();
Error _check_capabilities();
VkBool32 _check_layers(uint32_t check_count, const char *const *check_names, uint32_t layer_count, VkLayerProperties *layers);
static VKAPI_ATTR VkBool32 VKAPI_CALL _debug_messenger_callback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
void *pUserData);
static VKAPI_ATTR VkBool32 VKAPI_CALL _debug_report_callback(
VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT objectType,
uint64_t object,
size_t location,
int32_t messageCode,
const char *pLayerPrefix,
const char *pMessage,
void *pUserData);
Error _create_instance();
Error _create_physical_device(VkSurfaceKHR p_surface);
Error _initialize_queues(VkSurfaceKHR p_surface);
Error _create_device(VkDevice &r_vk_device);
Error _clean_up_swap_chain(Window *window);
Error _update_swap_chain(Window *window);
Error _create_swap_chain();
Error _create_semaphores();
Vector<VkAttachmentReference> _convert_VkAttachmentReference2(uint32_t p_count, const VkAttachmentReference2 *p_refs);
protected:
virtual const char *_get_platform_surface_extension() const { return nullptr; }
virtual Error _window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, VkSurfaceKHR p_surface, int p_width, int p_height);
virtual bool _use_validation_layers();
Error _get_preferred_validation_layers(uint32_t *count, const char *const **names);
virtual VkExtent2D _compute_swapchain_extent(const VkSurfaceCapabilitiesKHR &p_surf_capabilities, int *p_window_width, int *p_window_height) const;
public:
// Extension calls.
bool supports_renderpass2() const { return is_device_extension_enabled(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME); }
VkResult vkCreateRenderPass2KHR(VkDevice p_device, const VkRenderPassCreateInfo2 *p_create_info, const VkAllocationCallbacks *p_allocator, VkRenderPass *p_render_pass);
virtual const char *get_api_name() const override final { return "Vulkan"; };
virtual RenderingDevice::Capabilities get_device_capabilities() const override final;
const SubgroupCapabilities &get_subgroup_capabilities() const { return subgroup_capabilities; };
virtual const RDD::MultiviewCapabilities &get_multiview_capabilities() const override final { return multiview_capabilities; };
const VRSCapabilities &get_vrs_capabilities() const { return vrs_capabilities; };
const ShaderCapabilities &get_shader_capabilities() const { return shader_capabilities; };
const StorageBufferCapabilities &get_storage_buffer_capabilities() const { return storage_buffer_capabilities; };
const VkPhysicalDeviceFeatures &get_physical_device_features() const { return physical_device_features; };
bool get_pipeline_cache_control_support() const { return pipeline_cache_control_support; };
VkDevice get_device();
VkPhysicalDevice get_physical_device();
VkInstance get_instance() { return inst; }
virtual int get_swapchain_image_count() const override final;
VkQueue get_graphics_queue() const;
uint32_t get_graphics_queue_family_index() const;
static void set_vulkan_hooks(VulkanHooks *p_vulkan_hooks) { vulkan_hooks = p_vulkan_hooks; };
static void register_requested_instance_extension(const CharString &extension_name, bool p_required);
bool is_instance_extension_enabled(const CharString &extension_name) const {
return enabled_instance_extension_names.has(extension_name);
}
static void register_requested_device_extension(const CharString &extension_name, bool p_required);
bool is_device_extension_enabled(const CharString &extension_name) const {
return enabled_device_extension_names.has(extension_name);
}
virtual void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height) override final;
virtual int window_get_width(DisplayServer::WindowID p_window = 0) override final;
virtual int window_get_height(DisplayServer::WindowID p_window = 0) override final;
virtual bool window_is_valid_swapchain(DisplayServer::WindowID p_window = 0) override final;
virtual void window_destroy(DisplayServer::WindowID p_window_id) override final;
virtual RDD::RenderPassID window_get_render_pass(DisplayServer::WindowID p_window = 0) override final;
virtual RDD::FramebufferID window_get_framebuffer(DisplayServer::WindowID p_window = 0) override final;
virtual RID local_device_create() override final;
virtual void local_device_push_command_buffers(RID p_local_device, const RDD::CommandBufferID *p_buffers, int p_count) override final;
virtual void local_device_sync(RID p_local_device) override final;
virtual void local_device_free(RID p_local_device) override final;
VkFormat get_screen_format() const;
const VkPhysicalDeviceLimits &get_device_limits() const;
virtual void set_setup_buffer(RDD::CommandBufferID p_command_buffer) override final;
virtual void append_command_buffer(RDD::CommandBufferID p_command_buffer) override final;
void resize_notify();
virtual void flush(bool p_flush_setup = false, bool p_flush_pending = false, bool p_sync = true) override final;
virtual Error prepare_buffers(RDD::CommandBufferID p_command_buffer) override final;
virtual void postpare_buffers(RDD::CommandBufferID p_command_buffer) override final;
virtual Error swap_buffers() override final;
virtual Error initialize() override final;
void set_object_name(VkObjectType p_object_type, uint64_t p_object_handle, String p_object_name);
virtual String get_device_vendor_name() const override final;
virtual String get_device_name() const override final;
virtual RDD::DeviceType get_device_type() const override final;
virtual String get_device_api_version() const override final;
virtual String get_device_pipeline_cache_uuid() const override final;
virtual void set_vsync_mode(DisplayServer::WindowID p_window, DisplayServer::VSyncMode p_mode) override final;
virtual DisplayServer::VSyncMode get_vsync_mode(DisplayServer::WindowID p_window = 0) const override final;
virtual RenderingDeviceDriver *get_driver(RID p_local_device = RID()) override final;
virtual bool is_debug_utils_enabled() const override final;
VulkanContext();
virtual ~VulkanContext();
};
#endif // VULKAN_CONTEXT_H

View file

@ -1,5 +1,5 @@
/**************************************************************************/
/* api_context_rd.cpp */
/* vulkan_hooks.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -28,6 +28,18 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "api_context_rd.h"
#include "vulkan_hooks.h"
ApiContextRD::~ApiContextRD() {}
VulkanHooks *VulkanHooks::singleton = nullptr;
VulkanHooks::VulkanHooks() {
if (singleton == nullptr) {
singleton = this;
}
}
VulkanHooks::~VulkanHooks() {
if (singleton == this) {
singleton = nullptr;
}
}

View file

@ -38,11 +38,17 @@
#endif
class VulkanHooks {
private:
static VulkanHooks *singleton;
public:
virtual bool create_vulkan_instance(const VkInstanceCreateInfo *p_vulkan_create_info, VkInstance *r_instance) { return false; };
virtual bool get_physical_device(VkPhysicalDevice *r_device) { return false; };
virtual bool create_vulkan_device(const VkDeviceCreateInfo *p_device_create_info, VkDevice *r_device) { return false; };
virtual ~VulkanHooks(){};
VulkanHooks();
virtual ~VulkanHooks();
virtual bool create_vulkan_instance(const VkInstanceCreateInfo *p_vulkan_create_info, VkInstance *r_instance) = 0;
virtual bool get_physical_device(VkPhysicalDevice *r_device) = 0;
virtual bool create_vulkan_device(const VkDeviceCreateInfo *p_device_create_info, VkDevice *r_device) = 0;
virtual void set_direct_queue_family_and_index(uint32_t p_queue_family_index, uint32_t p_queue_index) = 0;
static VulkanHooks *get_singleton() { return singleton; }
};
#endif // VULKAN_HOOKS_H

View file

@ -113,3 +113,10 @@ Validate extension JSON: API was removed: classes/TileMap/methods/set_tileset
Validate extension JSON: API was removed: classes/TileMap/properties/tile_set
Moved to the parent TileMapLayerGroup class. No change should be necessary.
GH-87340
--------
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/RenderingDevice/methods/screen_get_framebuffer_format': arguments
screen_get_framebuffer_format can now specify the screen it should get the format from. The argument defaults to the main window to emulate the behavior of the old function.

View file

@ -39,7 +39,7 @@
#include <glslang/SPIRV/GlslangToSpv.h>
static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage, const String &p_source_code, RenderingDevice::ShaderLanguage p_language, String *r_error, const RenderingDevice *p_render_device) {
const RD::Capabilities *capabilities = p_render_device->get_device_capabilities();
const RDD::Capabilities &capabilities = p_render_device->get_device_capabilities();
Vector<uint8_t> ret;
ERR_FAIL_COND_V(p_language == RenderingDevice::SHADER_LANGUAGE_HLSL, ret);
@ -57,17 +57,17 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage
glslang::EShTargetClientVersion ClientVersion = glslang::EShTargetVulkan_1_2;
glslang::EShTargetLanguageVersion TargetVersion = glslang::EShTargetSpv_1_5;
if (capabilities->device_family == RenderingDevice::DeviceFamily::DEVICE_VULKAN) {
if (capabilities->version_major == 1 && capabilities->version_minor == 0) {
if (capabilities.device_family == RDD::DEVICE_VULKAN) {
if (capabilities.version_major == 1 && capabilities.version_minor == 0) {
ClientVersion = glslang::EShTargetVulkan_1_0;
TargetVersion = glslang::EShTargetSpv_1_0;
} else if (capabilities->version_major == 1 && capabilities->version_minor == 1) {
} else if (capabilities.version_major == 1 && capabilities.version_minor == 1) {
ClientVersion = glslang::EShTargetVulkan_1_1;
TargetVersion = glslang::EShTargetSpv_1_3;
} else {
// use defaults
}
} else if (capabilities->device_family == RenderingDevice::DeviceFamily::DEVICE_DIRECTX) {
} else if (capabilities.device_family == RDD::DEVICE_DIRECTX) {
// NIR-DXIL is Vulkan 1.1-conformant.
ClientVersion = glslang::EShTargetVulkan_1_1;
// The SPIR-V part of Mesa supports 1.6, but:
@ -186,9 +186,9 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage
}
static String _get_cache_key_function_glsl(const RenderingDevice *p_render_device) {
const RD::Capabilities *capabilities = p_render_device->get_device_capabilities();
const RenderingDeviceDriver::Capabilities &capabilities = p_render_device->get_device_capabilities();
String version;
version = "SpirVGen=" + itos(glslang::GetSpirvGeneratorVersion()) + ", major=" + itos(capabilities->version_major) + ", minor=" + itos(capabilities->version_minor) + " , subgroup_size=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_SIZE)) + " , subgroup_ops=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_OPERATIONS)) + " , subgroup_in_shaders=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_IN_SHADERS)) + " , debug=" + itos(Engine::get_singleton()->is_generate_spirv_debug_info_enabled());
version = "SpirVGen=" + itos(glslang::GetSpirvGeneratorVersion()) + ", major=" + itos(capabilities.version_major) + ", minor=" + itos(capabilities.version_minor) + " , subgroup_size=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_SIZE)) + " , subgroup_ops=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_OPERATIONS)) + " , subgroup_in_shaders=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_IN_SHADERS)) + " , debug=" + itos(Engine::get_singleton()->is_generate_spirv_debug_info_enabled());
return version;
}

View file

@ -41,6 +41,10 @@
#include "editor/editor_settings.h"
#include "servers/rendering/rendering_device_binds.h"
#if defined(VULKAN_ENABLED)
#include "drivers/vulkan/rendering_context_driver_vulkan.h"
#endif
//uncomment this if you want to see textures from all the process saved
//#define DEBUG_TEXTURES
@ -1017,7 +1021,35 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
}
#endif
RenderingDevice *rd = RenderingDevice::get_singleton()->create_local_device();
// Attempt to create a local device by requesting it from rendering server first.
// If that fails because the current renderer is not implemented on top of RD, we fall back to creating
// a local rendering device manually depending on the current platform.
Error err;
RenderingContextDriver *rcd = nullptr;
RenderingDevice *rd = RenderingServer::get_singleton()->create_local_rendering_device();
if (rd == nullptr) {
#if defined(RD_ENABLED)
#if defined(VULKAN_ENABLED)
rcd = memnew(RenderingContextDriverVulkan);
rd = memnew(RenderingDevice);
#endif
#endif
if (rcd != nullptr && rd != nullptr) {
err = rcd->initialize();
if (err == OK) {
err = rd->initialize(rcd);
}
if (err != OK) {
memdelete(rd);
memdelete(rcd);
rd = nullptr;
rcd = nullptr;
}
}
}
ERR_FAIL_NULL_V(rd, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES);
RID albedo_array_tex;
RID emission_array_tex;
@ -1187,7 +1219,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
//shaders
Ref<RDShaderFile> raster_shader;
raster_shader.instantiate();
Error err = raster_shader->parse_versions_from_text(lm_raster_shader_glsl);
err = raster_shader->parse_versions_from_text(lm_raster_shader_glsl);
if (err != OK) {
raster_shader->print_errors("raster_shader");
@ -1195,6 +1227,10 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
FREE_BUFFERS
memdelete(rd);
if (rcd != nullptr) {
memdelete(rcd);
}
}
ERR_FAIL_COND_V(err != OK, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES);
@ -1367,6 +1403,11 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
FREE_BUFFERS
FREE_RASTER_RESOURCES
memdelete(rd);
if (rcd != nullptr) {
memdelete(rcd);
}
compute_shader->print_errors("compute_shader");
}
ERR_FAIL_COND_V(err != OK, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES);
@ -1789,6 +1830,11 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
FREE_RASTER_RESOURCES
FREE_COMPUTE_RESOURCES
memdelete(rd);
if (rcd != nullptr) {
memdelete(rcd);
}
blendseams_shader->print_errors("blendseams_shader");
}
ERR_FAIL_COND_V(err != OK, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES);
@ -1964,6 +2010,10 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
memdelete(rd);
if (rcd != nullptr) {
memdelete(rcd);
}
return BAKE_OK;
}

View file

@ -38,14 +38,6 @@
#include "servers/rendering/rendering_server_globals.h"
#include "servers/rendering_server.h"
OpenXRVulkanExtension::OpenXRVulkanExtension() {
VulkanContext::set_vulkan_hooks(this);
}
OpenXRVulkanExtension::~OpenXRVulkanExtension() {
VulkanContext::set_vulkan_hooks(nullptr);
}
HashMap<String, bool *> OpenXRVulkanExtension::get_requested_extensions() {
HashMap<String, bool *> request_extensions;
@ -178,10 +170,6 @@ bool OpenXRVulkanExtension::get_physical_device(VkPhysicalDevice *r_device) {
bool OpenXRVulkanExtension::create_vulkan_device(const VkDeviceCreateInfo *p_device_create_info, VkDevice *r_device) {
ERR_FAIL_NULL_V(OpenXRAPI::get_singleton(), false);
// the first entry in our queue list should be the one we need to remember...
vulkan_queue_family_index = p_device_create_info->pQueueCreateInfos[0].queueFamilyIndex;
vulkan_queue_index = 0; // ??
XrVulkanDeviceCreateInfoKHR create_info = {
XR_TYPE_VULKAN_DEVICE_CREATE_INFO_KHR, // type
nullptr, // next
@ -209,9 +197,17 @@ bool OpenXRVulkanExtension::create_vulkan_device(const VkDeviceCreateInfo *p_dev
return true;
}
void OpenXRVulkanExtension::set_direct_queue_family_and_index(uint32_t p_queue_family_index, uint32_t p_queue_index) {
vulkan_queue_family_index = p_queue_family_index;
vulkan_queue_index = p_queue_index;
}
XrGraphicsBindingVulkanKHR OpenXRVulkanExtension::graphics_binding_vulkan;
void *OpenXRVulkanExtension::set_session_create_and_get_next_pointer(void *p_next_pointer) {
DEV_ASSERT(vulkan_queue_family_index < UINT32_MAX && "Direct queue family index was not specified yet.");
DEV_ASSERT(vulkan_queue_index < UINT32_MAX && "Direct queue index was not specified yet.");
graphics_binding_vulkan.type = XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR;
graphics_binding_vulkan.next = p_next_pointer;
graphics_binding_vulkan.instance = vulkan_instance;

View file

@ -36,23 +36,25 @@
#include "../openxr_extension_wrapper.h"
#include "core/templates/vector.h"
#include "drivers/vulkan/vulkan_hooks.h"
// Always include this as late as possible.
#include "../../openxr_platform_inc.h"
class OpenXRVulkanExtension : public OpenXRGraphicsExtensionWrapper, VulkanHooks {
public:
OpenXRVulkanExtension();
virtual ~OpenXRVulkanExtension() override;
OpenXRVulkanExtension() = default;
virtual ~OpenXRVulkanExtension() override = default;
virtual HashMap<String, bool *> get_requested_extensions() override;
virtual void on_instance_created(const XrInstance p_instance) override;
virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) override;
virtual bool create_vulkan_instance(const VkInstanceCreateInfo *p_vulkan_create_info, VkInstance *r_instance) override;
virtual bool get_physical_device(VkPhysicalDevice *r_device) override;
virtual bool create_vulkan_device(const VkDeviceCreateInfo *p_device_create_info, VkDevice *r_device) override;
virtual bool create_vulkan_instance(const VkInstanceCreateInfo *p_vulkan_create_info, VkInstance *r_instance) override final;
virtual bool get_physical_device(VkPhysicalDevice *r_device) override final;
virtual bool create_vulkan_device(const VkDeviceCreateInfo *p_device_create_info, VkDevice *r_device) override final;
virtual void set_direct_queue_family_and_index(uint32_t p_queue_family_index, uint32_t p_queue_index) override final;
virtual void get_usable_swapchain_formats(Vector<int64_t> &p_usable_swap_chains) override;
virtual void get_usable_depth_formats(Vector<int64_t> &p_usable_swap_chains) override;
@ -76,8 +78,8 @@ private:
VkInstance vulkan_instance = nullptr;
VkPhysicalDevice vulkan_physical_device = nullptr;
VkDevice vulkan_device = nullptr;
uint32_t vulkan_queue_family_index = 0;
uint32_t vulkan_queue_index = 0;
uint32_t vulkan_queue_family_index = UINT32_MAX;
uint32_t vulkan_queue_index = UINT32_MAX;
EXT_PROTO_XRRESULT_FUNC3(xrGetVulkanGraphicsRequirements2KHR, (XrInstance), p_instance, (XrSystemId), p_system_id, (XrGraphicsRequirementsVulkanKHR *), p_graphics_requirements)
EXT_PROTO_XRRESULT_FUNC4(xrCreateVulkanInstanceKHR, (XrInstance), p_instance, (const XrVulkanInstanceCreateInfoKHR *), p_create_info, (VkInstance *), r_vulkan_instance, (VkResult *), r_vulkan_result)

View file

@ -36,7 +36,7 @@
#ifdef VULKAN_ENABLED
#define XR_USE_GRAPHICS_API_VULKAN
#include "drivers/vulkan/vulkan_context.h"
#include "drivers/vulkan/rendering_context_driver_vulkan.h"
#endif // VULKAN_ENABLED
#if defined(GLES3_ENABLED) && !defined(MACOS_ENABLED)

View file

@ -23,7 +23,7 @@ android_files = [
"android_keys_utils.cpp",
"display_server_android.cpp",
"plugin/godot_plugin_jni.cpp",
"vulkan_context_android.cpp",
"rendering_context_driver_vulkan_android.cpp",
]
env_android = env.Clone()

View file

@ -42,7 +42,7 @@
#include "servers/rendering/rendering_device.h"
#if defined(VULKAN_ENABLED)
#include "vulkan_context_android.h"
#include "rendering_context_driver_vulkan_android.h"
#endif
#endif
@ -518,15 +518,17 @@ void DisplayServerAndroid::register_android_driver() {
void DisplayServerAndroid::reset_window() {
#if defined(RD_ENABLED)
if (context_rd) {
VSyncMode last_vsync_mode = context_rd->get_vsync_mode(MAIN_WINDOW_ID);
context_rd->window_destroy(MAIN_WINDOW_ID);
if (rendering_context) {
if (rendering_device) {
rendering_device->screen_free(MAIN_WINDOW_ID);
}
Size2i display_size = OS_Android::get_singleton()->get_display_size();
VSyncMode last_vsync_mode = rendering_context->window_get_vsync_mode(MAIN_WINDOW_ID);
rendering_context->window_destroy(MAIN_WINDOW_ID);
union {
#ifdef VULKAN_ENABLED
VulkanContextAndroid::WindowPlatformData vulkan;
RenderingContextDriverVulkanAndroid::WindowPlatformData vulkan;
#endif
} wpd;
#ifdef VULKAN_ENABLED
@ -537,12 +539,20 @@ void DisplayServerAndroid::reset_window() {
}
#endif
if (context_rd->window_create(MAIN_WINDOW_ID, last_vsync_mode, display_size.width, display_size.height, &wpd) != OK) {
ERR_PRINT(vformat("Failed to reset %s window.", context_rd->get_api_name()));
memdelete(context_rd);
context_rd = nullptr;
if (rendering_context->window_create(MAIN_WINDOW_ID, &wpd) != OK) {
ERR_PRINT(vformat("Failed to reset %s window.", rendering_driver));
memdelete(rendering_context);
rendering_context = nullptr;
return;
}
Size2i display_size = OS_Android::get_singleton()->get_display_size();
rendering_context->window_set_size(MAIN_WINDOW_ID, display_size.width, display_size.height);
rendering_context->window_set_vsync_mode(MAIN_WINDOW_ID, last_vsync_mode);
if (rendering_device) {
rendering_device->screen_create(MAIN_WINDOW_ID);
}
}
#endif
}
@ -565,28 +575,26 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis
#endif
#if defined(RD_ENABLED)
context_rd = nullptr;
rendering_context = nullptr;
rendering_device = nullptr;
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
context_rd = memnew(VulkanContextAndroid);
rendering_context = memnew(RenderingContextDriverVulkanAndroid);
}
#endif
if (context_rd) {
if (context_rd->initialize() != OK) {
ERR_PRINT(vformat("Failed to initialize %s context", context_rd->get_api_name()));
memdelete(context_rd);
context_rd = nullptr;
if (rendering_context) {
if (rendering_context->initialize() != OK) {
ERR_PRINT(vformat("Failed to initialize %s context", rendering_driver));
memdelete(rendering_context);
rendering_context = nullptr;
return;
}
Size2i display_size = OS_Android::get_singleton()->get_display_size();
union {
#ifdef VULKAN_ENABLED
VulkanContextAndroid::WindowPlatformData vulkan;
RenderingContextDriverVulkanAndroid::WindowPlatformData vulkan;
#endif
} wpd;
#ifdef VULKAN_ENABLED
@ -597,15 +605,20 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis
}
#endif
if (context_rd->window_create(MAIN_WINDOW_ID, p_vsync_mode, display_size.width, display_size.height, &wpd) != OK) {
ERR_PRINT(vformat("Failed to create %s window.", context_rd->get_api_name()));
memdelete(context_rd);
context_rd = nullptr;
if (rendering_context->window_create(MAIN_WINDOW_ID, &wpd) != OK) {
ERR_PRINT(vformat("Failed to create %s window.", rendering_driver));
memdelete(rendering_context);
rendering_context = nullptr;
return;
}
Size2i display_size = OS_Android::get_singleton()->get_display_size();
rendering_context->window_set_size(MAIN_WINDOW_ID, display_size.width, display_size.height);
rendering_context->window_set_vsync_mode(MAIN_WINDOW_ID, p_vsync_mode);
rendering_device = memnew(RenderingDevice);
rendering_device->initialize(context_rd);
rendering_device->initialize(rendering_context, MAIN_WINDOW_ID);
rendering_device->screen_create(MAIN_WINDOW_ID);
RendererCompositorRD::make_current();
}
@ -620,11 +633,10 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis
DisplayServerAndroid::~DisplayServerAndroid() {
#if defined(RD_ENABLED)
if (rendering_device) {
rendering_device->finalize();
memdelete(rendering_device);
}
if (context_rd) {
memdelete(context_rd);
if (rendering_context) {
memdelete(rendering_context);
}
#endif
}
@ -716,16 +728,16 @@ void DisplayServerAndroid::cursor_set_custom_image(const Ref<Resource> &p_cursor
void DisplayServerAndroid::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
#if defined(RD_ENABLED)
if (context_rd) {
context_rd->set_vsync_mode(p_window, p_vsync_mode);
if (rendering_context) {
rendering_context->window_set_vsync_mode(p_window, p_vsync_mode);
}
#endif
}
DisplayServer::VSyncMode DisplayServerAndroid::window_get_vsync_mode(WindowID p_window) const {
#if defined(RD_ENABLED)
if (context_rd) {
return context_rd->get_vsync_mode(p_window);
if (rendering_context) {
return rendering_context->window_get_vsync_mode(p_window);
}
#endif
return DisplayServer::VSYNC_ENABLED;

View file

@ -34,7 +34,7 @@
#include "servers/display_server.h"
#if defined(RD_ENABLED)
class ApiContextRD;
class RenderingContextDriver;
class RenderingDevice;
#endif
@ -73,7 +73,7 @@ class DisplayServerAndroid : public DisplayServer {
CursorShape cursor_shape = CursorShape::CURSOR_ARROW;
#if defined(RD_ENABLED)
ApiContextRD *context_rd = nullptr;
RenderingContextDriver *rendering_context = nullptr;
RenderingDevice *rendering_device = nullptr;
#endif

View file

@ -1,5 +1,5 @@
/**************************************************************************/
/* vulkan_context_android.cpp */
/* rendering_context_driver_vulkan_android.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "vulkan_context_android.h"
#include "rendering_context_driver_vulkan_android.h"
#ifdef VULKAN_ENABLED
@ -38,32 +38,32 @@
#include <vulkan/vulkan.h>
#endif
const char *VulkanContextAndroid::_get_platform_surface_extension() const {
const char *RenderingContextDriverVulkanAndroid::_get_platform_surface_extension() const {
return VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
}
Error VulkanContextAndroid::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) {
const WindowPlatformData *wpd = (const WindowPlatformData *)p_platform_data;
RenderingContextDriver::SurfaceID RenderingContextDriverVulkanAndroid::surface_create(const void *p_platform_data) {
const WindowPlatformData *wpd = (const WindowPlatformData *)(p_platform_data);
VkAndroidSurfaceCreateInfoKHR createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
createInfo.window = wpd->window;
VkAndroidSurfaceCreateInfoKHR create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
create_info.window = wpd->window;
VkSurfaceKHR surface = VK_NULL_HANDLE;
VkResult err = vkCreateAndroidSurfaceKHR(get_instance(), &createInfo, nullptr, &surface);
if (err != VK_SUCCESS) {
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "vkCreateAndroidSurfaceKHR failed with error " + itos(err));
}
VkSurfaceKHR vk_surface = VK_NULL_HANDLE;
VkResult err = vkCreateAndroidSurfaceKHR(instance_get(), &create_info, nullptr, &vk_surface);
ERR_FAIL_COND_V(err != VK_SUCCESS, SurfaceID());
return _window_create(DisplayServer::MAIN_WINDOW_ID, p_vsync_mode, surface, p_width, p_height);
Surface *surface = memnew(Surface);
surface->vk_surface = vk_surface;
return SurfaceID(surface);
}
bool VulkanContextAndroid::_use_validation_layers() {
uint32_t count = 0;
_get_preferred_validation_layers(&count, nullptr);
bool RenderingContextDriverVulkanAndroid::_use_validation_layers() const {
TightLocalVector<const char *> layer_names;
Error err = _find_validation_layers(layer_names);
// On Android, we use validation layers automatically if they were explicitly linked with the app.
return count > 0;
return (err == OK) && !layer_names.is_empty();
}
#endif // VULKAN_ENABLED

View file

@ -1,5 +1,5 @@
/**************************************************************************/
/* vulkan_context_android.h */
/* rendering_context_driver_vulkan_android.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -28,31 +28,32 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef VULKAN_CONTEXT_ANDROID_H
#define VULKAN_CONTEXT_ANDROID_H
#ifndef RENDERING_CONTEXT_DRIVER_VULKAN_ANDROID_H
#define RENDERING_CONTEXT_DRIVER_VULKAN_ANDROID_H
#ifdef VULKAN_ENABLED
#include "drivers/vulkan/vulkan_context.h"
#include "drivers/vulkan/rendering_context_driver_vulkan.h"
struct ANativeWindow;
class VulkanContextAndroid : public VulkanContext {
class RenderingContextDriverVulkanAndroid : public RenderingContextDriverVulkan {
private:
virtual const char *_get_platform_surface_extension() const override final;
protected:
SurfaceID surface_create(const void *p_platform_data) override final;
bool _use_validation_layers() const override final;
public:
struct WindowPlatformData {
ANativeWindow *window;
};
virtual Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) override final;
VulkanContextAndroid() = default;
~VulkanContextAndroid() override = default;
protected:
bool _use_validation_layers() override;
RenderingContextDriverVulkanAndroid() = default;
~RenderingContextDriverVulkanAndroid() override = default;
};
#endif // VULKAN_ENABLED
#endif // VULKAN_CONTEXT_ANDROID_H
#endif // RENDERING_CONTEXT_DRIVER_VULKAN_ANDROID_H

View file

@ -9,7 +9,7 @@ ios_lib = [
"app_delegate.mm",
"view_controller.mm",
"ios.mm",
"vulkan_context_ios.mm",
"rendering_context_driver_vulkan_ios.mm",
"display_server_ios.mm",
"joypad_ios.mm",
"godot_view.mm",

View file

@ -39,7 +39,7 @@
#include "servers/rendering/rendering_device.h"
#if defined(VULKAN_ENABLED)
#import "vulkan_context_ios.h"
#import "rendering_context_driver_vulkan_ios.h"
#ifdef USE_VOLK
#include <volk.h>
@ -62,7 +62,7 @@ class DisplayServerIOS : public DisplayServer {
_THREAD_SAFE_CLASS_
#if defined(RD_ENABLED)
ApiContextRD *context_rd = nullptr;
RenderingContextDriver *rendering_context = nullptr;
RenderingDevice *rendering_device = nullptr;
#endif

View file

@ -63,14 +63,14 @@ DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode
}
#if defined(RD_ENABLED)
context_rd = nullptr;
rendering_context = nullptr;
rendering_device = nullptr;
CALayer *layer = nullptr;
union {
#ifdef VULKAN_ENABLED
VulkanContextIOS::WindowPlatformData vulkan;
RenderingContextDriverVulkanIOS::WindowPlatformData vulkan;
#endif
} wpd;
@ -81,29 +81,33 @@ DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode
ERR_FAIL_MSG("Failed to create iOS Vulkan rendering layer.");
}
wpd.vulkan.layer_ptr = &layer;
context_rd = memnew(VulkanContextIOS);
rendering_context = memnew(RenderingContextDriverVulkanIOS);
}
#endif
if (context_rd) {
if (context_rd->initialize() != OK) {
ERR_PRINT(vformat("Failed to initialize %s context", context_rd->get_api_name()));
memdelete(context_rd);
context_rd = nullptr;
if (rendering_context) {
if (rendering_context->initialize() != OK) {
ERR_PRINT(vformat("Failed to initialize %s context", rendering_driver));
memdelete(rendering_context);
rendering_context = nullptr;
return;
}
Size2i size = Size2i(layer.bounds.size.width, layer.bounds.size.height) * screen_get_max_scale();
if (context_rd->window_create(MAIN_WINDOW_ID, p_vsync_mode, size.width, size.height, &wpd) != OK) {
ERR_PRINT(vformat("Failed to create %s window.", context_rd->get_api_name()));
memdelete(context_rd);
context_rd = nullptr;
if (rendering_context->window_create(MAIN_WINDOW_ID, &wpd) != OK) {
ERR_PRINT(vformat("Failed to create %s window.", rendering_driver));
memdelete(rendering_context);
rendering_context = nullptr;
r_error = ERR_UNAVAILABLE;
return;
}
Size2i size = Size2i(layer.bounds.size.width, layer.bounds.size.height) * screen_get_max_scale();
rendering_context->window_set_size(MAIN_WINDOW_ID, size.width, size.height);
rendering_context->window_set_vsync_mode(MAIN_WINDOW_ID, p_vsync_mode);
rendering_device = memnew(RenderingDevice);
rendering_device->initialize(context_rd);
rendering_device->initialize(rendering_context, MAIN_WINDOW_ID);
rendering_device->screen_create(MAIN_WINDOW_ID);
RendererCompositorRD::make_current();
}
@ -132,15 +136,15 @@ DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode
DisplayServerIOS::~DisplayServerIOS() {
#if defined(RD_ENABLED)
if (rendering_device) {
rendering_device->finalize();
rendering_device->screen_free(MAIN_WINDOW_ID);
memdelete(rendering_device);
rendering_device = nullptr;
}
if (context_rd) {
context_rd->window_destroy(MAIN_WINDOW_ID);
memdelete(context_rd);
context_rd = nullptr;
if (rendering_context) {
rendering_context->window_destroy(MAIN_WINDOW_ID);
memdelete(rendering_context);
rendering_context = nullptr;
}
#endif
}
@ -714,8 +718,8 @@ void DisplayServerIOS::resize_window(CGSize viewSize) {
Size2i size = Size2i(viewSize.width, viewSize.height) * screen_get_max_scale();
#if defined(RD_ENABLED)
if (context_rd) {
context_rd->window_resize(MAIN_WINDOW_ID, size.x, size.y);
if (rendering_context) {
rendering_context->window_set_size(MAIN_WINDOW_ID, size.x, size.y);
}
#endif
@ -726,8 +730,8 @@ void DisplayServerIOS::resize_window(CGSize viewSize) {
void DisplayServerIOS::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
_THREAD_SAFE_METHOD_
#if defined(RD_ENABLED)
if (context_rd) {
context_rd->set_vsync_mode(p_window, p_vsync_mode);
if (rendering_context) {
rendering_context->window_set_vsync_mode(p_window, p_vsync_mode);
}
#endif
}
@ -735,8 +739,8 @@ void DisplayServerIOS::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mo
DisplayServer::VSyncMode DisplayServerIOS::window_get_vsync_mode(WindowID p_window) const {
_THREAD_SAFE_METHOD_
#if defined(RD_ENABLED)
if (context_rd) {
return context_rd->get_vsync_mode(p_window);
if (rendering_context) {
return rendering_context->window_get_vsync_mode(p_window);
}
#endif
return DisplayServer::VSYNC_ENABLED;

View file

@ -45,7 +45,7 @@
#include "servers/rendering/rendering_device.h"
#if defined(VULKAN_ENABLED)
#import "vulkan_context_ios.h"
#import "rendering_context_driver_vulkan_ios.h"
#endif
#endif

View file

@ -1,5 +1,5 @@
/**************************************************************************/
/* vulkan_context_ios.h */
/* rendering_context_driver_vulkan_ios.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -28,28 +28,31 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef VULKAN_CONTEXT_IOS_H
#define VULKAN_CONTEXT_IOS_H
#ifndef RENDERING_CONTEXT_DRIVER_VULKAN_IOS_H
#define RENDERING_CONTEXT_DRIVER_VULKAN_IOS_H
#ifdef VULKAN_ENABLED
#include "drivers/vulkan/vulkan_context.h"
#include "drivers/vulkan/rendering_context_driver_vulkan.h"
#import <UIKit/UIKit.h>
class VulkanContextIOS : public VulkanContext {
class RenderingContextDriverVulkanIOS : public RenderingContextDriverVulkan {
private:
virtual const char *_get_platform_surface_extension() const override final;
protected:
SurfaceID surface_create(const void *p_platform_data) override final;
public:
struct WindowPlatformData {
CALayer *const *layer_ptr;
};
virtual Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) override final;
VulkanContextIOS();
~VulkanContextIOS();
RenderingContextDriverVulkanIOS();
~RenderingContextDriverVulkanIOS();
};
#endif // VULKAN_ENABLED
#endif // VULKAN_CONTEXT_IOS_H
#endif // RENDERING_CONTEXT_DRIVER_VULKAN_IOS_H

View file

@ -1,5 +1,5 @@
/**************************************************************************/
/* vulkan_context_ios.mm */
/* rendering_context_driver_vulkan_ios.mm */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#import "vulkan_context_ios.h"
#import "rendering_context_driver_vulkan_ios.h"
#ifdef VULKAN_ENABLED
@ -38,26 +38,32 @@
#include <vulkan/vulkan.h>
#endif
const char *VulkanContextIOS::_get_platform_surface_extension() const {
const char *RenderingContextDriverVulkanIOS::_get_platform_surface_extension() const {
return VK_MVK_IOS_SURFACE_EXTENSION_NAME;
}
Error VulkanContextIOS::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) {
const WindowPlatformData *wpd = (const WindowPlatformData *)p_platform_data;
RenderingContextDriver::SurfaceID RenderingContextDriverVulkanIOS::surface_create(const void *p_platform_data) {
const WindowPlatformData *wpd = (const WindowPlatformData *)(p_platform_data);
VkIOSSurfaceCreateInfoMVK createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK;
createInfo.pView = (__bridge const void *)(*wpd->layer_ptr);
VkIOSSurfaceCreateInfoMVK create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK;
create_info.pView = (__bridge const void *)(*wpd->layer_ptr);
VkSurfaceKHR surface = VK_NULL_HANDLE;
VkResult err = vkCreateIOSSurfaceMVK(get_instance(), &createInfo, nullptr, &surface);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
VkSurfaceKHR vk_surface = VK_NULL_HANDLE;
VkResult err = vkCreateIOSSurfaceMVK(instance_get(), &create_info, nullptr, &vk_surface);
ERR_FAIL_COND_V(err != VK_SUCCESS, SurfaceID());
return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
Surface *surface = memnew(Surface);
surface->vk_surface = vk_surface;
return SurfaceID(surface);
}
VulkanContextIOS::VulkanContextIOS() {}
RenderingContextDriverVulkanIOS::RenderingContextDriverVulkanIOS() {
// Does nothing.
}
VulkanContextIOS::~VulkanContextIOS() {}
RenderingContextDriverVulkanIOS::~RenderingContextDriverVulkanIOS() {
// Does nothing.
}
#endif // VULKAN_ENABLED

View file

@ -195,7 +195,7 @@ if env["use_sowrap"]:
if env["vulkan"]:
source_files.append("vulkan_context_wayland.cpp")
source_files.append("rendering_context_driver_vulkan_wayland.cpp")
if env["opengl3"]:
source_files.append("egl_manager_wayland.cpp")

View file

@ -100,8 +100,8 @@ void DisplayServerWayland::_resize_window(const Size2i &p_size) {
wd.rect.size = p_size;
#ifdef RD_ENABLED
if (wd.visible && context_rd) {
context_rd->window_resize(MAIN_WINDOW_ID, wd.rect.size.width, wd.rect.size.height);
if (wd.visible && rendering_context) {
rendering_context->window_set_size(MAIN_WINDOW_ID, wd.rect.size.width, wd.rect.size.height);
}
#endif
@ -140,10 +140,10 @@ void DisplayServerWayland::_show_window() {
// the only acceptable way of implementing window showing is to move the
// graphics context window creation logic here.
#ifdef RD_ENABLED
if (context_rd) {
if (rendering_context) {
union {
#ifdef VULKAN_ENABLED
VulkanContextWayland::WindowPlatformData vulkan;
RenderingContextDriverVulkanWayland::WindowPlatformData vulkan;
#endif
} wpd;
#ifdef VULKAN_ENABLED
@ -152,14 +152,17 @@ void DisplayServerWayland::_show_window() {
wpd.vulkan.display = wayland_thread.get_wl_display();
}
#endif
Error err = context_rd->window_create(wd.id, wd.vsync_mode, wd.rect.size.width, wd.rect.size.height, &wpd);
ERR_FAIL_COND_MSG(err != OK, vformat("Can't create a %s window", context_rd->get_api_name()));
Error err = rendering_context->window_create(wd.id, &wpd);
ERR_FAIL_COND_MSG(err != OK, vformat("Can't create a %s window", rendering_driver));
emulate_vsync = (context_rd->get_vsync_mode(wd.id) == DisplayServer::VSYNC_ENABLED);
rendering_context->window_set_size(wd.id, wd.rect.size.width, wd.rect.size.height);
rendering_context->window_set_vsync_mode(wd.id, wd.vsync_mode);
emulate_vsync = (rendering_context->window_get_vsync_mode(wd.id) == DisplayServer::VSYNC_ENABLED);
if (emulate_vsync) {
print_verbose("VSYNC: manually throttling frames using MAILBOX.");
context_rd->set_vsync_mode(wd.id, DisplayServer::VSYNC_MAILBOX);
rendering_context->window_set_vsync_mode(wd.id, DisplayServer::VSYNC_MAILBOX);
}
}
#endif
@ -885,14 +888,14 @@ void DisplayServerWayland::window_set_vsync_mode(DisplayServer::VSyncMode p_vsyn
MutexLock mutex_lock(wayland_thread.mutex);
#ifdef RD_ENABLED
if (context_rd) {
context_rd->set_vsync_mode(p_window_id, p_vsync_mode);
if (rendering_context) {
rendering_context->window_set_vsync_mode(p_window_id, p_vsync_mode);
emulate_vsync = (context_rd->get_vsync_mode(p_window_id) == DisplayServer::VSYNC_ENABLED);
emulate_vsync = (rendering_context->window_get_vsync_mode(p_window_id) == DisplayServer::VSYNC_ENABLED);
if (emulate_vsync) {
print_verbose("VSYNC: manually throttling frames using MAILBOX.");
context_rd->set_vsync_mode(p_window_id, DisplayServer::VSYNC_MAILBOX);
rendering_context->window_set_vsync_mode(p_window_id, DisplayServer::VSYNC_MAILBOX);
}
}
#endif // VULKAN_ENABLED
@ -917,8 +920,8 @@ DisplayServer::VSyncMode DisplayServerWayland::window_get_vsync_mode(DisplayServ
}
#ifdef VULKAN_ENABLED
if (context_rd) {
return context_rd->get_vsync_mode(p_window_id);
if (rendering_context) {
return rendering_context->window_get_vsync_mode(p_window_id);
}
#endif // VULKAN_ENABLED
@ -1236,15 +1239,15 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
#ifdef RD_ENABLED
#ifdef VULKAN_ENABLED
if (p_rendering_driver == "vulkan") {
context_rd = memnew(VulkanContextWayland);
rendering_context = memnew(RenderingContextDriverVulkanWayland);
}
#endif
if (context_rd) {
if (context_rd->initialize() != OK) {
ERR_PRINT(vformat("Could not initialize %s", context_rd->get_api_name()));
memdelete(context_rd);
context_rd = nullptr;
if (rendering_context) {
if (rendering_context->initialize() != OK) {
ERR_PRINT(vformat("Could not initialize %s", p_rendering_driver));
memdelete(rendering_context);
rendering_context = nullptr;
r_error = ERR_CANT_CREATE;
return;
}
@ -1329,9 +1332,10 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
_show_window();
#ifdef RD_ENABLED
if (context_rd) {
if (rendering_context) {
rendering_device = memnew(RenderingDevice);
rendering_device->initialize(context_rd);
rendering_device->initialize(rendering_context, MAIN_WINDOW_ID);
rendering_device->screen_create(MAIN_WINDOW_ID);
RendererCompositorRD::make_current();
}
@ -1351,8 +1355,12 @@ DisplayServerWayland::~DisplayServerWayland() {
// TODO: Multiwindow support.
if (main_window.visible) {
#ifdef VULKAN_ENABLED
if (context_rd) {
context_rd->window_destroy(MAIN_WINDOW_ID);
if (rendering_device) {
rendering_device->screen_free(MAIN_WINDOW_ID);
}
if (rendering_context) {
rendering_context->window_destroy(MAIN_WINDOW_ID);
}
#endif
@ -1374,12 +1382,11 @@ DisplayServerWayland::~DisplayServerWayland() {
// Destroy all drivers.
#ifdef RD_ENABLED
if (rendering_device) {
rendering_device->finalize();
memdelete(rendering_device);
}
if (context_rd) {
memdelete(context_rd);
if (rendering_context) {
memdelete(rendering_context);
}
#endif

View file

@ -39,7 +39,7 @@
#include "servers/rendering/rendering_device.h"
#ifdef VULKAN_ENABLED
#include "wayland/vulkan_context_wayland.h"
#include "wayland/rendering_context_driver_vulkan_wayland.h"
#endif
#endif //RD_ENABLED
@ -123,7 +123,7 @@ class DisplayServerWayland : public DisplayServer {
String rendering_driver;
#ifdef RD_ENABLED
ApiContextRD *context_rd = nullptr;
RenderingContextDriver *rendering_context = nullptr;
RenderingDevice *rendering_device = nullptr;
#endif

View file

@ -1,5 +1,5 @@
/**************************************************************************/
/* vulkan_context_wayland.cpp */
/* rendering_context_driver_vulkan_wayland.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -28,32 +28,43 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "vulkan_context_wayland.h"
#ifdef VULKAN_ENABLED
#include "rendering_context_driver_vulkan_wayland.h"
#ifdef USE_VOLK
#include <volk.h>
#else
#include <vulkan/vulkan.h>
#endif
const char *VulkanContextWayland::_get_platform_surface_extension() const {
const char *RenderingContextDriverVulkanWayland::_get_platform_surface_extension() const {
return VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME;
}
Error VulkanContextWayland::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) {
const WindowPlatformData *wpd = (const WindowPlatformData *)p_platform_data;
RenderingContextDriver::SurfaceID RenderingContextDriverVulkanWayland::surface_create(const void *p_platform_data) {
const WindowPlatformData *wpd = (const WindowPlatformData *)(p_platform_data);
VkWaylandSurfaceCreateInfoKHR createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
createInfo.display = wpd->display;
createInfo.surface = wpd->surface;
VkWaylandSurfaceCreateInfoKHR create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
create_info.display = wpd->display;
create_info.surface = wpd->surface;
VkSurfaceKHR surface = VK_NULL_HANDLE;
VkResult err = vkCreateWaylandSurfaceKHR(get_instance(), &createInfo, nullptr, &surface);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
VkSurfaceKHR vk_surface = VK_NULL_HANDLE;
VkResult err = vkCreateWaylandSurfaceKHR(instance_get(), &create_info, nullptr, &vk_surface);
ERR_FAIL_COND_V(err != VK_SUCCESS, SurfaceID());
Surface *surface = memnew(Surface);
surface->vk_surface = vk_surface;
return SurfaceID(surface);
}
RenderingContextDriverVulkanWayland::RenderingContextDriverVulkanWayland() {
// Does nothing.
}
RenderingContextDriverVulkanWayland::~RenderingContextDriverVulkanWayland() {
// Does nothing.
}
#endif // VULKAN_ENABLED

View file

@ -1,5 +1,5 @@
/**************************************************************************/
/* vulkan_context_win.h */
/* rendering_context_driver_vulkan_wayland.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -28,30 +28,30 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef VULKAN_CONTEXT_WIN_H
#define VULKAN_CONTEXT_WIN_H
#ifndef RENDERING_CONTEXT_DRIVER_VULKAN_WAYLAND_H
#define RENDERING_CONTEXT_DRIVER_VULKAN_WAYLAND_H
#ifdef VULKAN_ENABLED
#include "drivers/vulkan/vulkan_context.h"
#include "drivers/vulkan/rendering_context_driver_vulkan.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
class VulkanContextWindows : public VulkanContext {
class RenderingContextDriverVulkanWayland : public RenderingContextDriverVulkan {
private:
virtual const char *_get_platform_surface_extension() const override final;
protected:
SurfaceID surface_create(const void *p_platform_data) override final;
public:
struct WindowPlatformData {
HWND window;
HINSTANCE instance;
struct wl_display *display;
struct wl_surface *surface;
};
virtual Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) override final;
VulkanContextWindows();
~VulkanContextWindows();
RenderingContextDriverVulkanWayland();
~RenderingContextDriverVulkanWayland();
};
#endif // VULKAN_ENABLED
#endif // VULKAN_CONTEXT_WIN_H
#endif // RENDERING_CONTEXT_DRIVER_VULKAN_WAYLAND_H

View file

@ -21,7 +21,7 @@ if env["use_sowrap"]:
)
if env["vulkan"]:
source_files.append("vulkan_context_x11.cpp")
source_files.append("rendering_context_driver_vulkan_x11.cpp")
if env["opengl3"]:
env.Append(CPPDEFINES=["GLAD_GLX_NO_X11"])

View file

@ -1670,7 +1670,11 @@ DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, V
window_set_flag(WindowFlags(i), true, id);
}
}
#ifdef RD_ENABLED
if (rendering_device) {
rendering_device->screen_create(id);
}
#endif
return id;
}
@ -1719,8 +1723,12 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) {
}
#if defined(RD_ENABLED)
if (context_rd) {
context_rd->window_destroy(p_id);
if (rendering_device) {
rendering_device->screen_free(p_id);
}
if (rendering_context) {
rendering_context->window_destroy(p_id);
}
#endif
#ifdef GLES3_ENABLED
@ -2245,8 +2253,8 @@ void DisplayServerX11::window_set_size(const Size2i p_size, WindowID p_window) {
// Keep rendering context window size in sync
#if defined(RD_ENABLED)
if (context_rd) {
context_rd->window_resize(p_window, xwa.width, xwa.height);
if (rendering_context) {
rendering_context->window_set_size(p_window, xwa.width, xwa.height);
}
#endif
#if defined(GLES3_ENABLED)
@ -3970,8 +3978,8 @@ void DisplayServerX11::_window_changed(XEvent *event) {
wd.size = new_rect.size;
#if defined(RD_ENABLED)
if (context_rd) {
context_rd->window_resize(window_id, wd.size.width, wd.size.height);
if (rendering_context) {
rendering_context->window_set_size(window_id, wd.size.width, wd.size.height);
}
#endif
#if defined(GLES3_ENABLED)
@ -5300,8 +5308,8 @@ void DisplayServerX11::set_icon(const Ref<Image> &p_icon) {
void DisplayServerX11::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
_THREAD_SAFE_METHOD_
#if defined(RD_ENABLED)
if (context_rd) {
context_rd->set_vsync_mode(p_window, p_vsync_mode);
if (rendering_context) {
rendering_context->window_set_vsync_mode(p_window, p_vsync_mode);
}
#endif
@ -5318,8 +5326,8 @@ void DisplayServerX11::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mo
DisplayServer::VSyncMode DisplayServerX11::window_get_vsync_mode(WindowID p_window) const {
_THREAD_SAFE_METHOD_
#if defined(RD_ENABLED)
if (context_rd) {
return context_rd->get_vsync_mode(p_window);
if (rendering_context) {
return rendering_context->window_get_vsync_mode(p_window);
}
#endif
#if defined(GLES3_ENABLED)
@ -5662,10 +5670,10 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
_update_size_hints(id);
#if defined(RD_ENABLED)
if (context_rd) {
if (rendering_context) {
union {
#ifdef VULKAN_ENABLED
VulkanContextX11::WindowPlatformData vulkan;
RenderingContextDriverVulkanX11::WindowPlatformData vulkan;
#endif
} wpd;
#ifdef VULKAN_ENABLED
@ -5674,8 +5682,11 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
wpd.vulkan.display = x11_display;
}
#endif
Error err = context_rd->window_create(id, p_vsync_mode, win_rect.size.width, win_rect.size.height, &wpd);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, vformat("Can't create a %s window", context_rd->get_api_name()));
Error err = rendering_context->window_create(id, &wpd);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, vformat("Can't create a %s window", rendering_driver));
rendering_context->window_set_size(id, win_rect.size.width, win_rect.size.height);
rendering_context->window_set_vsync_mode(id, p_vsync_mode);
}
#endif
#ifdef GLES3_ENABLED
@ -6077,15 +6088,15 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
#if defined(RD_ENABLED)
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
context_rd = memnew(VulkanContextX11);
rendering_context = memnew(RenderingContextDriverVulkanX11);
}
#endif
if (context_rd) {
if (context_rd->initialize() != OK) {
ERR_PRINT(vformat("Could not initialize %s", context_rd->get_api_name()));
memdelete(context_rd);
context_rd = nullptr;
if (rendering_context) {
if (rendering_context->initialize() != OK) {
ERR_PRINT(vformat("Could not initialize %s", rendering_driver));
memdelete(rendering_context);
rendering_context = nullptr;
r_error = ERR_CANT_CREATE;
return;
}
@ -6197,9 +6208,10 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
show_window(main_window);
#if defined(RD_ENABLED)
if (context_rd) {
if (rendering_context) {
rendering_device = memnew(RenderingDevice);
rendering_device->initialize(context_rd);
rendering_device->initialize(rendering_context, MAIN_WINDOW_ID);
rendering_device->screen_create(MAIN_WINDOW_ID);
RendererCompositorRD::make_current();
}
@ -6374,8 +6386,12 @@ DisplayServerX11::~DisplayServerX11() {
//destroy all windows
for (KeyValue<WindowID, WindowData> &E : windows) {
#if defined(RD_ENABLED)
if (context_rd) {
context_rd->window_destroy(E.key);
if (rendering_device) {
rendering_device->screen_free(E.key);
}
if (rendering_context) {
rendering_context->window_destroy(E.key);
}
#endif
#ifdef GLES3_ENABLED
@ -6419,14 +6435,13 @@ DisplayServerX11::~DisplayServerX11() {
//destroy drivers
#if defined(RD_ENABLED)
if (rendering_device) {
rendering_device->finalize();
memdelete(rendering_device);
rendering_device = nullptr;
}
if (context_rd) {
memdelete(context_rd);
context_rd = nullptr;
if (rendering_context) {
memdelete(rendering_context);
rendering_context = nullptr;
}
#endif

View file

@ -61,7 +61,7 @@
#include "servers/rendering/rendering_device.h"
#if defined(VULKAN_ENABLED)
#include "x11/vulkan_context_x11.h"
#include "x11/rendering_context_driver_vulkan_x11.h"
#endif
#endif
@ -144,7 +144,7 @@ class DisplayServerX11 : public DisplayServer {
GLManagerEGL_X11 *gl_manager_egl = nullptr;
#endif
#if defined(RD_ENABLED)
ApiContextRD *context_rd = nullptr;
RenderingContextDriver *rendering_context = nullptr;
RenderingDevice *rendering_device = nullptr;
#endif

View file

@ -1,5 +1,5 @@
/**************************************************************************/
/* vulkan_context_x11.cpp */
/* rendering_context_driver_vulkan_x11.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -30,7 +30,7 @@
#ifdef VULKAN_ENABLED
#include "vulkan_context_x11.h"
#include "rendering_context_driver_vulkan_x11.h"
#ifdef USE_VOLK
#include <volk.h>
@ -38,28 +38,33 @@
#include <vulkan/vulkan.h>
#endif
const char *VulkanContextX11::_get_platform_surface_extension() const {
const char *RenderingContextDriverVulkanX11::_get_platform_surface_extension() const {
return VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
}
Error VulkanContextX11::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) {
const WindowPlatformData *wpd = (const WindowPlatformData *)p_platform_data;
RenderingContextDriver::SurfaceID RenderingContextDriverVulkanX11::surface_create(const void *p_platform_data) {
const WindowPlatformData *wpd = (const WindowPlatformData *)(p_platform_data);
VkXlibSurfaceCreateInfoKHR createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
createInfo.dpy = wpd->display;
createInfo.window = wpd->window;
VkXlibSurfaceCreateInfoKHR create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
create_info.dpy = wpd->display;
create_info.window = wpd->window;
VkSurfaceKHR surface = VK_NULL_HANDLE;
VkResult err = vkCreateXlibSurfaceKHR(get_instance(), &createInfo, nullptr, &surface);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
VkSurfaceKHR vk_surface = VK_NULL_HANDLE;
VkResult err = vkCreateXlibSurfaceKHR(instance_get(), &create_info, nullptr, &vk_surface);
ERR_FAIL_COND_V(err != VK_SUCCESS, SurfaceID());
Surface *surface = memnew(Surface);
surface->vk_surface = vk_surface;
return SurfaceID(surface);
}
VulkanContextX11::VulkanContextX11() {
RenderingContextDriverVulkanX11::RenderingContextDriverVulkanX11() {
// Does nothing.
}
VulkanContextX11::~VulkanContextX11() {
RenderingContextDriverVulkanX11::~RenderingContextDriverVulkanX11() {
// Does nothing.
}
#endif // VULKAN_ENABLED

View file

@ -1,5 +1,5 @@
/**************************************************************************/
/* vulkan_context_x11.h */
/* rendering_context_driver_vulkan_x11.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -28,29 +28,32 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef VULKAN_CONTEXT_X11_H
#define VULKAN_CONTEXT_X11_H
#ifndef RENDERING_CONTEXT_DRIVER_VULKAN_X11_H
#define RENDERING_CONTEXT_DRIVER_VULKAN_X11_H
#ifdef VULKAN_ENABLED
#include "drivers/vulkan/vulkan_context.h"
#include "drivers/vulkan/rendering_context_driver_vulkan.h"
#include <X11/Xlib.h>
class VulkanContextX11 : public VulkanContext {
class RenderingContextDriverVulkanX11 : public RenderingContextDriverVulkan {
private:
virtual const char *_get_platform_surface_extension() const override final;
protected:
SurfaceID surface_create(const void *p_platform_data) override final;
public:
struct WindowPlatformData {
::Window window;
Display *display;
};
virtual Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) override final;
VulkanContextX11();
~VulkanContextX11();
RenderingContextDriverVulkanX11();
~RenderingContextDriverVulkanX11();
};
#endif // VULKAN_ENABLED
#endif // VULKAN_CONTEXT_X11_H
#endif // RENDERING_CONTEXT_DRIVER_VULKAN_X11_H

View file

@ -24,7 +24,7 @@ files = [
"dir_access_macos.mm",
"tts_macos.mm",
"joypad_macos.cpp",
"vulkan_context_macos.mm",
"rendering_context_driver_vulkan_macos.mm",
"gl_manager_macos_angle.mm",
"gl_manager_macos_legacy.mm",
]

View file

@ -43,7 +43,7 @@
#include "servers/rendering/rendering_device.h"
#if defined(VULKAN_ENABLED)
#include "vulkan_context_macos.h"
#include "rendering_context_driver_vulkan_macos.h"
#endif // VULKAN_ENABLED
#endif // RD_ENABLED
@ -137,7 +137,7 @@ private:
GLManagerANGLE_MacOS *gl_manager_angle = nullptr;
#endif
#if defined(RD_ENABLED)
ApiContextRD *context_rd = nullptr;
RenderingContextDriver *rendering_context = nullptr;
RenderingDevice *rendering_device = nullptr;
#endif
String rendering_driver;

View file

@ -195,10 +195,10 @@ DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mod
}
#if defined(RD_ENABLED)
if (context_rd) {
if (rendering_context) {
union {
#ifdef VULKAN_ENABLED
VulkanContextMacOS::WindowPlatformData vulkan;
RenderingContextDriverVulkanMacOS::WindowPlatformData vulkan;
#endif
} wpd;
#ifdef VULKAN_ENABLED
@ -206,8 +206,11 @@ DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mod
wpd.vulkan.view_ptr = &wd.window_view;
}
#endif
Error err = context_rd->window_create(window_id_counter, p_vsync_mode, p_rect.size.width, p_rect.size.height, &wpd);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, vformat("Can't create a %s context", context_rd->get_api_name()));
Error err = rendering_context->window_create(window_id_counter, &wpd);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, vformat("Can't create a %s context", rendering_driver));
rendering_context->window_set_size(window_id_counter, p_rect.size.width, p_rect.size.height);
rendering_context->window_set_vsync_mode(window_id_counter, p_vsync_mode);
}
#endif
#if defined(GLES3_ENABLED)
@ -257,11 +260,6 @@ DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mod
gl_manager_angle->window_resize(id, wd.size.width, wd.size.height);
}
#endif
#if defined(RD_ENABLED)
if (context_rd) {
context_rd->window_resize(id, wd.size.width, wd.size.height);
}
#endif
return id;
}
@ -791,8 +789,12 @@ void DisplayServerMacOS::window_destroy(WindowID p_window) {
}
#endif
#ifdef RD_ENABLED
if (context_rd) {
context_rd->window_destroy(p_window);
if (rendering_device) {
rendering_device->screen_free(p_window);
}
if (rendering_context) {
rendering_context->window_destroy(p_window);
}
#endif
windows.erase(p_window);
@ -800,6 +802,11 @@ void DisplayServerMacOS::window_destroy(WindowID p_window) {
}
void DisplayServerMacOS::window_resize(WindowID p_window, int p_width, int p_height) {
#if defined(RD_ENABLED)
if (rendering_context) {
rendering_context->window_set_size(p_window, p_width, p_height);
}
#endif
#if defined(GLES3_ENABLED)
if (gl_manager_legacy) {
gl_manager_legacy->window_resize(p_window, p_width, p_height);
@ -808,11 +815,6 @@ void DisplayServerMacOS::window_resize(WindowID p_window, int p_width, int p_hei
gl_manager_angle->window_resize(p_window, p_width, p_height);
}
#endif
#if defined(VULKAN_ENABLED)
if (context_rd) {
context_rd->window_resize(p_window, p_width, p_height);
}
#endif
}
bool DisplayServerMacOS::has_feature(Feature p_feature) const {
@ -2850,7 +2852,11 @@ DisplayServer::WindowID DisplayServerMacOS::create_sub_window(WindowMode p_mode,
window_set_flag(WindowFlags(i), true, id);
}
}
#ifdef RD_ENABLED
if (rendering_device) {
rendering_device->screen_create(id);
}
#endif
return id;
}
@ -3811,8 +3817,8 @@ void DisplayServerMacOS::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_
}
#endif
#if defined(VULKAN_ENABLED)
if (context_rd) {
context_rd->set_vsync_mode(p_window, p_vsync_mode);
if (rendering_context) {
rendering_context->window_set_vsync_mode(p_window, p_vsync_mode);
}
#endif
}
@ -3828,8 +3834,8 @@ DisplayServer::VSyncMode DisplayServerMacOS::window_get_vsync_mode(WindowID p_wi
}
#endif
#if defined(VULKAN_ENABLED)
if (context_rd) {
return context_rd->get_vsync_mode(p_window);
if (rendering_context) {
return rendering_context->window_get_vsync_mode(p_window);
}
#endif
return DisplayServer::VSYNC_ENABLED;
@ -4632,16 +4638,16 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
#if defined(RD_ENABLED)
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
context_rd = memnew(VulkanContextMacOS);
rendering_context = memnew(RenderingContextDriverVulkanMacOS);
}
#endif
if (context_rd) {
if (context_rd->initialize() != OK) {
memdelete(context_rd);
context_rd = nullptr;
if (rendering_context) {
if (rendering_context->initialize() != OK) {
memdelete(rendering_context);
rendering_context = nullptr;
r_error = ERR_CANT_CREATE;
ERR_FAIL_MSG("Could not initialize Vulkan");
ERR_FAIL_MSG("Could not initialize " + rendering_driver);
}
}
#endif
@ -4676,9 +4682,10 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
}
#endif
#if defined(RD_ENABLED)
if (context_rd) {
if (rendering_context) {
rendering_device = memnew(RenderingDevice);
rendering_device->initialize(context_rd);
rendering_device->initialize(rendering_context, MAIN_WINDOW_ID);
rendering_device->screen_create(MAIN_WINDOW_ID);
RendererCompositorRD::make_current();
}
@ -4714,14 +4721,13 @@ DisplayServerMacOS::~DisplayServerMacOS() {
#endif
#if defined(RD_ENABLED)
if (rendering_device) {
rendering_device->finalize();
memdelete(rendering_device);
rendering_device = nullptr;
}
if (context_rd) {
memdelete(context_rd);
context_rd = nullptr;
if (rendering_context) {
memdelete(rendering_context);
rendering_context = nullptr;
}
#endif

View file

@ -1,5 +1,5 @@
/**************************************************************************/
/* vulkan_context_macos.h */
/* rendering_context_driver_vulkan_macos.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -28,28 +28,31 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef VULKAN_CONTEXT_MACOS_H
#define VULKAN_CONTEXT_MACOS_H
#ifndef RENDERING_CONTEXT_DRIVER_VULKAN_MACOS_H
#define RENDERING_CONTEXT_DRIVER_VULKAN_MACOS_H
#ifdef VULKAN_ENABLED
#include "drivers/vulkan/vulkan_context.h"
#include "drivers/vulkan/rendering_context_driver_vulkan.h"
#import <AppKit/AppKit.h>
class VulkanContextMacOS : public VulkanContext {
class RenderingContextDriverVulkanMacOS : public RenderingContextDriverVulkan {
private:
virtual const char *_get_platform_surface_extension() const override final;
protected:
SurfaceID surface_create(const void *p_platform_data) override final;
public:
struct WindowPlatformData {
const id *view_ptr;
};
virtual Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) override final;
VulkanContextMacOS();
~VulkanContextMacOS();
RenderingContextDriverVulkanMacOS();
~RenderingContextDriverVulkanMacOS();
};
#endif // VULKAN_ENABLED
#endif // VULKAN_CONTEXT_MACOS_H
#endif // RENDERING_CONTEXT_DRIVER_VULKAN_MACOS_H

View file

@ -1,5 +1,5 @@
/**************************************************************************/
/* vulkan_context_macos.mm */
/* rendering_context_driver_vulkan_macos.mm */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "vulkan_context_macos.h"
#include "rendering_context_driver_vulkan_macos.h"
#ifdef VULKAN_ENABLED
@ -38,27 +38,32 @@
#include <vulkan/vulkan.h>
#endif
const char *VulkanContextMacOS::_get_platform_surface_extension() const {
const char *RenderingContextDriverVulkanMacOS::_get_platform_surface_extension() const {
return VK_MVK_MACOS_SURFACE_EXTENSION_NAME;
}
Error VulkanContextMacOS::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) {
const WindowPlatformData *wpd = (const WindowPlatformData *)p_platform_data;
RenderingContextDriver::SurfaceID RenderingContextDriverVulkanMacOS::surface_create(const void *p_platform_data) {
const WindowPlatformData *wpd = (const WindowPlatformData *)(p_platform_data);
VkMacOSSurfaceCreateInfoMVK createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
createInfo.pView = (__bridge const void *)(*wpd->view_ptr);
VkMacOSSurfaceCreateInfoMVK create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
create_info.pView = (__bridge const void *)(*wpd->view_ptr);
VkSurfaceKHR surface = VK_NULL_HANDLE;
VkResult err = vkCreateMacOSSurfaceMVK(get_instance(), &createInfo, nullptr, &surface);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
VkSurfaceKHR vk_surface = VK_NULL_HANDLE;
VkResult err = vkCreateMacOSSurfaceMVK(instance_get(), &create_info, nullptr, &vk_surface);
ERR_FAIL_COND_V(err != VK_SUCCESS, SurfaceID());
Surface *surface = memnew(Surface);
surface->vk_surface = vk_surface;
return SurfaceID(surface);
}
VulkanContextMacOS::VulkanContextMacOS() {
RenderingContextDriverVulkanMacOS::RenderingContextDriverVulkanMacOS() {
// Does nothing.
}
VulkanContextMacOS::~VulkanContextMacOS() {
RenderingContextDriverVulkanMacOS::~RenderingContextDriverVulkanMacOS() {
// Does nothing.
}
#endif // VULKAN_ENABLED

View file

@ -18,10 +18,10 @@ common_win = [
"joypad_windows.cpp",
"tts_windows.cpp",
"windows_terminal_logger.cpp",
"vulkan_context_win.cpp",
"gl_manager_windows_native.cpp",
"gl_manager_windows_angle.cpp",
"wgl_detect_version.cpp",
"rendering_context_driver_vulkan_windows.cpp",
]
common_win_wrap = [

View file

@ -39,6 +39,12 @@
#include "main/main.h"
#include "scene/resources/atlas_texture.h"
#if defined(VULKAN_ENABLED)
#include "rendering_context_driver_vulkan_windows.h"
#endif
#if defined(D3D12_ENABLED)
#include "drivers/d3d12/rendering_context_driver_d3d12.h"
#endif
#if defined(GLES3_ENABLED)
#include "drivers/gles3/rasterizer_gles3.h"
#endif
@ -1290,6 +1296,11 @@ DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mod
if (mainwindow_icon) {
SendMessage(windows[window_id].hWnd, WM_SETICON, ICON_BIG, (LPARAM)mainwindow_icon);
}
#ifdef RD_ENABLED
if (rendering_device) {
rendering_device->screen_create(window_id);
}
#endif
return window_id;
}
@ -1344,8 +1355,12 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) {
}
#ifdef RD_ENABLED
if (context_rd) {
context_rd->window_destroy(p_window);
if (rendering_device) {
rendering_device->screen_free(p_window);
}
if (rendering_context) {
rendering_context->window_destroy(p_window);
}
#endif
#ifdef GLES3_ENABLED
@ -1776,8 +1791,8 @@ void DisplayServerWindows::window_set_size(const Size2i p_size, WindowID p_windo
wd.height = h;
#if defined(RD_ENABLED)
if (context_rd) {
context_rd->window_resize(p_window, w, h);
if (rendering_context) {
rendering_context->window_set_size(p_window, w, h);
}
#endif
#if defined(GLES3_ENABLED)
@ -2830,8 +2845,8 @@ void DisplayServerWindows::set_icon(const Ref<Image> &p_icon) {
void DisplayServerWindows::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
_THREAD_SAFE_METHOD_
#if defined(RD_ENABLED)
if (context_rd) {
context_rd->set_vsync_mode(p_window, p_vsync_mode);
if (rendering_context) {
rendering_context->window_set_vsync_mode(p_window, p_vsync_mode);
}
#endif
@ -2848,8 +2863,8 @@ void DisplayServerWindows::window_set_vsync_mode(DisplayServer::VSyncMode p_vsyn
DisplayServer::VSyncMode DisplayServerWindows::window_get_vsync_mode(WindowID p_window) const {
_THREAD_SAFE_METHOD_
#if defined(RD_ENABLED)
if (context_rd) {
return context_rd->get_vsync_mode(p_window);
if (rendering_context) {
return rendering_context->window_get_vsync_mode(p_window);
}
#endif
@ -4054,9 +4069,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
rect_changed = true;
}
#if defined(RD_ENABLED)
if (context_rd && window.context_created) {
if (rendering_context && window.context_created) {
// Note: Trigger resize event to update swapchains when window is minimized/restored, even if size is not changed.
context_rd->window_resize(window_id, window.width, window.height);
rendering_context->window_set_size(window_id, window.width, window.height);
}
#endif
}
@ -4612,13 +4627,13 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
}
#ifdef RD_ENABLED
if (context_rd) {
if (rendering_context) {
union {
#ifdef VULKAN_ENABLED
VulkanContextWindows::WindowPlatformData vulkan;
RenderingContextDriverVulkanWindows::WindowPlatformData vulkan;
#endif
#ifdef D3D12_ENABLED
D3D12Context::WindowPlatformData d3d12;
RenderingContextDriverD3D12::WindowPlatformData d3d12;
#endif
} wpd;
#ifdef VULKAN_ENABLED
@ -4632,13 +4647,16 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
wpd.d3d12.window = wd.hWnd;
}
#endif
if (context_rd->window_create(id, p_vsync_mode, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, &wpd) != OK) {
ERR_PRINT(vformat("Failed to create %s Window.", context_rd->get_api_name()));
memdelete(context_rd);
context_rd = nullptr;
if (rendering_context->window_create(id, &wpd) != OK) {
ERR_PRINT(vformat("Failed to create %s window.", rendering_driver));
memdelete(rendering_context);
rendering_context = nullptr;
windows.erase(id);
return INVALID_WINDOW_ID;
}
rendering_context->window_set_size(id, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top);
rendering_context->window_set_vsync_mode(id, p_vsync_mode);
wd.context_created = true;
}
#endif
@ -4949,19 +4967,19 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
#if defined(RD_ENABLED)
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
context_rd = memnew(VulkanContextWindows);
rendering_context = memnew(RenderingContextDriverVulkanWindows);
}
#endif
#if defined(D3D12_ENABLED)
if (rendering_driver == "d3d12") {
context_rd = memnew(D3D12Context);
rendering_context = memnew(RenderingContextDriverD3D12);
}
#endif
if (context_rd) {
if (context_rd->initialize() != OK) {
memdelete(context_rd);
context_rd = nullptr;
if (rendering_context) {
if (rendering_context->initialize() != OK) {
memdelete(rendering_context);
rendering_context = nullptr;
r_error = ERR_UNAVAILABLE;
return;
}
@ -5051,9 +5069,10 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
show_window(MAIN_WINDOW_ID);
#if defined(RD_ENABLED)
if (context_rd) {
if (rendering_context) {
rendering_device = memnew(RenderingDevice);
rendering_device->initialize(context_rd);
rendering_device->initialize(rendering_context, MAIN_WINDOW_ID);
rendering_device->screen_create(MAIN_WINDOW_ID);
RendererCompositorRD::make_current();
}
@ -5165,8 +5184,12 @@ DisplayServerWindows::~DisplayServerWindows() {
if (windows.has(MAIN_WINDOW_ID)) {
#ifdef RD_ENABLED
if (context_rd) {
context_rd->window_destroy(MAIN_WINDOW_ID);
if (rendering_device) {
rendering_device->screen_free(MAIN_WINDOW_ID);
}
if (rendering_context) {
rendering_context->window_destroy(MAIN_WINDOW_ID);
}
#endif
if (wintab_available && windows[MAIN_WINDOW_ID].wtctx) {
@ -5178,14 +5201,13 @@ DisplayServerWindows::~DisplayServerWindows() {
#ifdef RD_ENABLED
if (rendering_device) {
rendering_device->finalize();
memdelete(rendering_device);
rendering_device = nullptr;
}
if (context_rd) {
memdelete(context_rd);
context_rd = nullptr;
if (rendering_context) {
memdelete(rendering_context);
rendering_context = nullptr;
}
#endif

View file

@ -54,13 +54,6 @@
#if defined(RD_ENABLED)
#include "servers/rendering/rendering_device.h"
#if defined(VULKAN_ENABLED)
#include "vulkan_context_win.h"
#endif
#if defined(D3D12_ENABLED)
#include "drivers/d3d12/d3d12_context.h"
#endif
#endif
#if defined(GLES3_ENABLED)
@ -349,7 +342,7 @@ class DisplayServerWindows : public DisplayServer {
#endif
#if defined(RD_ENABLED)
ApiContextRD *context_rd = nullptr;
RenderingContextDriver *rendering_context = nullptr;
RenderingDevice *rendering_device = nullptr;
#endif

View file

@ -48,13 +48,6 @@
#if defined(RD_ENABLED)
#include "servers/rendering/rendering_device.h"
#if defined(VULKAN_ENABLED)
#include "vulkan_context_win.h"
#endif
#if defined(D3D12_ENABLED)
#include "drivers/d3d12/d3d12_context.h"
#endif
#endif
#include <io.h>

View file

@ -1,5 +1,5 @@
/**************************************************************************/
/* vulkan_context_win.cpp */
/* rendering_context_driver_vulkan_windows.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -30,7 +30,9 @@
#if defined(WINDOWS_ENABLED) && defined(VULKAN_ENABLED)
#include "vulkan_context_win.h"
#include "core/os/os.h"
#include "rendering_context_driver_vulkan_windows.h"
#ifdef USE_VOLK
#include <volk.h>
@ -38,32 +40,36 @@
#include <vulkan/vulkan.h>
#endif
const char *VulkanContextWindows::_get_platform_surface_extension() const {
const char *RenderingContextDriverVulkanWindows::_get_platform_surface_extension() const {
return VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
}
Error VulkanContextWindows::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) {
const WindowPlatformData *wpd = (const WindowPlatformData *)p_platform_data;
VkWin32SurfaceCreateInfoKHR createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
createInfo.hinstance = wpd->instance;
createInfo.hwnd = wpd->window;
VkSurfaceKHR surface = VK_NULL_HANDLE;
VkResult err = vkCreateWin32SurfaceKHR(get_instance(), &createInfo, nullptr, &surface);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
}
VulkanContextWindows::VulkanContextWindows() {
RenderingContextDriverVulkanWindows::RenderingContextDriverVulkanWindows() {
// Workaround for Vulkan not working on setups with AMD integrated graphics + NVIDIA dedicated GPU (GH-57708).
// This prevents using AMD integrated graphics with Vulkan entirely, but it allows the engine to start
// even on outdated/broken driver setups.
OS::get_singleton()->set_environment("DISABLE_LAYER_AMD_SWITCHABLE_GRAPHICS_1", "1");
}
VulkanContextWindows::~VulkanContextWindows() {
RenderingContextDriverVulkanWindows::~RenderingContextDriverVulkanWindows() {
// Does nothing.
}
RenderingContextDriver::SurfaceID RenderingContextDriverVulkanWindows::surface_create(const void *p_platform_data) {
const WindowPlatformData *wpd = (const WindowPlatformData *)(p_platform_data);
VkWin32SurfaceCreateInfoKHR create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
create_info.hinstance = wpd->instance;
create_info.hwnd = wpd->window;
VkSurfaceKHR vk_surface = VK_NULL_HANDLE;
VkResult err = vkCreateWin32SurfaceKHR(instance_get(), &create_info, nullptr, &vk_surface);
ERR_FAIL_COND_V(err != VK_SUCCESS, SurfaceID());
Surface *surface = memnew(Surface);
surface->vk_surface = vk_surface;
return SurfaceID(surface);
}
#endif // WINDOWS_ENABLED && VULKAN_ENABLED

View file

@ -1,5 +1,5 @@
/**************************************************************************/
/* vulkan_context_wayland.h */
/* rendering_context_driver_vulkan_windows.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -28,25 +28,33 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef VULKAN_CONTEXT_WAYLAND_H
#define VULKAN_CONTEXT_WAYLAND_H
#ifndef RENDERING_CONTEXT_DRIVER_VULKAN_WINDOWS_H
#define RENDERING_CONTEXT_DRIVER_VULKAN_WINDOWS_H
#ifdef VULKAN_ENABLED
#include "drivers/vulkan/vulkan_context.h"
#include "drivers/vulkan/rendering_context_driver_vulkan.h"
class VulkanContextWayland : public VulkanContext {
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
class RenderingContextDriverVulkanWindows : public RenderingContextDriverVulkan {
private:
const char *_get_platform_surface_extension() const override final;
protected:
SurfaceID surface_create(const void *p_platform_data) override final;
public:
struct WindowPlatformData {
struct wl_display *display;
struct wl_surface *surface;
HWND window;
HINSTANCE instance;
};
Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) override final;
RenderingContextDriverVulkanWindows();
~RenderingContextDriverVulkanWindows() override final;
};
#endif // VULKAN_ENABLED
#endif // VULKAN_CONTEXT_WAYLAND_H
#endif // RENDERING_CONTEXT_DRIVER_VULKAN_WINDOWS_H

View file

@ -86,7 +86,6 @@ public:
time += frame_step;
}
void prepare_for_blitting_render_targets() override {}
void blit_render_targets_to_screen(int p_screen, const BlitToScreen *p_render_targets, int p_amount) override {}
void end_viewport(bool p_swap_buffers) override {}

View file

@ -96,7 +96,6 @@ public:
virtual void initialize() = 0;
virtual void begin_frame(double frame_step) = 0;
virtual void prepare_for_blitting_render_targets() = 0;
virtual void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) = 0;
virtual void end_viewport(bool p_swap_buffers) = 0;

View file

@ -1,82 +0,0 @@
/**************************************************************************/
/* api_context_rd.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef API_CONTEXT_RD_H
#define API_CONTEXT_RD_H
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/rendering_device_driver.h"
class ApiContextRD {
public:
virtual const char *get_api_name() const = 0;
virtual RenderingDevice::Capabilities get_device_capabilities() const = 0;
virtual const RDD::MultiviewCapabilities &get_multiview_capabilities() const = 0;
virtual int get_swapchain_image_count() const = 0;
virtual Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) = 0;
virtual void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height) = 0;
virtual int window_get_width(DisplayServer::WindowID p_window = 0) = 0;
virtual int window_get_height(DisplayServer::WindowID p_window = 0) = 0;
virtual bool window_is_valid_swapchain(DisplayServer::WindowID p_window = 0) = 0;
virtual void window_destroy(DisplayServer::WindowID p_window_id) = 0;
virtual RDD::RenderPassID window_get_render_pass(DisplayServer::WindowID p_window = 0) = 0;
virtual RDD::FramebufferID window_get_framebuffer(DisplayServer::WindowID p_window = 0) = 0;
virtual RID local_device_create() = 0;
virtual void local_device_push_command_buffers(RID p_local_device, const RDD::CommandBufferID *p_buffers, int p_count) = 0;
virtual void local_device_sync(RID p_local_device) = 0;
virtual void local_device_free(RID p_local_device) = 0;
virtual void set_setup_buffer(RDD::CommandBufferID p_command_buffer) = 0;
virtual void append_command_buffer(RDD::CommandBufferID p_command_buffer) = 0;
virtual void flush(bool p_flush_setup = false, bool p_flush_pending = false, bool p_sync = true) = 0;
virtual Error prepare_buffers(RDD::CommandBufferID p_command_buffer) = 0;
virtual void postpare_buffers(RDD::CommandBufferID p_command_buffer) = 0;
virtual Error swap_buffers() = 0;
virtual Error initialize() = 0;
virtual String get_device_vendor_name() const = 0;
virtual String get_device_name() const = 0;
virtual RDD::DeviceType get_device_type() const = 0;
virtual String get_device_api_version() const = 0;
virtual String get_device_pipeline_cache_uuid() const = 0;
virtual void set_vsync_mode(DisplayServer::WindowID p_window, DisplayServer::VSyncMode p_mode) = 0;
virtual DisplayServer::VSyncMode get_vsync_mode(DisplayServer::WindowID p_window = 0) const = 0;
virtual RenderingDeviceDriver *get_driver(RID p_local_device = RID()) = 0;
virtual bool is_debug_utils_enabled() const = 0;
virtual ~ApiContextRD();
};
#endif // API_CONTEXT_RD_H

View file

@ -33,16 +33,16 @@
#include "core/config/project_settings.h"
#include "core/io/dir_access.h"
void RendererCompositorRD::prepare_for_blitting_render_targets() {
RD::get_singleton()->prepare_screen_for_drawing();
}
void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) {
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin_for_screen(p_screen);
if (draw_list == RD::INVALID_ID) {
return; // Window is minimized and does not have valid swapchain, skip drawing without printing errors.
Error err = RD::get_singleton()->screen_prepare_for_drawing(p_screen);
if (err != OK) {
// Window is minimized and does not have valid swapchain, skip drawing without printing errors.
return;
}
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin_for_screen(p_screen);
ERR_FAIL_COND(draw_list == RD::INVALID_ID);
for (int i = 0; i < p_amount; i++) {
RID rd_texture = texture_storage->render_target_get_rd_texture(p_render_targets[i].render_target);
ERR_CONTINUE(rd_texture.is_null());
@ -122,7 +122,7 @@ void RendererCompositorRD::initialize() {
blit.shader_version = blit.shader.version_create();
for (int i = 0; i < BLIT_MODE_MAX; i++) {
blit.pipelines[i] = RD::get_singleton()->render_pipeline_create(blit.shader.version_get_shader(blit.shader_version, i), RD::get_singleton()->screen_get_framebuffer_format(), RD::INVALID_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), i == BLIT_MODE_NORMAL_ALPHA ? RenderingDevice::PipelineColorBlendState::create_blend() : RenderingDevice::PipelineColorBlendState::create_disabled(), 0);
blit.pipelines[i] = RD::get_singleton()->render_pipeline_create(blit.shader.version_get_shader(blit.shader_version, i), RD::get_singleton()->screen_get_framebuffer_format(DisplayServer::MAIN_WINDOW_ID), RD::INVALID_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), i == BLIT_MODE_NORMAL_ALPHA ? RenderingDevice::PipelineColorBlendState::create_blend() : RenderingDevice::PipelineColorBlendState::create_disabled(), 0);
}
//create index array for copy shader
@ -169,7 +169,7 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
return;
}
RD::get_singleton()->prepare_screen_for_drawing();
RD::get_singleton()->screen_prepare_for_drawing(DisplayServer::MAIN_WINDOW_ID);
RID texture = texture_storage->texture_allocate();
texture_storage->texture_2d_initialize(texture, p_image);

View file

@ -120,7 +120,6 @@ public:
void initialize();
void begin_frame(double frame_step);
void prepare_for_blitting_render_targets();
void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount);
void end_viewport(bool p_swap_buffers) {}

View file

@ -36,7 +36,6 @@
#include "core/object/worker_thread_pool.h"
#include "core/version.h"
#include "renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/api_context_rd.h"
#include "servers/rendering/rendering_device.h"
#include "thirdparty/misc/smolv.h"
@ -398,7 +397,7 @@ static const uint32_t cache_file_version = 3;
String ShaderRD::_get_cache_file_path(Version *p_version, int p_group) {
const String &sha1 = _version_get_sha1(p_version);
const String &api_safe_name = String(RD::get_singleton()->get_context()->get_api_name()).validate_filename().to_lower();
const String &api_safe_name = String(RD::get_singleton()->get_device_api_name()).validate_filename().to_lower();
const String &path = shader_cache_dir.path_join(name).path_join(group_sha256[p_group]).path_join(sha1) + "." + api_safe_name + ".cache";
return path;
}

View file

@ -824,9 +824,6 @@ void RendererViewport::draw_viewports(bool p_swap_buffers) {
RENDER_TIMESTAMP("< Render Viewports");
if (p_swap_buffers && !blit_to_screen_list.is_empty()) {
// This needs to be called to make screen swapping more efficient.
RSG::rasterizer->prepare_for_blitting_render_targets();
for (const KeyValue<int, Vector<BlitToScreen>> &E : blit_to_screen_list) {
RSG::rasterizer->blit_render_targets_to_screen(E.key, E.value.ptr(), E.value.size());
}

View file

@ -0,0 +1,85 @@
/**************************************************************************/
/* rendering_context_driver.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "rendering_context_driver.h"
RenderingContextDriver::~RenderingContextDriver() {
}
RenderingContextDriver::SurfaceID RenderingContextDriver::surface_get_from_window(DisplayServer::WindowID p_window) const {
HashMap<DisplayServer::WindowID, SurfaceID>::ConstIterator it = window_surface_map.find(p_window);
if (it != window_surface_map.end()) {
return it->value;
} else {
return SurfaceID();
}
}
Error RenderingContextDriver::window_create(DisplayServer::WindowID p_window, const void *p_platform_data) {
SurfaceID surface = surface_create(p_platform_data);
if (surface != 0) {
window_surface_map[p_window] = surface;
return OK;
} else {
return ERR_CANT_CREATE;
}
}
void RenderingContextDriver::window_set_size(DisplayServer::WindowID p_window, uint32_t p_width, uint32_t p_height) {
SurfaceID surface = surface_get_from_window(p_window);
if (surface) {
surface_set_size(surface, p_width, p_height);
}
}
void RenderingContextDriver::window_set_vsync_mode(DisplayServer::WindowID p_window, DisplayServer::VSyncMode p_vsync_mode) {
SurfaceID surface = surface_get_from_window(p_window);
if (surface) {
surface_set_vsync_mode(surface, p_vsync_mode);
}
}
DisplayServer::VSyncMode RenderingContextDriver::window_get_vsync_mode(DisplayServer::WindowID p_window) const {
SurfaceID surface = surface_get_from_window(p_window);
if (surface) {
return surface_get_vsync_mode(surface);
} else {
return DisplayServer::VSYNC_DISABLED;
}
}
void RenderingContextDriver::window_destroy(DisplayServer::WindowID p_window) {
SurfaceID surface = surface_get_from_window(p_window);
if (surface) {
surface_destroy(surface);
}
window_surface_map.erase(p_window);
}

View file

@ -0,0 +1,101 @@
/**************************************************************************/
/* rendering_context_driver.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RENDERING_CONTEXT_DRIVER_H
#define RENDERING_CONTEXT_DRIVER_H
#include "core/object/object.h"
#include "servers/display_server.h"
class RenderingDeviceDriver;
class RenderingContextDriver {
public:
typedef uint64_t SurfaceID;
private:
HashMap<DisplayServer::WindowID, SurfaceID> window_surface_map;
public:
SurfaceID surface_get_from_window(DisplayServer::WindowID p_window) const;
Error window_create(DisplayServer::WindowID p_window, const void *p_platform_data);
void window_set_size(DisplayServer::WindowID p_window, uint32_t p_width, uint32_t p_height);
void window_set_vsync_mode(DisplayServer::WindowID p_window, DisplayServer::VSyncMode p_vsync_mode);
DisplayServer::VSyncMode window_get_vsync_mode(DisplayServer::WindowID p_window) const;
void window_destroy(DisplayServer::WindowID p_window);
public:
enum Vendor {
VENDOR_UNKNOWN = 0x0,
VENDOR_AMD = 0x1002,
VENDOR_IMGTEC = 0x1010,
VENDOR_APPLE = 0x106B,
VENDOR_NVIDIA = 0x10DE,
VENDOR_ARM = 0x13B5,
VENDOR_MICROSOFT = 0x1414,
VENDOR_QUALCOMM = 0x5143,
VENDOR_INTEL = 0x8086
};
enum DeviceType {
DEVICE_TYPE_OTHER = 0x0,
DEVICE_TYPE_INTEGRATED_GPU = 0x1,
DEVICE_TYPE_DISCRETE_GPU = 0x2,
DEVICE_TYPE_VIRTUAL_GPU = 0x3,
DEVICE_TYPE_CPU = 0x4,
DEVICE_TYPE_MAX = 0x5
};
struct Device {
String name = "Unknown";
Vendor vendor = VENDOR_UNKNOWN;
DeviceType type = DEVICE_TYPE_OTHER;
};
virtual ~RenderingContextDriver();
virtual Error initialize() = 0;
virtual const Device &device_get(uint32_t p_device_index) const = 0;
virtual uint32_t device_get_count() const = 0;
virtual bool device_supports_present(uint32_t p_device_index, SurfaceID p_surface) const = 0;
virtual RenderingDeviceDriver *driver_create() = 0;
virtual void driver_free(RenderingDeviceDriver *p_driver) = 0;
virtual SurfaceID surface_create(const void *p_platform_data) = 0;
virtual void surface_set_size(SurfaceID p_surface, uint32_t p_width, uint32_t p_height) = 0;
virtual void surface_set_vsync_mode(SurfaceID p_surface, DisplayServer::VSyncMode p_vsync_mode) = 0;
virtual DisplayServer::VSyncMode surface_get_vsync_mode(SurfaceID p_surface) const = 0;
virtual uint32_t surface_get_width(SurfaceID p_surface) const = 0;
virtual uint32_t surface_get_height(SurfaceID p_surface) const = 0;
virtual void surface_set_needs_resize(SurfaceID p_surface, bool p_needs_resize) = 0;
virtual bool surface_get_needs_resize(SurfaceID p_surface) const = 0;
virtual void surface_destroy(SurfaceID p_surface) = 0;
virtual bool is_debug_utils_enabled() const = 0;
};
#endif // RENDERING_CONTEXT_DRIVER_H

View file

@ -117,6 +117,10 @@ Error RenderingDevice::_texture_resolve_multisample_bind_compat_84976(RID p_from
return texture_resolve_multisample(p_from_texture, p_to_texture);
}
RenderingDevice::FramebufferFormatID RenderingDevice::_screen_get_framebuffer_format_bind_compat_87340() const {
return screen_get_framebuffer_format(DisplayServer::MAIN_WINDOW_ID);
}
void RenderingDevice::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("shader_create_from_bytecode", "binary_data"), &RenderingDevice::_shader_create_from_bytecode_bind_compat_79606);
ClassDB::bind_compatibility_method(D_METHOD("draw_list_end", "post_barrier"), &RenderingDevice::_draw_list_end_bind_compat_81356, DEFVAL(7));
@ -132,6 +136,7 @@ void RenderingDevice::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("texture_copy", "from_texture", "to_texture", "from_pos", "to_pos", "size", "src_mipmap", "dst_mipmap", "src_layer", "dst_layer", "post_barrier"), &RenderingDevice::_texture_copy_bind_compat_84976, DEFVAL(0x7FFF));
ClassDB::bind_compatibility_method(D_METHOD("texture_clear", "texture", "color", "base_mipmap", "mipmap_count", "base_layer", "layer_count", "post_barrier"), &RenderingDevice::_texture_clear_bind_compat_84976, DEFVAL(0x7FFF));
ClassDB::bind_compatibility_method(D_METHOD("texture_resolve_multisample", "from_texture", "to_texture", "post_barrier"), &RenderingDevice::_texture_resolve_multisample_bind_compat_84976, DEFVAL(0x7FFF));
ClassDB::bind_compatibility_method(D_METHOD("screen_get_framebuffer_format"), &RenderingDevice::_screen_get_framebuffer_format_bind_compat_87340);
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -64,36 +64,11 @@ class RenderingDevice : public RenderingDeviceCommons {
_THREAD_SAFE_CLASS_
public:
enum DeviceFamily {
DEVICE_UNKNOWN,
DEVICE_OPENGL,
DEVICE_VULKAN,
DEVICE_DIRECTX,
};
enum ShaderLanguage {
SHADER_LANGUAGE_GLSL,
SHADER_LANGUAGE_HLSL
};
enum SubgroupOperations {
SUBGROUP_BASIC_BIT = 1,
SUBGROUP_VOTE_BIT = 2,
SUBGROUP_ARITHMETIC_BIT = 4,
SUBGROUP_BALLOT_BIT = 8,
SUBGROUP_SHUFFLE_BIT = 16,
SUBGROUP_SHUFFLE_RELATIVE_BIT = 32,
SUBGROUP_CLUSTERED_BIT = 64,
SUBGROUP_QUAD_BIT = 128,
};
struct Capabilities {
// main device info
DeviceFamily device_family = DEVICE_UNKNOWN;
uint32_t version_major = 1;
uint32_t version_minor = 0;
};
typedef int64_t DrawListID;
typedef int64_t ComputeListID;
@ -110,9 +85,9 @@ private:
static RenderingDevice *singleton;
Capabilities device_capabilities;
RenderingDeviceDriver *driver = nullptr; // Owned by the context.
RenderingContextDriver *context = nullptr;
RenderingDeviceDriver *driver = nullptr;
RenderingContextDriver::Device device;
protected:
static void _bind_methods();
@ -188,8 +163,8 @@ private:
enum StagingRequiredAction {
STAGING_REQUIRED_ACTION_NONE,
STAGING_REQUIRED_ACTION_FLUSH_CURRENT,
STAGING_REQUIRED_ACTION_FLUSH_OLDER
STAGING_REQUIRED_ACTION_FLUSH_AND_STALL_ALL,
STAGING_REQUIRED_ACTION_STALL_PREVIOUS
};
Error _staging_buffer_allocate(uint32_t p_amount, uint32_t p_required_align, uint32_t &r_alloc_offset, uint32_t &r_alloc_size, StagingRequiredAction &r_required_action, bool p_can_segment = true);
@ -819,12 +794,11 @@ private:
Error _texture_copy_bind_compat_84976(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, BitField<BarrierMask> p_post_barrier);
Error _texture_clear_bind_compat_84976(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, BitField<BarrierMask> p_post_barrier);
Error _texture_resolve_multisample_bind_compat_84976(RID p_from_texture, RID p_to_texture, BitField<BarrierMask> p_post_barrier);
FramebufferFormatID _screen_get_framebuffer_format_bind_compat_87340() const;
#endif
public:
ApiContextRD *get_context() const { return context; }
const Capabilities *get_device_capabilities() const { return &device_capabilities; };
const RDD::Capabilities &get_device_capabilities() const { return driver->get_capabilities(); }
bool has_feature(const Features p_feature) const;
@ -996,10 +970,10 @@ private:
RID_Owner<RenderPipeline> render_pipeline_owner;
bool pipelines_cache_enabled = false;
size_t pipelines_cache_size = 0;
String pipelines_cache_file_path;
WorkerThreadPool::TaskID pipelines_cache_save_task = WorkerThreadPool::INVALID_TASK_ID;
bool pipeline_cache_enabled = false;
size_t pipeline_cache_size = 0;
String pipeline_cache_file_path;
WorkerThreadPool::TaskID pipeline_cache_save_task = WorkerThreadPool::INVALID_TASK_ID;
Vector<uint8_t> _load_pipeline_cache();
void _update_pipeline_cache(bool p_closing = false);
@ -1024,13 +998,22 @@ public:
RID compute_pipeline_create(RID p_shader, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>());
bool compute_pipeline_is_valid(RID p_pipeline);
private:
/****************/
/**** SCREEN ****/
/****************/
HashMap<DisplayServer::WindowID, RDD::SwapChainID> screen_swap_chains;
HashMap<DisplayServer::WindowID, RDD::FramebufferID> screen_framebuffers;
int screen_get_width(DisplayServer::WindowID p_screen = 0) const;
int screen_get_height(DisplayServer::WindowID p_screen = 0) const;
FramebufferFormatID screen_get_framebuffer_format() const;
uint32_t _get_swap_chain_desired_count() const;
public:
Error screen_create(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID);
Error screen_prepare_for_drawing(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID);
int screen_get_width(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;
int screen_get_height(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;
FramebufferFormatID screen_get_framebuffer_format(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;
Error screen_free(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID);
/*************************/
/**** DRAW LISTS (II) ****/
@ -1101,7 +1084,6 @@ private:
DrawList *draw_list = nullptr;
uint32_t draw_list_subpass_count = 0;
uint32_t draw_list_count = 0;
RDD::RenderPassID draw_list_render_pass;
RDD::FramebufferID draw_list_vkframebuffer;
#ifdef DEBUG_ENABLED
@ -1214,6 +1196,15 @@ private:
RenderingDeviceGraph draw_graph;
/**************************/
/**** QUEUE MANAGEMENT ****/
/**************************/
RDD::CommandQueueFamilyID main_queue_family;
RDD::CommandQueueFamilyID present_queue_family;
RDD::CommandQueueID main_queue;
RDD::CommandQueueID present_queue;
/**************************/
/**** FRAME MANAGEMENT ****/
/**************************/
@ -1232,7 +1223,6 @@ private:
// nature of the GPU. They will get deleted
// when the frame is cycled.
private:
struct Frame {
// List in usage order, from last to free to first to free.
List<Buffer> buffers_to_dispose_of;
@ -1245,13 +1235,30 @@ private:
List<ComputePipeline> compute_pipelines_to_dispose_of;
RDD::CommandPoolID command_pool;
// Used at the beginning of every frame for set-up.
// Used for filling up newly created buffers with data provided on creation.
// Primarily intended to be accessed by worker threads.
// Ideally this cmd buffer should use an async transfer queue.
RDD::CommandBufferID setup_command_buffer; // Used at the beginning of every frame for set-up.
// The main cmd buffer for drawing and compute.
// Ideally this command buffer should use an async transfer queue.
RDD::CommandBufferID setup_command_buffer;
// The main command buffer for drawing and compute.
// Primarily intended to be used by the main thread to do most stuff.
RDD::CommandBufferID draw_command_buffer; // Used at the beginning of every frame for set-up.
RDD::CommandBufferID draw_command_buffer;
// Signaled by the setup submission. Draw must wait on this semaphore.
RDD::SemaphoreID setup_semaphore;
// Signaled by the draw submission. Present must wait on this semaphore.
RDD::SemaphoreID draw_semaphore;
// Signaled by the draw submission. Must wait on this fence before beginning
// command recording for the frame.
RDD::FenceID draw_fence;
bool draw_fence_signaled = false;
// Swap chains prepared for drawing during the frame that must be presented.
LocalVector<RDD::SwapChainID> swap_chains_to_present;
struct Timestamp {
String description;
@ -1272,37 +1279,32 @@ private:
uint32_t max_timestamp_query_elements = 0;
TightLocalVector<Frame> frames; // Frames available, for main device they are cycled (usually 3), for local devices only 1.
int frame = 0; // Current frame.
int frame_count = 0; // Total amount of frames.
int frame = 0;
TightLocalVector<Frame> frames;
uint64_t frames_drawn = 0;
RID local_device;
bool local_device_processing = false;
void _free_pending_resources(int p_frame);
ApiContextRD *context = nullptr;
uint64_t texture_memory = 0;
uint64_t buffer_memory = 0;
void _free_internal(RID p_id);
void _flush(bool p_current_frame);
bool screen_prepared = false;
void _begin_frame();
void _end_frame();
void _execute_frame(bool p_signal_for_present);
void _present_frame();
void _stall_for_previous_frames();
void _flush_and_stall_for_all_frames();
template <class T>
void _free_rids(T &p_owner, const char *p_type);
void _finalize_command_buffers(bool p_postpare);
void _begin_frame();
#ifdef DEV_ENABLED
HashMap<RID, String> resource_names;
#endif
public:
void initialize(ApiContextRD *p_context, bool p_local_device = false);
Error initialize(RenderingContextDriver *p_context, DisplayServer::WindowID p_main_window = DisplayServer::INVALID_WINDOW_ID);
void finalize();
void free(RID p_id);
@ -1324,9 +1326,6 @@ public:
uint64_t limit_get(Limit p_limit) const;
//methods below not exposed, used by RenderingDeviceRD
void prepare_screen_for_drawing();
void swap_buffers();
uint32_t get_frame_delay() const;
@ -1352,6 +1351,7 @@ public:
String get_device_vendor_name() const;
String get_device_name() const;
DeviceType get_device_type() const;
String get_device_api_name() const;
String get_device_api_version() const;
String get_device_pipeline_cache_uuid() const;

View file

@ -820,6 +820,17 @@ public:
SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS,
};
enum SubgroupOperations {
SUBGROUP_BASIC_BIT = 1,
SUBGROUP_VOTE_BIT = 2,
SUBGROUP_ARITHMETIC_BIT = 4,
SUBGROUP_BALLOT_BIT = 8,
SUBGROUP_SHUFFLE_BIT = 16,
SUBGROUP_SHUFFLE_RELATIVE_BIT = 32,
SUBGROUP_CLUSTERED_BIT = 64,
SUBGROUP_QUAD_BIT = 128,
};
////////////////////////////////////////////
// PROTECTED STUFF
// Not exposed by RenderingDevice, but shared

View file

@ -49,12 +49,11 @@
#include "core/object/object.h"
#include "core/variant/type_info.h"
#include "servers/display_server.h"
#include "servers/rendering/rendering_context_driver.h"
#include "servers/rendering/rendering_device_commons.h"
#include <algorithm>
class ApiContextRD;
// This may one day be used in Godot for interoperability between C arrays, Vector and LocalVector.
// (See https://github.com/godotengine/godot-proposals/issues/5144.)
template <class T>
@ -127,20 +126,22 @@ public:
id(p_id) {}
};
#define DEFINE_ID(m_name) \
struct m_name##ID : public ID { \
_ALWAYS_INLINE_ operator bool() const { return id != 0; } \
_ALWAYS_INLINE_ m_name##ID &operator=(m_name##ID p_other) { \
id = p_other.id; \
return *this; \
} \
_ALWAYS_INLINE_ bool operator<(const m_name##ID &p_other) const { return id < p_other.id; } \
_ALWAYS_INLINE_ m_name##ID(const m_name##ID &p_other) : ID(p_other.id) {} \
_ALWAYS_INLINE_ explicit m_name##ID(uint64_t p_int) : ID(p_int) {} \
_ALWAYS_INLINE_ explicit m_name##ID(void *p_ptr) : ID((size_t)p_ptr) {} \
_ALWAYS_INLINE_ m_name##ID() = default; \
}; \
/* Ensure type-punnable to pointer. Makes some things easier.*/ \
#define DEFINE_ID(m_name) \
struct m_name##ID : public ID { \
_ALWAYS_INLINE_ operator bool() const { return id != 0; } \
_ALWAYS_INLINE_ m_name##ID &operator=(m_name##ID p_other) { \
id = p_other.id; \
return *this; \
} \
_ALWAYS_INLINE_ bool operator<(const m_name##ID &p_other) const { return id < p_other.id; } \
_ALWAYS_INLINE_ bool operator==(const m_name##ID &p_other) const { return id == p_other.id; } \
_ALWAYS_INLINE_ bool operator!=(const m_name##ID &p_other) const { return id != p_other.id; } \
_ALWAYS_INLINE_ m_name##ID(const m_name##ID &p_other) : ID(p_other.id) {} \
_ALWAYS_INLINE_ explicit m_name##ID(uint64_t p_int) : ID(p_int) {} \
_ALWAYS_INLINE_ explicit m_name##ID(void *p_ptr) : ID((size_t)p_ptr) {} \
_ALWAYS_INLINE_ m_name##ID() = default; \
}; \
/* Ensure type-punnable to pointer. Makes some things easier.*/ \
static_assert(sizeof(m_name##ID) == sizeof(void *));
// Id types declared before anything else to prevent cyclic dependencies between the different concerns.
@ -148,14 +149,26 @@ public:
DEFINE_ID(Texture);
DEFINE_ID(Sampler);
DEFINE_ID(VertexFormat);
DEFINE_ID(CommandQueue);
DEFINE_ID(CommandQueueFamily);
DEFINE_ID(CommandPool);
DEFINE_ID(CommandBuffer);
DEFINE_ID(SwapChain);
DEFINE_ID(Framebuffer);
DEFINE_ID(Shader);
DEFINE_ID(UniformSet);
DEFINE_ID(Pipeline);
DEFINE_ID(RenderPass);
DEFINE_ID(QueryPool);
DEFINE_ID(Fence);
DEFINE_ID(Semaphore);
public:
/*****************/
/**** GENERIC ****/
/*****************/
virtual Error initialize(uint32_t p_device_index, uint32_t p_frame_count) = 0;
/****************/
/**** MEMORY ****/
@ -361,10 +374,44 @@ public:
VectorView<BufferBarrier> p_buffer_barriers,
VectorView<TextureBarrier> p_texture_barriers) = 0;
/****************/
/**** FENCES ****/
/****************/
virtual FenceID fence_create() = 0;
virtual Error fence_wait(FenceID p_fence) = 0;
virtual void fence_free(FenceID p_fence) = 0;
/********************/
/**** SEMAPHORES ****/
/********************/
virtual SemaphoreID semaphore_create() = 0;
virtual void semaphore_free(SemaphoreID p_semaphore) = 0;
/*************************/
/**** COMMAND BUFFERS ****/
/*************************/
// ----- QUEUE FAMILY -----
enum CommandQueueFamilyBits {
COMMAND_QUEUE_FAMILY_GRAPHICS_BIT = 0x1,
COMMAND_QUEUE_FAMILY_COMPUTE_BIT = 0x2,
COMMAND_QUEUE_FAMILY_TRANSFER_BIT = 0x4
};
// The requested command queue family must support all specified bits or it'll fail to return a valid family otherwise. If a valid surface is specified, the queue must support presenting to it.
// It is valid to specify no bits and a valid surface: in this case, the dedicated presentation queue family will be the preferred option.
virtual CommandQueueFamilyID command_queue_family_get(BitField<CommandQueueFamilyBits> p_cmd_queue_family_bits, RenderingContextDriver::SurfaceID p_surface = 0) = 0;
// ----- QUEUE -----
virtual CommandQueueID command_queue_create(CommandQueueFamilyID p_cmd_queue_family, bool p_identify_as_main_queue = false) = 0;
virtual Error command_queue_execute(CommandQueueID p_cmd_queue, VectorView<CommandBufferID> p_cmd_buffers, VectorView<SemaphoreID> p_wait_semaphores, VectorView<SemaphoreID> p_signal_semaphores, FenceID p_signal_fence) = 0;
virtual Error command_queue_present(CommandQueueID p_cmd_queue, VectorView<SwapChainID> p_swap_chains, VectorView<SemaphoreID> p_wait_semaphores) = 0;
virtual void command_queue_free(CommandQueueID p_cmd_queue) = 0;
// ----- POOL -----
enum CommandBufferType {
@ -372,17 +419,39 @@ public:
COMMAND_BUFFER_TYPE_SECONDARY,
};
virtual CommandPoolID command_pool_create(CommandBufferType p_cmd_buffer_type) = 0;
virtual CommandPoolID command_pool_create(CommandQueueFamilyID p_cmd_queue_family, CommandBufferType p_cmd_buffer_type) = 0;
virtual void command_pool_free(CommandPoolID p_cmd_pool) = 0;
// ----- BUFFER -----
virtual CommandBufferID command_buffer_create(CommandBufferType p_cmd_buffer_type, CommandPoolID p_cmd_pool) = 0;
virtual CommandBufferID command_buffer_create(CommandPoolID p_cmd_pool) = 0;
virtual bool command_buffer_begin(CommandBufferID p_cmd_buffer) = 0;
virtual bool command_buffer_begin_secondary(CommandBufferID p_cmd_buffer, RenderPassID p_render_pass, uint32_t p_subpass, FramebufferID p_framebuffer) = 0;
virtual void command_buffer_end(CommandBufferID p_cmd_buffer) = 0;
virtual void command_buffer_execute_secondary(CommandBufferID p_cmd_buffer, VectorView<CommandBufferID> p_secondary_cmd_buffers) = 0;
/********************/
/**** SWAP CHAIN ****/
/********************/
// The swap chain won't be valid for use until it is resized at least once.
virtual SwapChainID swap_chain_create(RenderingContextDriver::SurfaceID p_surface) = 0;
// The swap chain must not be in use when a resize is requested. Wait until all rendering associated to the swap chain is finished before resizing it.
virtual Error swap_chain_resize(CommandQueueID p_cmd_queue, SwapChainID p_swap_chain, uint32_t p_desired_framebuffer_count) = 0;
// Acquire the framebuffer that can be used for drawing. This must be called only once every time a new frame will be rendered.
virtual FramebufferID swap_chain_acquire_framebuffer(CommandQueueID p_cmd_queue, SwapChainID p_swap_chain, bool &r_resize_required) = 0;
// Retrieve the render pass that can be used to draw on the swap chain's framebuffers.
virtual RenderPassID swap_chain_get_render_pass(SwapChainID p_swap_chain) = 0;
// Retrieve the format used by the swap chain's framebuffers.
virtual DataFormat swap_chain_get_format(SwapChainID p_swap_chain) = 0;
// Wait until all rendering associated to the swap chain is finished before deleting it.
virtual void swap_chain_free(SwapChainID p_swap_chain) = 0;
/*********************/
/**** FRAMEBUFFER ****/
/*********************/
@ -633,17 +702,11 @@ public:
virtual void command_begin_label(CommandBufferID p_cmd_buffer, const char *p_label_name, const Color &p_color) = 0;
virtual void command_end_label(CommandBufferID p_cmd_buffer) = 0;
/****************/
/**** SCREEN ****/
/****************/
virtual DataFormat screen_get_format() = 0;
/********************/
/**** SUBMISSION ****/
/********************/
virtual void begin_segment(CommandBufferID p_cmd_buffer, uint32_t p_frame_index, uint32_t p_frames_drawn) = 0;
virtual void begin_segment(uint32_t p_frame_index, uint32_t p_frames_drawn) = 0;
virtual void end_segment() = 0;
/**************/
@ -682,6 +745,19 @@ public:
SHADER_CHANGE_INVALIDATION_ALL_OR_NONE_ACCORDING_TO_LAYOUT_HASH,
};
enum DeviceFamily {
DEVICE_UNKNOWN,
DEVICE_OPENGL,
DEVICE_VULKAN,
DEVICE_DIRECTX,
};
struct Capabilities {
DeviceFamily device_family = DEVICE_UNKNOWN;
uint32_t version_major = 1;
uint32_t version_minor = 0;
};
virtual void set_object_name(ObjectType p_type, ID p_driver_id, const String &p_name) = 0;
virtual uint64_t get_resource_native_handle(DriverResource p_type, ID p_driver_id) = 0;
virtual uint64_t get_total_memory_used() = 0;
@ -689,6 +765,10 @@ public:
virtual uint64_t api_trait_get(ApiTrait p_trait);
virtual bool has_feature(Features p_feature) = 0;
virtual const MultiviewCapabilities &get_multiview_capabilities() = 0;
virtual String get_api_name() const = 0;
virtual String get_api_version() const = 0;
virtual String get_pipeline_cache_uuid() const = 0;
virtual const Capabilities &get_capabilities() const = 0;
/******************/

View file

@ -40,15 +40,6 @@ RenderingDeviceGraph::RenderingDeviceGraph() {
}
RenderingDeviceGraph::~RenderingDeviceGraph() {
_wait_for_secondary_command_buffer_tasks();
for (Frame &f : frames) {
for (SecondaryCommandBuffer &secondary : f.secondary_command_buffers) {
if (secondary.command_pool.id != 0) {
driver->command_pool_free(secondary.command_pool);
}
}
}
}
bool RenderingDeviceGraph::_is_write_usage(ResourceUsage p_usage) {
@ -1246,7 +1237,7 @@ void RenderingDeviceGraph::_print_compute_list(const uint8_t *p_instruction_data
}
}
void RenderingDeviceGraph::initialize(RDD *p_driver, uint32_t p_frame_count, uint32_t p_secondary_command_buffers_per_frame) {
void RenderingDeviceGraph::initialize(RDD *p_driver, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame) {
driver = p_driver;
frames.resize(p_frame_count);
@ -1255,8 +1246,8 @@ void RenderingDeviceGraph::initialize(RDD *p_driver, uint32_t p_frame_count, uin
for (uint32_t j = 0; j < p_secondary_command_buffers_per_frame; j++) {
SecondaryCommandBuffer &secondary = frames[i].secondary_command_buffers[j];
secondary.command_pool = driver->command_pool_create(RDD::COMMAND_BUFFER_TYPE_SECONDARY);
secondary.command_buffer = driver->command_buffer_create(RDD::COMMAND_BUFFER_TYPE_SECONDARY, secondary.command_pool);
secondary.command_pool = driver->command_pool_create(p_secondary_command_queue_family, RDD::COMMAND_BUFFER_TYPE_SECONDARY);
secondary.command_buffer = driver->command_buffer_create(secondary.command_pool);
secondary.task = WorkerThreadPool::INVALID_TASK_ID;
}
}
@ -1264,6 +1255,20 @@ void RenderingDeviceGraph::initialize(RDD *p_driver, uint32_t p_frame_count, uin
driver_honors_barriers = driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS);
}
void RenderingDeviceGraph::finalize() {
_wait_for_secondary_command_buffer_tasks();
for (Frame &f : frames) {
for (SecondaryCommandBuffer &secondary : f.secondary_command_buffers) {
if (secondary.command_pool.id != 0) {
driver->command_pool_free(secondary.command_pool);
}
}
}
frames.clear();
}
void RenderingDeviceGraph::begin() {
command_data.clear();
command_data_offsets.clear();

View file

@ -619,7 +619,8 @@ private:
public:
RenderingDeviceGraph();
~RenderingDeviceGraph();
void initialize(RDD *p_driver, uint32_t p_frame_count, uint32_t p_secondary_command_buffers_per_frame);
void initialize(RDD *p_driver, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame);
void finalize();
void begin();
void add_buffer_clear(RDD::BufferID p_dst, ResourceTracker *p_dst_tracker, uint32_t p_offset, uint32_t p_size);
void add_buffer_copy(RDD::BufferID p_src, ResourceTracker *p_src_tracker, RDD::BufferID p_dst, ResourceTracker *p_dst_tracker, RDD::BufferCopyRegion p_region);