// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Platform/Platform.h"
#include "Engine/Platform/CriticalSection.h"
#include "Engine/Core/NonCopyable.h"
#include "Engine/Core/Collections/Array.h"
#include "Engine/Scripting/ScriptingObject.h"
#include "GPUAdapter.h"
#include "GPULimits.h"
#include "Enums.h"
#include "Config.h"
class ITextureOwner;
class RenderTask;
class GPUResource;
class GPUContext;
class GPUShader;
class GPUTimerQuery;
class GPUTexture;
class GPUBuffer;
class GPUSampler;
class GPUPipelineState;
class GPUConstantBuffer;
class GPUVertexLayout;
class GPUTasksContext;
class GPUTasksExecutor;
class GPUSwapChain;
class GPUTasksManager;
class Shader;
class Model;
class Material;
class MaterialBase;
///
/// Graphics device object for rendering on GPU.
///
API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API GPUDevice : public ScriptingObject
{
DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUDevice);
public:
///
/// Graphics Device states that describe its lifetime.
///
enum class DeviceState
{
Missing = 0,
Created,
Ready,
Removed,
Disposing,
Disposed
};
///
/// Describes a video output display mode.
///
API_STRUCT() struct VideoOutputMode
{
DECLARE_SCRIPTING_TYPE_NO_SPAWN(VideoOutputMode);
///
/// The resolution width (in pixel).
///
API_FIELD() uint32 Width;
///
/// The resolution height (in pixel).
///
API_FIELD() uint32 Height;
///
/// The screen refresh rate (in hertz).
///
API_FIELD() uint32 RefreshRate;
};
///
/// The singleton instance of the graphics device.
///
API_FIELD(ReadOnly) static GPUDevice* Instance;
protected:
// State
DeviceState _state;
bool _isRendering;
bool _wasVSyncUsed;
int32 _drawGpuEventIndex;
RendererType _rendererType;
ShaderProfile _shaderProfile;
FeatureLevel _featureLevel;
// Private resources (hidden with declaration)
struct PrivateData;
PrivateData* _res;
Array _resources;
CriticalSection _resourcesLock;
void OnRequestingExit();
protected:
///
/// Initializes a new instance of the class.
///
/// The renderer type.
/// The shader profile.
GPUDevice(RendererType type, ShaderProfile profile);
public:
///
/// Finalizes an instance of the class.
///
virtual ~GPUDevice();
public:
///
/// The graphics device locking mutex.
///
CriticalSection Locker;
///
/// The total amount of graphics memory in bytes.
///
API_FIELD(ReadOnly) uint64 TotalGraphicsMemory;
///
/// Indicates that debug tool is profiling device (eg. RenderDoc).
///
API_FIELD(ReadOnly) bool IsDebugToolAttached;
///
/// The GPU limits.
///
API_FIELD(ReadOnly) GPULimits Limits;
///
/// The available video output modes.
///
API_FIELD(ReadOnly) Array VideoOutputModes;
///
/// Quad rendering shader
///
API_FIELD(ReadOnly) GPUShader* QuadShader;
///
/// The current task being executed.
///
RenderTask* CurrentTask;
///
/// The supported features for the specified format (index is the pixel format value).
///
FormatFeatures FeaturesPerFormat[static_cast(PixelFormat::MAX)];
///
/// Gets the supported features for the specified format (index is the pixel format value).
///
/// The format.
/// The format features flags.
API_FUNCTION() FormatFeatures GetFormatFeatures(const PixelFormat format) const
{
return FeaturesPerFormat[(int32)format];
}
public:
///
/// Gets current device state.
///
FORCE_INLINE DeviceState GetState() const
{
return _state;
}
///
/// Returns true if device is during rendering state, otherwise false.
///
API_PROPERTY() FORCE_INLINE bool IsRendering() const
{
return _isRendering;
}
///
/// Returns true if VSync was used during the last frame present.
///
FORCE_INLINE bool WasVSyncUsed() const
{
return _wasVSyncUsed;
}
///
/// Gets the device renderer type.
///
API_PROPERTY() FORCE_INLINE RendererType GetRendererType() const
{
return _rendererType;
}
///
/// Gets device shader profile type.
///
API_PROPERTY() FORCE_INLINE ShaderProfile GetShaderProfile() const
{
return _shaderProfile;
}
///
/// Gets device feature level type.
///
API_PROPERTY() FORCE_INLINE FeatureLevel GetFeatureLevel() const
{
return _featureLevel;
}
///
/// Gets the main GPU context.
///
API_PROPERTY() virtual GPUContext* GetMainContext() = 0;
///
/// Gets the adapter device.
///
API_PROPERTY() virtual GPUAdapter* GetAdapter() const = 0;
///
/// Gets the native pointer to the underlying graphics device. It's a low-level platform-specific handle.
///
API_PROPERTY() virtual void* GetNativePtr() const = 0;
///
/// Gets the amount of memory usage by all the GPU resources (in bytes).
///
API_PROPERTY() uint64 GetMemoryUsage() const;
///
/// Gets the list with all active GPU resources.
///
API_PROPERTY() Array GetResources() const;
///
/// Gets the GPU asynchronous work manager.
///
GPUTasksManager* GetTasksManager() const;
///
/// Gets the default material.
///
API_PROPERTY() MaterialBase* GetDefaultMaterial() const;
///
/// Gets the default material (Deformable domain).
///
MaterialBase* GetDefaultDeformableMaterial() const;
///
/// Gets the default normal map texture.
///
GPUTexture* GetDefaultNormalMap() const;
///
/// Gets the default solid white texture.
///
API_PROPERTY() GPUTexture* GetDefaultWhiteTexture() const;
///
/// Gets the default solid black texture.
///
API_PROPERTY() GPUTexture* GetDefaultBlackTexture() const;
///
/// Gets the shader pipeline state object for linear, fullscreen texture copy.
///
GPUPipelineState* GetCopyLinearPS() const;
///
/// Gets the shader pipeline state object for solid-color texture clear.
///
GPUPipelineState* GetClearPS() const;
///
/// Gets the shader pipeline state object for YUY2 frame decoding to RGBA.
///
GPUPipelineState* GetDecodeYUY2PS() const;
///
/// Gets the shader pipeline state object for NV12 frame decoding to RGBA.
///
GPUPipelineState* GetDecodeNV12PS() const;
///
/// Gets the fullscreen-triangle vertex buffer.
///
GPUBuffer* GetFullscreenTriangleVB() const;
public:
///
/// Init device resources
///
/// True if cannot init, otherwise false.
virtual bool Init();
///
/// Load private device content (called when Content Pool is created)
///
/// True if cannot load data in a proper way, otherwise false.
virtual bool LoadContent();
///
/// Checks if GPU can render frame now (all data is ready), otherwise will skip frame rendering.
///
/// True if skip rendering, otherwise false.
virtual bool CanDraw();
///
/// Call frame rendering and process data using GPU
///
virtual void Draw();
///
/// Clean all allocated data by device
///
virtual void Dispose();
///
/// Wait for GPU end doing submitted work
///
virtual void WaitForGPU() = 0;
public:
void AddResource(GPUResource* resource);
void RemoveResource(GPUResource* resource);
///
/// Dumps all GPU resources information to the log.
///
void DumpResourcesToLog() const;
protected:
virtual void preDispose();
///
/// Called during Draw method before any frame rendering initialization. Cannot be used to submit commands to GPU.
///
virtual void DrawBegin();
///
/// Called during Draw method after rendering. Cannot be used to submit commands to GPU.
///
virtual void DrawEnd();
///
/// Called during Draw method after rendering begin. Can be used to submit commands to the GPU after opening GPU command list.
///
virtual void RenderBegin();
///
/// Called during Draw method before rendering end. Can be used to submit commands to the GPU before closing GPU command list.
///
virtual void RenderEnd();
public:
///
/// Creates the texture.
///
/// The resource name.
/// The texture.
API_FUNCTION() virtual GPUTexture* CreateTexture(const StringView& name = StringView::Empty) = 0;
///
/// Creates the shader.
///
/// The resource name.
/// The shader.
virtual GPUShader* CreateShader(const StringView& name = StringView::Empty) = 0;
///
/// Creates the GPU pipeline state object.
///
/// The pipeline state.
virtual GPUPipelineState* CreatePipelineState() = 0;
///
/// Creates the timer query object.
///
/// The timer query.
virtual GPUTimerQuery* CreateTimerQuery() = 0;
///
/// Creates the buffer.
///
/// The resource name.
/// The buffer.
API_FUNCTION() virtual GPUBuffer* CreateBuffer(const StringView& name = StringView::Empty) = 0;
///
/// Creates the texture sampler.
///
/// The sampler.
API_FUNCTION() virtual GPUSampler* CreateSampler() = 0;
///
/// Creates the vertex buffer layout.
///
/// The vertex buffer layout.
API_FUNCTION() virtual GPUVertexLayout* CreateVertexLayout(const Array>& elements, bool explicitOffsets = false) = 0;
typedef Array> VertexElements;
///
/// Creates the native window swap chain.
///
/// The output window.
/// The native window swap chain.
virtual GPUSwapChain* CreateSwapChain(Window* window) = 0;
///
/// Creates the constant buffer.
///
/// The resource name.
/// The buffer size (in bytes).
/// The constant buffer.
virtual GPUConstantBuffer* CreateConstantBuffer(uint32 size, const StringView& name = StringView::Empty) = 0;
///
/// Creates the GPU tasks context.
///
/// The GPU tasks context.
virtual GPUTasksContext* CreateTasksContext();
///
/// Creates the GPU tasks executor.
///
/// The GPU tasks executor.
virtual GPUTasksExecutor* CreateTasksExecutor();
};
///
/// Utility structure to safety graphics device locking.
///
struct FLAXENGINE_API GPUDeviceLock : NonCopyable
{
const GPUDevice* Device;
GPUDeviceLock(const GPUDevice* device)
: Device(device)
{
Device->Locker.Lock();
}
~GPUDeviceLock()
{
Device->Locker.Unlock();
}
};