// fark_hesap_gpu — CAD Fark GPU mesafe yolu (fark_enyakin.comp dispatch'i). // CPU'da kurulan IsinBvh düz dizileri SSBO'ya paketlenir; her sorgu vertexi bir // GPU is-ogesi olur. RTX-sınıfı kartta milyonlarca closest-point sorgusu tek // dispatch'te biter (CPU çok-çekirdeğe göre ~50-100×). Her hata yolunda false // döner — çağıran (farkHesapla) sessizce CPU'ya düşer, sonuç sözleşmesi aynı. #include #include #include "fiko/render/compute_baglam.hpp" #include "fiko/render/vulkan_baglam.hpp" #include "fiko/sahne/fark_hesap.hpp" #include "fiko/sahne/isin_bvh.hpp" namespace fiko { namespace { constexpr const char* kFarkSpv = "shader/fark_enyakin.comp.spv"; constexpr u32 kYaprakBit = 0x80000000u; constexpr u32 kYerelBoy = 128; // shader local_size_x ile eş struct FarkItme { u32 sorguSayi; }; } // namespace bool farkGpuMesafeKare(VulkanBaglam& vb, const IsinBvh& bvh, const Vec3f* hedefKonum, size_t hedefKonumSayi, const u32* hedefIndeks, size_t hedefIndeksSayi, const Vec3f* sorgular, size_t sorguSayi, std::vector& ciktiKare) { if (vb.aygitKayipMi() || bvh.dallar.empty() || sorguSayi == 0) return false; // yaprakBit b'nin üst bitini kullanır — taşma kontrolü (2^31 üstü indeks imkansız // ama sözleşmeyi belgele). for (const IsinBvh::Dal& d : bvh.dallar) if ((d.b & kYaprakBit) != 0) return false; ComputeBaglam comp(vb); ComputeBoruHatti boru(vb, kFarkSpv, 6, (u32)sizeof(FarkItme)); if (!boru.gecerli()) return false; // Dal paketleme: 2×vec4 — (asgari, bits(a)) + (azami, bits(b|yaprakBit)). std::vector dallarVeri(bvh.dallar.size() * 8); for (size_t i = 0; i < bvh.dallar.size(); ++i) { const IsinBvh::Dal& d = bvh.dallar[i]; f32* v = &dallarVeri[i * 8]; v[0] = d.kutu.asgari.x; v[1] = d.kutu.asgari.y; v[2] = d.kutu.asgari.z; std::memcpy(&v[3], &d.a, 4); v[4] = d.kutu.azami.x; v[5] = d.kutu.azami.y; v[6] = d.kutu.azami.z; const u32 bY = d.b | (d.yaprak ? kYaprakBit : 0u); std::memcpy(&v[7], &bY, 4); } SsboTampon dallarSsbo(vb, dallarVeri.size() * 4); SsboTampon ucgenSsbo(vb, bvh.ucgen.size() * 4); SsboTampon konumSsbo(vb, hedefKonumSayi * 12); SsboTampon indeksSsbo(vb, hedefIndeksSayi * 4); SsboTampon sorguSsbo(vb, sorguSayi * 12); SsboTampon ciktiSsbo(vb, sorguSayi * 4); if (!dallarSsbo.gecerli() || !ucgenSsbo.gecerli() || !konumSsbo.gecerli() || !indeksSsbo.gecerli() || !sorguSsbo.gecerli() || !ciktiSsbo.gecerli()) return false; dallarSsbo.yaz(dallarVeri.data(), dallarVeri.size() * 4); ucgenSsbo.yaz(bvh.ucgen.data(), bvh.ucgen.size() * 4); konumSsbo.yaz(hedefKonum, hedefKonumSayi * 12); indeksSsbo.yaz(hedefIndeks, hedefIndeksSayi * 4); sorguSsbo.yaz(sorgular, sorguSayi * 12); boru.bagla({dallarSsbo.tampon(), ucgenSsbo.tampon(), konumSsbo.tampon(), indeksSsbo.tampon(), sorguSsbo.tampon(), ciktiSsbo.tampon()}); const FarkItme itme{(u32)sorguSayi}; const u32 grup = (u32)((sorguSayi + kYerelBoy - 1) / kYerelBoy); const bool ok = comp.calis([&](VkCommandBuffer kb) { boru.dispatchKaydet(kb, &itme, sizeof(itme), grup, 1, 1); }); if (!ok) return false; ciktiKare.resize(sorguSayi); ciktiSsbo.oku(ciktiKare.data(), sorguSayi * 4); return true; } } // namespace fiko