2024-11-01 16:55:46 +08:00
|
|
|
#include "RenderAPI.h"
|
|
|
|
|
#include "PlatformBase.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Direct3D 12 implementation of RenderAPI.
|
|
|
|
|
|
|
|
|
|
#if SUPPORT_D3D12
|
|
|
|
|
|
2024-11-22 12:09:31 +08:00
|
|
|
#include <cmath>
|
|
|
|
|
|
2024-11-01 16:55:46 +08:00
|
|
|
#include <assert.h>
|
|
|
|
|
#include <dxgi1_6.h>
|
|
|
|
|
#include <initguid.h>
|
|
|
|
|
#include <d3d12.h>
|
|
|
|
|
#include "Unity/IUnityGraphicsD3D12.h"
|
|
|
|
|
#include <atomic>
|
|
|
|
|
#include <unordered_map>
|
|
|
|
|
#include <utility>
|
|
|
|
|
#include <map>
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
|
|
#define ReturnOnFail(x, hr, OnFailureMsg, onFailureReturnValue) hr = x; if(FAILED(hr)){OutputDebugStringA(OnFailureMsg); return onFailureReturnValue;}
|
|
|
|
|
|
|
|
|
|
#define D3D12_DEFAULT_HEAP_TRIANGLE_BUFFER_NAME L"Native Plugin Default Heap Triangle Vertex Buffer"
|
|
|
|
|
#define D3D12_UPLOAD_HEAP_TRIANGLE_BUFFER_NAME L"Native Plugin Upload Heap Triangle Vertex Buffer"
|
|
|
|
|
#define D3D12_UPLOAD_HEAP_TEXTURE_BUFFER_NAME L"Native Plugin Upload Heap Texture"
|
|
|
|
|
#define D3D12_UPLOAD_HEAP_VERTEX_BUFFER_NAME L"Native Plugin Upload Heap Vertex Buffer"
|
|
|
|
|
|
|
|
|
|
// Compiled from:
|
|
|
|
|
/*
|
2024-12-12 17:41:33 +08:00
|
|
|
cbuffer MyCB : register(b0)
|
|
|
|
|
{
|
|
|
|
|
float4x4 worldMatrix;
|
|
|
|
|
}
|
|
|
|
|
void VS(float3 pos : POSITION, float4 color : COLOR, out float4 ocolor : COLOR, out float4 opos : SV_Position)
|
|
|
|
|
{
|
|
|
|
|
opos = mul(worldMatrix, float4(pos, 1));
|
|
|
|
|
ocolor = color;
|
|
|
|
|
}
|
|
|
|
|
float4 PS(float4 color : COLOR) : SV_TARGET
|
|
|
|
|
{
|
|
|
|
|
return color;
|
|
|
|
|
}
|
2024-11-01 16:55:46 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// using:
|
|
|
|
|
/*
|
2024-12-12 17:41:33 +08:00
|
|
|
dxc -T vs_6_0 -E VSMain -Fo vertex_shader .\shaders.hlsl -Qstrip_reflect -Qstrip_debug
|
|
|
|
|
dxc -T ps_6_0 -E PSMain -Fo pixel_shader .\shaders.hlsl -Qstrip_reflect -Qstrip_debug
|
2024-11-01 16:55:46 +08:00
|
|
|
*/
|
2024-12-12 17:41:33 +08:00
|
|
|
extern void unityLog(const char* msg);
|
2024-11-01 16:55:46 +08:00
|
|
|
|
|
|
|
|
static void handle_hr(HRESULT hr, const char* error = "")
|
|
|
|
|
{
|
2024-12-12 17:41:33 +08:00
|
|
|
if (FAILED(hr))
|
|
|
|
|
{
|
|
|
|
|
OutputDebugStringA(error);
|
|
|
|
|
std::cerr << error << "\n";
|
|
|
|
|
abort();
|
|
|
|
|
}
|
2024-11-01 16:55:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct D3D12MemoryObject
|
|
|
|
|
{
|
2024-12-12 17:41:33 +08:00
|
|
|
ID3D12Resource* resource;
|
|
|
|
|
void* mapped;
|
|
|
|
|
D3D12_HEAP_TYPE heapType;
|
|
|
|
|
D3D12_RESOURCE_FLAGS resourceFlags;
|
|
|
|
|
UINT64 deviceMemorySize;
|
2024-11-01 16:55:46 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct D3D12DefaultBufferMemoryObject
|
|
|
|
|
{
|
2024-12-12 17:41:33 +08:00
|
|
|
D3D12MemoryObject uploadResource;
|
|
|
|
|
D3D12MemoryObject defaultResource;
|
2024-11-01 16:55:46 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class RenderAPI_D3D12 : public RenderAPI
|
|
|
|
|
{
|
|
|
|
|
public:
|
2024-12-12 17:41:33 +08:00
|
|
|
RenderAPI_D3D12();
|
|
|
|
|
virtual ~RenderAPI_D3D12() override {}
|
2024-11-01 16:55:46 +08:00
|
|
|
|
2024-12-12 17:41:33 +08:00
|
|
|
virtual void processDeviceEvent(UnityGfxDeviceEventType type, IUnityInterfaces* interfaces) override;
|
|
|
|
|
virtual bool getUsesReverseZ() override { return true; }
|
2024-11-01 16:55:46 +08:00
|
|
|
|
|
|
|
|
|
2024-12-12 17:41:33 +08:00
|
|
|
virtual bool isSwapChainAvailable() override;
|
|
|
|
|
virtual unsigned int getPresentFlags() override;
|
|
|
|
|
virtual unsigned int getSyncInterval() override;
|
|
|
|
|
virtual unsigned int getBackbufferWidth() override;
|
|
|
|
|
virtual unsigned int getBackbufferHeight() override;
|
2024-11-01 16:55:46 +08:00
|
|
|
|
|
|
|
|
|
2024-12-18 17:53:48 +08:00
|
|
|
virtual void enableVRS(void* data) override;
|
2024-12-12 17:41:33 +08:00
|
|
|
virtual void disableVRS() override;
|
2024-11-01 16:55:46 +08:00
|
|
|
|
2024-12-12 17:41:33 +08:00
|
|
|
virtual void initSupportFeature() override;
|
2024-11-01 16:55:46 +08:00
|
|
|
|
2024-12-12 17:41:33 +08:00
|
|
|
IUnityGraphicsD3D12v7* s_d3d12;
|
2024-12-16 20:33:34 +08:00
|
|
|
static RenderAPI_D3D12* instance;
|
2024-11-01 16:55:46 +08:00
|
|
|
};
|
2024-12-16 20:33:34 +08:00
|
|
|
RenderAPI_D3D12* RenderAPI_D3D12::instance = nullptr;
|
2024-11-01 16:55:46 +08:00
|
|
|
|
|
|
|
|
RenderAPI* CreateRenderAPI_D3D12()
|
|
|
|
|
{
|
2024-12-16 20:33:34 +08:00
|
|
|
RenderAPI_D3D12::instance = new RenderAPI_D3D12();
|
|
|
|
|
return RenderAPI_D3D12::instance;
|
2024-11-01 16:55:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RenderAPI_D3D12::RenderAPI_D3D12()
|
2024-12-12 17:41:33 +08:00
|
|
|
: s_d3d12(NULL)
|
2024-11-01 16:55:46 +08:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UINT64 CalcByteAlignedValue(unsigned int byteSize, unsigned int byteAlignment)
|
|
|
|
|
{
|
2024-12-12 17:41:33 +08:00
|
|
|
UINT byteAlignmentMinusOne = byteAlignment - 2;
|
|
|
|
|
return (byteSize + byteAlignmentMinusOne) & ~byteAlignmentMinusOne;
|
2024-11-01 16:55:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2024-12-11 17:42:08 +08:00
|
|
|
void RenderAPI_D3D12::processDeviceEvent(UnityGfxDeviceEventType type, IUnityInterfaces* interfaces)
|
2024-11-01 16:55:46 +08:00
|
|
|
{
|
2024-12-12 17:41:33 +08:00
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case kUnityGfxDeviceEventInitialize:
|
|
|
|
|
s_d3d12 = interfaces->Get<IUnityGraphicsD3D12v7>();
|
|
|
|
|
|
|
|
|
|
UnityD3D12PluginEventConfig config_1;
|
|
|
|
|
config_1.graphicsQueueAccess = kUnityD3D12GraphicsQueueAccess_DontCare;
|
|
|
|
|
config_1.flags = kUnityD3D12EventConfigFlag_SyncWorkerThreads | kUnityD3D12EventConfigFlag_ModifiesCommandBuffersState | kUnityD3D12EventConfigFlag_EnsurePreviousFrameSubmission;
|
|
|
|
|
config_1.ensureActiveRenderTextureIsBound = true;
|
|
|
|
|
s_d3d12->ConfigureEvent(1, &config_1);
|
|
|
|
|
|
|
|
|
|
UnityD3D12PluginEventConfig config_2;
|
|
|
|
|
config_2.graphicsQueueAccess = kUnityD3D12GraphicsQueueAccess_Allow;
|
|
|
|
|
config_2.flags = kUnityD3D12EventConfigFlag_SyncWorkerThreads | kUnityD3D12EventConfigFlag_ModifiesCommandBuffersState | kUnityD3D12EventConfigFlag_EnsurePreviousFrameSubmission;
|
|
|
|
|
config_2.ensureActiveRenderTextureIsBound = false;
|
|
|
|
|
s_d3d12->ConfigureEvent(2, &config_2);
|
|
|
|
|
initSupportFeature();
|
|
|
|
|
break;
|
|
|
|
|
case kUnityGfxDeviceEventShutdown:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2024-11-01 16:55:46 +08:00
|
|
|
}
|
|
|
|
|
|
2024-12-11 17:42:08 +08:00
|
|
|
bool RenderAPI_D3D12::isSwapChainAvailable()
|
2024-11-01 16:55:46 +08:00
|
|
|
{
|
2024-12-12 17:41:33 +08:00
|
|
|
return s_d3d12->GetSwapChain();
|
2024-11-01 16:55:46 +08:00
|
|
|
}
|
|
|
|
|
|
2024-12-11 17:42:08 +08:00
|
|
|
unsigned int RenderAPI_D3D12::getPresentFlags()
|
2024-11-01 16:55:46 +08:00
|
|
|
{
|
2024-12-12 17:41:33 +08:00
|
|
|
return s_d3d12->GetPresentFlags();
|
2024-12-11 17:42:08 +08:00
|
|
|
};
|
2024-11-01 16:55:46 +08:00
|
|
|
|
2024-12-11 17:42:08 +08:00
|
|
|
unsigned int RenderAPI_D3D12::getSyncInterval()
|
2024-11-01 16:55:46 +08:00
|
|
|
{
|
2024-12-12 17:41:33 +08:00
|
|
|
return s_d3d12->GetSyncInterval();
|
2024-11-01 16:55:46 +08:00
|
|
|
}
|
|
|
|
|
|
2024-12-11 17:42:08 +08:00
|
|
|
unsigned int RenderAPI_D3D12::getBackbufferWidth()
|
2024-11-01 16:55:46 +08:00
|
|
|
{
|
2024-12-12 17:41:33 +08:00
|
|
|
IDXGISwapChain* swap_chain = s_d3d12->GetSwapChain();
|
|
|
|
|
if (!swap_chain)
|
|
|
|
|
return 0;
|
2024-11-01 16:55:46 +08:00
|
|
|
|
2024-12-12 17:41:33 +08:00
|
|
|
DXGI_SWAP_CHAIN_DESC desc;
|
|
|
|
|
handle_hr(swap_chain->GetDesc(&desc), "Failed to get DXGI swap chain desc\n");
|
2024-11-01 16:55:46 +08:00
|
|
|
|
2024-12-12 17:41:33 +08:00
|
|
|
return desc.BufferDesc.Width;
|
2024-11-01 16:55:46 +08:00
|
|
|
}
|
|
|
|
|
|
2024-12-11 17:42:08 +08:00
|
|
|
unsigned int RenderAPI_D3D12::getBackbufferHeight()
|
2024-11-01 16:55:46 +08:00
|
|
|
{
|
2024-12-12 17:41:33 +08:00
|
|
|
IDXGISwapChain* swap_chain = s_d3d12->GetSwapChain();
|
|
|
|
|
if (!swap_chain)
|
|
|
|
|
return 0;
|
2024-11-01 16:55:46 +08:00
|
|
|
|
2024-12-12 17:41:33 +08:00
|
|
|
DXGI_SWAP_CHAIN_DESC desc;
|
|
|
|
|
handle_hr(swap_chain->GetDesc(&desc), "Failed to get DXGI swap chain desc\n");
|
2024-11-01 16:55:46 +08:00
|
|
|
|
2024-12-12 17:41:33 +08:00
|
|
|
return desc.BufferDesc.Height;
|
2024-11-01 16:55:46 +08:00
|
|
|
}
|
|
|
|
|
|
2024-12-11 17:42:08 +08:00
|
|
|
static D3D12_SHADING_RATE vrs_argment_size_table[] = {
|
2024-12-12 17:41:33 +08:00
|
|
|
D3D12_SHADING_RATE_1X1,
|
|
|
|
|
D3D12_SHADING_RATE_2X1,
|
|
|
|
|
D3D12_SHADING_RATE_1X2,
|
|
|
|
|
D3D12_SHADING_RATE_2X2,
|
|
|
|
|
D3D12_SHADING_RATE_4X2,
|
|
|
|
|
D3D12_SHADING_RATE_2X4,
|
|
|
|
|
D3D12_SHADING_RATE_4X4
|
2024-12-11 17:42:08 +08:00
|
|
|
};
|
2024-11-01 16:55:46 +08:00
|
|
|
|
2024-12-18 17:53:48 +08:00
|
|
|
void RenderAPI_D3D12::enableVRS(void* data)
|
2024-11-01 16:55:46 +08:00
|
|
|
{
|
2024-12-18 17:53:48 +08:00
|
|
|
int vrs_enum = *(int*) data;
|
2024-12-12 17:41:33 +08:00
|
|
|
UnityGraphicsD3D12RecordingState recordingState;
|
|
|
|
|
if (!s_d3d12->CommandRecordingState(&recordingState))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ID3D12GraphicsCommandList* cmdLst = recordingState.commandList;
|
2024-12-18 17:53:48 +08:00
|
|
|
reinterpret_cast<ID3D12GraphicsCommandList5*>(cmdLst)->RSSetShadingRate(vrs_argment_size_table[vrs_enum], nullptr);
|
2024-11-01 16:55:46 +08:00
|
|
|
}
|
|
|
|
|
|
2024-12-11 17:42:08 +08:00
|
|
|
void RenderAPI_D3D12::disableVRS()
|
2024-11-01 16:55:46 +08:00
|
|
|
{
|
2024-12-12 17:41:33 +08:00
|
|
|
UnityGraphicsD3D12RecordingState recordingState;
|
|
|
|
|
if (!s_d3d12->CommandRecordingState(&recordingState))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ID3D12GraphicsCommandList* cmdLst = recordingState.commandList;
|
|
|
|
|
reinterpret_cast<ID3D12GraphicsCommandList5*>(cmdLst)->RSSetShadingRate(D3D12_SHADING_RATE_1X1, nullptr);
|
2024-11-01 16:55:46 +08:00
|
|
|
}
|
|
|
|
|
|
2024-12-11 17:42:08 +08:00
|
|
|
void RenderAPI_D3D12::initSupportFeature()
|
2024-11-01 16:55:46 +08:00
|
|
|
{
|
2024-12-12 17:41:33 +08:00
|
|
|
D3D12_FEATURE_DATA_D3D12_OPTIONS6 options = {};
|
|
|
|
|
s_d3d12->GetDevice()->CheckFeatureSupport(
|
|
|
|
|
D3D12_FEATURE_D3D12_OPTIONS6,
|
|
|
|
|
&options,
|
|
|
|
|
sizeof(options));
|
|
|
|
|
if (options.VariableShadingRateTier == D3D12_VARIABLE_SHADING_RATE_TIER_1)
|
|
|
|
|
{
|
|
|
|
|
support_features[GraphicsFeature::VRS_DRAW] = true;
|
|
|
|
|
}
|
|
|
|
|
else if (options.VariableShadingRateTier == D3D12_VARIABLE_SHADING_RATE_TIER_2)
|
|
|
|
|
{
|
|
|
|
|
support_features[GraphicsFeature::VRS_DRAW] = true;
|
|
|
|
|
support_features[GraphicsFeature::VRS_PRIMITIVE] = true;
|
|
|
|
|
support_features[GraphicsFeature::VRS_ATTACHMENT] = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (options.AdditionalShadingRatesSupported)
|
|
|
|
|
{
|
|
|
|
|
// xxx: 一般用不到这么高级别
|
|
|
|
|
// 表示支持 2x4、4x2 和 4x4
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-01 16:55:46 +08:00
|
|
|
}
|
|
|
|
|
|
2024-12-16 20:33:34 +08:00
|
|
|
|
|
|
|
|
#undef ReturnOnFail
|
2024-11-01 16:55:46 +08:00
|
|
|
|
|
|
|
|
#endif // #if SUPPORT_D3D12
|