2012-01-23 10 views
21

मैं हाल ही में शीर्ष सरणी वस्तुओं के साथ कुछ ओपन 3.3 कोड (VAO) लेखन और बाद में इंटेल ग्राफिक्स एडाप्टर, जहां मैं अपने निराशा करने के लिए मिल गया है, पर यह परीक्षण किया गया था, उस तत्व सरणी बफर बाध्यकारी जाहिर नहीं है VAO राज्य का हिस्सा है, बुला के रूप में:VAO और तत्व सरणी बफर राज्य

glBindVertexArray(my_vao); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, my_index_buffer); // ? 
glDrawElements(GL_TRIANGLE_STRIP, count, GL_UNSIGNED_INTEGER, 0); 

ज्यामिति गाया:

glBindVertexArray(my_vao); 
glDrawElements(GL_TRIANGLE_STRIP, count, GL_UNSIGNED_INTEGER, 0); 

जबकि, कोई प्रभाव नहीं पड़ा। मैंने सोचा कि यह ओपन (क्योंकि यह स्पष्ट रूप से (और GL_ARB_vertex_array_object में कहा गया है यहां तक ​​कि GL_OES_vertex_array_object में) उस तत्व सरणी बचाया राज्य के हिस्सा है) का इंटेल कार्यान्वयन में एक मात्र बग था, लेकिन तब यह मोबाइल NVIDIA Quadro 4200 पर हुई है कि कोई मज़ा नहीं।

क्या यह एक ड्राइवर बग, एक चश्मा बग, या मेरे कोड में कहीं एक बग है? कोड GeForce 260 और 480 पर बेकार ढंग से काम करता है।

किसी के पास समान अनुभव था?

क्या भी अजीब बात है कि GL_EXT_direct_state_access VAO को एक तत्व सरणी बफर बाध्य करने के लिए एक समारोह नहीं है (लेकिन यह शीर्ष attrib सरणियों, और इसलिए सरणी बफ़र्स निर्दिष्ट करने के लिए कार्य करता है) है। क्या जीपीयू निर्माता चश्मे को धोखा दे रहे हैं और धोखाधड़ी कर रहे हैं, या क्या?

संपादित:

मैं मूल रूप से, क्योंकि मैं मानना ​​था कि यह यहाँ आवश्यक नहीं था किसी भी स्रोत कोड को दिखाने के लिए इरादा नहीं था। लेकिन के रूप में अनुरोध, यहाँ कम से कम परीक्षण का मामला है कि समस्या को पुनरुत्पादित करता है:

static GLuint n_vertex_buffer_object, p_index_buffer_object_list[3]; 
static GLuint p_vao[2]; 

bool InitGLObjects() 
{ 
    const float p_quad_verts_colors[] = { 
     1, 0, 0, -1, 1, 0, 
     1, 0, 0, 1, 1, 0, 
     1, 0, 0, 1, -1, 0, 
     1, 0, 0, -1, -1, 0, // red quad 
     0, 0, 1, -1, 1, 0, 
     0, 0, 1, 1, 1, 0, 
     0, 0, 1, 1, -1, 0, 
     0, 0, 1, -1, -1, 0, // blue quad 
     0, 0, 0, -1, 1, 0, 
     0, 0, 0, 1, 1, 0, 
     0, 0, 0, 1, -1, 0, 
     0, 0, 0, -1, -1, 0 // black quad 
    }; 
    const unsigned int p_quad_indices[][6] = { 
     {0, 1, 2, 0, 2, 3}, 
     {4, 5, 6, 4, 6, 7}, 
     {8, 9, 10, 8, 10, 11} 
    }; 
    glGenBuffers(1, &n_vertex_buffer_object); 
    glBindBuffer(GL_ARRAY_BUFFER, n_vertex_buffer_object); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(p_quad_verts_colors), p_quad_verts_colors, GL_STATIC_DRAW); 
    glGenBuffers(3, p_index_buffer_object_list); 
    for(int n = 0; n < 3; ++ n) { 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p_index_buffer_object_list[n]); 
     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(p_quad_indices[n]), p_quad_indices[n], GL_STATIC_DRAW); 
    } 

    glGenVertexArrays(2, p_vao); 
    glBindVertexArray(p_vao[0]); 
    { 
     glBindBuffer(GL_ARRAY_BUFFER, n_vertex_buffer_object); 
     glEnableVertexAttribArray(0); 
     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), p_OffsetInVBO(0)); 
     glEnableVertexAttribArray(1); 
     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), p_OffsetInVBO(3 * sizeof(float))); 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p_index_buffer_object_list[0]); // red 
    } 
    glBindVertexArray(0); 

    glBindVertexArray(p_vao[1]); 
    { 
     glBindBuffer(GL_ARRAY_BUFFER, n_vertex_buffer_object); 
     glEnableVertexAttribArray(0); 
     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), p_OffsetInVBO(0)); 
     glEnableVertexAttribArray(1); 
     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), p_OffsetInVBO(3 * sizeof(float))); 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p_index_buffer_object_list[1]); // blue 
    } 
    glBindVertexArray(0); 

#ifdef BIND_BLACK_QUAD_ELEMENT_ARRAY_BUFFER 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p_index_buffer_object_list[2]); 
    // bind the buffer with the black quad (not inside VAO, should NOT be seen) 
#endif // BIND_BLACK_QUAD_ELEMENT_ARRAY_BUFFER 

    // [compile shaders here] 

    return true; // success 
} 

ऊपर कोड तीन quads, लाल एक, नीले और काले एक एक युक्त एक शीर्ष बफर पैदा करता है। फिर यह तीन सूचकांक बफर बनाता है जो व्यक्तिगत quads को इंगित करता है। फिर दो वीएओ बनाए जाते हैं और स्थापित होते हैं, एक में लाल क्वाड इंडेक्स होना चाहिए और दूसरे में ब्लू क्वाड इंडेक्स होना चाहिए। ब्लैक क्वाड को बिल्कुल प्रस्तुत नहीं किया जाना चाहिए (मान लें कि BIND_BLACK_QUAD_ELEMENT_ARRAY_BUFFER परिभाषित है)।

void onDraw() 
{ 
    glClearColor(.5f, .5f, .5f, 0); 
    glClear(GL_COLOR_BUFFER_BIT); 
    glDisable(GL_DEPTH_TEST); 

    glUseProgram(n_program_object); 

    static int n_last_color = -1; 
    int n_color = (clock()/2000) % 2; 
    if(n_last_color != n_color) { 
     printf("now drawing %s quad\n", (n_color)? "blue" : "red"); 
     n_last_color = n_color; 
    } 

    glBindVertexArray(p_vao[n_color]); 
#ifdef VAO_DOESNT_STORE_ELEMENT_ARRAY_BUFFER 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p_index_buffer_object_list[n_color]); // fixes the problem 
#endif // VAO_DOESNT_STORE_ELEMENT_ARRAY_BUFFER 
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 
    glBindVertexArray(0); 
} 

यह व्यूपोर्ट ग्रे को साफ करता है और तरीके से दोहरा में या तो नीला या लाल ट्रैक्टर renders (यह भी प्रिंट जो एक)। हालांकि यह डेस्कटॉप जीपीयू पर काम करता है, यह नोटबुक जीपीयू पर काम नहीं करता है (ब्लैक क्वाड तब तक प्रस्तुत किया जाता है जब तक कि VAO_DOESNT_STORE_ELEMENT_ARRAY_BUFFER मैक्रो परिभाषित नहीं किया जाता है। BIND_BLACK_QUAD_ELEMENT_ARRAY_BUFFER मैक्रो को परिभाषित करना क्वाड ब्लू बनाता है, क्योंकि ब्लू इंडेक्स बफर आखिरी है। लेकिन यह नहीं है लाल ट्रैक्टर कोई फर्क नहीं पड़ता प्रस्तुत करना क्या।

तो जिस तरह से मैं इसे देख, यह या तो कैसे काम करते हैं, मेरी कोड में एक बग, या एक ड्राइवर बग Vao चाहिए की मेरी समझ में एक घातक गलत धारणा है।

Full source
Binaries (windows, 32 bit)

+6

यह अधिक संभावना है कि आपका कोड प्रारंभ में वीएओ में तत्व बफर नहीं डाल रहा है। आप हमें अपना वीएओ प्रारंभिक कोड क्यों नहीं दिखाते हैं। –

+7

ओह आओ, बेवकूफ नहीं। इसके अलावा मैंने कहा कि यह GeForce 260/480 पर काम करता है। टिप्पणियां लिखने से पहले पोस्ट पढ़ें। मैं अपने ओपनजीएल कोड को डीबग करने में पूरी तरह से सक्षम हूं। यह प्रश्न ओपनजीएल कार्यान्वयन और संगतता के बीच मतभेदों के बारे में है। –

+6

सिर्फ इसलिए कि कोड काम का मतलब यह नहीं है कि यह * सही * है। चाहे सौहार्दपूर्ण परिस्थिति या जो कुछ भी हो, कोड काम करने में सक्षम हो सकता है। तथ्य यह है कि यह दोनों एनवीआईडीआईए ड्राइवरों में विफल रहता है और सफल होता है उपयोगकर्ता त्रुटि का सुझाव देता है। अगर यह एनवीआईडीआईए पर काम करता है और एटीआई में विफल रहता है, या इसके विपरीत, यह ड्राइवर बग होने की अधिक संभावना होगी। लेकिन एनवीआईडीआईए विशेष रूप से बहुत ही समान है। तो अगर यह कभी-कभी कुछ एनवीआईडीआईए हार्डवेयर पर काम करता है और कभी-कभी ऐसा नहीं होता है, तो यह उपयोगकर्ता त्रुटि की तरह लगता है। –

उत्तर

22

कुछ समय बाद, मुझे पता चला कि यह वास्तव में मेरा बुरा था। मोबाइल एनवीआईडीआईए क्वाड्रो 4200 ग्राफिक्स कार्ड वाला लैपटॉप सेट किया गया था ताकि सभी ऐप डिफ़ॉल्ट रूप से इंटेल ग्राफिक्स पर चल सकें, भले ही लैपटॉप प्रदर्शन मोड में था।मुझे समझ में नहीं आ रहा है कि कोई ऐसा क्यों करना चाहेगा, तब किसी भी एप्लिकेशन को ओपनजीएल से अधिक शक्तिशाली जीपीयू का उपयोग करने का कोई तरीका नहीं था (ओपनसीएल के लिए इसका उपयोग करना अभी भी संभव था क्योंकि स्पष्ट डिवाइस चयन भी है, शायद डायरेक्टएक्स - यह समझाएगा कि कुछ गेम सुचारू रूप से क्यों चलते हैं)।

फिर भी, वर्णित गलत व्यवहार इंटेल ड्राइवरों में बस एक बग है, यह सब कुछ है। इंटेल ड्राइवर ELEMENT_ARRAY_BUFFER_BINDING को सहेजते नहीं हैं। क्या आप वहां मौजूद हैं.

मुझे सवाल पूछने के लिए ईमानदारी से खेद है, क्योंकि उपरोक्त को जानने के बिना कोई अच्छा जवाब देने का कोई तरीका नहीं था।

+0

क्या आपने इंटेल के साथ एक बग फाइल किया था? इस कहानी पर कोई फॉलो अप? दुनिया में ऐसे सूक्ष्म मुद्दों को जानना एक नौसिखिया ग्राफिक्स प्रोग्रामर के रूप में मुझे गहराई से परेशान करता है। – Philip

+0

@ फिलिप मैंने यह नहीं माना है, मैं इंटेल को इंटेल को एक प्रयोग योग्य जीपीयू पर विचार करता हूं इसलिए मेरे लिए यह कहना आसान था कि मैं इंटेल जीपीयू का समर्थन नहीं करूंगा। लेकिन शायद यह एक अच्छा विचार है। यदि आप ऐसा करते हैं, तो कृपया टिप्पणी में बग ट्रैकर को एक लिंक पोस्ट करें। धन्यवाद। –

+7

भले ही यह आपके लिए सहायक न हो, भले ही एसओ पर दस्तावेज किया गया ड्राइवर बग मेरे लिए सहायक था। – Justin

17

मुझे वास्तव में विश्वास है कि एआरबी वीएओ में तत्व सरणी बफर बाध्यकारी (या कोई अन्य बफर बाध्यकारी) स्थिति गुम है।

विश्वास की आवश्यकता नहीं है; कल्पना तथ्यों को बताती है।

ARB_vertex_array_object विनिर्देश से

:

आदेश

void GenVertexArrays(sizei n, uint *arrays); 

रिटर्न पिछले अप्रयुक्त शिखर सरणी वस्तु में नाम। इन नामों को केवल GenVertexArrays के प्रयोजनों के लिए उपयोग किया जाता है, और तालिका 6.6 में सूचीबद्ध राज्य के साथ प्रारंभ किया जाता है (CLIENT_ACTIVE_TEXTURE चयनकर्ता राज्य को छोड़कर), 6.7 और 6.8 (ARRAY_BUFFER_BINDING स्थिति को छोड़कर)।

तो हमारे पास यह है: वीएओ द्वारा सम्मिलित संपूर्ण राज्य उन तीन तालिकाओं की सामग्री है, जो उल्लेखनीय अपवादों के साथ हैं।

विस्तार The OpenGL Graphics Specification version 2.1 (PDF) के खिलाफ लिखा गया है। इसलिए, किसी भी पेज नंबर, सेक्शन लेबल्स, या टेबल नंबरों को उस स्पेक के सापेक्ष संदर्भित किया जाता है।

मैं उन तीन तालिकाओं को कॉपी करने वाला नहीं हूं। लेकिन यदि आप पेज 273 (spec के पेज गिनती से)/पेज 287 (भौतिक पृष्ठों की संख्या से) देखते हैं, तो आपको तालिका 6.8 मिल जाएगी।

ELEMENT_ARRAY_BUFFER_BINDING यहाँ कोई अस्पष्टता नहीं है: और मेज पर इस प्रकार है। जानकारी स्पष्ट रूप से नहीं कहा जा सकता है। लेकिन यह है, निर्विवाद रूप से। ELEMENT_ARRAY_BUFFER_BINDING वीएओ राज्य का हिस्सा है।

इसलिए, आपकी समस्या को दो स्रोतों में से एक से आ सकता है:

  1. ड्राइवर बग। जैसा कि मैंने एक टिप्पणी में कहा था, एक ड्राइवर बग असंभव लगता है। असंभव नहीं, बस असंभव है। एनवीआईडीआईए के ड्राइवर विभिन्न हार्डवेयर के लिए बहुत ही समान हैं, और वीएओ हार्डवेयर में शायद ही कभी प्रतिबिंबित होते हैं। जब तक आप ड्राइवरों के विभिन्न संस्करणों का उपयोग नहीं कर रहे हैं, तब तक ड्राइवर की बग के कारण त्रुटि होने की अपेक्षा करने का कोई कारण नहीं है।

  2. उपयोगकर्ता त्रुटि। मुझे पता है कि आप दावा करते हैं कि आपका कोड काम करता है, और इसलिए यह ठीक है। हर कोई कुछ कोड के बारे में दावा करता है। और कई बार ऐसा हुआ है जब मैं ऊपर और नीचे कसम खाता हूं कि कुछ कोड ठीक काम कर रहे थे। फिर भी यह टूट गया था; यह बस इतना हुआ। हो जाता है। यदि आप अपना कोड पोस्ट करते हैं, तो कम से कम हम इस संभावना को छूट पाएंगे। अन्यथा, हमारे पास आपके शब्द से ज्यादा कुछ नहीं है। और इस पर विचार करते हुए कि मनुष्यों के बारे में कितनी बार गलत है, यह अधिक मूल्यवान नहीं है।

+0

पर्याप्त मेला। मैं पूरा कोड पोस्ट नहीं कर सकता लेकिन मैं त्रुटि को पुन: उत्पन्न करने के लिए पर्याप्त न्यूनतम कोड के साथ आने का प्रयास करूंगा। इसके अलावा एआरबी चीज ठोस है, राज्य वास्तव में वहां प्रतीत होता है। –

+0

और यहां स्रोत कोड आता है (मूल प्रश्न में संपादित करें)। तो क्या यह एक ड्राइवर बग या मेरी गलती है? –

0

इसका एक संभावित कारण यह है कि आपका इंटेल एडाप्टर ओपनजीएल 3.3 संदर्भ प्रदान नहीं कर सकता है, बल्कि इसके बजाय 2.1 या इसी तरह के डिफ़ॉल्ट है। जैसा कि अन्य ने इंगित किया है, ओपनजीएल के पुराने संस्करणों में तत्व सरणी बफर राज्य वीएओ का हिस्सा नहीं था।

+1

यह वास्तव में संभव नहीं है, क्योंकि मैं संदर्भ को संगत रूप से संगत बना रहा हूं, इसलिए यह निचले स्तर पर डिफ़ॉल्ट नहीं हो सकता है। या अगर ऐसा होता है, तो यह निश्चित रूप से नहीं होना चाहिए। –

+0

मैंने सोचा कि एक ग्लिगेट कॉल था जिसे आप संदर्भ संस्करण से पूछने के लिए चला सकते हैं। तलाश करना। –

+0

@StevenLu हां, 'glGetString (GL_VERSION) 'है, लेकिन इसका मतलब यह होगा कि एक बग (तत्व सरणी कैश नहीं किया जा रहा है) केवल एक बहुत ही खराब बग के कारण था (आगे-संगत एक के बजाय पुराने 2.1 संदर्भ बनाना) । –

-1

मैं कल्पना कर सकता हूं कि ELEMENT बफर कैश नहीं किया जा रहा है; यदि आप कार्य करें:

glBindBuffer(GL_ARRAY_BUFFER, n_vertex_buffer_object); 
glEnableVertexAttribArray(0); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), p_OffsetInVBO(0)); 

यह कह रही है की तरह है:

gBoundBuffer_GL_ARRAY_BUFFER=n_vertex_buffer_object; 
currentVAO->enable|=(1<<0); 
currentVAO->vertexBuffer=IndexToPointer(gBoundBuffer_GL_ARRAY_BUFFER); 

दूसरे शब्दों में, glBindBuffer() कुछ भी लेकिन GL_ARRAY_BUFFER का मान सेट नहीं करता है। यह glVertexAttribPointer() पर है जहां आप वीएओ को संशोधित करते हैं।

तो तुम जब कार्य करें:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p_index_buffer_object_list[0]); 
glBindVertexArray(0); 

आप वास्तव में कार्य करें:

gBoundBuffer_GL_ELEMENT_ARRAY_BUFFER=p_index_buffer_object_list[0]; 
currentVAO=0; 

यह कहाँ इस अर्थ में कि GL_ELEMENT_ARRAY_BUFFER बाध्यकारी कुछ भी करने से नहीं है बनाता है। मुझे यकीन नहीं है कि glVertexAttribPointer() तत्वों के समान संस्करण हैं (जैसे glElementPointer()), जो वास्तव में वीएओ पर कार्य करेगा।

+0

ठीक है, आपके द्वारा वर्णित व्यवहार (तत्व सरणी कैश नहीं है) वास्तव में विनिर्देश के खिलाफ है, और इसे इस तरह से करने में थोड़ा सा अर्थ नहीं है। जब आप कुछ ज्यामिति आकर्षित करना चाहते हैं, तो केवल दुर्लभ मामले होते हैं जब शिखर और सूचकांक अलग-अलग होते हैं। अधिकांशतः, मॉडल कलाकार-निर्मित फाइलों से लोड होते हैं, और एक मॉडल के सूचकांक किसी अन्य मॉडल से शिखर फिट नहीं होंगे। इसलिए यह वास्तव में एक ही समय में इंडेक्स बफर और वर्टेक्स अट्रिब पॉइंटर्स को बांधने के लिए सही मायने रखता है, कम से कम "ग्राफिक्स एप्लिकेशन, 3 डी मेष प्रदर्शित करना" परिदृश्य में। –

संबंधित मुद्दे