OpenGL'de “buffer” ve “array” arasındaki fark nedir?


12

WebGL veya OpenGL'de doc okuduğumda, işlevlerin ve nesnelerin adlarının nasıl kullanıldığına dair bazı desenler görülebilir. Ancak buffer nesnesi ile bir dizi arasındaki farkı anlayamıyorum.

"Köşe tampon nesneleri", "köşe dizisi nesneleri" ve hatta bir çeşit "tampon dizisi" veya "dizi tamponu" vardır.

OpenGL bağlamında, Ne zaman bir şey "dizi" ve ne zaman "tampon" olarak adlandırılmalıdır?


Bazı bakış açıları, ağ üzerinden veri almayı ve alınan her şeyin kaydını tutmayı düşünün. Soketi okumanız ve alınan verileri bir yere koymanız gerekir, böylece etrafından geçebilirsiniz, bu bir tampon. Genellikle yerel olarak kapsamlı, dinamik olarak ayrılmış basit bir liste türü olabilir. Bazen bir char* buffer = socketRead();(sözde kod) kadar basittir . Diğer yandan günlük, tüm uygulama yaşam döngüsü boyunca yaşar. Böylece bir yerde bir dizi oluşturursunuz ve soketi okumaya başlıyorsunuz, diziye yazdığınız verileri her aldığınızda, aldığınız tüm verilerin temiz bir listesini verir.
Kevin

Yanıtlar:


5

Vertex Array Nesnesinin adlandırılması biraz talihsizdir. Uygulamanızda / çevresinde / çevresinde görünen (farklı olarak adlandırılan) üç farklı şey vardır ve bunlar (tarihsel olarak) farklı bir şekilde adlandırılmıştır, adında "dizi" veya "arabellek" (Eh, çerçeve tamponu nesneleri de vardır, ama bunu görmezden geleceğim).

  1. Başvurunuzda resmi olarak ve gerçekte yaşayan, ancak bir seferde OpenGL tarafından çekilen (tepe noktaya göre değil) veriler. Bu, bir zamanlar vertex dizisi dediğiniz şeydi .
    Bunun amacı, erişimin daha verimli olmasını sağlamaktı çünkü OpenGL, verilerin tutarlı olduğuna dair söz verdiğinizde her şeyi iyi tanımlanmış bir zamanda tek seferde kopyalayabiliyordu ve AGP'yi veya tek bir blokta olanı itiyordu. Bu artık mevcut değil.
  2. "Bağlanabilir", yani aktif hale getirilebilen bir tutamaç tarafından gizlenmiş ve erişilebilir veriler. Veri olabilir ana bellekte olgusal canlı veya grafik kartında veya her neyse, ama her iki şekilde PCIe Haritalanabilir bölgeye taşınacak resmen bilgi verilmesi başvurunun geldiği RAM, ve eğer fiziksel olarak bile (değil kendi yapmak ) - şu anda ilgili API aracılığıyla "eşlemediyseniz", yazılabilir (ve bazen okunabilir) bir işaretçi geri alabilirsiniz. Ayrıca, verilere ne olduğunu kontrol etme yeteneğiniz de sınırlıdır (bazı ipuçları verebilirsiniz, ancak neredeyse bu kadar).
    OpenGL, bu verileri daha fazla veya daha az serbestçe hareket ettirebilir ve yalnızca karşılık gelen API aracılığıyla ara belleğe / arabellekten kopyalanabilir / kopyalanabilir veya eşlenirken verilere erişebilirsiniz. Bu bir tampon nesnesi olarak adlandırdığınız şeydir (köşe noktaları içeriyorsa köşe tampon nesnesi, ancak gerçekten görüntü verisi veya üniforma olması gerekmiyor, sadece bir zamanlar desteklenecek ilk köşelerdi).
    Bunun amacı OpenGL'nin (prensip olarak) istediklerini yapabileceğini garanti etmek, hatta çizmeden önce tamponu bile PCIe üzerinde spekülatif olarak itebilir. Bu, verilerin sahibi olmadığınız (OpenGL var!) Ve yalnızca verilen API aracılığıyla erişebileceğiniz için çalışır, bu nedenle verilerin geçerli olduğu her zaman bilinir. Sürücü, farklı bir şey için belleğe ihtiyaç duyduğunda grafik kartına arabellek atmayı seçebilir ve daha sonra gerektiğinde gizli kopyasından geri yükleyebilir.
  3. Çok daha iyi bir adın arabellek kümesi veya tanımlayıcı kümesi gibi bir şey olacağı gerçekten aptal bir yanlış adlandırma, bu rezil köşe dizisi nesnesidir . Sizin bakış açınızdan, başka bir belirsiz tutamağın altında birleştirilen bir dizi tampon tutamağından başka bir şey değildir (bu da bağlayabilirsiniz). Olduğu gibi, gerçeklik biraz daha karmaşıktır. Aslında, VAO gerçek donanımın çalışma şekline çok daha yakın. Grafik kartlarında, aralarında çok verimli geçiş yapabildikleri çok sayıda giriş içeren az sayıda (genellikle 2, 4 veya 8 gibi bir şey) tanımlayıcı kümeleri (yalnızca arabellekler için değil, aynı zamanda örnekleyiciler için) vardır. .
    Şimdi, köşe dizisi nesnesinin amacı, API çağrılarının sayısını azaltmak ve OpenGL'nin dahili olarak yapması gereken tutarlılık denetimlerinin sayısını azaltmak ve elbette donanımı olduğu gibi kullanmaktır. 5 arabellek bağlarsanız, her birinin olası pahalı denetimlerden geçmesi gerekir ve her biri sürücüdeki önbellek özlemeleri için bir adaydır, ayrıca her birinin bir tanımlayıcıyı vb. Değiştirmek için grafik kartıyla iletişim kurması gerekir. bir VAO bağlayın, sürücü (genellikle) basitçe grafik kartındaki tanımlayıcıyı değiştirebilir ve yapılabilir.

8

Vertex Array Nesnesi (VAO), bir veya daha fazla Vertex Buffer Nesnesi içeren bir nesnedir ve tamamlanmış bir nesne için bilgileri saklamak üzere tasarlanmıştır.

( khronos'tan çekilmiş )

Her arabellek, bir köşe dizisinin (nesne) bir niteliğini oluşturma eğilimindedir. Bir VAO birçok tepe noktası özelliği içerebilir (örn. Konum, renk, UV). Her biri kendi arabelleğinde tutulabilir, burada tampon biçimlendirilmemiş bir bitişik bayt serisini gösterir ve hem CPU tarafı OpenGL çağrıları hem de GPU tarafı gölgelendirici çalışması için tampon öğesi başına boyutu (tür) açıkça belirtmeniz gerekir.

Bu bir yol. Bunun çalışabileceği diğer yollar:

  • Tüm öznitelikler, tek bir arabellekte araya eklenmiş olarak saklanır , VEYA
  • Bazı özellikler kendi ayrılmış arabelleklerinde bulunurken, diğerleri arabellekleri paylaşır.

Aşağıdaki şemada bu son iki durum gösterilmektedir.

resim açıklamasını buraya girin

Alt satır: "Köşe dizisi" ifadesi OpenGL'de niteliksiz olarak kullanılıyorsa, bunun bir OpenGL bağlamında (özellikle) gerçekten bir arabellekten çok farklı bir şey olduğu VAO anlamına geldiğini varsayabilirsiniz.

Yorumunuzu DÜZENLE: GL_ARRAY_BUFFERbu tampon nesnesini yukarıda açıklandığı gibi köşe özniteliği verileri için kullanma niyetini belirtir. Bunun nedeni, arabelleklerin yalnızca köşe özellikleri için kullanılmamasıdır . Ancak, en yaygın kullanım örneği olduğu ve VAO'ları sorduğunuz için, diğerlerine girmeyeceğim; ancak burada ayarlanabilecek diğer tampon türlerinin bir listesi bulunmaktadır.


Yani tamponlar : 1. GPU'da bulunur, 2. çoğu zaman bir tür veri içerir (sadece tepe noktası, sadece renk vb), 3.Veri araya eklenmiştir, yani 111122223333 vb. 4. verilere erişmek için hiçbir yöntem sağlama (tampon [2] veya tampon [vertex_3434] değil) Şimdi, diziler şunlardır: 1. tamponların toplanması, 2. içerdiği tamponların ayrıştırılması hakkında bilgi depolar. bir element, ofset, büyüklüğü tamponlar gönderilen verinin doğru ulaşılabilir böylece doğru.?
coobit

1. Her iki uçta da arabellekler bulunur ve CPU ile GPU arasında aktarım (potansiyel olarak ileri ve geri), yoksa diskten mesh yüklerken GPU'ya yüklenecek verileri nasıl doldurursunuz ?. Evet, öğeler tampon boyunca tek tiptir, ancak kullandığınız teknolojiye bağlı olarak, her tampon elemanı bir ilkel veya bir structtip olabilir. Veriler , arabellek başına serpiştirilebilir veya tamamen homojen olabilir . CPU'da geleneksel bir C dizisinde olduğu gibi bunlara dizin oluşturabilirsiniz. Dizi nesneleri (bu doğru terminolojiyi kullanın veya kendinizi karıştırın!) ... (aşağıda devam ediyor)
Mühendis

2. Evet, ve köşe işlemci tarafından kullanılan verileri tanımına ilişkin tüm devlet bir tepe içinde hapsedilmiştir": Eğer emin içinde tarayıcılı tampon bildirimleri CPU tarafta VAO ayarlanmış olan spesifikasyonları maç olacak açıkça yapmak gerekir dizi nesnesi. " (Khronos Docs)
Mühendis

Yani, sadece çiviye daha fazla vurmak için ... İnsanlar sadece BO kullanarak AO'dan önce nasıl çalıştı? Yoksa AO her zaman OpenGL'de mevcuttu ve daha sonra VBO'dan sonra tanıtılan sadece VAO?
coobit

@coobit io7m.com/documents/history-vertex-spec - bu size sabit boru hattı (eski okul) OpenGL, 3Dfx vb. ile modern, programlanabilir boru hattı OpenGL ve Direct3D arasındaki farklar hakkında bir fikir verir.
Mühendis

5

Bu terminoloji, OpenGL tarihine dayanır. Unutulmaması gereken, burada alakalı olan GL sürümlerinin çoğu için OpenGL'nin aşamalı olarak ve API'yi değiştirmek yerine mevcut bir API'ye yeni işlevler ekleyerek geliştiğidir.

OpenGL'nin ilk sürümünde bu nesne türlerinden hiçbiri yoktu. Çizim birden fazla glBegin / glEnd çağrısı yapılarak sağlandı ve bu modelle ilgili bir problem, fonksiyon çağrısı yükü açısından çok verimsiz olmasıydı.

OpenGL 1.1, tepe dizileri tanıtarak bu sorunu gidermek için ilk adımları atmıştır. Köşe verilerini doğrudan belirtmek yerine artık C / C ++ dizilerinden kaynaklayabilirsiniz - dolayısıyla adı. Yani bir köşe dizisi sadece - bir dizi köşe ve bunları belirtmek için gereken GL durumu.

Bir sonraki büyük evrim GL 1.5 ile geldi ve köşe dizisi verilerinin sistem ("istemci tarafı") belleğinden ziyade GPU belleğinde depolanmasına izin verdi. GL 1.1 köşe dizisi spesifikasyonunun zayıflığı, her köşe verisi setinin her kullanmak istediğinizde GPU'ya aktarılması gerektiğiydi; zaten GPU'daysa, bu aktarımdan kaçınılabilir ve potansiyel performans kazanımları elde edilebilir.

Bu nedenle, bu verilerin GPU'da depolanmasına izin vermek için yeni bir GL nesnesi türü oluşturuldu. Tıpkı bir doku nesnesinin doku verilerini depolamak için kullanıldığı gibi, bir tepe tamponu nesnesi tepe verilerini saklar. Bu aslında sadece spesifik olmayan verileri depolayabilen daha genel bir tampon nesne tipinin özel bir durumudur.

Köşe tamponu nesnelerini kullanma API'si zaten mevcut köşe dizileri API'sında piggy-back olarak kullanıldı, bu yüzden bayt ofsetlerini içindeki işaretçilere dönüştürmek gibi garip şeyler görüyorsunuz. Şimdi verileri depolayan bir köşe dizisi API'sine sahibiz, veriler bellek içi dizilerden ziyade arabellek nesnelerinden kaynaklanmaktadır.

Bu bizi neredeyse hikayemizin sonuna getiriyor. Sonuçta ortaya çıkan API, köşe dizisi durumunu belirtme söz konusu olduğunda oldukça ayrıntılıydı, bu nedenle başka bir optimizasyon yolu, bu durumun tümünü bir araya toplayan, tek bir API çağrısında birden fazla köşe dizisi durumu değişikliğine izin veren ve GPU'lara izin veren yeni bir nesne türü oluşturmaktı. önceden hangi durumun kullanılacağını bilmesi nedeniyle potansiyel olarak optimizasyon yapmak.

Tüm bunları bir araya getiren köşe dizisi nesnesini girin.

Özetlemek gerekirse, bir tepe dizisi , çizim için durum ve veri (bir dizide depolanan) koleksiyonu olarak hayata başladı. Bir köşe arabelleği , bellek içi dizi depolamasını bir GL nesne türüyle değiştirir ve köşe dizisini yalnızca durum olarak bırakır . Bir köşe dizisi nesnesi , bu durum için yalnızca bir kapsayıcı nesnesidir ve daha kolay ve daha az API çağrısı ile değiştirilmesine izin verir.


0

Bir süredir OpenGL ile çalışmadım, bu yüzden sadece yarı sağ olabilirim. Genel olarak konuşursak: Tamponlar, biçimlendirilmemiş bir dizi belleği saklar. Dizi, bitişik belleğin genel bir terimidir.

Bir arabellek bağlama bağlanırken bir dizi sadece bir veri dizisidir. Doğru hatırlıyorsam, arabellekteki verilerin grafik kartına kopyalanması amaçlanır (dolayısıyla ciltleme).

Umarım bu biraz yardımcı olur


O zaman GL_ARRAY_BUFFER nedir? Neden böyle deniyordu? Size göre hipotez "Biçimlendirilmemiş bitişik bellek" :)
coobit

Peki, bu özel örnek sadece bir arabellek (dizinizi bağladığınız) için bir kimliktir. Dizi Arabelleği (örneğinizde) köşe özellikleri için kullanılır, bu nedenle temel olarak köşe özelliği dizinizi bir arabelleğe bağlarsınız. Kafa karıştırıcı geliyor bu yüzden size bir örnek vereyim. İşlemci tarafında renkli, normal, pozisyonlar vb. Olabilen bir dizi var ve şimdi gpu'nun ona erişmesini istiyorsunuz. Bu bindBuffer geldiğinde, temel olarak "cpu dizinizi" "gpu dizisine" eşler.
Juicef

Neden böyle çağrıldığına gelince, buna cevap veremem. Ben orada, renk, normal, vb farklı veri dizi var çünkü
varsayalım
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.