Perbedaan antara "buffer" dan "array" di OpenGL?

12

Ketika saya membaca dokumen di webGL atau OpenGL dapat dilihat beberapa pola bagaimana nama fungsi dan objek digunakan. Tapi saya tidak bisa mengerti perbedaan antara objek buffer dan array.

Ada "objek buffer vertex", "objek array vertex" dan bahkan semacam "buffer array" atau "arraybuffer".

Dalam konteks OpenGL, Kapan sesuatu "array" dan kapan seharusnya disebut "buffer"?

coobit
sumber
Beberapa perspektif, pikirkan mengambil data melalui jaringan dan menyimpan log dari semua yang diterima. Anda perlu membaca soket dan meletakkan data yang diterima di suatu tempat sehingga Anda bisa menyebarkannya, itu buffer. Ini sering dapat berupa tipe daftar sederhana yang dialokasikan secara lokal dan dialokasikan secara dinamis. Terkadang sesederhana a char* buffer = socketRead();(pseudocode). Log di sisi lain, hidup melalui seluruh siklus hidup aplikasi. Jadi Anda membuat array di suatu tempat dan mulai membaca socket, kapan pun Anda mendapatkan data yang Anda tuliskan potongan itu ke array, memberi Anda daftar rapi semua data yang Anda terima.
Kevin

Jawaban:

5

Penamaan Objek Array Vertex agak disayangkan. Ada tiga hal berbeda yang muncul (dulu muncul) di / dengan / sekitar aplikasi Anda, dan yang (secara historis) dinamai berbeda, dengan "array" atau "buffer" pada namanya (well, ada juga objek framebuffer, tapi saya akan mengabaikan itu).

  1. Data yang hidup di aplikasi Anda, secara formal dan faktual, tetapi ditarik oleh OpenGL dalam sekali jalan (sebagai lawan dari vertex-by-vertex). Ini pada suatu waktu apa yang Anda sebut array vertex .
    Maksud dari ini adalah untuk membuat pengaksesan menjadi lebih efisien karena OpenGL hanya dapat menyalin semuanya sekaligus dalam waktu yang ditentukan ketika Anda memberikan janji bahwa data konsisten, dan mendorongnya ke atas AGP atau apa pun dalam satu blok. Ini tidak ada lagi.
  2. Data dikaburkan dan diakses oleh pegangan yang dapat "terikat", yaitu dibuat aktif. Data dapat secara faktual hidup dalam memori utama, atau pada kartu grafis, atau dipindahkan ke wilayah PCIe-mappable, apa pun, tetapi apa pun yang secara formal tidak Anda miliki (meskipun secara fisik dalam RAM dan jika data tersebut berasal dari aplikasi Anda ) itu - kecuali jika Anda saat ini telah "memetakan" melalui API yang sesuai, mendapatkan kembali pointer yang dapat ditulis (dan kadang-kadang dapat dibaca). Anda juga terbatas dalam kemampuan Anda mengendalikan apa yang terjadi pada data sama sekali (Anda dapat memberikan beberapa petunjuk, tetapi cukup banyak).
    OpenGL dapat memindahkan data ini lebih kurang atau lebih bebas, dan Anda hanya diizinkan / dapat menyalin ke / dari buffer melalui API yang sesuai atau mengakses data saat sedang dipetakan. Itulah yang Anda sebut objek penyangga ( objek penyangga verteks jika berisi simpul, tetapi sebenarnya tidak harus, bisa juga data gambar atau seragam, hanya simpul yang pertama kali didukung, satu kali).
    Maksudnya adalah untuk menjamin bahwa OpenGL dapat (pada prinsipnya) melakukan apa yang diinginkannya, bahkan dapat mendorong buffer lebih dari PCIe secara spekulatif bahkan sebelum Anda menggambar. Itu berfungsi karena Anda tidak memiliki data (OpenGL memilikinya!) Dan Anda hanya dapat mengaksesnya melalui API yang diberikan, sehingga diketahui setiap saat bahwa data itu valid. Pengemudi bahkan dapat memilih untuk membuang memori buffer pada kartu grafis ketika itu membutuhkan memori untuk sesuatu yang berbeda dan kemudian mengembalikannya dari salinan rahasia ketika diperlukan.
  3. Keliru yang benar-benar bodoh di mana nama yang jauh lebih baik akan menjadi sesuatu seperti buffer-set atau deskriptor-set, ini adalah objek array vertex yang terkenal . Dari sudut pandang Anda, itu tidak lain adalah satu set pegangan penyangga yang disatukan di bawah pegangan yang tidak jelas lainnya (yang dapat Anda ikat). Ketika itu terjadi, kenyataan sedikit lebih rumit. Bahkan, VAO jauh lebih dekat dengan cara kerja perangkat keras yang sebenarnya. Kartu grafis memiliki sejumlah kecil (sering sekitar 2, 4, atau 8) set deskriptor (tidak hanya untuk buffer, tetapi juga untuk sampler) dengan entri begitu-dan-begitu banyak di masing-masing, di mana mereka dapat beralih dengan sangat efisien .
    Sekarang, maksud dari objek array vertex adalah untuk mengurangi jumlah panggilan API dan untuk mengurangi jumlah pemeriksaan konsistensi yang harus dilakukan OpenGL secara internal, dan tentu saja, untuk menggunakan perangkat keras saat bekerja. Jika Anda mengikat 5 buffer, maka masing-masing harus melalui beberapa pemeriksaan yang mungkin mahal, dan masing-masing adalah kandidat untuk cache yang hilang dalam driver, ditambah setiap satu membutuhkan komunikasi dengan kartu grafis untuk mengubah deskriptor, dll. Jika Anda sebaliknya mengikat satu VAO, pengemudi dapat (sering) cukup mengganti deskriptor yang ditetapkan pada kartu grafis, dan dilakukan.
Damon
sumber
8

Vertex Array Object (VAO) adalah objek yang berisi satu atau lebih Objek Penyangga Vertex dan dirancang untuk menyimpan informasi untuk objek yang dirender lengkap.

(ditarik dari khronos )

Setiap buffer cenderung membentuk satu atribut array verteks (objek). VAO dapat berisi banyak atribut simpul (misalnya posisi, warna, UV). Masing-masing mungkin disimpan dalam buffernya sendiri, di mana buffer menunjukkan serangkaian byte yang berdekatan yang tidak diformat, dan di mana Anda perlu secara eksplisit menentukan ukuran (jenis) per elemen buffer untuk panggilan OpenGL sisi CPU dan kerja shader sisi GPU.

Itu satu arah. Cara lain ini bisa bekerja adalah:

  • Semua atribut disimpan disisipkan dalam satu buffer, OR
  • Beberapa atribut ada di buffer khusus mereka sendiri, sementara yang lain berbagi buffer.

Diagram di bawah ini menggambarkan dua kasus terakhir ini.

masukkan deskripsi gambar di sini

Intinya: Jika frasa "array vertex" digunakan tidak memenuhi syarat dalam OpenGL, Anda dapat menganggap itu berarti VAO, yang, dalam konteks OpenGL (khusus) memang sangat berbeda dari buffer.

Sunting komentar Anda: GL_ARRAY_BUFFERmenunjukkan niat untuk menggunakan objek buffer itu untuk data atribut vertex, seperti dijelaskan di atas. Ini karena buffer tidak hanya digunakan untuk atribut vertex. Namun, karena ini adalah kasus penggunaan yang paling umum dan Anda bertanya tentang VAO, saya tidak akan membahas yang lain; Namun di sini adalah daftar tipe buffer lain yang dapat diatur.

Insinyur
sumber
Jadi penyangga adalah: 1. berada di GPU, 2. sebagian besar waktu mengandung satu jenis data (hanya simpul, hanya warna dll), 3. Data disisipkan, yaitu 111122223333 dll. 4. tidak menyediakan metode untuk mengakses data (bukan buffer [2] atau buffer [vertex_3434]) Sekarang, array adalah: 1. koleksi buffer, 2. menyimpan informasi tentang cara mengurai buffer yang dikandungnya (yaitu array store stride , ukuran elemen, offset, sehingga data dari buffer dapat diakses dengan benar.
coobit
1. Buffer ada di kedua ujungnya dan transfer antara CPU dan GPU (potensial DAN balik), jika tidak, bagaimana cara Anda mengisi data yang akan diunggah ke GPU saat memuat mesh dari disk ?. Ya, elemen-elemen memiliki tipe seragam di seluruh buffer, tetapi tergantung pada teknologi yang Anda gunakan, setiap elemen buffer dapat berupa primitif atau structtipe. Data dapat disisipkan atau sepenuhnya seragam, per buffer. Anda dapat mengindeks ke dalamnya, sama seperti dengan array C tradisional pada CPU. Array objek (gunakan terminologi yang benar ini atau berakhir membingungkan Anda sendiri!) ... (lanjutan di bawah)
Insinyur
2. Ya, dan Anda perlu memastikan secara eksplisit deklarasi buffer in-shader Anda akan cocok dengan spesifikasi yang Anda tetapkan pada VAO Anda di sisi CPU: "Semua negara yang terkait dengan definisi data yang digunakan oleh prosesor vertex dienkapsulasi dalam sebuah vertex objek array. " (khronos docs)
Insinyur
Jadi, hanya untuk memukul lebih banyak ... Bagaimana orang bekerja sebelum AO hanya menggunakan BO? Atau AO selalu hadir di OpenGL dan itu hanya VAO yang diperkenalkan kemudian VBO?
coobit
@coobit io7m.com/documents/history-vertex-spec - ini memberi Anda gambaran tentang perbedaan antara OpenGL pipeline (old school), 3Dfx dll. dan OpenGL pipeline dan Direct3D yang modern dan dapat diprogram.
Insinyur
5

Terminologi ini berakar pada sejarah OpenGL. Yang penting untuk diingat adalah bahwa, untuk sebagian besar versi GL yang relevan di sini, OpenGL berevolusi secara bertahap dan dengan menambahkan fungsionalitas baru ke API yang sudah ada daripada mengubah API.

Versi pertama OpenGL tidak memiliki tipe objek ini. Menggambar dicapai dengan mengeluarkan beberapa panggilan glBegin / glEnd, dan satu masalah dengan model ini adalah bahwa itu sangat tidak efisien, dalam hal fungsi panggilan overhead.

OpenGL 1.1 mengambil langkah pertama untuk mengatasinya dengan memperkenalkan array vertex. Alih-alih secara langsung menentukan data titik Anda sekarang dapat sumbernya dari array C / C ++ - karenanya namanya. Jadi array vertex hanya itu - array verteks dan status GL yang diperlukan untuk menentukannya.

Evolusi besar berikutnya datang dengan GL 1.5 dan memungkinkan menyimpan data array vertex dalam memori GPU daripada dalam memori sistem ("sisi klien"). Kelemahan dari spesifikasi vertex array GL 1.1 adalah set lengkap data vertex harus ditransfer ke GPU setiap kali Anda ingin menggunakannya; jika sudah ada pada GPU maka transfer ini dapat dihindari dan potensi peningkatan kinerja tercapai.

Jadi tipe objek GL baru dibuat untuk memungkinkan penyimpanan data ini pada GPU. Sama seperti objek tekstur digunakan untuk menyimpan data tekstur, objek buffer verteks menyimpan data verteks. Ini sebenarnya hanya kasus khusus dari tipe objek buffer yang lebih umum yang dapat menyimpan data non-spesifik.

API untuk menggunakan objek vertex buffer didukung oleh API array vertex yang sudah ada, itulah sebabnya Anda melihat hal-hal aneh seperti mengonversi byte offset ke pointer di dalamnya. Jadi sekarang kita memiliki API array vertex yang baru saja menyimpan status, dengan data yang bersumber dari objek buffer daripada dari dalam array memori.

Ini membawa kita hampir ke akhir cerita kita. API yang dihasilkan cukup bertele-tele ketika menentukan keadaan array vertex, jadi jalan lain optimasi adalah membuat tipe objek baru yang mengumpulkan semua state ini bersama-sama, memungkinkan beberapa perubahan status array vertex dalam satu panggilan API, dan memungkinkan GPU untuk berpotensi melakukan optimasi karena dapat mengetahui keadaan apa yang akan digunakan sebelumnya.

Masukkan objek array vertex, yang mengumpulkan semua ini bersama-sama.

Jadi, untuk meringkas, array vertex mulai hidup sebagai kumpulan status dan data (disimpan dalam array) untuk menggambar. Sebuah penyangga vertex menggantikan di memori penyimpanan array dengan tipe GL objek, meninggalkan berbagai titik hanya menjadi negara. Sebuah benda titik array yang hanya objek wadah untuk negara ini, yang memungkinkan untuk diubah lebih mudah dan dengan sedikit panggilan API.

Maximus Minimus
sumber
0

Saya belum pernah bekerja dengan OpenGL dalam beberapa saat, jadi saya mungkin hanya setengah benar. Secara umum: Buffer menyimpan array memori yang belum diformat. Array adalah istilah umum dari memori yang berdekatan.

Buffer harus diikat ke konteks, sedangkan array hanyalah sebuah array data. Jika saya ingat dengan benar, data dalam buffer dimaksudkan untuk disalin ke kartu grafis (karenanya mengikat).

Semoga ini bisa membantu sedikit

Juicef
sumber
Apa itu GL_ARRAY_BUFFER? Mengapa disebut demikian? Menurut hipotesis Anda, ini adalah "memori berdampingan yang tidak diformat" :)
coobit
Nah, contoh khusus ini hanya id ke buffer (yang Anda ikat array Anda). Array Buffer (dalam contoh Anda) digunakan untuk atribut vertex, jadi pada dasarnya Anda mengikat array atribut vertex Anda ke buffer. Kedengarannya membingungkan jadi izinkan saya memberi Anda sebuah contoh. Anda memiliki beberapa larik di sisi cpu yang bisa berupa warna, normal, posisi, dll, dan sekarang Anda ingin gpu mengaksesnya. Itulah ketika bindBuffer masuk, pada dasarnya memetakan "cpu-array" Anda ke "gpu-array".
Juicef
Mengapa disebut demikian, saya tidak bisa menjawabnya. Saya kira itu karena Anda memiliki berbagai data berbeda yang masuk ke sana, warna, normal, dll.
Juicef