2016-10-28 17 views
5

मैं छवि प्रसंस्करण के लिए एक बहु गणना शेडर लागू करने के लिए कोशिश कर रहा हूँ। प्रत्येक पास में एक इनपुट छवि और एक आउटपुट छवि है। अगली पास 'इनपुट छवि पिछले वाले' आउटपुट है।ओपन गणना शेडर - अजीब परिणाम

यह मैं ओपन में गणना शेडर का उपयोग कर तो वहाँ मेरी सेटअप के साथ कुछ समस्या हो सकती है के लिए पहली बार है। मैं ओपनसीवी की मैट का उपयोग कंटेनर को पढ़ने/कॉपी करने के लिए कंटेनर के रूप में कर रहा हूं।

कोड के कुछ भागों जो समस्या से संबंधित नहीं है तो मैं शामिल नहीं किया था रहे हैं। इनमें से कुछ हिस्सों में छवि लोड करना या संदर्भ आरंभ करना शामिल है।

प्रारंभ:

//texture init 
glGenTextures(1, &feedbackTexture_); 
glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, feedbackTexture_); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glBindTexture(GL_TEXTURE_2D, 0); 

glGenTextures(1, &resultTexture_); 
glActiveTexture(GL_TEXTURE0+1); 
glBindTexture(GL_TEXTURE_2D, resultTexture_); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glBindTexture(GL_TEXTURE_2D, 0); 

// shader init 
computeShaderID = glCreateShader(GL_COMPUTE_SHADER); 
glShaderSource(computeShaderID, 1, &computeShaderSourcePtr, &computeShaderLength); 
glCompileShader(computeShaderID); 
programID = glCreateProgram(); 
glAttachShader(programID, computeShaderID); 
glLinkProgram(programID); 
glDeleteShader(computeShaderID); 

छायांकर्ता कोड:

//shader code (simple invert) 
#version 430 
layout (local_size_x = 1, local_size_y = 1) in; 

layout (location = 0, binding = 0, /*format*/ rgba32f) uniform readonly image2D inImage; 
layout (location = 1, binding = 1, /*format*/ rgba32f) uniform writeonly image2D resultImage; 

uniform writeonly image2D image; 

void main() 
{ 
    // Acquire the coordinates to the texel we are to process. 
    ivec2 texelCoords = ivec2(gl_GlobalInvocationID.xy); 

    // Read the pixel from the first texture. 
    vec4 pixel = imageLoad(inImage, texelCoords); 

    pixel.rgb = 1. - pixel.rgb; 

    imageStore(resultImage, texelCoords, pixel); 
} 

उपयोग:

cv::Mat image = loadImage().clone(); 
cv::Mat result(image.rows,image.cols,image.type()); 
// These get the appropriate enums used by glTexImage2D 
GLenum internalformat = GLUtils::getMatOpenGLImageFormat(image); 
GLenum format = GLUtils::getMatOpenGLFormat(image); 
GLenum type = GLUtils::getMatOpenGLType(image); 

int dispatchX = 1; 
int dispatchY = 1; 

for (int i = 0; i < shaderPasses_.size(); ++i) 
{ 
    // Update textures 
    glBindTexture(GL_TEXTURE_2D, feedbackTexture_); 
    glTexImage2D(GL_TEXTURE_2D, 0, internalformat, result.cols, result.rows, 0, format, type, result.data); 
    glBindTexture(GL_TEXTURE_2D, resultTexture_); 
    glTexImage2D(GL_TEXTURE_2D, 0, internalformat, image.cols, image.rows, 0, format, type, 0); 
    glBindTexture(GL_TEXTURE_2D, 0); 

    glClear(GL_COLOR_BUFFER_BIT); 
    std::shared_ptr<Shader> shaderPtr = shaderPasses_[i]; 
    // Enable shader 
    shaderPtr->enable(); 
    { 
     // Bind textures 
     // location = 0, binding = 0 
     glUniform1i(0,0); 
     // binding = 0 
     glBindImageTexture(0, feedbackTexture_, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 
     // location = 1, binding = 1 
     glUniform1i(1,1); 
     // binding = 1 
     glBindImageTexture(1, resultTexture_, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 

     // Dispatch rendering 
     glDispatchCompute((GLuint)image.cols/dispatchX,(GLuint)image.rows/dispatchY,1); 
     // Barrier will synchronize 
     glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 
    } 
    // disable shader 
    shaderPtr->disable(); 

    // Here result is now the result of the last pass. 
} 

कभी कभी मैं अजीब परिणाम (glitchy बनावट, आंशिक रूप से प्रदान की गई बनावट) मिलता है, यह भी पहले पिक्सेल (0,0 पर) कभी-कभी लिखा नहीं जाता है। क्या मैंने सब कुछ ठीक से स्थापित किया था या क्या मुझे कुछ याद आ रही है? ऐसा लगता है कि बनावट के साथ इस पद्धति वास्तव में धीमी है, वहाँ किसी भी विकल्प है जो प्रदर्शन में वृद्धि होगी है?

संपादित 1:मेमोरीबियर ध्वज बदल गया।

उत्तर

3

मैं अंत में इस समस्या को हल कर सकता है!

समस्या सीवी :: मैट के निर्माता में झूठ बोला। निम्न पंक्ति केवल सीवी :: चटाई के लिए एक हैडर बनाता है:

cv::Mat result(image.rows,image.cols,image.type()); 

यह करता डेटा आवंटित लेकिन यह नहीं प्रारंभ है कि डेटा, यही कारण है कि मैं ये अजीब परिणाम मिला है नहीं करता है। यह स्मृति में कचरा था।

cv::Mat::zeros 
cv::Mat::ones 
cv::Mat::create 
+1

कड़ाई से बोलते हुए, आपका प्रारंभिक कॉल 'सीवी :: मट परिणाम (image.rows, image.cols, image.type());' _vocate_ छवि क्लिप बफर होना चाहिए, जैसा कि 'cv :: mat :: create' के समान है, हालांकि यह पिक्सेल मान _initialize_ नहीं है। 'सीवी :: मैट :: शून्य 'और' सीवी :: मैट :: वाले' दोनों पिक्सेल मान आवंटित और आरंभ करते हैं। – AldurDisciple

+0

हाँ आप सही हैं, मैं अपना जवाब अपडेट करूंगा। –

5
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 

यह गलत बाधा नहीं है। बाधा how you intend to access the data after the incoherent accesses निर्दिष्ट करती है। आप glGetTexImage साथ बनावट से पढ़ने के लिए कोशिश कर रहे हैं, तो आप GL_TEXTURE_UPDATE_BARRIER_BIT उपयोग करना चाहिए।

+0

वह हिस्सा ओह मैं याद किया, स्पष्ट करने के लिए धन्यवाद:

किसी भी समारोह जो और आवंटित का उपयोग करते हुए इस डेटा मुद्दे को हल करती है initializes।अपलोड/डाउनलोड भाग की गति बढ़ाने के लिए भी कोई तरीका है? मेरी छवियां कार्यक्रम के माध्यम से शायद ही कभी आकार बदल जाएंगी और वे लगभग 30 एफपीएस आ रहे हैं। –

+0

ठीक है, ऐसा लगता है कि ध्वज परिवर्तन ने कुछ भी नहीं किया, पहला पिक्सेल अभी भी झटकेदार है, और कभी-कभी अजीब कलाकृतियां पूरी छवि में दिखाई देती हैं। –

3

मैं 100% यकीन है कि अगर यह आपकी समस्या है या नहीं ठीक कर देंगे नहीं हूँ, लेकिन मुझे आपकी बनावट सेटिंग्स को शुरू करने के लिए अपने झंडे के साथ स्पष्ट रूप से कुछ भी गलत नहीं दिख रहा है। जब मैं अपने प्रोजेक्ट में अपना कोड तुलना कर रहा था तो यह एपीआई कॉल का ऑर्डर था जिसने मेरा ध्यान खींचा। अपने स्रोत में आप इस आदेश है:

glGenTextures(...); // Generate 
glActiveTexture(...); // Set Active 
glBindTexture(...); // Bind Texture 
glTexParameteri(...); // Wrap Setting 
glTexParameteri(...); // Wrap Setting 
glTexParameteri(...); // Mipmap Setting 
glTexParameteri(...); // Mipmap Setting 
glBindTexture(...); // Bind/Unbind 

और आप बनावट चर के निधन और आईडी मूल्य में वृद्धि के अलावा प्रत्येक बनावट के लिए इस दोहराएँ।

मुझे नहीं पता कि इससे कोई फर्क पड़ता है लेकिन मेरे इंजन में और लॉजिकल पथ के बाद मैंने स्थापित किया है; इस क्रम में यह करने का प्रयास करें और देखें कि क्या कोई फर्क

glGenTextures(...); // Generate 
glBindTexture(...); // Bind Texture 
glTexParameteri(...); // Wrap Setting 
glTexParameteri(...); // Wrap Setting 
glTexParameteri(...); // Mipmap Setting 
glTexParameteri(...); // Mipmap Setting 

glActiveTexture(...); // Set Active 
glBindTexture(...); // Bind/Unbind 

मैं गणना shaders का उपयोग नहीं कर रहा हूँ बनाता है, लेकिन मेरे इंजन के भीतर मैं कई वर्गों है कि अलग अलग चीजें का प्रबंधन करता है। मेरे पास एक एसेट स्टोरेज है जो सभी संपत्तियों को छवियों के लिए बनावट सहित मेमोरी डेटाबेस में सहेज लेगा, मेरे पास शेडरमेनगर क्लास है जो विभिन्न शेडर्स का प्रबंधन करने के लिए है जो वर्तमान में केवल कशेरुक और टुकड़े टुकड़े का उपयोग कर रहे हैं। यह शेडर फ़ाइलों को पढ़ और संकलित करेगा, शेडर प्रोग्राम बनाएं, विशेषताओं और वर्दी सेट करें, प्रोग्राम्स को लिंक करें और शेडर्स चलाएं। मैं बैच प्रक्रिया का उपयोग कर रहा हूं जहां मेरे पास बैच क्लास और बैच मैनेजर क्लास है जो विभिन्न प्रकार के प्राइमेटिव्स को प्रस्तुत करता है।तो जब मैं अपने समाधान के माध्यम से जा रहा था और पथ या तर्क के प्रवाह को निम्नलिखित यह है कि क्या मैं अपने कोड में देख रहा था है।

यह एसेटस्टॉरेज क्लास था जो बनावट के लिए गुण स्थापित कर रहा था और यह स्मृति में बनावट जोड़ने के लिए add() फ़ंक्शन के भीतर इस एपीआई कॉल को कॉल कर रहा था।

glGenTextures(...); 
glBindTextures(...); 
glTexParameteri(...); 
glTexParameteri(...); 
glTexParameteri(...); 
glTexParameteri(...); 

फिर AssetStorage इन के रूप में अच्छी

glPixelStorei(...); 
glTexImage2D(...) 

और कार्यप्रणाली को कॉल किया गया था AssetStorage में संरचनाएं जोड़ने के लिए अंत में एक TextureInfo वस्तु की एक कस्टम संरचना लौट आते हैं।

जब मैं अपने render() समारोह कॉल के तहत मेरे बैच कक्षा जाँच की यह वह जगह है जहां यह ShaderManager की कार्यप्रणाली को कॉल वर्दी यदि सेट करने के लिए फिर से बनावट का उपयोग करने के लिए, तो ShaderManager की कार्यप्रणाली को कॉल बनावट सेट करने के लिए वर्दी सेट और फिर करने के लिए था बनावट में अल्फा चैनल था। setTexture() समारोह के लिए ShaderManger वर्ग के भीतर इस जहां glActiveTexture() और glBindTexture() अंत में कहा जा रहा है है।

तो संक्षेप में संक्षेप में अपने glActiveTexture() को अंतिम glTexParameter() और पिछले glBindTexture() दोनों बनावट के लिए कॉल करने के लिए कॉल करने का प्रयास करें। मैं यह भी सच है कि आप बनावट सक्रिय बस के रूप में आप के बारे में यह रेंडर करने के लिए कर रहे हैं बनाना चाहते की वजह से इन दोनों कॉल के बाद आने के रूप में अच्छी तरह glPixelStorei() & glTexImage2D() चाहिए सोच रहा हूँ।

मैंने पहले मैं 100% यकीन है कि अगर यह आपकी समस्या की जड़ है नहीं कर रहा हूँ लेकिन मैं यह करता है, तो यह आप या मदद नहीं करता है को देखने के लिए यह कोशिश कर के शॉट के लायक है विश्वास है उल्लेख किया था। कृपया मुझे बताएं कि यदि आप इसे आजमाते हैं तो क्या होता है। मैं अपने लिए जानना चाहता हूं कि इन एपीआई कॉलों के ऑर्डर करने से इसका कोई असर पड़ता है। मैं इसे अपने स्वयं के समाधान में आज़माउंगा लेकिन मैं अपनी कक्षाओं या परियोजना को तोड़ना नहीं चाहता क्योंकि इसके लिए वर्तमान में ठीक से काम कर रहा है।

एक नोट के रूप में, अपने बनावट सेटिंग्स के लिए झंडे के साथ केवल एक ही चीज़ चादर/दोहराने वर्गों के भीतर है। आप GL_CLAMP_TO_EDGE का उपयोग करने के बजाय पहले दो glTexParameteri() कॉल के लिए GL_REPEAT का उपयोग करने का प्रयास कर सकते हैं और मुझे बताएं कि आप किसके साथ आते हैं, आपको पिछले दो glTexParameteri() कॉल के लिए mipmap सेटिंग्स के बारे में चिंता करने की आवश्यकता नहीं है क्योंकि ऐसा लगता है कि आप नहीं हैं आपके द्वारा उपयोग की जा रही सेटिंग्स से mipmaps का उपयोग करना।

+1

अपना समय लेने और मेरी समस्या का हल ढूंढने के लिए धन्यवाद। मुझे बहुत पहले समाधान नहीं मिला है, जवाब वास्तव में ग्लो कॉल या बनावट पैरामीटर का ऑर्डर नहीं था, लेकिन ओपनसीवी के मैट कन्स्ट्रक्टर। मैं जल्द ही एक उत्तर प्रदान करूंगा। –

+0

@ गैबरफेकेट ओह ठीक है, हाँ हमेशा संभावना है कि त्रुटि किसी बाहरी स्रोत या तृतीय पक्ष लाइब्रेरी से हो सकती है। –

+0

ओपनएलवी से ओपनसीवी डीबग करना वास्तव में आसान है। ओपनग्ल के लिए राज्य ठीक थे, शायद कुछ झंडे और 'ग्लैक्टीवटेक्चर' का उल्लेख आपने किया था। और मैंने पुस्तकालयों में से किसी एक पर भरोसा करने की गलती की ... उन पर भरोसा न करें! : डी –

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