// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #pragma once #include "GPUBufferDescription.h" #include "GPUResource.h" class Task; template class DataContainer; typedef DataContainer BytesContainer; /// /// Defines a view for the . Used to bind buffer to the shaders (for input as shader resource or for input/output as unordered access). /// API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API GPUBufferView : public GPUResourceView { DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUBufferView); protected: GPUBufferView() : GPUResourceView(SpawnParams(Guid::New(), TypeInitializer)) { } }; /// /// All-in-one GPU buffer class. This class is able to create index buffers, vertex buffers, structured buffer and argument buffers. /// /// 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; /// /// Initializes a new instance of the class. /// GPUBuffer() { // Buffer with size 0 is considered to be invalid _desc.Size = 0; } public: /// /// Finalizes an instance of the class. /// virtual ~GPUBuffer() { } public: /// /// Gets a value indicating whether this buffer has been allocated. /// API_PROPERTY() FORCE_INLINE bool IsAllocated() const { return _desc.Size > 0; } /// /// Gets buffer size in bytes. /// API_PROPERTY() FORCE_INLINE uint32 GetSize() const { return _desc.Size; } /// /// Gets buffer stride in bytes. /// API_PROPERTY() FORCE_INLINE uint32 GetStride() const { return _desc.Stride; } /// /// Gets buffer data format (if used). /// API_PROPERTY() FORCE_INLINE PixelFormat GetFormat() const { return _desc.Format; } /// /// Gets buffer elements count (size divided by the stride). /// API_PROPERTY() FORCE_INLINE uint32 GetElementsCount() const { ASSERT(_desc.Stride > 0); return _desc.Size / _desc.Stride; } /// /// Gets buffer flags. /// FORCE_INLINE GPUBufferFlags GetFlags() const { return _desc.Flags; } /// /// Checks if buffer is a staging buffer (supports CPU readback). /// API_PROPERTY() FORCE_INLINE bool IsStaging() const { return _desc.Usage == GPUResourceUsage::StagingReadback || _desc.Usage == GPUResourceUsage::StagingUpload; } /// /// Checks if buffer is a staging buffer (supports CPU readback). /// API_PROPERTY() FORCE_INLINE bool IsDynamic() const { return _desc.Usage == GPUResourceUsage::Dynamic; } /// /// Gets a value indicating whether this buffer is a shader resource. /// API_PROPERTY() FORCE_INLINE bool IsShaderResource() const { return _desc.IsShaderResource(); } /// /// Gets a value indicating whether this buffer is a unordered access. /// API_PROPERTY() FORCE_INLINE bool IsUnorderedAccess() const { return _desc.IsUnorderedAccess(); } /// /// Gets buffer description structure. /// API_PROPERTY() const GPUBufferDescription& GetDescription() const { return _desc; } /// /// Gets the view for the whole buffer. /// API_FUNCTION() virtual GPUBufferView* View() const = 0; public: /// /// Creates new buffer. /// /// The buffer description. /// True if cannot create buffer, otherwise false. API_FUNCTION() bool Init(API_PARAM(Ref) const GPUBufferDescription& desc); /// /// 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). /// /// Staging readback buffer. GPUBuffer* ToStagingReadback() const; /// /// 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). /// /// Staging upload buffer. GPUBuffer* ToStagingUpload() const; /// /// Tries to resize the buffer (warning: contents will be lost). /// /// The new size (in bytes). /// True if cannot resize buffer, otherwise false. API_FUNCTION() bool Resize(uint32 newSize); public: /// /// 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. /// /// The result data. /// True if cannot download data, otherwise false. API_FUNCTION() bool DownloadData(API_PARAM(Out) BytesContainer& result); /// /// Creates GPU async task that will gather buffer data from the GPU. /// /// The result data. /// Download data task (not started yet). Task* DownloadDataAsync(BytesContainer& result); /// /// 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). /// /// The output data container. /// True if failed, otherwise false. API_FUNCTION() bool GetData(API_PARAM(Out) BytesContainer& output); /// /// Sets the buffer data via map/memcpy/unmap sequence. Always supported for dynamic buffers (other types support depends on graphics backend implementation). /// /// The source data to upload. /// The size of data (in bytes). API_FUNCTION() void SetData(const void* data, uint32 size); /// /// Gets a CPU pointer to the resource by mapping its contents. Denies the GPU access to that resource. /// /// The map operation mode. /// The pointer ot the mapped CPU buffer with resource data or null if failed. API_FUNCTION() virtual void* Map(GPUResourceMapMode mode) = 0; /// /// Invalidates the mapped pointer to a resource and restores the GPU's access to that resource. /// API_FUNCTION() virtual void Unmap() = 0; protected: virtual bool OnInit() = 0; public: // [GPUResource] String ToString() const override; ResourceType GetResourceType() const final override; ObjectType GetObjectType() const final override; protected: // [GPUResource] void OnReleaseGPU() override; };