DirectX raytracing - يطفو على السطح



في عام 2018 ، أعلنت Microsoft عن واجهة برمجة تطبيقات raytracing (DXR) كجزء من DirectX 12. يفرض نهج raytracing إعادة التفكير بشكل كامل في طريقة عرض المشاهد ثلاثية الأبعاد ، مما يؤدي إلى تحويل نهج التنقيط الكلاسيكي إلى الخلفية. يتم تحديث واجهات برمجة التطبيقات ، وتطوير وحدات معالجة رسومات أكثر كفاءة ، ويحاول مطورو حزم التصور إمكانيات جديدة. ومع ذلك ، حتى في أقوى بطاقات الرسومات ، فإن الطاقة كافية لتوليد حزم قليلة فقط لكل بكسل لضمان معدل إطارات ثابت. بالإضافة إلى ذلك ، يعتمد الأداء بشكل كبير على مدى تعقيد المواد والمشهد. ولكن حتى اليوم ، تسمح الخوارزميات المتقدمة لتقليل الضوضاء وتراكم نتيجة الإضاءة بتحقيق درجة عالية من الواقعية. كل هذا يحفز على التجربة في هذا المجال.



يعد تتبع شعاع GPU جديدًا نسبيًا. في عام 2009 ، جاء DirectX 11 مزودًا بأجهزة تظليل للحوسبة - وقد أعطى ذلك قوة دفع لتطوير الحوسبة غير الرسومية. ومع ذلك ، فقد وقع تصميم هياكل التسريع بالكامل على عاتق المبرمج ، مما أدى إلى إبطاء عملية التطوير. أصبحت مكتبات التقاطعات المتخصصة منتشرة على نطاق واسع ، مثل AMD's Radeon Rays. في DXR ، يتم تمثيل الهياكل المتسارعة وفقًا لمبدأ الصندوق الأسود ويحدث التقاطع باستخدام كتل أجهزة خاصة. تمت إضافة تتبع الشعاع أيضًا إلى Vulkan كامتداد لـ VK_NV_ray_tracing لبطاقات Nvidia. في مارس 2020 ، مع إجراء تغييرات طفيفة ، تم إصدار امتدادات VK_KHR_ray_tracing ، ولم تعد خاصة بالمورد ، وربما سيتم تضمينها في مواصفات Vulkan 1.3.تم التخطيط لتتبع الأشعة الكامل لـ AMD بحلول نهاية عام 2020. الدعم الشامل يجعل التكنولوجيا واعدة أكثر.



DXR . — . , . , , , . , (, ). , (hit, miss, procedural hit, closest hit), , , , . pipeline .





DXR- GPU Nvidia RTX 2060 . Windows SDK 19041 ( , Miscrosoft ), IDE Visual Studio 2019, C++.





DXR , raygen-. ID3D12GraphicsCommandList4::DispatchRays() c , TraceRay(). top level acceleration structure. , . , , , (closest hit). , .





miss hit-. payload — . DirectX, global root signature. per-shader , local root signature Shader binding table. , .





:



  • bottom-level, top-level acceleration structures
  • raytracing pipeline
  • shading binding table (SBT) — per-shader


.



Bottom-level acceleration structure (BLAS)



, — . BLAS . BLAS . . BLAS GPU, command list . , BLAS (scratch-). DirectX 12, API, ID3D12Device5::GetRaytracingAccelerationStructurePrebuildInfo. D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE — .



D3D12_RAYTRACING_GEOMETRY_DESC — BLAS. ( index-buffer ):



D3D12_RAYTRACING_GEOMETRY_DESC geometryDesc = {};
geometryDesc.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES;
geometryDesc.Triangles.IndexBuffer = 0;// GPU-address index- (  )
geometryDesc.Triangles.IndexCount = 0;
geometryDesc.Triangles.IndexFormat = 0;//  DXGI_FORMAT_R16_UINT;
geometryDesc.Triangles.VertexFormat = DXGI_FORMAT_R32G32B32_FLOAT;
geometryDesc.Triangles.VertexCount = < >;
geometryDesc.Triangles.VertexBuffer.StartAddress = <GPU-address  >;
geometryDesc.Triangles.VertexBuffer.StrideInBytes = sizeof(Vertex);


BLAS:



D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS bottomLevelInputs;
bottomLevelInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY;
bottomLevelInputs.Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE;
bottomLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL;
bottomLevelInputs.pGeometryDescs = &geometryDesc;
bottomLevelInputs.NumDescs = 1;

D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC bottomLevelBuildDesc = {};
bottomLevelBuildDesc.Inputs = bottomLevelInputs;
bottomLevelBuildDesc.ScratchAccelerationStructureData = scratchResource->GetGPUVirtualAddress();
bottomLevelBuildDesc.DestAccelerationStructureData = bottomLevelAccelerationStructure->GetGPUVirtualAddress(); // ID3D12Resource* bottomLevelAccelerationStructure -    


BLAS:



dxrCommandList->BuildRaytracingAccelerationStructure(&bottomLevelBuildDesc, 0, nullptr);


Top-level acceleration structure (TLAS)



TLAS BLAS . BLAS , . TLAS BLAS — scratch-. , scratch-, TLAS BLAS. TLAS :



    D3D12_RAYTRACING_INSTANCE_DESC instanceDesc[2] = {};

    for (int i = 0; i < 2; ++i)
    {
        instanceDesc[i].Transform = YourEngineTransformToDXR(transforms[i]);
        instanceDesc[i].InstanceMask = 1;
        instanceDesc[i].InstanceID = 0; //  
        instanceDesc[i].InstanceContributionToHitGroupIndex = i; //     hit SBT
        instanceDesc[i].AccelerationStructure = bottomLevelAccelerationStructure->GetGPUVirtualAddress();
    }


TLAS (D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC) BLAS.



Raytracing pipeline



graphic compute raytracing pipeline state object — . RT pipeline -, . CD3DX12_STATE_OBJECT_DESC CreateSubobject(< >).



  1. . BytecodeLength pShaderBytecode D3D12_SHADER_BYTECODE, SetDXILLibrary() DefineExport(). 3- : raygen, hit, miss.
  2. Hit group (CD3DX12_HIT_GROUP_SUBOBJECT). hit group-, . SetHitGroupExport, SetHitGroupType(D3D12_HIT_GROUP_TYPE_TRIANGLES). hit-group, .
  3. (CD3DX12_RAYTRACING_SHADER_CONFIG_SUBOBJECT). payload — , TraceRay , closest hit — 2 float.
  4. (CD3DX12_RAYTRACING_PIPELINE_CONFIG_SUBOBJECT). 1.
  5. root signature (CD3DX12_LOCAL_ROOT_SIGNATURE_SUBOBJECT). , hit-. SBT ( ).
  6. local root signatore c hit group (CD3DX12_SUBOBJECT_TO_EXPORTS_ASSOCIATION_SUBOBJECT). root signature SetSubobjectToAssociate() AddExport().
  7. root signature (CD3DX12_GLOBAL_ROOT_SIGNATURE_SUBOBJECT). , . SetComputeRootDescriptorTable, SetComputeRootShaderResourceView SetComputeRoot32BitConstants.


Shader binding table (SBT)



SBT — . , , . , GPU-, . .



shader record. TLAS , — . . TLAS BLAS, TraceRay(), .



3 : ray generation, hit miss, , , . , . GPU- , DispatchRays(). shader record-.



shader record-a . raygen miss , shader record-a . , , , root signature, SBT. shader record D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT ( 32 ).



void*, GetShaderIdentifier() ID3D12StateObjectProperties, COM- raytracing pipeline. raygen- (miss ) :



ComPtr<ID3D12StateObjectProperties> stateObjectProperties;
dxrStateObject.As(&stateObjectProperties);
void* rayGenShaderIdentifier = stateObjectProperties->GetShaderIdentifier(L"RayGen");


. SBT raygen miss .



hit float4 . SBT root signature: virtual GPU-address/GPU-handle. constant buffer, hit SBT shader record-. 32- 4x4- , 48, - 64 . :







vertex-fragment shader 3: raygen, hit, miss.



raygen:



#include "Common.hlsl"
#include "Global.hlsl"

struct CameraData
{
    float4 forward;
    float4 right;
    float4 up;
    float4 origin;
};

ConstantBuffer<CameraData> gCamera : register(b0);

[shader("raygeneration")] 
void RayGen() 
{
    HitInfo payload;
    payload.colorAndDistance = float4(0, 0, 0, 0);

    uint2 launchIndex = DispatchRaysIndex().xy;
    float2 dims = float2(DispatchRaysDimensions().xy);

    float2 ndc = float2(
        float(launchIndex.x + 0.5f) / dims.x * 2 - 1,
        float(dims.y - launchIndex.y - 1 + 0.5) / dims.y * 2 - 1);

    RayDesc ray;
    ray.Origin = gCamera.origin.xyz;
    ray.Direction = GetWorldRay(ndc, gCamera.forward.xyz, gCamera.right.xyz, gCamera.up.xyz);
    ray.TMin = 0;
    ray.TMax = 100000;

    TraceRay(
        SceneBVH,
        RAY_FLAG_NONE,
        0xFF, 
        0, // RayContributionToHitGroupIndex
        0, // MultiplierForGeometryContributionToHitGroupIndex
        0, // MissShaderIndex
        ray,
        payload);

    gOutput[launchIndex] = float4(payload.colorAndDistance.rgb, 1.f);
}


. TLAS, , SBT. TraceRay() payload . [shader("raygeneration")] , , , "RayGen" , .



closesthit



#include "Common.hlsl"
#include "Global.hlsl"

struct InstanceData
{
    float4 color;
};
ConstantBuffer<InstanceData> instanceData : register(b1);

[shader("closesthit")] 
void ClosestHit(inout HitInfo payload, Attributes attrib)
{
    float3 barycentrics = float3(1.f - attrib.bary.x - attrib.bary.y, attrib.bary.x, attrib.bary.y);

    float3 vertexNormals[3] = {
        Vertices[PrimitiveIndex() * 3].normal,
        Vertices[PrimitiveIndex() * 3 + 1].normal,
        Vertices[PrimitiveIndex() * 3 + 2].normal
    };

    float3 N = vertexNormals[0] * barycentrics.x +
        vertexNormals[1] * barycentrics.y +
        vertexNormals[2] * barycentrics.z;

    const float3 L = normalize(float3(0, -0.4, 1));

    payload.colorAndDistance = float4(instanceData.color.rgb * max(0, dot(N, L)), RayTCurrent());
}


. - payload. . . , .



miss.



#include "Common.hlsl"

[shader("miss")] 
void Miss(inout HitInfo payload : SV_RayPayload)
{
    payload.colorAndDistance = float4(0.0f, 0.2f, 0.7f, -1.0f);
}


— .



Main loop



main loop :



//...
//   root signature
dxrCommandList->SetComputeRootSignature(raytracingGlobalRootSignature.Get());

//   descriptor heap
dxrCommandList->SetDescriptorHeaps(1, descriptorHeap.GetAddressOf());

//   
dxrCommandList->SetComputeRootDescriptorTable(0, raytracingOutputResourceUAVGpuDescriptor);
dxrCommandList->SetComputeRootDescriptorTable(1, buffersGpuDescriptor);
dxrCommandList->SetComputeRootShaderResourceView(2, topLevelAccelerationStructure->GetGPUVirtualAddress());

//   
//...

D3D12_DISPATCH_RAYS_DESC dispatchDesc = {};
dispatchDesc.HitGroupTable.StartAddress = hitGroupShaderTable->GetGPUVirtualAddress();
dispatchDesc.HitGroupTable.SizeInBytes = hitGroupShaderTable->GetDesc().Width;
dispatchDesc.HitGroupTable.StrideInBytes = 64; //  hit shader record 
dispatchDesc.MissShaderTable.StartAddress = missShaderTable->GetGPUVirtualAddress();
dispatchDesc.MissShaderTable.SizeInBytes = missShaderTable->GetDesc().Width;
dispatchDesc.MissShaderTable.StrideInBytes = dispatchDesc.MissShaderTable.SizeInBytes;
dispatchDesc.RayGenerationShaderRecord.StartAddress = rayGenShaderTable->GetGPUVirtualAddress();
dispatchDesc.RayGenerationShaderRecord.SizeInBytes = rayGenShaderTable->GetDesc().Width;
dispatchDesc.Width = width;
dispatchDesc.Height = height;
dispatchDesc.Depth = 1;

dxrCommandList->SetPipelineState1(dxrStateObject.Get());

dxrCommandList->DispatchRays(&dispatchDesc);
//...






في المقالة ، قمنا بفحص العناصر الأساسية اللازمة لبدء استخدام DXR ، كما قمنا بتطبيق هذه المعرفة في الممارسة العملية. تم حذف أسئلة تهيئة DirectX ، ونماذج التحميل ، وتجميع المظلات ، وما إلى ذلك ، والتي ليست ذات صلة ، عمدًا. في المقالات التالية ، من المخطط تحويل التركيز إلى الرسومات بدلاً من العمل مع API.



الروابط:



https://github.com/k-payl/X12Lib/blob/master/src/examples/raytracing.cpp

https://microsoft.github.io/DirectX-Specs/d3d/Raytracing.html

https: // developer. nvidia.com/rtx/raytracing/dxr/DX12-Raytracing-tutorial-Part-1




All Articles