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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    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
    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
    27 129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 129
    Billets dans le blog
    149
    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 : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    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
    Membre averti
    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
    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 : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    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
    Membre averti
    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
    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 : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    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

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