Files
FlaxEngine/Source/Engine/Graphics/GPUBuffer.h

222 lines
7.2 KiB
C++

// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
#pragma once
#include "GPUBufferDescription.h"
#include "GPUResource.h"
class Task;
template<typename T>
class DataContainer;
typedef DataContainer<byte> BytesContainer;
/// <summary>
/// Defines a view for the <see cref="GPUBuffer"/>. Used to bind buffer to the shaders (for input as shader resource or for input/output as unordered access).
/// </summary>
API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API GPUBufferView : public GPUResourceView
{
DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUBufferView);
protected:
GPUBufferView();
};
/// <summary>
/// All-in-one GPU buffer class. This class is able to create index buffers, vertex buffers, structured buffer and argument buffers.
/// </summary>
/// <seealso cref="GPUResource" />
API_CLASS(Sealed) class FLAXENGINE_API GPUBuffer : public GPUResource
{
DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUBuffer);
static GPUBuffer* Spawn(const SpawnParams& params);
static GPUBuffer* New();
protected:
GPUBufferDescription _desc;
bool _isLocked = false;
GPUBuffer();
public:
/// <summary>
/// Gets a value indicating whether this buffer has been allocated.
/// </summary>
API_PROPERTY() FORCE_INLINE bool IsAllocated() const
{
return _desc.Size > 0;
}
/// <summary>
/// Gets buffer size in bytes.
/// </summary>
API_PROPERTY() FORCE_INLINE uint32 GetSize() const
{
return _desc.Size;
}
/// <summary>
/// Gets buffer stride in bytes.
/// </summary>
API_PROPERTY() FORCE_INLINE uint32 GetStride() const
{
return _desc.Stride;
}
/// <summary>
/// Gets buffer data format (if used).
/// </summary>
API_PROPERTY() FORCE_INLINE PixelFormat GetFormat() const
{
return _desc.Format;
}
/// <summary>
/// Gets buffer elements count (size divided by the stride).
/// </summary>
API_PROPERTY() FORCE_INLINE uint32 GetElementsCount() const
{
return _desc.Stride > 0 ? _desc.Size / _desc.Stride : 0;
}
/// <summary>
/// Gets buffer flags.
/// </summary>
FORCE_INLINE GPUBufferFlags GetFlags() const
{
return _desc.Flags;
}
/// <summary>
/// Gets vertex elements layout used by vertex buffers only.
/// </summary>
API_PROPERTY() FORCE_INLINE GPUVertexLayout* GetVertexLayout() const
{
return _desc.VertexLayout;
}
/// <summary>
/// Checks if buffer is a staging buffer (supports CPU readback).
/// </summary>
API_PROPERTY() FORCE_INLINE bool IsStaging() const
{
return _desc.Usage == GPUResourceUsage::StagingReadback || _desc.Usage == GPUResourceUsage::StagingUpload;
}
/// <summary>
/// Checks if buffer is a staging buffer (supports CPU readback).
/// </summary>
API_PROPERTY() FORCE_INLINE bool IsDynamic() const
{
return _desc.Usage == GPUResourceUsage::Dynamic;
}
/// <summary>
/// Gets a value indicating whether this buffer is a shader resource.
/// </summary>
API_PROPERTY() FORCE_INLINE bool IsShaderResource() const
{
return _desc.IsShaderResource();
}
/// <summary>
/// Gets a value indicating whether this buffer is a unordered access.
/// </summary>
API_PROPERTY() FORCE_INLINE bool IsUnorderedAccess() const
{
return _desc.IsUnorderedAccess();
}
/// <summary>
/// Gets buffer description structure.
/// </summary>
API_PROPERTY() const GPUBufferDescription& GetDescription() const
{
return _desc;
}
/// <summary>
/// Gets the view for the whole buffer.
/// </summary>
API_FUNCTION() virtual GPUBufferView* View() const = 0;
public:
/// <summary>
/// Creates new buffer.
/// </summary>
/// <param name="desc">The buffer description.</param>
/// <returns>True if cannot create buffer, otherwise false.</returns>
API_FUNCTION() bool Init(API_PARAM(Ref) const GPUBufferDescription& desc);
/// <summary>
/// Creates new staging readback buffer with the same dimensions and properties as a source buffer (but without a data transferred; warning: caller must delete object).
/// </summary>
/// <returns>Staging readback buffer.</returns>
GPUBuffer* ToStagingReadback() const;
/// <summary>
/// Creates new staging upload buffer with the same dimensions and properties as a source buffer (but without a data transferred; warning: caller must delete object).
/// </summary>
/// <returns>Staging upload buffer.</returns>
GPUBuffer* ToStagingUpload() const;
/// <summary>
/// Tries to resize the buffer (warning: contents will be lost).
/// </summary>
/// <param name="newSize">The new size (in bytes).</param>
/// <returns>True if cannot resize buffer, otherwise false.</returns>
API_FUNCTION() bool Resize(uint32 newSize);
public:
/// <summary>
/// Stops current thread execution to gather buffer data from the GPU. Cannot be called from main thread if the buffer is not a dynamic nor staging readback.
/// </summary>
/// <param name="result">The result data.</param>
/// <returns>True if cannot download data, otherwise false.</returns>
API_FUNCTION() bool DownloadData(API_PARAM(Out) BytesContainer& result);
/// <summary>
/// Creates GPU async task that will gather buffer data from the GPU.
/// </summary>
/// <param name="result">The result data.</param>
/// <returns>Download data task (not started yet).</returns>
Task* DownloadDataAsync(BytesContainer& result);
/// <summary>
/// Gets the buffer data via map/memcpy/unmap sequence. Always supported for dynamic and staging readback buffers (other types support depends on graphics backend implementation).
/// </summary>
/// <param name="output">The output data container.</param>
/// <returns>True if failed, otherwise false.</returns>
API_FUNCTION() bool GetData(API_PARAM(Out) BytesContainer& output);
/// <summary>
/// Sets the buffer data via map/memcpy/unmap sequence. Always supported for dynamic buffers (other types support depends on graphics backend implementation).
/// </summary>
/// <param name="data">The source data to upload.</param>
/// <param name="size">The size of data (in bytes).</param>
API_FUNCTION() void SetData(const void* data, uint32 size);
/// <summary>
/// Gets a CPU pointer to the resource by mapping its contents. Denies the GPU access to that resource.
/// </summary>
/// <remarks>Always call Unmap if the returned pointer is valid to release resources.</remarks>
/// <param name="mode">The map operation mode.</param>
/// <returns>The pointer of the mapped CPU buffer with resource data or null if failed.</returns>
API_FUNCTION() virtual void* Map(GPUResourceMapMode mode) = 0;
/// <summary>
/// Invalidates the mapped pointer to a resource and restores the GPU's access to that resource.
/// </summary>
API_FUNCTION() virtual void Unmap() = 0;
protected:
virtual bool OnInit() = 0;
public:
// [GPUResource]
String ToString() const override;
GPUResourceType GetResourceType() const final override;
protected:
// [GPUResource]
void OnReleaseGPU() override;
};