liballeg / allegro5

The official Allegro 5 git repository. Pull requests welcome!
https://liballeg.org
Other
1.9k stars 285 forks source link

Multisampling doesn't work with DirectX renderer #922

Open ArosPrince opened 6 years ago

ArosPrince commented 6 years ago

I have lately installed nuget package with 5.2.4 and found out that there is still a problem that I am reporting for years.

Based on my experience there are two cases:

  1. Multisampling doesn't work with DirectX renderer at all. All the lines are jagged as if the multisampling was not enabled at all.
  2. Multisampling works well, but the window that is created with multisampling flickers like crazy when being created.

Whether on the given computer it is case 1 or 2 depends definitely on the graphics card. Based on my experience the first case is more often for integrated Intel graphics cards in notebooks and the second case is more usual for AiB cards in desktop.

This one either flickers or doesn't work: al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST); al_set_new_display_option(ALLEGRO_SAMPLES, 8, ALLEGRO_SUGGEST);

This one doesn't flicker, but of course there is no multisampling: al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 0, ALLEGRO_SUGGEST); al_set_new_display_option(ALLEGRO_SAMPLES, 0, ALLEGRO_SUGGEST);

I have reported the issue on the forum several times already, for example: https://www.allegro.cc/forums/thread/612022 https://www.allegro.cc/forums/thread/612248/978749 https://www.allegro.cc/forums/thread/617479

fatcerberus commented 6 years ago

~This sounds to me more like a issue with DirectX and/or the graphics drivers than Allegro; Allegro is a pretty thin interface and doesn’t tend to do a lot of “magic” behind the scenes other than translating its own calls to equivalent DX/GL calls.~

edit: Disregard - I read through the linked threads and there might be more going on under the hood than meets the eye.

EdgarReynaldo commented 6 years ago

On 8/1/2018 2:04 PM, Bruce Pascoe wrote:

This sounds to me more like a issue with DirectX and/or the graphics drivers than Allegro; Allegro is a pretty thin interface and doesn’t tend to do a lot of “magic” behind the scenes other than translating its own calls to equivalent DX/GL calls.

/edit:/ Disregard - I read through the linked threads and there might be more going on under the hood than meets the eye.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/liballeg/allegro5/issues/922#issuecomment-409685132, or mute the thread https://github.com/notifications/unsubscribe-auth/AXSQ4WPvo9-Cd5kVYEshTUayMKLk_vOWks5uMfvXgaJpZM4Vq9ZH.

It's clear that Allegro is trying and failing to set several graphics modes. Hence the flickering on window creation. Allegro 4's GFX_AUTODETECT driver does this, and it drives me crazy, because many of the example programs use GFX_AUTODETECT.

allegro.log should have useful information when enabling MultiSampling on DirectX.

fatcerberus commented 6 years ago

Yeah, I edited my post above after reading the linked threads. I had forgotten that Allegro does a pretty heavy trial-and-error enumeration of display modes when creating a display.

ArosPrince commented 6 years ago

Yeah, from the log from the first linked thread the trial&error is quite obvious. It comes from very old 5.0.8 but this behavior didn't change a bit over the time so I guess it is still useful.

As for why it doesn't work on some of the graphics cards... Any ideas? I mean even Intel's integrated graphics must be capable of drawing simple smooth lines...

ArosPrince commented 6 years ago

OK, so I made some tests. On my workstation laptop I have both integrated Intel HD 530 and Nvidia Quadro M1200.

It's quite complicated but I will explain as best I can:

1) nVidia Quadro and DX it flickers on startup, but looks OK, like this: allegro_dx_nvidia_quadro You should see a green outline of the inner area of the window. Also the font looks nice and all the lines and the sine wave are nicely smoothed. Everything looks nice, but it flickers on window creation.

2) Intel HD 530 with DX. It really looks the same, apart from the fact that multisampling obviously doesn't work, but also it doesn't flicker on startup. allegro_dx_intel_hd_530

3) Intel HD 530 with OpenGL. If I use the same graphics as in the previous case but just add the ALLEGRO_OPENGL flag, it looks like this: allegro_gl_intel_hd_530 As you can see, multisampling somehow works, but looks terrible - see the jaggy places at the sine wave. Also the font looks weird and the green outline disappeared beyond the window borders. To be able to see it, I need to adjust the line thickness to at least 18 which means that the line is shifted at least 9 pixels. See here: allegro_gl_intel_hd_530_thickborders The mouse coordinates of course stay the same, so the mouse down event and the object you visually click on do not match, which is extremely annoying. Needless to say that this mode is just absolutely unusable.

4) nVidia Quadro with OpenGL. No flickering, everything is smooth, nice fonts, coordinates match. Sounds good, right? Well, not exactly this one takes a long time to display. Even if I count in the flickering, the DX version displays MUCH quickly. This one takes like 5 seconds from when the window shows to the point when the content of the window is rendered... allegro_gl_nvidia_quadro

Resume: nVidia, DX: usable but annoying flickering Intel, DX: unsuable because of lacking anti-aliasing (ehm, I really need it!) nVidia GL: usable, no flickering, but takes a long time to load Intel GL: absolutely unusable, terrible AA with artifacts, coordinates don't match, crappy fonts

There is no perfect option. Everything's wrong in a way. I could use GL, if it at least worked on Intel HDs, without AA, but this way, it absolutely breaks the whole app. It's not a game but a UI Control Panel and I need it to work with Intel HDs because those are the most common laptop graphics.

The code used to generate the images (comment or uncomment the OpenGL flag):


#include <iostream>
#include "Allegro5/allegro.h"
#include <allegro5/allegro_image.h>
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_ttf.h>
#include <cmath>

bool as_al_init(int display_width, int display_height, ALLEGRO_DISPLAY** display, ALLEGRO_EVENT_QUEUE** event_queue, ALLEGRO_TIMER** timer, ALLEGRO_EVENT_SOURCE* redraw_event_source, double timerInterval, int withMultisampling, bool fullscreen) {
  int flags = 0;
  if (!al_init()) {
    std::cerr << "Failed to initialize allegro!" << std::endl;
    return false;
  }
  if (!al_install_mouse()) {
    std::cerr << "Failed to install mouse!" << std::endl;
    return false;
  }
  if (!al_install_keyboard()) {
    std::cerr << "Failed to install keyboard!" << std::endl;
    return false;
  }
  if (!display) return false;

  if (fullscreen) {
    flags |= ALLEGRO_FULLSCREEN_WINDOW | ALLEGRO_NOFRAME;

    ALLEGRO_MONITOR_INFO info;
    int i = 0;
    do {
      al_get_monitor_info(i++, &info);
    } while (!(info.x1 == 0 && info.y1 == 0));
    display_width = info.x2 - info.x1;
    display_height = info.y2 - info.y1;
  }
  //al_set_new_display_flags(ALLEGRO_OPENGL_3_0);

  flags |= ALLEGRO_OPENGL;

  flags |= ALLEGRO_GENERATE_EXPOSE_EVENTS;
  al_set_new_display_flags(flags);

  if (withMultisampling) {
    al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST);
    al_set_new_display_option(ALLEGRO_SAMPLES, withMultisampling, ALLEGRO_SUGGEST);
  }
  else {
    al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 0, ALLEGRO_SUGGEST);
    al_set_new_display_option(ALLEGRO_SAMPLES, 0, ALLEGRO_SUGGEST);
  }
  if (!(*display = al_create_display(display_width, display_height))) {
    return false;
  }

  if (!event_queue) { al_destroy_display(*display); return false; }
  if (!(*event_queue = al_create_event_queue())) {
    al_destroy_display(*display);
    std::cerr << "Failed to create event queue!" << std::endl;
    return false;
  }
  if (!(al_init_image_addon())) {
    std::cerr << "Failed to initialize image addon." << std::endl;
    al_destroy_display(*display);
    return false;
  }
  if (!(al_init_primitives_addon())) {
    std::cerr << "Failed to initialize primitives addon." << std::endl;
    al_destroy_display(*display);
    return false;
  }
  al_init_font_addon();
  if (!(al_init_ttf_addon())) {
    std::cerr << "Failed to initialize ttf addon." << std::endl;
    al_destroy_display(*display);
    return false;
  }
  if (!timer) return true;
  if (!(*timer = al_create_timer(timerInterval))) {
    std::cerr << "Failed to create timer!" << std::endl;
    al_destroy_display(*display);
    return false;
  }
  if (redraw_event_source) {
    al_init_user_event_source(redraw_event_source);
    al_register_event_source(*event_queue, redraw_event_source);
  }

  return true;
}

void as_al_cleanUp(ALLEGRO_DISPLAY* display, ALLEGRO_EVENT_QUEUE* event_queue, ALLEGRO_TIMER* timer, ALLEGRO_EVENT_SOURCE* redraw_event_source) {
  if (redraw_event_source) al_destroy_user_event_source(redraw_event_source);
  if (timer) al_destroy_timer(timer);
  if (event_queue) al_destroy_event_queue(event_queue);
  if (display) al_destroy_display(display);
  al_shutdown_ttf_addon();
  al_shutdown_font_addon();
  al_shutdown_primitives_addon();
  al_shutdown_image_addon();
  al_uninstall_keyboard();
  al_uninstall_mouse();
  al_uninstall_system(); //all allegro shutdowns have to go before this one...
}

#define D_WIDTH 640
#define D_HEIGHT 480

int main()
{
  ALLEGRO_DISPLAY* display = NULL;
  ALLEGRO_EVENT_QUEUE* event_queue = NULL;
  ALLEGRO_TIMER* timer = NULL;
  ALLEGRO_EVENT_SOURCE redraw_event_source;

  if (!as_al_init(D_WIDTH, D_HEIGHT, &display, &event_queue, &timer, &redraw_event_source, 1.0 / 30, 8, false)) return 1;

  al_register_event_source(event_queue, al_get_display_event_source(display));
  al_register_event_source(event_queue, al_get_timer_event_source(timer));
  al_register_event_source(event_queue, al_get_mouse_event_source());
  al_register_event_source(event_queue, al_get_keyboard_event_source());

  ALLEGRO_FONT* font = al_load_ttf_font("titilliumtext25l002.ttf", 20, ALLEGRO_TTF_NO_AUTOHINT/*0*/);

  al_clear_to_color(al_map_rgb(0, 0, 0));

  al_draw_text(font, al_map_rgba(255, 255, 255, 0), D_WIDTH / 2, D_HEIGHT / 4, ALLEGRO_ALIGN_CENTRE, "Loading...");

  al_draw_line(0, 0, 100, 100, al_map_rgb(255, 255, 255), 1.0f);
  al_draw_line(0, 0, 100, D_HEIGHT, al_map_rgb(255, 255, 255), 1.0f);

  ALLEGRO_COLOR c = al_map_rgb(0, 255, 0);

  float thickness = 1.0f;
  //thickness = 18;

  al_draw_line(0, 0, D_WIDTH, 0, c, thickness + 2.0f);
  al_draw_line(D_WIDTH, 0, D_WIDTH, D_HEIGHT, c, thickness);
  al_draw_line(D_WIDTH, D_HEIGHT, 0, D_HEIGHT, c, thickness);
  al_draw_line(0, D_HEIGHT, 0, 0, c, thickness + 2.0f);

  float PI = 3.14;
  float prev = D_HEIGHT / 2, cur;
  for (int i = 0; i < D_WIDTH; i++) {
    cur = D_HEIGHT / 2 - sin(i*PI / 100) * 25;
    al_draw_line(i - 1, prev, i, cur, al_map_rgb(255, 255, 255), 1.0f);
    prev = cur;
  }

  al_flip_display();

  al_start_timer(timer);

  while (true) {
    ALLEGRO_EVENT ev;

    al_wait_for_event(event_queue, &ev);
    if (ev.type == ALLEGRO_EVENT_KEY_CHAR) {
      break;
    }
  }

  al_destroy_font(font);
  as_al_cleanUp(display, event_queue, timer, &redraw_event_source);

  return 0;
}
dos1 commented 6 years ago

Not a Windows guy here, but I think posting allegro.logs from every of those cases would be pretty helpful :)

ArosPrince commented 6 years ago

Can I do that with the NuGet version? It seems to me that there is only a release build.

fatcerberus commented 6 years ago

There is also an option to use the debug build if you go into your project properties. In any case you can enable logging even in the release build, though I don’t remember how...

EdgarReynaldo commented 6 years ago

I tested this on my Windows 10 laptop. It's got an integrated Intel HD 5600 and an NVIDIA GeForce GTX 965M.

Intel DX Fullscreen - No Multisampling, no flicker Intel GL Fullscreen - MS enabled, looks fine NVIDIA DX Fullscreen - MS enabled, looks fine NVIDIA GL Fullscreen - MS enabled, looks fine

So at this point I would recommend the usual advice and see if there are any updates available for your graphics drivers, because I don't have any of the problems you describe and I haven't even updated my drivers in at least a year.

Giacom commented 5 years ago

Multisampling is working for me but it will have to destroy and recreate the display device before doing so, which can cause the window to be unfocused which is very annoying.

Giacom commented 5 years ago

This is the log messages I get when trying to use multisampling. There's multiple error messages about D3DERR_INVALIDCALL

[ALLEGRO] system   I            wsystem.c:702  load_library_at_path             [   0.07297] Loaded C:\WINDOWS\system32\d3d9.dll
[ALLEGRO] d3d      I         d3d_disp.cpp:674  d3d_init_display                 [   0.08890] Render-to-texture: 1
[ALLEGRO] d3d      I         d3d_disp.cpp:1768 d3d_create_display_locked        [   0.09044] faux_fullscreen=0
[ALLEGRO] d3d      I d3d_display_formats.cpp:144  _al_d3d_generate_display_format_list [   0.09242] found 160 format combinations
[ALLEGRO] d3d      I         d3d_disp.cpp:1344 d3d_display_thread_proc          [   0.09276] Chose a display format: 23
[ALLEGRO] d3d      I         d3d_disp.cpp:1413 d3d_display_thread_proc          [   0.09290] Normal window.
[ALLEGRO] d3d      I         d3d_disp.cpp:781  d3d_create_device                [   0.10770] Using no depth stencil buffer
[ALLEGRO] d3d      E         d3d_disp.cpp:822  d3d_create_device                [   0.11303] CreateDevice failed: D3DERR_INVALIDCALL
[ALLEGRO] d3d      I         d3d_disp.cpp:901  d3d_destroy_display              [   0.11324] destroying display 00000207C2A6F510 (current 0000000000000000)
[ALLEGRO] d3d      I         d3d_disp.cpp:1699 d3d_create_display_internals     [   0.11362] Format 0 failed.
[ALLEGRO] d3d      I         d3d_disp.cpp:1344 d3d_display_thread_proc          [   0.11660] Chose a display format: 23
[ALLEGRO] d3d      I         d3d_disp.cpp:1413 d3d_display_thread_proc          [   0.11679] Normal window.
[ALLEGRO] d3d      I         d3d_disp.cpp:778  d3d_create_device                [   0.13314] Chose depth stencil format 75
[ALLEGRO] d3d      E         d3d_disp.cpp:822  d3d_create_device                [   0.13717] CreateDevice failed: D3DERR_INVALIDCALL
[ALLEGRO] d3d      I         d3d_disp.cpp:901  d3d_destroy_display              [   0.13737] destroying display 00000207C2A6F510 (current 0000000000000000)
[ALLEGRO] d3d      I         d3d_disp.cpp:1699 d3d_create_display_internals     [   0.13772] Format 1 failed.
[ALLEGRO] d3d      I         d3d_disp.cpp:1344 d3d_display_thread_proc          [   0.14219] Chose a display format: 23
[ALLEGRO] d3d      I         d3d_disp.cpp:1413 d3d_display_thread_proc          [   0.14236] Normal window.
[ALLEGRO] d3d      I         d3d_disp.cpp:778  d3d_create_device                [   0.15120] Chose depth stencil format 77
[ALLEGRO] d3d      E         d3d_disp.cpp:822  d3d_create_device                [   0.15396] CreateDevice failed: D3DERR_INVALIDCALL
[ALLEGRO] d3d      I         d3d_disp.cpp:901  d3d_destroy_display              [   0.15416] destroying display 00000207C2A6F510 (current 0000000000000000)
[ALLEGRO] d3d      I         d3d_disp.cpp:1699 d3d_create_display_internals     [   0.15447] Format 2 failed.
[ALLEGRO] d3d      I         d3d_disp.cpp:1344 d3d_display_thread_proc          [   0.15804] Chose a display format: 23
[ALLEGRO] d3d      I         d3d_disp.cpp:1413 d3d_display_thread_proc          [   0.15818] Normal window.
[ALLEGRO] d3d      I         d3d_disp.cpp:778  d3d_create_device                [   0.16482] Chose depth stencil format 80
[ALLEGRO] d3d      E         d3d_disp.cpp:822  d3d_create_device                [   0.16708] CreateDevice failed: D3DERR_INVALIDCALL
[ALLEGRO] d3d      I         d3d_disp.cpp:901  d3d_destroy_display              [   0.16720] destroying display 00000207C2A4E500 (current 0000000000000000)
[ALLEGRO] d3d      I         d3d_disp.cpp:1699 d3d_create_display_internals     [   0.16744] Format 3 failed.
[ALLEGRO] d3d      I         d3d_disp.cpp:1344 d3d_display_thread_proc          [   0.17084] Chose a display format: 13
[ALLEGRO] d3d      I         d3d_disp.cpp:1413 d3d_display_thread_proc          [   0.17127] Normal window.
[ALLEGRO] d3d      I         d3d_disp.cpp:781  d3d_create_device                [   0.17785] Using no depth stencil buffer
[ALLEGRO] d3d      E         d3d_disp.cpp:822  d3d_create_device                [   0.18088] CreateDevice failed: D3DERR_INVALIDCALL
[ALLEGRO] d3d      I         d3d_disp.cpp:901  d3d_destroy_display              [   0.18103] destroying display 00000207C2A4D510 (current 0000000000000000)
[ALLEGRO] d3d      I         d3d_disp.cpp:1699 d3d_create_display_internals     [   0.18149] Format 4 failed.
[ALLEGRO] d3d      I         d3d_disp.cpp:1344 d3d_display_thread_proc          [   0.18450] Chose a display format: 13
[ALLEGRO] d3d      I         d3d_disp.cpp:1413 d3d_display_thread_proc          [   0.18462] Normal window.
[ALLEGRO] d3d      I         d3d_disp.cpp:778  d3d_create_device                [   0.19416] Chose depth stencil format 75
[ALLEGRO] d3d      E         d3d_disp.cpp:822  d3d_create_device                [   0.19621] CreateDevice failed: D3DERR_INVALIDCALL
[ALLEGRO] d3d      I         d3d_disp.cpp:901  d3d_destroy_display              [   0.19632] destroying display 00000207C2A4EFA0 (current 0000000000000000)
[ALLEGRO] d3d      I         d3d_disp.cpp:1699 d3d_create_display_internals     [   0.19652] Format 5 failed.
[ALLEGRO] d3d      I         d3d_disp.cpp:1344 d3d_display_thread_proc          [   0.19934] Chose a display format: 13
[ALLEGRO] d3d      I         d3d_disp.cpp:1413 d3d_display_thread_proc          [   0.19946] Normal window.
[ALLEGRO] d3d      I         d3d_disp.cpp:778  d3d_create_device                [   0.20468] Chose depth stencil format 77
[ALLEGRO] d3d      E         d3d_disp.cpp:822  d3d_create_device                [   0.20703] CreateDevice failed: D3DERR_INVALIDCALL
[ALLEGRO] d3d      I         d3d_disp.cpp:901  d3d_destroy_display              [   0.20715] destroying display 00000207C2A4CA70 (current 0000000000000000)
[ALLEGRO] d3d      I         d3d_disp.cpp:1699 d3d_create_display_internals     [   0.20738] Format 6 failed.
[ALLEGRO] d3d      I         d3d_disp.cpp:1344 d3d_display_thread_proc          [   0.20977] Chose a display format: 13
[ALLEGRO] d3d      I         d3d_disp.cpp:1413 d3d_display_thread_proc          [   0.21005] Normal window.
[ALLEGRO] d3d      I         d3d_disp.cpp:778  d3d_create_device                [   0.21742] Chose depth stencil format 80
[ALLEGRO] d3d      E         d3d_disp.cpp:822  d3d_create_device                [   0.21998] CreateDevice failed: D3DERR_INVALIDCALL
[ALLEGRO] d3d      I         d3d_disp.cpp:901  d3d_destroy_display              [   0.22010] destroying display 00000207C2A4C520 (current 0000000000000000)
[ALLEGRO] d3d      I         d3d_disp.cpp:1699 d3d_create_display_internals     [   0.22030] Format 7 failed.
[ALLEGRO] d3d      I         d3d_disp.cpp:1344 d3d_display_thread_proc          [   0.22262] Chose a display format: 23
[ALLEGRO] d3d      I         d3d_disp.cpp:1413 d3d_display_thread_proc          [   0.22276] Normal window.
[ALLEGRO] d3d      I         d3d_disp.cpp:781  d3d_create_device                [   0.22837] Using no depth stencil buffer
[ALLEGRO] d3d      I         d3d_disp.cpp:1724 d3d_create_display_internals     [   0.26576] Format 83 succeeded.
[ALLEGRO] system   I            wsystem.c:702  load_library_at_path             [   0.26651] Loaded C:\WINDOWS\system32\d3dx9_43.dll
[ALLEGRO] d3dx9    I        d3d_d3dx9.cpp:88   _imp_load_d3dx9_module_version   [   0.26663] Module "d3dx9_43.dll" loaded.
[ALLEGRO] d3d      I         d3d_disp.cpp:2377 d3d_create_bitmap                [   0.26708] Chose bitmap format 9
Giacom commented 5 years ago

Another interesting thing is that it'll only render the multisampling if you set the importance of the request to SUGGEST. If you try to use REQUIRE it'll not work.

EdgarReynaldo commented 5 years ago

Don't suppose DX is smart enough to have a debugging callback function....

EdgarReynaldo commented 5 years ago

There's a failure chain it goes through when a format fails to succeed.

https://github.com/liballeg/allegro5/blob/master/src/win/d3d_disp.cpp#L814-L839

fatcerberus commented 5 years ago

fails to succeed

I thought I was the only person who made this joke. Now I have competition, it seems. 😸

EdgarReynaldo commented 5 years ago

Well I just broke Visual Studio beyond repair by getting it stuck in an update loop where I need to download 22 GB of crapware just to get it to work again. Can someone else with Visual Studio and the Window SDK installed debug this? It will tell you exactly what errors are occurring in the DX runtime.

ArosPrince commented 2 years ago

@EdgarReynaldo Several years passed, but this would still come in handy. Do you still want me to try it out?

SiegeLord commented 2 years ago

Note that we have fixed the flickering in https://github.com/liballeg/allegro5/commit/b1f96f7bf0a6221b0e6110358971f99bba96f237 (and 3 more commits after that). As part of that, we found an issue that the D3D sample selection was fundamentally broken, as then number passed to the Allegro API ends up corresponding to D3D sample quality, which isn't always 1:1 mapping to the number of samples taken, unlike what is done in OGL: https://github.com/liballeg/allegro5/issues/1246

ArosPrince commented 2 years ago

Wow, that's interesting. I've been living with the issue for about 10 years now! Great to hear that.

Also, I take it this has not yet ended up in any of the official releases, right?

SiegeLord commented 2 years ago

No. Slated for 5.2.8 which is coming soon:tm:

ArosPrince commented 2 years ago

And the other issue mentioned above - multisampling not working on Intel GPUs?

SiegeLord commented 2 years ago

I don't have an Intel GPU to test with, but given how broken this system was before, perhaps it's fixed there now as well?

ArosPrince commented 2 years ago

It definitely isn't in 5.2.7.1. Will test the new version once released and let you know.

SiegeLord commented 2 years ago

If you'd like, you could test the development binaries I made a few months ago. They have the commits above in them: http://siegelord.net/files/5.2.8%20dev/