IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

OpenGL Discussion :

OpenGL 4.2 et context partagés.


Sujet :

OpenGL

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 20
    Points : 7
    Points
    7
    Par défaut OpenGL 4.2 et context partagés.
    Bonjour à vous.

    Après une après-midi de recherches et de tests infructueux, je me tourne vers vous pour tenter de régler un problème.

    Mise en situation : Je créer un moteur de rendu avec OpenGL en C++ pour Windows.

    Je créer moi même mon context OpenGL ainsi que ma fenêtre. Je gère tout à la main, pas de SDL pas de SFML, donc ne me dites pas d'utiliser une de ces bibliothèques ce n'est pas ce que je recherche.

    Pour l'input, je gère les messages en provenance de la fenêtre ( clavier/souris ) ainsi qu'une pile de message interne au moteur.
    Je vérifie les messages de la fenêtre à chaque tour de boucle de rendu.

    J'ai donc une Classe Input_Manager qui gère ces entrées.

    Il est possible de lancer ce manager dans deux mode : Synchrone ( les inputs sont traitées directement dans le thread de rendu ) ou Asynchrone ( les inputs sont traitées dans des threads séparés ( un pour les messages internes, un pour le clavier et un pour la souris ).

    Le Input est sencé servir à initialiser les menus et à les donner une fois préparer au renderer qui les affiches ( c'est un peu plus compliqué que ça mais globalement ça se résume à ça ).

    Le mode asynchrone sert donc à ne pas bloquer la boucle de rendu pendant l'initialisation d'un menu/scène qui comporte donc le chargement de ressources, etc...

    Pour ce qui est des threads du mode asynchrone, ils disposent chacun d'un context opengl qui leur permet d'appeler des commandes gl.

    En ce qui concerne la création de context, on initialise dans un premier temps un context global qui sert de référence pour les autres. Enfin, chaque context créer après est partagé avec le context global ( ce qui permet que tous les contexts créés soient liés les uns aux autres ).

    Comme sujet de test, je créer un VBO, un shader, un IBO et une texture.

    Le but étant simplement d'afficher une image en 600x600 dans une fenêtre de la même taille.

    Je dispose de deux cartes graphique ( une créant obligatoirement un context opengl 3.0 ) et une qui dispose de opengl 4.2.

    TOUT se passe correctement et l'image s'affiche dans la fenêtre tant que je reste en mode synchrone avec les deux cartes graphique.

    Le problème vient du mode asynchrone. Il fonctionne correctement avec la carte graphique disposant d'opengl 3.0, mais la carte en 4.2 n'affiche strictement rien même si elle ne lève aucune erreur opengl.
    Tout semble fonctionner correctement, mais la fenêtre est désespérément noire.

    Je ne vois plus d'où peut provenir le problème étant donné que la texture ( comme toutes les ressources cités plus haut ) est créer dans le thread de gestion des messages internes mais le thread de rendu réussit tout de même à en récupérer les données afin de l'écrire dans un fichier.
    J'en déduis donc que le partage est un succès entre les contexts.

    En fait je suis à cours d'idée pour testé plus de chose... j'ai tenté de mettre des récupérations d'erreur opengl un peu partout, aucune erreur n'est levée.

    Si vous aviez une piste suplémentaire que je puisse explorer, un truc que j'ai raté sur opengl 4.2 qui change quelques choses dans le partage de context...

    Merci de votre aide.

    exkise


    Edit : J'ai aussi testé en désactivant l'affichage de la texture, simplement la couleur, ca ne marche pas plus.

    Edit 2 : Un test supplémentaire m'a permis d'isoler le problème au VBO et IBO ( buffer object ). Je continue mes recherches pour tenter d'isoler la fonction qui pose problème.

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 860
    Points : 219 062
    Points
    219 062
    Billets dans le blog
    120
    Par défaut
    Bonjour

    Je ne vois plus d'où peut provenir le problème étant donné que la texture ( comme toutes les ressources cités plus haut ) est créer dans le thread de gestion des messages internes mais le thread de rendu réussit tout de même à en récupérer les données afin de l'écrire dans un fichier.
    C'est bien là le problème, je pense. Chaque action OpenGL, doit être fait dans le thread qui a initialisé le contexte. Car le contexte est lié au thread. (On retrouve un peu le même cas en lisant la documentation de la SDL).
    Ainsi, la création des ressources dans un autre thread a des chances d'échouer (ou de ne pas fonctionner). Par contre, je croyais qu'un tel cas renvoyait une erreur OpenGL (GL_NO_CONTEXT, ou un truc du genre).
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Tu cumules les difficultés

    Il est possible de lancer ce manager dans deux mode : Synchrone ( les inputs sont traitées directement dans le thread de rendu ) ou Asynchrone ( les inputs sont traitées dans des threads séparés ( un pour les messages internes, un pour le clavier et un pour la souris ).
    Pourquoi autant de thread ?
    En général, le traitement des entrées n'est pas lourd et donc fait directement dans le thread principal (juste pour récupérer la position de la souris et dire au render "il faut que tu déplaces de autant", pas besoin de threader)
    Du coup, tu as combien de thread ? Tes contextes sont utilisées dans quels threads ? Et quels fonctions gl tu appelles dans chaque thread ?

    Mon avis (a priori sans en savoir plus), c'est de faire 3 threads : principal, pour la carte 1 et pour la carte 2. De plus, les appels gl étant asynchrones (je suppose que tu n'utilises pas le mode direct avec GL 3/4 ), tu peux tout a fait les mettre dans le thread principal et faire dans les threads que la partie calcul CPU et envoyer un signal au thread principal pour dire "ok, j'ai fini les calculs, tu peux appeler les fonctions gl"

    En ce qui concerne la création de context, on initialise dans un premier temps un context global qui sert de référence pour les autres. Enfin, chaque context créer après est partagé avec le context global ( ce qui permet que tous les contexts créés soient liés les uns aux autres ).
    Comment fais tu ça ? Tu peux donner le code de création des threads, des contextes et le partage ?

    Le problème vient du mode asynchrone. Il fonctionne correctement avec la carte graphique disposant d'opengl 3.0, mais la carte en 4.2 n'affiche strictement rien même si elle ne lève aucune erreur opengl.
    Comment envoies tu les commandes gl ? Comment gère tu le current context ? Au niveau accès concurrent aux données, c'est ok ? Tu utilises quoi comme lib de thread ?

    un truc que j'ai raté sur opengl 4.2 qui change quelques choses dans le partage de context...
    Rien
    Par contre, tu devrais peut être tester OpenGL 4.3 qui vient de sortir en beta (si tu as NVIDIA). Il ajoute une nouvelle extension GL_KHR_debug, qui améliorer le debug, en particulier pour les erreurs silencieuses. Voir chapitre 20 des spécifications OpenGL 4.3

  4. #4
    screetch
    Invité(e)
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    Chaque action OpenGL, doit être fait dans le thread qui a initialisé le contexte.
    Source?

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 20
    Points : 7
    Points
    7
    Par défaut
    Merci pour vos réponses.

    LittleWhite : Chaque thread possède son propre context qui est partagé avec les autres contexts.

    Pour exemple, la SFML permet d'utiliser opengl dans n'importe quel thread de façon totalement transparente.



    gbdivers :

    Pourquoi autant de thread ?
    Dans l'absolu il est vraie que ce n'est pas indispensable, c'est une largesse que je me donne en me donnant la possibilité de bloquer un thread un court instant sans pour autant que cela ne se ressente trop ( surtout pour les messages internes en fait, comme c'est principalement eux qui bloque le thread, je ne veux pas bloquer la souris et le clavier pendant ce temps, ca me permet d'avoir une souplesse au niveau des actions effectuées par l'utilisateur. )

    Du coup, tu as combien de thread ? Tes contextes sont utilisées dans quels threads ? Et quels fonctions gl tu appelles dans chaque thread ?
    Actuellement j'ai 4 threads, le thread principal qui sert au rendu, un thread pour les messages internes, un pour la souris et un pour le clavier ( c'est accessoir, mais finalement je vais fusionner le thread clavier et souris et gérer la souris comme des touches clavier étant donné que je gère les déplacement de la souris indépendamment depuis peu ).

    Chaque thread dispose d'un context opengl lié lui via wglMakeCurrent.
    J'ai donc 5 contexts ( le context global, et les 4 autres les threads ).
    les quatres context de threads sont dans la sharelist du context global.

    c'est de faire 3 threads : principal, pour la carte 1 et pour la carte 2.
    oO mais je ne gère pas les deux cartes en temps réelle. Soit je lance l'appli avec la carte 1 soit avec la carte 2.


    Comment envoies tu les commandes gl ?
    euh cette question me semble bizarre... je ne connais pas 36 façons...

    quelque chose comme glGenBuffers ou glBindBuffer ( par exemple ).

    Enfin comme des fonctions normales le tout encapsuler dans de jolies classes.

    du coup quand je fais Vertex_Buffer.Bind() il appel glBindBuffer(GL_VERTEX_ARRAY, _vbo_id); ( entre autre ! )

    Comment gère tu le current context ?
    Bah chaque thread a son propre current context.

    Au niveau accès concurrent aux données, c'est ok ?
    Dans l'absolu non, le Resources_Manager n'est pas fini, mais dans le cas présent ca ne pose pas de problème étant donnée que la boucle de rendu n'a pas accès au donnée avant qu'elles aient pu être initialisé.

    Pour te dire, j'ai une Classe Z, l'initialisation se fait dans le constructeur et l'utilisation se fait dans méthode de cette classe Z donc l'initialisation est fini lorsque les ressources sont utilisées.

    Tu utilises quoi comme lib de thread ?
    euh pthread et winapi pour l'instant mais ensuite juste winapi ( pour windows évidement pour linux et mac on vera après ).

    Tu peux donner le code de création des threads, des contextes et le partage ?
    Euh oui, mais y'a un pavé je te préviens ^^

    Bon alors ca c'est pour la création de context.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    585
    586
    587
    588
    589
    590
    591
    592
    593
    594
    595
    596
    597
    598
    599
    600
    601
    602
    603
    604
    605
    bool Windows_OpenGL_Video_Context::Create_Global_Context(Video_Context_Settings vcs, int16_t major_limit, int16_t minor_limit)
    {
        _dummy_mutex.Lock();
        Render_API & render_api = Render_API::Get_Instance();
     
        render_api._API = vcs.Get_Render_API();
     
        /* Okay, so here we'll try to set up the context and fill the Render API Instance*/
     
        int major, minor;
     
        vcs.Set_Bit_For_Colors(Check_Color(vcs.Get_Bits_For_Colors()));
        vcs.Set_Depth_Bits(Check_Depth(vcs.Get_Depth_Bits()));
        vcs.Set_Stencil_Bits(Check_Stencil(vcs.Get_Stencil_Bits()));
        vcs.Set_Accum_Bits(Check_Accum(vcs.Get_Accum_Bits()));
        vcs.Set_Antialiasing_Level(Check_Antialiasing(vcs.Get_Antialiasing_Level()));
     
        // Initialize the dummy context to acceed the ARB function.
     
     
     
        _dummy_window = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, 10, 10, NULL, NULL, GetModuleHandle(NULL), NULL);
        ShowWindow(_dummy_window, SW_HIDE);
        _dummy_dc = GetDC(_dummy_window);
     
        if(!_dummy_dc)
        {
            SEND_ERROR(10302, "Unable to get dummy DC.");
            _dummy_mutex.Unlock();
            return false;
        }
     
        uint16_t flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
     
        if(vcs.Get_Double_Buffer())
        {
            flags |= PFD_DOUBLEBUFFER;
        }
     
        PIXELFORMATDESCRIPTOR descriptor;
        ZeroMemory(&descriptor, sizeof(descriptor));
        descriptor.nSize        = sizeof(descriptor);
        descriptor.nVersion     = 1;
        descriptor.iLayerType   = PFD_MAIN_PLANE;
        descriptor.dwFlags      = flags;
        descriptor.iPixelType   = PFD_TYPE_RGBA;
        descriptor.cColorBits   = vcs.Get_Bits_For_Colors();
        descriptor.cDepthBits   = vcs.Get_Depth_Bits();
        descriptor.cStencilBits = vcs.Get_Stencil_Bits();
        descriptor.cAccumBits   = vcs.Get_Accum_Bits();
        descriptor.cAlphaBits   = vcs.Get_Bits_For_Colors() == 32 ? 8 : 0;
     
        int32_t format_number = ChoosePixelFormat(_dummy_dc, &descriptor);
     
        if(format_number==0)
        {
            SEND_ERROR(10303, "Unable to chose pixel format.");
            _dummy_mutex.Unlock();
            return false;
        }
     
        PIXELFORMATDESCRIPTOR chosen_pixelformat;
        chosen_pixelformat.nSize    = sizeof(chosen_pixelformat);
        chosen_pixelformat.nVersion = 1;
     
        DescribePixelFormat(_dummy_dc, format_number, sizeof(chosen_pixelformat), &chosen_pixelformat);
     
        vcs.Set_Double_Buffer( ( (chosen_pixelformat.dwFlags & PFD_DOUBLEBUFFER) != 0 ) );
        vcs.Set_Bit_For_Colors(chosen_pixelformat.cColorBits);
        vcs.Set_Depth_Bits(chosen_pixelformat.cDepthBits);
        vcs.Set_Stencil_Bits(chosen_pixelformat.cStencilBits);
        vcs.Set_Accum_Bits(chosen_pixelformat.cAccumBits);
     
        if(!SetPixelFormat (_dummy_dc, format_number, &chosen_pixelformat))
        {
            SEND_ERROR(10304, "Unable to set pixel format for dummy context.");
            _dummy_mutex.Unlock();
            return false;
        }
     
        _dummy_rc = wglCreateContext(_dummy_dc);
     
     
        if (!_dummy_rc)
        {
            SEND_ERROR(10305, "Unable to create OpenGL dummy context.");
            _dummy_mutex.Unlock();
            return false;
        }
     
        wglMakeCurrent(_dummy_dc,_dummy_rc);
     
     
        static bool glew_init = false;
        if(!glew_init)
        {
            GLenum err = glewInit();
            if ( err != GLEW_OK)
            {
                SEND_ERROR(10306, "Unable to initialize GLEW.");
                _dummy_mutex.Unlock();
                return false;
            }
        }
     
        glew_init = true;
     
        // we now are able to make our real context.
     
        _own_my_window = true;
        _my_window = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, 10, 10, NULL, NULL, GetModuleHandle(NULL), NULL);
        ShowWindow(_my_window, SW_HIDE);
        _device_context = GetDC(_my_window);
     
        if(!_device_context)
        {
            SEND_ERROR(10307, "Unable to get global DC.");
            _dummy_mutex.Unlock();
            return false;
        }
     
        // first test the possible function
        if(wglewIsSupported("WGL_ARB_create_context") && wglewIsSupported("WGL_ARB_pixel_format") && major_limit !=2)
        {
            bool valid = false;
            uint32_t number_of_pixelformat;
     
            int32_t pixelformat_attribute[] =
            {
                WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
                WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
                WGL_STEREO_ARB, vcs.Get_Stereo() ? GL_TRUE : GL_FALSE,
                WGL_DOUBLE_BUFFER_ARB, vcs.Get_Double_Buffer() ? GL_TRUE : GL_FALSE,
                WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
     
                WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
                WGL_COLOR_BITS_ARB,vcs.Get_Bits_For_Colors(),
                WGL_ALPHA_BITS_ARB,vcs.Get_Bits_For_Colors() == 32 ? 8 : 0,
     
                WGL_DEPTH_BITS_ARB,vcs.Get_Depth_Bits(),
                WGL_STENCIL_BITS_ARB,vcs.Get_Stencil_Bits(),
                WGL_ACCUM_BITS_ARB, vcs.Get_Accum_Bits(),
     
                WGL_SAMPLE_BUFFERS_ARB, 0,
                WGL_SAMPLES_ARB, 0,
     
                0
            };
     
            if(vcs.Get_Antialiasing_Level() != 0 && wglewIsSupported("WGL_ARB_multisample"))
            {
                pixelformat_attribute[23] = 1;
                pixelformat_attribute[25] = vcs.Get_Antialiasing_Level();
     
                while(vcs.Get_Antialiasing_Level()>0)
                {
                    valid = wglChoosePixelFormatARB(_device_context, pixelformat_attribute, NULL, 1, &format_number, &number_of_pixelformat);
     
                    if(valid && number_of_pixelformat > 0)
                    {
                        break;
                    }
     
                    pixelformat_attribute[25]--;
                    vcs.Set_Antialiasing_Level(pixelformat_attribute[25]);
                }
     
                if(!valid || number_of_pixelformat<1)
                {
                    SEND_ERROR(10308, "Unable to find a suitable multisample configuration.");
     
                    pixelformat_attribute[23] = 0;
                    pixelformat_attribute[25] = 0;
     
                    if(!wglChoosePixelFormatARB(_device_context, pixelformat_attribute, NULL, 1, &format_number, &number_of_pixelformat))
                    {
                        SEND_ERROR (10309, "Unable to create pixelformat.(1)");
                        _dummy_mutex.Unlock();
                        return false;
                    }
                }
            }
            else
            {
                if(!wglChoosePixelFormatARB(_device_context, pixelformat_attribute, NULL, 1, &format_number, &number_of_pixelformat))
                {
                    SEND_ERROR (10309, "Unable to create pixelformat.(2)");
                    _dummy_mutex.Unlock();
                    return false;
                }
     
            }
     
            if(!SetPixelFormat (_device_context, format_number, &chosen_pixelformat))
            {
                SEND_ERROR(10310, "Unable to set pixel format.(1)");
                _dummy_mutex.Unlock();
                return false;
            }
     
            int context_attribs[] =
            {
                WGL_CONTEXT_MAJOR_VERSION_ARB, 0,
                WGL_CONTEXT_MINOR_VERSION_ARB, 0,
                /*WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,*/
                WGL_CONTEXT_FLAGS_ARB, 0,
                0
            };
     
            if(major_limit!=-1 && minor_limit!=-1)
            {
                context_attribs[1] = major_limit;
                context_attribs[3] = minor_limit;
     
                _rendering_context = wglCreateContextAttribsARB(_device_context, NULL, context_attribs);
     
                if(!_rendering_context)
                {
                    SEND_ERROR (10311, "Unable to limit render context version.");
                }
            }
     
            int version = 9;
     
            while(!_rendering_context)
            {
                switch(version)
                {
                    case 9:
                    {
                        context_attribs[1] = 4;
                        context_attribs[3] = 2;
                        break;
                    }
     
                    case 8:
                    {
                        context_attribs[1] = 4;
                        context_attribs[3] = 1;
                        break;
                    }
     
                    case 7:
                    {
                        context_attribs[1] = 4;
                        context_attribs[3] = 0;
                        break;
                    }
     
                    case 6:
                    {
                        context_attribs[1] = 3;
                        context_attribs[3] = 3;
                        break;
                    }
     
                    case 5:
                    {
                        context_attribs[1] = 3;
                        context_attribs[3] = 2;
                        break;
                    }
     
                    case 4:
                    {
                        context_attribs[1] = 3;
                        context_attribs[3] = 1;
                        break;
                    }
     
                    case 3:
                    {
                        context_attribs[1] = 3;
                        context_attribs[3] = 0;
                        break;
                    }
     
                    case 2:
                    {
                        context_attribs[1] = 2;
                        context_attribs[3] = 1;
                        break;
                    }
     
                    case 1:
                    {
                        context_attribs[1] = 2;
                        context_attribs[3] = 0;
                        break;
                    }
     
                    default:
                    {
                        context_attribs[1] = 2;
                        context_attribs[3] = 0;
                        break;
                    }
                }
     
                _rendering_context = wglCreateContextAttribsARB(_device_context, NULL, context_attribs);
     
                if(!_rendering_context && context_attribs[1] == 2 && context_attribs[3] == 0)
                {
                    SEND_ERROR(10312, "Unable to create render context.(1)");
                    _dummy_mutex.Unlock();
                    return false;
                }
     
                version--;
            }
        }
        else
        {
            if(!SetPixelFormat (_device_context, format_number, &chosen_pixelformat))
            {
                SEND_ERROR(10310, "Unable to set pixel format.(2)");
                _dummy_mutex.Unlock();
                return false;
            }
     
            _rendering_context = wglCreateContext(_device_context);
            if (!_rendering_context)
            {
                SEND_ERROR(10312, "Unable to create render context.(2)");
                _dummy_mutex.Unlock();
                return false;
            }
        }
     
        wglMakeCurrent(NULL,NULL);
     
        wglMakeCurrent(_device_context,_rendering_context);
     
        glGetIntegerv(GL_MAJOR_VERSION, &major);
        glGetIntegerv(GL_MINOR_VERSION, &minor);
     
        wglMakeCurrent(NULL, NULL);
     
        _pixelformat_number = format_number;
        _shared_context = _rendering_context;
        _initialized = true;
     
        render_api._API = vcs.Get_Render_API();
        render_api.Set_Version(major, minor);
        render_api._double_buffer = vcs.Get_Double_Buffer();
        render_api._stereo = vcs.Get_Stereo();
        render_api._bit_for_colors = vcs.Get_Bits_For_Colors();
        render_api._depth_bits = vcs.Get_Depth_Bits();
        render_api._accum_bits = vcs.Get_Accum_Bits();
        render_api._stencil_bits = vcs.Get_Stencil_Bits();
        render_api._antialiasing_level = vcs.Get_Antialiasing_Level();
     
        _dummy_mutex.Unlock();
     
        return true;
    }
     
    bool Windows_OpenGL_Video_Context::Create_Thread_Context()
    {
        _dummy_mutex.Lock();
        Render_API & render_api = Render_API::Get_Instance();
     
        if(!_shared_context || !_initialized || !_dummy_dc || !_dummy_rc)
        {
            SEND_ERROR(10313, "You have to initialize global video context before try to create a video context");
            _dummy_mutex.Unlock();
            return false;
        }
     
        wglMakeCurrent(_dummy_dc,_dummy_rc);
     
        _own_my_window = true;
        _my_window = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, 10, 10, NULL, NULL, GetModuleHandle(NULL), NULL);
        ShowWindow(_my_window, SW_HIDE);
        _device_context = GetDC(_my_window);
     
        uint16_t flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
     
        if(render_api.Get_Double_Buffer())
        {
            flags |= PFD_DOUBLEBUFFER;
        }
     
        PIXELFORMATDESCRIPTOR descriptor;
        ZeroMemory(&descriptor, sizeof(descriptor));
        descriptor.nSize        = sizeof(descriptor);
        descriptor.nVersion     = 1;
        descriptor.iLayerType   = PFD_MAIN_PLANE;
        descriptor.dwFlags      = flags;
        descriptor.iPixelType   = PFD_TYPE_RGBA;
        descriptor.cColorBits   = render_api.Get_Bits_For_Colors();
        descriptor.cDepthBits   = render_api.Get_Depth_Bits();
        descriptor.cStencilBits = render_api.Get_Stencil_Bits();
        descriptor.cAccumBits   = render_api.Get_Accum_Bits();
        descriptor.cAlphaBits   = render_api.Get_Bits_For_Colors() == 32 ? 8 : 0;
     
        if(!SetPixelFormat(_device_context, _pixelformat_number, &descriptor))
        {
            SEND_ERROR(10310, "Unable to set pixel format.(3)");
            wglMakeCurrent(NULL,NULL);
            _dummy_mutex.Unlock();
            return false;
        }
     
        if(!_device_context)
        {
            SEND_ERROR(10314, "Unable to get DC.(1)");
            wglMakeCurrent(NULL,NULL);
            _dummy_mutex.Unlock();
            return false;
        }
     
        if(wglewIsSupported("WGL_ARB_create_context") && wglewIsSupported("WGL_ARB_pixel_format"))
        {
            Render_API::OpenGL_Version* version = reinterpret_cast<Render_API::OpenGL_Version*>(render_api._version);
     
            int context_attribs[] =
            {
                WGL_CONTEXT_MAJOR_VERSION_ARB, version->_major_version,
                WGL_CONTEXT_MINOR_VERSION_ARB, version->_minor_version,
                /*WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,*/
                WGL_CONTEXT_FLAGS_ARB, 0,
                0
            };
     
            _rendering_context = wglCreateContextAttribsARB(_device_context, _shared_context, context_attribs);
     
            if(!_rendering_context)
            {
                SEND_ERROR(10312, "Unable to create render context.(3)");
                wglMakeCurrent(NULL,NULL);
                _dummy_mutex.Unlock();
                return false;
            }
        }
        else
        {
            _rendering_context = wglCreateContext(_device_context);
            if (!_rendering_context)
            {
                SEND_ERROR(10312, "Unable to create render context.(4)");
                wglMakeCurrent(NULL,NULL);
                _dummy_mutex.Unlock();
                return false;
            }
     
            static Mutex mutex;
            mutex.Lock();
            if (!wglShareLists(_shared_context, _rendering_context))
            {
                SEND_ERROR(10315, "Unable to share render context.(1)");
                wglMakeCurrent(NULL,NULL);
                _dummy_mutex.Unlock();
                return false;
            }
            mutex.Unlock();
     
        }
     
        wglMakeCurrent(NULL,NULL);
        _dummy_mutex.Unlock();
        return true;
    }
     
    bool Windows_OpenGL_Video_Context::Create_Window_Context(Window *window)
    {
        _dummy_mutex.Lock();
        if(!window)
        {
            SEND_ERROR(10316, "Invalid window.");
            _dummy_mutex.Unlock();
            return false;
        }
        Render_API & render_api = Render_API::Get_Instance();
     
        if(!_shared_context || !_initialized || !_dummy_dc || !_dummy_rc)
        {
            SEND_ERROR(10313, "You have to initialize global video context before try to create a video context");
            _dummy_mutex.Unlock();
            return false;
        }
     
        wglMakeCurrent(_dummy_dc,_dummy_rc);
     
        _own_my_window = false;
        Windows_Window* windows_window = reinterpret_cast<Windows_Window*>(window);
        _my_window = windows_window->Get_Handle();
        _device_context = GetDC(_my_window);
     
        uint16_t flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
     
        if(render_api.Get_Double_Buffer())
        {
            flags |= PFD_DOUBLEBUFFER;
        }
     
        PIXELFORMATDESCRIPTOR descriptor;
        ZeroMemory(&descriptor, sizeof(descriptor));
        descriptor.nSize        = sizeof(descriptor);
        descriptor.nVersion     = 1;
        descriptor.iLayerType   = PFD_MAIN_PLANE;
        descriptor.dwFlags      = flags;
        descriptor.iPixelType   = PFD_TYPE_RGBA;
        descriptor.cColorBits   = render_api.Get_Bits_For_Colors();
        descriptor.cDepthBits   = render_api.Get_Depth_Bits();
        descriptor.cStencilBits = render_api.Get_Stencil_Bits();
        descriptor.cAccumBits   = render_api.Get_Accum_Bits();
        descriptor.cAlphaBits   = render_api.Get_Bits_For_Colors() == 32 ? 8 : 0;
     
        if(!SetPixelFormat(_device_context, _pixelformat_number, &descriptor))
        {
            SEND_ERROR(10310, "Unable to set pixel format.(4)");
            wglMakeCurrent(NULL,NULL);
            _dummy_mutex.Unlock();
            return false;
        }
     
        if(!_device_context)
        {
            SEND_ERROR(10314, "Unable to get DC.(2)");
            wglMakeCurrent(NULL,NULL);
            _dummy_mutex.Unlock();
            return false;
        }
     
        if(wglewIsSupported("WGL_ARB_create_context") && wglewIsSupported("WGL_ARB_pixel_format"))
        {
            Render_API::OpenGL_Version* version = reinterpret_cast<Render_API::OpenGL_Version*>(render_api._version);
     
            int context_attribs[] =
            {
                WGL_CONTEXT_MAJOR_VERSION_ARB, version->_major_version,
                WGL_CONTEXT_MINOR_VERSION_ARB, version->_minor_version,
                /*WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,*/
                WGL_CONTEXT_FLAGS_ARB, 0,
                0
            };
     
            _rendering_context = wglCreateContextAttribsARB(_device_context, _shared_context, context_attribs);
     
            if(!_rendering_context)
            {
                SEND_ERROR(10312, "Unable to create render context.(5)");
                wglMakeCurrent(NULL,NULL);
                _dummy_mutex.Unlock();
                return false;
            }
        }
        else
        {
            _rendering_context = wglCreateContext(_device_context);
            if (!_rendering_context)
            {
                SEND_ERROR(10312, "Unable to create render context.(6)");
                wglMakeCurrent(NULL,NULL);
                _dummy_mutex.Unlock();
                return false;
            }
     
            static Mutex mutex;
            mutex.Lock();
            if (!wglShareLists(_shared_context, _rendering_context))
            {
                SEND_ERROR(10315, "Unable to share render context.(2)");
                wglMakeCurrent(NULL,NULL);
                _dummy_mutex.Unlock();
                return false;
            }
            mutex.Unlock();
     
        }
     
        wglMakeCurrent(NULL,NULL);
        _dummy_mutex.Unlock();
        return true;
    }
     
    bool Windows_OpenGL_Video_Context::Make_Current()
    {
        if(!_device_context || !_rendering_context)
        {
            SEND_ERROR(10301, "Invalid video context, cannot make current");
            return false;
        }
     
        if(!wglMakeCurrent(_device_context, _rendering_context))
        {
            return false;
        }
     
        if(SYSTEM::Render_API::Get_Instance().Get_Bits_For_Colors() == 32)
        {
            glShadeModel(GL_SMOOTH);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            glEnable(GL_BLEND);
        }
     
        /** THIS FUCKING SHIT IS REQUIRED BY OPENGL TO WORK CORRECTLY WITH 3.1 and greater **/
        GLuint vao=0;
        glGenVertexArrays(1, &vao);
        glBindVertexArray(vao);
        /*******OpenGL give me a cute 1282 error when calling glVertexAttribPointerARB*******/
     
        return true;
    }
    Ici la création de thread :
    ( je met juste le thread message, les deux autres sont strictement pareil si ce n'est le nom des variables. )

    Le thread est instancié

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    void Asynchronous_Input_Manager::Messages_Thread_Function(Asynchronous_Input_Manager *owner)
    {
        SYSTEM::Video_Context *context = SYSTEM::Platform::Get_Instance().Create_Video_Context();
        if(!context->Make_Current())
        {
            SEND_ERROR(30103, "Unable to make video context current in message thread.");
            return;
        }
     
        while(owner->_messages_have_to_continue)
        {
            owner->_messages_mutex.Lock();
            owner->_add_messages_mutex.Lock();
     
            if(owner->_messages.size()>0)
            {
                uint32_t message = owner->_messages[0];
                owner->_messages.pop_front();
                owner->_add_messages_mutex.Unlock();
                owner->_message_holder->Treat_Message(message);
            }
            else
            {
                owner->_add_messages_mutex.Unlock();
            }
            if(owner->_messages.size()>0)
            {
                owner->_messages_mutex.Unlock();
            }
        }
     
        delete context;
    }

    Je vais regarder opengl 4.3.

  6. #6
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Citation Envoyé par screetch Voir le message
    Source?
    Rien dans les spécifications, ça dit simplement que la liaison des contextes avec les threads est implémentation spécifique. Ca dit aussi que certain type de variables sont partageable entre plusieurs contextes et d'autres non

    Sur le wiki d'OpenGL (http://www.opengl.org/wiki/OpenGL_context) :
    In order for any OpenGL commands to work, a context must be current; all OpenGL commands affect the state of whichever context is current. The current context is a thread-local variable, so a single process can have several threads, each of which has its own current context. However, a single context cannot be current in multiple threads at the same time.
    Mais difficile de savoir si c'est une source sur (ce qui veut dire, si on ne peut pas juger de la qualité de la source, qu'elle doit être considéré comme non fiable)

    Pour windows par exemple, on a dans le msdn (http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx) :
    A thread can have one current rendering context. A process can have multiple rendering contexts by means of multithreading. A thread must set a current rendering context before calling any OpenGL functions. Otherwise, all OpenGL calls are ignored.

    A rendering context can be current to only one thread at a time. You cannot make a rendering context current to multiple threads.

    An application can perform multithread drawing by making different rendering contexts current to different threads, supplying each thread with its own rendering context and device context.
    Ca ne dit pas si on peut créer un contexte et le partager entre plusieurs threads, mais ça parle bien d'avoir 1 contexte "courant" par thread si on veut faire du multi threading

    De toute façon, sans précision sur le fait qu'un contexte est thread-safe, il faut considérer que ce n'est pas le cas (donc pas d'accès à un contexte depuis plusieurs threads)


    Bref, perso je fais pour éviter les problèmes :
    * 1 thread créé son propre contexte
    * pas de partage d'un contexte entre plusieurs threads

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 20
    Points : 7
    Points
    7
    Par défaut
    Bref, perso je fais pour éviter les problèmes :
    * 1 thread créé son propre contexte
    * pas de partage d'un contexte entre plusieurs threads
    C'est ce que je fais à priori, mais les context sont partagés entre eux via les fonctions opengl ( _rendering_context = wglCreateContextAttribsARB(_device_context, NULL, context_attribs); ). Ici le paramètre NULL est la liste de partage ( le context de rendu avec lequel on partage les données ), il est NULL car c'est la création du context global, mais dans les autres contexts, le paramètre est a _shared_context qui est un handle static à la classe sur le _renderind_context global.



    Ps : je vais essayé ( au point ou j'en suis ) de toujours mettre ce param a NULL et de me servir de wglShareLists.

    edit : avec wglShareLists, aucune amélioration, ca marche toujours en 3.0 mais toujours pas en 4.2...

  8. #8
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Citation Envoyé par exkise Voir le message
    C'est ce que je fais à priori, mais les context sont partagés entre eux via les fonctions opengl ( _rendering_context = wglCreateContextAttribsARB(_device_context, NULL, context_attribs); ). Ici le paramètre NULL est la liste de partage ( le context de rendu avec lequel on partage les données ), il est NULL car c'est la création du context global, mais dans les autres contexts, le paramètre est a _shared_context qui est un handle static à la classe sur le _renderind_context global.



    Ps : je vais essayé ( au point ou j'en suis ) de toujours mettre ce param a NULL et de me servir de wglShareLists.

    edit : avec wglShareLists, aucune amélioration, ca marche toujours en 3.0 mais toujours pas en 4.2...
    voir mes remarques précédentes, mais je crois pas que l'on puisse partager des contextes s'ils ne sont pas dans le même thread. Et on ne peut pas partager tous les types de données non plus
    Pour cela que je demandais du code

  9. #9
    screetch
    Invité(e)
    Par défaut
    ca fait plusieurs annees que mon projet est multi threaded et que les appels a OpenGL sont sur des threads different de celui qui a cree le contexte. Le tout c'est comme tu l'as dit d'avoir seulement un seul trhead qui utilise le contexte.

    En tous les cas je suis sur qu on a pas "Chaque action OpenGL, doit être fait dans le thread qui a initialisé le contexte"

  10. #10
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 20
    Points : 7
    Points
    7
    Par défaut
    Peut être avec opengl 4.2, mais avec opengl 3.0 tout fonctionne parfaitement, en partageant des contexts current dans des threads différents...

    De plus, la SFML le fait, par un temps je l'utilisais et j'avais mis au point le même système multithread pour la préparation d'un côté l'affichage de l'autre, ca fonctionnait très bien, alors je ne comprends pas ce qui se passe...

    Pour ce qui est des données partagées entres les contexts, les textures, buffers, shaders sont sensés en faire partie, ce qui n'est pas partagé ce sont les VAO, la texture 0, buffers 0, shader program 0, etc...

    Il va donc me falloir trouver une nouvelle architecture pour faire les chargements de ressources dans le threads de chargement et l'envoie des données à opengl dans le thread de rendu ?

    Ca va être encore plus bancale

  11. #11
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Citation Envoyé par screetch Voir le message
    En tous les cas je suis sur qu on a pas "Chaque action OpenGL, doit être fait dans le thread qui a initialisé le contexte
    ça ok. Les threads partagent la même mémoire, tant que l'on fait pas une copie du contexte pour l'utiliser dans un autre thread, mais qu'on utilise bien un pointeur ou référence, ça ne doit pas poser de problème

    Sauf pour ce qui est des accès concurrents, puisque a priori rien ne garantie que le contexte soit thread safe, mais ça on est d'accord aussi

    De plus, la SFML le fait, par un temps je l'utilisais et j'avais mis au point le même système multithread pour la préparation d'un côté l'affichage de l'autre, ca fonctionnait très bien, alors je ne comprends pas ce qui se passe...
    Je sais pas comment c'est implémenter dans la SFML et comment tu as fais dans ton projet. Faudrait demander à Laurent

    Il va donc me falloir trouver une nouvelle architecture pour faire les chargements de ressources dans le threads de chargement et l'envoie des données à opengl dans le thread de rendu ?
    Qu'appelles tu chargement des données ? Si c'est charger les données en mémoire depuis le disque, ok tu as besoin d'un thread, mais pas des fonctions gl.

    Bref, pas un problème d'architecture mais probablement d'accès concurrent (mais je spécule un peu, difficile à dire)

  12. #12
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 20
    Points : 7
    Points
    7
    Par défaut
    J'ai étudié le code de la SFML, dans chaque fonction devant utilisé opengl, il appel la fonction EnsureGlContext(); ( qui est propre à la sfml ) et qui vérifie qu'il y a bien un context dans le thread d'où est appelé la fonction. Si il n'y a pas de context, il en crée un qui est partagé avec les autres ( même principe que moi ) sinon il ne fait rien. Ce qui diffère de moi est le fait qu'il a une implémentation spécifique pour ses threads qui permettent de facilement retrouvé le context lié à un thread, mais je n'ai pas besoin de sa car personnellement je sais précisément dans quel thread sont créer et utilisé les contexts alors que lui ( ne gérant pas la boucle de rendu et se contentant de fournir (grosso modo ^^) une encapsulation d'opengl, il ne peut pas savoir à l'avance quel thread va utilisé un context ou non ). Comme moi j'encapsule en suplément la gestion des évènements ainsi que la boucle de rendu, je n'ai pas ce soucis.

    Bon dans un premier temps, je vais commencé par faire un schéma complet afin de voir précisément l'ordre d'appel des fonctions de mon moteur pour listé l'ordre d'appel à opengl pour tenter de trouver un éventuel conflit.

    Puis je relirai pour la n-ième fois la doc opengl en long, en large et en travers et je finirais par obtenir ce que je veux

    Je reviens vers vous afin de vous donner la solution ( si tant est qu'il en ai une ) et clore le sujet.

    Merci de votre temps.

  13. #13
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Citation Envoyé par exkise Voir le message
    Puis je relirai pour la n-ième fois la doc opengl en long, en large et en travers et je finirais par obtenir ce que je veux :ccool
    Je crois pas que tu trouveras le problème dans la doc (spécifications ?) d'OpenGL, pour moi, c'est plutôt un problème de gestion des threads

  14. #14
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    J'ai un doute en relisant tes posts (EDIT : et je viens du coup de voir que j'ai loupé ton post avec ton code... je regarde demain)

    L'intérêt de plusieurs contextes, c'est de faire plusieurs rendus, pas de découpé 1 rendu en plusieurs parties. Ça sert à rien, les appels des commandes GL sont asynchrones (dans la majorité des cas ; comme exception, il y a en particulier les fonctions de synchronisation). Si tu fais qu'un rendu, tu n'as besoin que d'un contexte OpenGL, les autres sont superflus

  15. #15
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 20
    Points : 7
    Points
    7
    Par défaut
    En réalité j'ai besoin de plusieurs context pour la raison suivante, c'est que je compte avoir la possibilité de disposer de plusieurs fenêtre. Hors ça me ferait vraiment trop mal de devoir stocké deux fois la même ressource parce que j'en ai besoin dans deux fenêtres différentes... Je vais éditer le post avec le code car j'ai changer certaine chose ( sans amélioration réelle du problème toutes fois ).

    Une petite précision intéressante : Les ressources créer dans le thread séparé sont accessible depuis le thread de rendu ! mais, allez savoir pourquoi, elles ne s'affichent pas...

    exemple, j'arrive à récupérer les données de la texture depuis le thread de rendu et écrire une zolie image avec ( un fichier png ).
    De plus, j'arrive ( après avoir bidouillé mes classes ) à récupérer le contenu des buffers ( mon vbo et mon ibo ) et à les écrire eux aussi dans un fichier à part. Du coup, pour être sûr je les écris une fois depuis le thread séparé ( donnée que je lui donne, pas donnée récupérer dans le buffer ( afin d'être sûr de bien écrire ce que je lui ai donnée pour se créer ) ) et une seconde fois à chaque fois que je bind le buffer ( je sais c'est vraiment sal, mais c'est une application de test et ca disparaitra une fois réglé. ). Le buffer étant bind depuis le thread de rendu, je récupère et écris bien les données depuis le thread de rendu. Hors, ces données sont exacte ( n'aillant que 304 octets de données pour le test j'ai pu les comparer rapidement ), donc opengl retrouve correctement le buffer reste maintenant à savoir ce qu'il trouve à redire pour ne pas accepter d'afficher. Ces données qui me semble somme toute correcte.

    De plus, j'ai mis un mutex dans les resources de façon à ce qu'un seul thread ne puisse agir( bind ) dessus à la fois. je le Lock avant chaque bind et je le Unlock apres le bind(0).

  16. #16
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 219
    Points : 239
    Points
    239
    Par défaut
    J'ai dejà eu à faire avec se problème.

    Ils y a beaucoup trop de problèmes pour pouvoir partagé des contexte de version différente. Autrement dit, tu peux pas d'un point de vue de rigueur, même si tu peut le codé.

    Si les deux carte graphique ne sont pas du même constructeur (Nvidia ou ATI/AMD), les drivers seront complètement différent, et donc incompatible, donc çà ne fonctionnera pas même avec des contextes partagé de même version.

    Par ailleurs, que tu ai un pont SLI ou Crossfire ou même pas du tout comme dans ton cas, toute tes données seront quand même dupliquées dans les deux mémoire. A titre d'exemple, les carte graphique BI-GPU n'ont pas 2x plus de mémoire accessible, car les données seront dupliquées dans les mémoire respective à chaque GPU. Les constructeur adore être vague la dessus pour vendre au maximum ces cartes hors de prix

    Si tu veux dessiné avec les deux carte graphique sur les instance d'un seul thread, il faut obligatoirement un SLI ou un Crossfire.

    Donc dans ton cas, tu doit crée tes 2 contextes indépendamment : un pour ta carte graphique en OpenGL 3.0, et un autre pour la carte graphique OpenGL 4.2 (pas encore de 4.3 ? ) et géré le chargement de tes éléments (texture, VBOs ...) dans chaqu'un des contextes (au besoins bien évidemment). Sa complexifie énormément l'architecture du moteur, le mien à du être entièrement reconçu jusqu'à la moelle pour çà. Mais le résultat est fonctionnel et le gain de performance par l'utilisation synchronisé de deux GPU est au rendez vous.

    C'est bien là le problème, je pense. Chaque action OpenGL, doit être fait dans le thread qui a initialisé le contexte. Car le contexte est lié au thread. (On retrouve un peu le même cas en lisant la documentation de la SDL).
    Ainsi, la création des ressources dans un autre thread a des chances d'échouer (ou de ne pas fonctionner). Par contre, je croyais qu'un tel cas renvoyait une erreur OpenGL (GL_NO_CONTEXT, ou un truc du genre).
    Non. Tu peut binder le context OpenGL dans un autre thread. C'est juste que quand tu crée ton context OpenGL, il est automatiquement bindé au thread l'ayant fait.
    Et tu peut faire du chargement on the fly avec des contexte partagé. Tu fais le rendu avec un contexte OpenGL, pendant que tu charge avec un autre thread avec un autre contexte OpenGL étant partagé avec le premier.
    D'un point de vue générale, çà plante si tu exécute dans un thread des commandes OpenGL qui n'aurai pas bindé au préalablement un contexte OpenGL.

    from China with love !

  17. #17
    Expert éminent sénior

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 031
    Points : 11 476
    Points
    11 476
    Billets dans le blog
    11
    Par défaut
    Je ne sais pas si ça peut t'aider, mais je sais que j'ai dû arrêter de faire du multithread avec les contextes OpenGL car sous Linux je n'ai pas réussi à les faire fonctionner.
    Par contre tu n'es pas obligé d'avoir plusieurs contextes pour faire du rendu multifenêtres.
    Tu crées un seul contexte et tu appelles glMakeCurrent avec le HDC de la fenêtre voulue.
    Il faut juste que les HDC soient*compatibles.
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  18. #18
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 20
    Points : 7
    Points
    7
    Par défaut
    Citation Envoyé par LastSpear Voir le message
    J'ai dejà eu à faire avec se problème.

    Ils y a beaucoup trop de problèmes pour pouvoir partagé des contexte de version différente. Autrement dit, tu peux pas d'un point de vue de rigueur, même si tu peut le codé.

    Si les deux carte graphique ne sont pas du même constructeur (Nvidia ou ATI/AMD), les drivers seront complètement différent, et donc incompatible, donc çà ne fonctionnera pas même avec des contextes partagé de même version.

    Par ailleurs, que tu ai un pont SLI ou Crossfire ou même pas du tout comme dans ton cas, toute tes données seront quand même dupliquées dans les deux mémoire. A titre d'exemple, les carte graphique BI-GPU n'ont pas 2x plus de mémoire accessible, car les données seront dupliquées dans les mémoire respective à chaque GPU. Les constructeur adore être vague la dessus pour vendre au maximum ces cartes hors de prix

    Si tu veux dessiné avec les deux carte graphique sur les instance d'un seul thread, il faut obligatoirement un SLI ou un Crossfire.

    Donc dans ton cas, tu doit crée tes 2 contextes indépendamment : un pour ta carte graphique en OpenGL 3.0, et un autre pour la carte graphique OpenGL 4.2 (pas encore de 4.3 ? ) et géré le chargement de tes éléments (texture, VBOs ...) dans chaqu'un des contextes (au besoins bien évidemment). Sa complexifie énormément l'architecture du moteur, le mien à du être entièrement reconçu jusqu'à la moelle pour çà. Mais le résultat est fonctionnel et le gain de performance par l'utilisation synchronisé de deux GPU est au rendez vous.


    Non. Tu peut binder le context OpenGL dans un autre thread. C'est juste que quand tu crée ton context OpenGL, il est automatiquement bindé au thread l'ayant fait.
    Et tu peut faire du chargement on the fly avec des contexte partagé. Tu fais le rendu avec un contexte OpenGL, pendant que tu charge avec un autre thread avec un autre contexte OpenGL étant partagé avec le premier.
    D'un point de vue générale, çà plante si tu exécute dans un thread des commandes OpenGL qui n'aurai pas bindé au préalablement un contexte OpenGL.

    from China with love !

    En fait, tu n'as pas compris mon problème.

    Je n'utilise pas les deux cartes graphiques en même temps.

    Je suis sur un ordinateur portable possédant deux cartes graphique une carte pour la bureautique ( power save, traitement de texte... ) et une GT 540M pour les jeux et tout ce qui nécessite un grosse puissance graphique. Quand je fais clic droit sur mon application, j'ai un menu : Executer avec le processeur graphique > Graphique intégrés OU Processeur NVIDIA Hautes performances.

    La carte "Graphique intégrés" dispose d'une implémentation opengl 3.0 et le partage de context entre les thread et donc le partage de ressources FONCTIONNE PARFAITEMENT lorsque je lance avec cette carte.

    La carte "Processeur NVIDIA Hautes performances" dispose d'une implémentation opengl 4.2 et le partage de context entre les thread et donc le partage de ressources EST DISFONCTIONNEL. Je réexplique :
    Avec cette carte, tout est sensé fonctionner étant donné que j'arrive depuis le thread de rendu ( celui qui n'a pas initialisé les ressources ) a récupérer le contenu de ces ressources ( je télécharge les données de mon VBO, IBO et de ma Texture depuis la carte graphique sans soucis ). Simplement, rien de s'affiche... et c'est la que j'ai besoin d'aide car je ne trouve pas d'erreur dans mon implémentation.

    Je tiens à précisé que tous les contexts sont initialisé avec les mêmes paramètres, même version d'opengl, même pixelformat, etc...

    ET je n'utilise jamais les deux cartes en même temps.

  19. #19
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 219
    Points : 239
    Points
    239
    Par défaut
    Au temps pour moi !

    La carte "Graphique intégrés" dispose d'une implémentation opengl 3.0 et le partage de context entre les thread et donc le partage de ressources FONCTIONNE PARFAITEMENT lorsque je lance avec cette carte.
    Oui çà je sais bien, je l'ai même souligné :
    Et tu peut faire du chargement on the fly avec des contexte partagé. Tu fais le rendu avec un contexte OpenGL, pendant que tu charge avec un autre thread avec un autre contexte OpenGL étant partagé avec le premier.
    De plus, j'ai mis un mutex dans les resources de façon à ce qu'un seul thread ne puisse agir( bind ) dessus à la fois. je le Lock avant chaque bind et je le Unlock apres le bind(0).
    Très movais, cela ne sert strictement a rien car le GPU est désynchronisé du CPU. Donc quand ton CPU arrivera à l'appel du bind(0), çà n'implique pas que l'utilisation de cette texture est terminé (voir même commencé). Il faut plutot synchronisé par fram avec un system de publication de nouvelle ressource (textures, VBOs) tout juste chargé pendant la fram précédente qui s'esecute au moment du swap buffer.

    Aussi crées ton context en core profile Parce que avec OpenGL 3.3 et superieur il y a des changement au niveau de l'utilisation des texture par exemple avec l'introduction des sampler, choix des swizzle ... Donc pour être sur qu'il n'y ai pas de collision, tu devrai les crée en core profile.

    Aussi regarde tu de temps en temps l'état de glGetError ? Même en release il est bon d'en gardé en fin de chargement de ressources, et un avant les swap buffer pour etre sur qu'aucune erreur survient.

    Aussi tu utilise aucun outil pour attribuer le context OpenGL à un GPU ...

  20. #20
    screetch
    Invité(e)
    Par défaut
    il n'y a pas moyen de choisir la carte graphique dans le programme, c'est l'OS qui choisit la carte graphique et tous les contextes sont crees pour cette carte graphique.

Discussions similaires

  1. Réponses: 5
    Dernier message: 20/10/2014, 16h49
  2. SDL/OpenGL / ActiveX probleme de contexte
    Par venomelektro dans le forum SDL
    Réponses: 0
    Dernier message: 15/04/2009, 14h36
  3. Partage entre contexte OpenGL
    Par Syl_20 dans le forum OpenGL
    Réponses: 14
    Dernier message: 09/12/2008, 16h44
  4. Réponses: 4
    Dernier message: 13/02/2007, 17h40
  5. Réponses: 4
    Dernier message: 20/04/2005, 13h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo