| 132 | } |
| 133 | |
| 134 | Result run(GPUTasksContext* tasksContext) override |
| 135 | { |
| 136 | PROFILE_GPU_CPU("GPUModelSDFTask"); |
| 137 | GPUContext* context = tasksContext->GPU; |
| 138 | #if GPU_ALLOW_PROFILE_EVENTS |
| 139 | _timerQuery = context->BeginQuery(GPUQueryType::Timer); |
| 140 | #endif |
| 141 | |
| 142 | // Allocate resources |
| 143 | if (_shader == nullptr || _shader->WaitForLoaded()) |
| 144 | return Result::Failed; |
| 145 | GPUShader* shader = _shader->GetShader(); |
| 146 | const uint32 resolutionSize = _resolution.X * _resolution.Y * _resolution.Z; |
| 147 | auto cb = shader->GetCB(0); |
| 148 | Data data; |
| 149 | data.Resolution = _resolution; |
| 150 | data.ResolutionSize = resolutionSize; |
| 151 | data.MaxDistance = _sdf->MaxDistance; |
| 152 | data.WorldUnitsPerVoxel = _sdf->WorldUnitsPerVoxel; |
| 153 | data.VoxelToPosMul = _xyzToLocalMul; |
| 154 | data.VoxelToPosAdd = _xyzToLocalAdd; |
| 155 | data.BackfacesThreshold = _backfacesThreshold - 0.05f; // Bias a bit |
| 156 | |
| 157 | // Send BVH to the GPU |
| 158 | auto bvh = _scene->ToGPU(); |
| 159 | CHECK_RETURN(bvh.BVHBuffer && bvh.VertexBuffer && bvh.IndexBuffer, Result::Failed); |
| 160 | data.VertexStride = sizeof(Float3); |
| 161 | data.TriangleCount = bvh.IndexBuffer->GetElementsCount() / 3; |
| 162 | |
| 163 | // Dispatch in 1D and fallback to 2D when using large resolution |
| 164 | Int3 threadGroups(Math::CeilToInt((float)resolutionSize / ThreadGroupSize), 1, 1); |
| 165 | if (threadGroups.X > GPU_MAX_CS_DISPATCH_THREAD_GROUPS) |
| 166 | { |
| 167 | const uint32 groups = threadGroups.X; |
| 168 | threadGroups.X = Math::CeilToInt(Math::Sqrt((float)groups)); |
| 169 | threadGroups.Y = Math::CeilToInt((float)groups / threadGroups.X); |
| 170 | } |
| 171 | data.ThreadGroupsX = threadGroups.X; |
| 172 | |
| 173 | // Init constants |
| 174 | context->BindCB(0, cb); |
| 175 | context->UpdateCB(cb, &data); |
| 176 | |
| 177 | // Allocate output texture |
| 178 | auto sdfTextureDesc = GPUTextureDescription::New3D(_resolution.X, _resolution.Y, _resolution.Z, PixelFormat::R16_UNorm, GPUTextureFlags::UnorderedAccess); |
| 179 | // TODO: use transient texture (single frame) |
| 180 | auto sdfTexture = GPUTexture::New(); |
| 181 | #if GPU_ENABLE_RESOURCE_NAMING |
| 182 | sdfTexture->SetName(TEXT("SDFTexture")); |
| 183 | #endif |
| 184 | sdfTexture->Init(sdfTextureDesc); |
| 185 | |
| 186 | // Renders directly to the output texture |
| 187 | context->BindUA(0, sdfTexture->ViewVolume()); |
| 188 | |
| 189 | // Init the volume (rasterization mixes with existing contents) |
| 190 | context->Dispatch(shader->GetCS("CS_Init"), threadGroups.X, threadGroups.Y, threadGroups.Z); |
| 191 | |