251 lines
6.5 KiB
C++
Raw Normal View History

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