Search
Duplicate

Ray Tracing Pipeline(레이트레이싱 파이프라인)

Directx 12의 레이트레이싱 하드웨어 쿼리를 API에 도입시켜 Path Tracing을 위한 특정 씬의 광원계산, 반사, 전역조명, 텍스처에 라이트 맵 또는 물리 연산 지오메트리 베이킹, 공간 후 처리 효과 등등 다양한 사례를 쉽고 빠르게 수행 할 수 있습니다.

Compiling Shaders

다이렉트x 12의 레이트레이싱 쉐이더 스테이지는 총 5종류 입니다.
Ray Generation - 시작 광선을 생성합니다. 예를 들어 뷰포트의 시점에서 나오는 광선이 될 수 있습니다.
Intersection - 충돌 처리를 위한 사용자 정의 솔루션으로, 벤더의 교차점 계산 기능에 의존하지 않고 주어진 광선에 대한 충돌 교차점을 프로그래밍 방식으로 보고할 수 있습니다.
Any Hit - 시점으로부터 멀리 있는 충돌을 포함하여 주어진 광선의 모든 충돌점입니다. 두께 테스트나 반투명 객체에 유용합니다.
Closest Hit - 주어진 광선에 대해 가장 먼저 발생하는 충돌로, 시점에서 가장 가까운 지점입니다.
Miss - 광선이 씬의 어떤 것과도 충돌하지 않을 때 발생합니다. 스카이박스의 기여도를 추가하는 데 유용합니다.
// 🌎 Global Resources RaytracingAccelerationStructure Scene : register(t0, space0); RWTexture2D<float4> tOutput : register(u0); cbuffer globalCB : register(b0) { row_major float4x4 projectionMatrix : packoffset(c0); row_major float4x4 viewMatrix : packoffset(c4); float3 origin : packoffset(c8); float near : packoffset(c9.x); float far : packoffset(c9.y); }; struct RayPayload { float4 color; }; /** * 🤾 Ray Generation */ [shader("raygeneration")] void raygen() { float2 screenCoords = (float2)DispatchRaysIndex() / (float2)DispatchRaysDimensions(); float2 ndc = screenCoords * 2.0 - float2(1.0, 1.0); float3 rayDir = normalize(mul(mul(viewMatrix, projectionMatrix), float4(ndc * (far - near), far + near, far - near))).xyz; RayDesc ray; ray.Origin = origin.xyz; ray.Direction = rayDir; ray.TMin = 0.1; ray.TMax = 300.0; RayPayload payload = {float4(0, 0, 0, 0)}; TraceRay(Scene, RAY_FLAG_NONE, ~0, 0, 1, 0, ray, payload); tOutput[DispatchRaysIndex().xy] = payload.color; } /** * 🏏 Closest Hit */ // Local Resources struct LocalCB { float time; }; ConstantBuffer<LocalCB> localCB : register(b1); Texture2D<float4> localTex : register(t1); SamplerState localSampler : register(s0); [shader("closesthit")] void closesthit(inout RayPayload payload, in BuiltInTriangleIntersectionAttributes attr) { float3 barycentrics = float3(1 - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y); float4 col = localTex.SampleLevel(localSampler, barycentrics.xy - barycentrics.yz * sin(localCB.time), 0.0); payload.color = col; } /** * ⚾ Miss */ [shader("miss")] void miss(inout RayPayload payload) { payload.color = float4(0.5, 0.5, 0.5, 1); }
C++
복사

Root Signature

레이트레이싱 파이프라인은 쉐이더가 읽을 수 있는 리소스를 설명하기 위해 로컬글로벌 루트 시그니처가 모두 필요합니다.
글로벌 루트 시그니처는 가속 구조체나 레디언스 버퍼와 같이 서로 다른 dispatchRays 호출 간에 공유하여 읽고 쓸 수 있는 데이터에 사용될 수 있습니다.
// 👋 Declare Handles ID3D12RootSignature* globalRootSignature = nullptr; // Global Root Signature // These can be configured prior to DispatchRays // Output radiance UAV D3D12_DESCRIPTOR_RANGE1 ranges[2]; ranges[0].BaseShaderRegister = 0; ranges[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; ranges[0].NumDescriptors = 1; ranges[0].RegisterSpace = 0; ranges[0].OffsetInDescriptorsFromTableStart = 0; ranges[0].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE; // Camera Matrices CBV ranges[1].BaseShaderRegister = 0; ranges[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV; ranges[1].NumDescriptors = 1; ranges[1].RegisterSpace = 0; ranges[1].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; ranges[1].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE | D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE; D3D12_ROOT_PARAMETER1 rootParameters[2]; // UAV, CBV rootParameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; rootParameters[0].DescriptorTable.NumDescriptorRanges = _countof(ranges); rootParameters[0].DescriptorTable.pDescriptorRanges = ranges; // Acceleration Structures rootParameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV; rootParameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; rootParameters[1].Descriptor = {}; D3D12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDesc; rootSignatureDesc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1; rootSignatureDesc.Desc_1_1.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; rootSignatureDesc.Desc_1_1.NumParameters = _countof(rootParameters); rootSignatureDesc.Desc_1_1.pParameters = rootParameters; rootSignatureDesc.Desc_1_1.NumStaticSamplers = 0; rootSignatureDesc.Desc_1_1.pStaticSamplers = nullptr; ID3DBlob* signature; ID3DBlob* error; try { ThrowIfFailed(D3D12SerializeVersionedRootSignature( &rootSignatureDesc, &signature, &error)); ThrowIfFailed(device->CreateRootSignature( 0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&globalRootSignature))); globalRootSignature->SetName(L"Global Root Signature"); } catch (std::exception e) { const char* errStr = (const char*)error->GetBufferPointer(); std::cout << errStr; error->Release(); error = nullptr; } if (signature) { signature->Release(); signature = nullptr; }
C++
복사
로컬 루트 시그니처는 레이트레이싱의 각 프로그래밍 가능한 단계가 자체적으로 정의할 수 있다는 점에서 특별합니다.
// 👋 Declare Handles ID3D12RootSignature* localRootSignature = nullptr; // Local Root Signature // Shader tables are able to configure this root signature. D3D12_ROOT_PARAMETER1 rootParameters[2] = {}; // Viewport Misc Constant rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; rootParameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; rootParameters[0].Constants = {}; rootParameters[0].Constants.ShaderRegister = 1; rootParameters[0].Constants.Num32BitValues = ((sizeof(mRayGenCB) - 1) / sizeof(UINT32) + 1); // Texture Param SRV Table D3D12_DESCRIPTOR_RANGE1 ranges[1] = {}; ranges[0].BaseShaderRegister = 1; ranges[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; ranges[0].NumDescriptors = 1; ranges[0].RegisterSpace = 0; ranges[0].OffsetInDescriptorsFromTableStart = 2; ranges[0].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC; rootParameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; rootParameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; rootParameters[1].DescriptorTable.pDescriptorRanges = &ranges[0]; rootParameters[1].DescriptorTable.NumDescriptorRanges = _countof(ranges); D3D12_STATIC_SAMPLER_DESC sampler = {}; sampler.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER; sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_BORDER; sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_BORDER; sampler.MipLODBias = 0; sampler.MaxAnisotropy = 0; sampler.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; sampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; sampler.MinLOD = 0.0f; sampler.MaxLOD = D3D12_FLOAT32_MAX; sampler.ShaderRegister = 0; sampler.RegisterSpace = 0; sampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; D3D12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDesc; rootSignatureDesc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1; rootSignatureDesc.Desc_1_1.Flags = D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE; rootSignatureDesc.Desc_1_1.NumParameters = _countof(rootParameters); rootSignatureDesc.Desc_1_1.pParameters = rootParameters; rootSignatureDesc.Desc_1_1.NumStaticSamplers = 1; rootSignatureDesc.Desc_1_1.pStaticSamplers = &sampler; ID3DBlob* signature; ID3DBlob* error; try { ThrowIfFailed(D3D12SerializeVersionedRootSignature( &rootSignatureDesc, &signature, &error)); ThrowIfFailed(device->CreateRootSignature( 0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&localRootSignature))); localRootSignature->SetName(L"Local Root Signature"); } catch (std::exception e) { const char* errStr = (const char*)error->GetBufferPointer(); std::cout << errStr; error->Release(); error = nullptr; } if (signature) { signature->Release(); signature = nullptr; }
C++
복사

Shader Table

쉐이더 레코드 테이블은 64비트 정렬된(D3D12_RAYTRACING_SHADER_TABLE_BYTE_ALIGNMENT) 쉐이더 레코드 목록으로, 식별자와 해당 쉐이더의 로컬 루트 시그니처로부터의 로컬 루트 인자들을 포함합니다. 이러한 루트 인자들은 상수 버퍼 데이터 전체이거나, 텍스처, 버퍼, 정렬되지 않은 접근 뷰 등에 대한 디스크립터 핸들이 될 수 있습니다.
struct LocalCB { float time; float _padding[3]; }; struct RootArguments { LocalCB localCB; D3D12_GPU_DESCRIPTOR_HANDLE localTex = {}; }; struct ShaderRecord { unsigned char shaderIdentifier[D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES]; RootArguments rootArguments; };
GLSL
복사

Pipeline State

레이 트레이싱 파이프라인은 주어진 씬에서 객체를 찾기 위해 가속 데이터 구조를 탐색하는 하드웨어 가속 방식입니다. DirectX 레이 트레이싱은 래스터나 컴퓨트 파이프라인과 같은 엄격한 레이아웃 대신, 필요한 모든 정보를 가진 서브 오브젝트를 정의하는 좀 더 선언적인 파이프라인 상태 설명 레이아웃을 채택합니다.
레이 트레이싱 파이프라인을 생성하기 위해 최소한 다음 항목들이 필요합니다:
레이 디스패치 시 사용할 컴파일된 쉐이더가 포함된 DXIL 쉐이더 라이브러리
교차점/미스에 대한 히트 페이로드 크기를 정의하는 쉐이더 구성
레이 탐색을 위한 재귀 깊이 수준을 정의하는 파이프라인 구성
히트 정보를 저장하는 삼각형 히트 그룹
로컬 리소스를 위한 로컬 루트 시그니처
RWTexture<float4> radiance 버퍼와 같은 전역 리소스를 위한 글로벌 루트 시그니처
// 👋 Declare handles ID3D12PipelineState* pipelineState; ID3D12StateObjectProperties* stateObjectProperties; // 🗺️ Create the State Object Description D3D12_STATE_OBJECT_DESC stateObjectDesc = {}; stateObjectDesc.Type = D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE; D3D12_STATE_SUBOBJECT subObjects[7]; stateObjectDesc.NumSubobjects = _countof(subObjects); stateObjectDesc.pSubobjects = subObjects; D3D12_EXPORT_DESC* exportDesc = nullptr; D3D12_SHADER_BYTECODE rtShaderByteCode = {rsBytecodeData.data(), rsBytecodeData.size()}; // 📚 Shader Library D3D12_DXIL_LIBRARY_DESC dxilLibraryDesc = {rtShaderByteCode, 0u, exportDesc}; subObjects[0u] = {D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &dxilLibraryDesc}; // 📕 Active Shaders static LPCWSTR shaderNames[3] = { L"raygen", L"closesthit", L"miss"}; D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION exportAssociations = { subObjects + 4, 3u, shaderNames}; subObjects[1] = { D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION, &exportAssociations}; // 💰 Payload Setup D3D12_RAYTRACING_SHADER_CONFIG shaderConfig = {}; shaderConfig.MaxPayloadSizeInBytes = 4 * sizeof(float); // float4 color shaderConfig.MaxAttributeSizeInBytes = 2 * sizeof(float); // float2 barycentrics subObjects[2] = {D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG, &shaderConfig}; // 📑 Hit Groups D3D12_HIT_GROUP_DESC myClosestHitGroup = { L"MyHitGroup", D3D12_HIT_GROUP_TYPE_TRIANGLES, nullptr, L"closesthit", nullptr}; subObjects[3] = {D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP, &myClosestHitGroup}; // 🚃 Root Signatures subObjects[4] = {D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE, &localRootSignature}; subObjects[5] = {D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE, &globalRootSignature}; // 🔁 Recursion Depth D3D12_RAYTRACING_PIPELINE_CONFIG pipelineConfig = {1u}; pipelineConfig.MaxTraceRecursionDepth = 1; subObjects[6] = {D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG, &pipelineConfig}; HRESULT result = device->CreateStateObject( &stateObjectDesc, __uuidof(**(&pipelineState)), IID_PPV_ARGS_Helper(&pipelineState)); pipelineState->SetName(L"RT Pipeline State"); pipelineState->QueryInterface( __uuidof(**(&stateObjectProperties)), IID_PPV_ARGS_Helper(&stateObjectProperties));
C++
복사

Acceleration Structures

가속화 데이터 구조(또는 가속화 구조/AS)는 주어진 씬의 순회를 가속화하며, 삼각형이나 축 정렬 경계 상자(AABB)의 집합을 순회하기 위해 하드웨어 벤더가 사용하는 내부 가속화 데이터 구조를 나타냅니다.
스크래치 버퍼는 가속화 구조를 생성하는 데 사용되는 중간 데이터를 포함합니다. 스크래치 버퍼 메모리는 벤더 구현에 특화된 가속화 구조 상태를 가리킵니다.
// 👋 Declare Handles ID3D12Device5* device; ID3D12Resource* vertexBuffer; ID3D12Resource* indexBuffer; ID3D12GraphicsCommandList4* commandList; // Declare Outputs ID3D12Resource* asBuffer; ID3D12Resource* asScratchBuffer; ID3D12Resource* instanceDescs; HRESULT hr; // 🌳 Top Level Acceleration Structure D3D12_RAYTRACING_GEOMETRY_DESC geomDescs[1]; geomDescs[0].Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES; geomDescs[0].Triangles.IndexBuffer = indexBuffer->GetGPUVirtualAddress(); geomDescs[0].Triangles.IndexCount = static_cast<UINT>(indexBuffer->GetDesc().Width) / sizeof(UINT16); geomDescs[0].Triangles.IndexFormat = DXGI_FORMAT_R16_UINT; geomDescs[0].Triangles.Transform3x4 = 0; geomDescs[0].Triangles.VertexFormat = DXGI_FORMAT_R32G32B32_FLOAT; geomDescs[0].Triangles.VertexCount = static_cast<UINT>(vertexBuffer->GetDesc().Width) / sizeof(Vertex); geomDescs[0].Triangles.VertexBuffer.StartAddress = vertexBuffer->GetGPUVirtualAddress(); geomDescs[0].Triangles.VertexBuffer.StrideInBytes = sizeof(Vertex); // 🧱 Get prebuild info D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS topLevelInputs[1]; topLevelInputs[0].DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY; topLevelInputs[0].Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE; topLevelInputs[0].NumDescs = 1; topLevelInputs[0].Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL; D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO topLevelPrebuildInfo = {}; device->GetRaytracingAccelerationStructurePrebuildInfo(topLevelInputs, topLevelPrebuildInfo); D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS bottomLevelInputs[1]; bottomLevelInputs[0] = topLevelInputs[0]; bottomLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL; bottomLevelInputs.pGeometryDescs = geomDescs; D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO bottomLevelPrebuildInfo = {}; device->GetRaytracingAccelerationStructurePrebuildInfo( &bottomLevelInputs, &bottomLevelPrebuildInfo); // 🍱 Create Scratch Buffer D3D12_RESOURCE_DESC asResourceDesc; asResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; asResourceDesc.Alignment = 0; asResourceDesc.Width = max(topLevelPrebuildInfo.ScratchDataSizeInBytes, bottomLevelPrebuildInfo.ScratchDataSizeInBytes); asResourceDesc.Height = 1; asResourceDesc.DepthOrArraySize = 1; asResourceDesc.MipLevels = 1; asResourceDesc.Format = DXGI_FORMAT_UNKNOWN; asResourceDesc.SampleDesc.Count = 1; asResourceDesc.SampleDesc.Quality = 0; asResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; asResourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; // 🍱 Create AS Scratch Buffer hr = device->CreateCommittedResource( &heapProps, D3D12_HEAP_FLAG_NONE, &asResourceDesc, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE, nullptr, IID_PPV_ARGS(&asScratchBuffer)); // 🍱 Create TLAS Buffer asResourceDesc.width = topLevelPrebuildInfo.ResultDataMaxSizeInBytes; hr = device->CreateCommittedResource( &heapProps, D3D12_HEAP_FLAG_NONE, &asResourceDesc, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE, nullptr, IID_PPV_ARGS(&tlasBuffer)); // 🍱 Create BLAS Buffer asResourceDesc.width = bottomLevelPrebuildInfo.ResultDataMaxSizeInBytes; hr = device->CreateCommittedResource( &heapProps, D3D12_HEAP_FLAG_NONE, &asResourceDesc, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE, nullptr, IID_PPV_ARGS(&blasBuffer)); D3D12_RAYTRACING_INSTANCE_DESC instanceDesc = {}; instanceDesc.Transform[0][0] = instanceDesc.Transform[1][1] = instanceDesc.Transform[2][2] = 1; instanceDesc.InstanceMask = 1; instanceDesc.AccelerationStructure = blasBuffer->GetGPUVirtualAddress(); D3D12_HEAP_PROPERTIES uploadHeapProperties = {}; uploadHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD; uploadHeapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; uploadHeapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; uploadHeapProperties.CreationNodeMask = 1; uploadHeapProperties.VisibleNodeMask = 1; D3D12_RESOURCE_DESC bufferDesc = {}; bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; bufferDesc.Alignment = 0; bufferDesc.Width = sizeof(instanceDesc); bufferDesc.Height = 1; bufferDesc.DepthOrArraySize = 1; bufferDesc.MipLevels = 1; bufferDesc.Format = DXGI_FORMAT_UNKNOWN; bufferDesc.SampleDesc.Count = 1; bufferDesc.SampleDesc.Quality = 0; bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; bufferDesc.Flags = D3D12_RESOURCE_FLAG_NONE; hr = device->CreateCommittedResource( &uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(instanceDescs)); void* pMappedData; (*instanceDescs)->Map(0, nullptr, &pMappedData); memcpy(pMappedData, &instanceDesc, sizeof(instanceDesc)); (*instanceDescs)->Unmap(0, nullptr); // 🏗️ BLAS build command D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC bottomLevelBuildDesc = {}; bottomLevelBuildDesc.Inputs = bottomLevelInputs; bottomLevelBuildDesc.ScratchAccelerationStructureData = scratchResource->GetGPUVirtualAddress(); bottomLevelBuildDesc.DestAccelerationStructureData = blasBuffer->GetGPUVirtualAddress(); // 🏗️ TLAS build command D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC topLevelBuildDesc = {}; topLevelInputs.InstanceDescs = instanceDescs->GetGPUVirtualAddress(); topLevelBuildDesc.Inputs = topLevelInputs; topLevelBuildDesc.DestAccelerationStructureData = tlasBuffer->GetGPUVirtualAddress(); topLevelBuildDesc.ScratchAccelerationStructureData = scratchResource->GetGPUVirtualAddress(); // 🏢 Execute build commandList->BuildRaytracingAccelerationStructure(&bottomLevelBuildDesc, 0, nullptr); D3D12_RESOURCE_BARRIER barrier = {}; barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; barrier.UAV.pResource = blasBuffer; commandList->ResourceBarrier(1, &barrier); commandList->BuildRaytracingAccelerationStructure(&topLevelBuildDesc, 0, nullptr);
C++
복사

Commands

레이트레이싱 파이프라인은 컴퓨트 파이프라인과 유사하지만, 전통적인 컴퓨트 dispatch에서처럼 그룹 단위가 아닌 주어진 커널 크기에 대해 dispatchRays를 수행합니다. 따라서 예를 들어 레디언스 버퍼의 각 픽셀에 대한 광선 집합으로 더 쉽게 이해할 수 있습니다.
commandList->SetComputeRootSignature(globalRootSignature); // 🌎 Bind global root signature descriptor data commandList->SetDescriptorHeaps(1, &srvHeap); commandList->SetComputeRootDescriptorTable(0, srvHeap->GetGPUDescriptorHandleForHeapStart()); // 🚞 Bind TLAS commandList->SetComputeRootShaderResourceView( 1, tlas->GetGPUVirtualAddress()); // ⚡ Setup dispatch description D3D12_DISPATCH_RAYS_DESC dispatchDesc = {}; dispatchDesc.Width = width; dispatchDesc.Height = height; dispatchDesc.Depth = 1; // 🏓 Shader Binding Tables dispatchDesc.RayGenerationShaderRecord.StartAddress = rayGenShaderTable->GetGPUVirtualAddress(); dispatchDesc.RayGenerationShaderRecord.SizeInBytes = rayGenShaderTable->GetDesc().Width; dispatchDesc.MissShaderTable.StartAddress = missShaderTable->GetGPUVirtualAddress(); dispatchDesc.MissShaderTable.SizeInBytes = missShaderTable->GetDesc().Width; dispatchDesc.MissShaderTable.StrideInBytes = dispatchDesc.MissShaderTable.SizeInBytes; dispatchDesc.HitGroupTable.StartAddress = hitShaderTable->GetGPUVirtualAddress(); dispatchDesc.HitGroupTable.SizeInBytes = hitShaderTable->GetDesc().Width; dispatchDesc.HitGroupTable.StrideInBytes = dispatchDesc.HitGroupTable.SizeInBytes; // 👨‍🔧 Setup Pipeline commandList->SetPipelineState1(pipelineState); // 🏁 Dispatch Rays commandList->DispatchRays(&dispatchDesc);
C++
복사

참고자료