# Conflicts: # Content/Shaders/GI/DDGI.flax # Content/Shaders/GI/GlobalSurfaceAtlas.flax # Content/Shaders/TAA.flax # Content/Shaders/VolumetricFog.flax # Source/Editor/CustomEditors/Editors/ActorTagEditor.cs # Source/Engine/Core/Config/GraphicsSettings.cpp # Source/Engine/Engine/PostProcessEffect.cs # Source/Engine/Graphics/GPUResourcesCollection.cpp # Source/Engine/Graphics/GPUResourcesCollection.h # Source/Engine/Graphics/PostProcessBase.h # Source/FlaxEngine.Gen.cs
238 lines
6.3 KiB
C++
238 lines
6.3 KiB
C++
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "GPUDeviceDX12.h"
|
|
#include "ResourceOwnerDX12.h"
|
|
|
|
#if GRAPHICS_API_DIRECTX12
|
|
|
|
#define DX12_DEFAULT_UPLOAD_PAGE_SIZE (4 * 1014 * 1024) // 4 MB
|
|
|
|
// Upload buffer generations timeout to dispose
|
|
#define DX12_UPLOAD_PAGE_GEN_TIMEOUT DX12_BACK_BUFFER_COUNT
|
|
|
|
// Upload buffer pages that are not used for a few frames are disposed
|
|
#define DX12_UPLOAD_PAGE_NOT_USED_FRAME_TIMEOUT 60
|
|
|
|
class GPUTextureDX12;
|
|
|
|
/// <summary>
|
|
/// Single page for the upload buffer
|
|
/// </summary>
|
|
class UploadBufferPageDX12 : public GPUResourceDX12<GPUResource>, public ResourceOwnerDX12
|
|
{
|
|
public:
|
|
|
|
/// <summary>
|
|
/// Init
|
|
/// </summary>
|
|
/// <param name="device">Graphics Device</param>
|
|
/// <param name="size">Page size</param>
|
|
UploadBufferPageDX12(GPUDeviceDX12* device, uint64 size);
|
|
|
|
public:
|
|
|
|
/// <summary>
|
|
/// Last generation that has been using that page
|
|
/// </summary>
|
|
uint64 LastGen;
|
|
|
|
/// <summary>
|
|
/// CPU memory address of the page
|
|
/// </summary>
|
|
void* CPUAddress;
|
|
|
|
/// <summary>
|
|
/// GPU memory address of the page
|
|
/// </summary>
|
|
D3D12_GPU_VIRTUAL_ADDRESS GPUAddress;
|
|
|
|
/// <summary>
|
|
/// Page size in bytes
|
|
/// </summary>
|
|
uint64 Size;
|
|
|
|
public:
|
|
|
|
// [GPUResourceDX12]
|
|
GPUResourceType GetResourceType() const final override
|
|
{
|
|
return GPUResourceType::Buffer;
|
|
}
|
|
|
|
// [ResourceOwnerDX12]
|
|
GPUResource* AsGPUResource() const override
|
|
{
|
|
return (GPUResource*)this;
|
|
}
|
|
|
|
protected:
|
|
|
|
// [GPUResourceDX12]
|
|
void OnReleaseGPU() final override;
|
|
};
|
|
|
|
/// <summary>
|
|
/// Upload buffer allocation
|
|
/// </summary>
|
|
struct DynamicAllocation
|
|
{
|
|
/// <summary>
|
|
/// CPU memory address of the allocation start.
|
|
/// </summary>
|
|
void* CPUAddress;
|
|
|
|
/// <summary>
|
|
/// Allocation offset in bytes (from the start of the heap buffer).
|
|
/// </summary>
|
|
uint64 Offset;
|
|
|
|
/// <summary>
|
|
/// Allocation size in bytes
|
|
/// </summary>
|
|
uint64 Size;
|
|
|
|
/// <summary>
|
|
/// GPU virtual memory address of the allocation start.
|
|
/// </summary>
|
|
D3D12_GPU_VIRTUAL_ADDRESS GPUAddress;
|
|
|
|
/// <summary>
|
|
/// Upload buffer page that owns that allocation
|
|
/// </summary>
|
|
UploadBufferPageDX12* Page;
|
|
|
|
/// <summary>
|
|
/// Generation number of that allocation (generally allocation is invalid after one or two generations)
|
|
/// </summary>
|
|
uint64 Generation;
|
|
|
|
/// <summary>
|
|
/// Init
|
|
/// </summary>
|
|
DynamicAllocation()
|
|
: CPUAddress(nullptr)
|
|
, Offset(0)
|
|
, Size(0)
|
|
, GPUAddress(0)
|
|
, Page(nullptr)
|
|
, Generation(0)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Init
|
|
/// </summary>
|
|
/// <param name="address">CPU memory address</param>
|
|
/// <param name="offset">Offset in byes</param>
|
|
/// <param name="size">Size in byes</param>
|
|
/// <param name="gpuAddress">GPU memory address</param>
|
|
/// <param name="page">Parent page</param>
|
|
/// <param name="generation">Generation</param>
|
|
DynamicAllocation(void* address, uint64 offset, uint64 size, D3D12_GPU_VIRTUAL_ADDRESS gpuAddress, UploadBufferPageDX12* page, uint64 generation)
|
|
: CPUAddress(address)
|
|
, Offset(offset)
|
|
, Size(size)
|
|
, GPUAddress(gpuAddress)
|
|
, Page(page)
|
|
, Generation(generation)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if allocation is invalid.
|
|
/// </summary>
|
|
bool IsInvalid() const
|
|
{
|
|
return CPUAddress == nullptr || Size == 0 || Page == nullptr;
|
|
}
|
|
};
|
|
|
|
/// <summary>
|
|
/// Uploading data to GPU buffer utility
|
|
/// </summary>
|
|
class UploadBufferDX12
|
|
{
|
|
private:
|
|
|
|
GPUDeviceDX12* _device;
|
|
UploadBufferPageDX12* _currentPage;
|
|
uint64 _currentOffset;
|
|
uint64 _currentGeneration;
|
|
|
|
Array<UploadBufferPageDX12*, InlinedAllocation<64>> _freePages;
|
|
Array<UploadBufferPageDX12*, InlinedAllocation<64>> _usedPages;
|
|
|
|
public:
|
|
|
|
/// <summary>
|
|
/// Init
|
|
/// </summary>
|
|
/// <param name="device">Graphics Device</param>
|
|
UploadBufferDX12(GPUDeviceDX12* device);
|
|
|
|
/// <summary>
|
|
/// Destructor
|
|
/// </summary>
|
|
~UploadBufferDX12();
|
|
|
|
public:
|
|
|
|
/// <summary>
|
|
/// Gets the current generation number.
|
|
/// </summary>
|
|
FORCE_INLINE uint64 GetCurrentGeneration() const
|
|
{
|
|
return _currentGeneration;
|
|
}
|
|
|
|
public:
|
|
|
|
/// <summary>
|
|
/// Allocates memory for custom data in the buffer.
|
|
/// </summary>
|
|
/// <param name="size">Size of the data in bytes</param>
|
|
/// <param name="align">Data alignment in buffer in bytes</param>
|
|
/// <returns>Dynamic location</returns>
|
|
DynamicAllocation Allocate(uint64 size, uint64 align);
|
|
|
|
/// <summary>
|
|
/// Uploads data to the buffer.
|
|
/// </summary>
|
|
/// <param name="context">GPU context to record upload command to it</param>
|
|
/// <param name="buffer">Destination buffer</param>
|
|
/// <param name="bufferOffset">Destination buffer offset in bytes.</param>
|
|
/// <param name="data">Data to allocate</param>
|
|
/// <param name="size">Size of the data in bytes</param>
|
|
/// <returns>True if cannot upload data, otherwise false.</returns>
|
|
bool UploadBuffer(GPUContextDX12* context, ID3D12Resource* buffer, uint32 bufferOffset, const void* data, uint64 size);
|
|
|
|
/// <summary>
|
|
/// Uploads data to the texture.
|
|
/// </summary>
|
|
/// <param name="context">GPU context to record upload command to it</param>
|
|
/// <param name="texture">Destination texture</param>
|
|
/// <param name="srcData">Data to allocate</param>
|
|
/// <param name="srcRowPitch">Source data row pitch value to upload.</param>
|
|
/// <param name="srcSlicePitch">Source data slice pitch value to upload.</param>
|
|
/// <param name="mipIndex">Mip map to stream index</param>
|
|
/// <param name="arrayIndex">Texture array index</param>
|
|
/// <returns>True if cannot upload data, otherwise false.</returns>
|
|
bool UploadTexture(GPUContextDX12* context, ID3D12Resource* texture, const void* srcData, uint32 srcRowPitch, uint32 srcSlicePitch, int32 mipIndex, int32 arrayIndex);
|
|
|
|
public:
|
|
|
|
/// <summary>
|
|
/// Begins new generation.
|
|
/// </summary>
|
|
/// <param name="generation">The generation ID to begin.</param>
|
|
void BeginGeneration(uint64 generation);
|
|
|
|
private:
|
|
|
|
UploadBufferPageDX12* requestPage(uint64 size);
|
|
};
|
|
|
|
#endif
|