DirectX raytracing - pop up



Pada tahun 2018, Microsoft mengumumkan raytracing API (DXR) sebagai bagian dari DirectX 12. Pendekatan raytracing memaksa pemikiran ulang lengkap tentang cara rendering adegan 3D, menggeser pendekatan rasterisasi klasik ke latar belakang. API sedang dimodernisasi, GPU yang lebih efisien sedang dikembangkan, dan pengembang paket visualisasi mencoba kemungkinan baru. Namun, bahkan pada kartu grafis paling kuat, kekuatannya cukup untuk menghasilkan hanya beberapa sinar per piksel untuk memastikan kecepatan bingkai yang stabil. Plus, performa sangat tergantung pada kompleksitas material dan pemandangan. Namun saat ini, algoritme canggih untuk pengurangan noise dan akumulasi hasil iluminasi memungkinkan pencapaian realisme tingkat tinggi. Semua ini memotivasi untuk bereksperimen di bidang ini.



Penelusuran sinar GPU relatif baru. Pada tahun 2009, DirectX 11 keluar dengan compute shader - ini memberikan dorongan pada pengembangan komputasi non-grafis. Namun, desain struktur percepatan sepenuhnya berada di pundak programmer, yang memperlambat pengembangan. Perpustakaan persimpangan khusus telah menyebar, seperti AMD Radeon Rays. Dalam DXR, struktur percepatan direpresentasikan pada prinsip kotak hitam dan persimpangan terjadi menggunakan blok perangkat keras khusus. Ray tracing juga telah ditambahkan ke Vulkan sebagai ekstensi VK_NV_ray_tracing untuk kartu Nvidia. Pada bulan Maret 2020, dengan perubahan kecil, ekstensi VK_KHR_ray_tracing dirilis, khusus vendor tidak lagi digunakan, mungkin ekstensi tersebut akan disertakan dalam spesifikasi Vulkan 1.3.Penelusuran sinar lengkap direncanakan untuk AMD pada akhir tahun 2020. Dukungan di mana-mana membuat teknologinya lebih menjanjikan.



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);
//...






Dalam artikel tersebut, kami memeriksa objek dasar yang diperlukan untuk memulai DXR, dan juga menerapkan pengetahuan ini dalam praktik. Pertanyaan tentang inisialisasi DirectX, model pemuatan, kompilasi shader, dll., Yang tidak relevan, sengaja dihilangkan. Dalam artikel berikutnya, direncanakan untuk mengalihkan penekanan pada, pada kenyataannya, grafik, daripada bekerja dengan API.



Tautan:



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

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

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




All Articles