Trying to use non-existing surface.

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Trying to use non-existing surface.

    Hi zusammen, wieder eine meiner lästigen Surface fragen.

    Seit kurzem, wahrscheinlich seit dem letzten Update von GM:S, bekomme ich diesen Fehler (Trying to use non-existing surface. NAME DES SURFACE) wenn ich das Spiel minimiere und wieder maximiere.

    Weiß jemand vielleicht woran das liegen könnte? Oder hatte das selbe Problem und es schon gelöst?

    Der Fehler tritt leider bei all meinen Programmen auf, egal ob ich es aus GM:S direkt starte oder aber erst Exportiere.
    Solange es Minimiert ist scheint es noch zu funktionieren, aber sobald ich es Maximiere bekomme ich diesen Fehler welcher das beenden des Programms zur folge hat.


    Edit: Sorry hab jetzt erst gesehen das es eine extra Abteilung für Studio gibt, bitte verschieben.
    Bilder
    • surface_bug.png

      24,65 kB, 615×537, 442 mal angesehen
  • Ich würde vermuten, dass der GM die Game Loop anhält, so lange das Fenster minimiert ist, deswegen kriegst du die Fehlermeldung erst, wenn das Fenster wieder zurückkommt und die Loop weiterläuft. Die Surfaces werden allerdings schon beim Minimieren gelöscht, um die belegten Ressourcen auf RAM, CPU und GPU wieder freizugeben.
    Ich weiß nicht, ob es möglich ist, das Minimier-Event im GM abzufangen. Wenn ja, ist die Sache recht einfach - dann kannst du nämlich einfach ansagen "Hey, ich hab grad minimiert, all meine Surfaces sind Rotz, erstell die bitte neu, sobald du wieder da bist". Zwischenspeichern wird ohne DLLs oder Extensions aber wohl nicht möglich sein.
    Wenn man das Event nicht abfangen kann (und das befürchte ich), läuft es wahrscheinlich auf die "Lösung" raus, vor absolut jedem Surface-Draw abzufragen, ob die entsprechende Surface überhaupt noch existiert und wenn nein, sie erst neu zu erstellen. Das macht dein Spiel insgesamt langsamer, je nachdem, wie exzessiv du Surfaces benutzt - aber es hebelt diesen Fehler aus.

    Edit:
    Liebend gern. *schyb*
  • Wenn man das Event nicht abfangen kann (und das befürchte ich), läuft es wahrscheinlich auf die "Lösung" raus, vor absolut jedem Surface-Draw abzufragen, ob die entsprechende Surface überhaupt noch existiert und wenn nein, sie erst neu zu erstellen. Das macht dein Spiel insgesamt langsamer, je nachdem, wie exzessiv du Surfaces benutzt - aber es hebelt diesen Fehler aus.

    Muss man wirklich vor jeder "draw_surface()" Anweisung die jeweilige Surface nach der existenz abfragen? Ich mache diesen check nur 1 mal im Step event für die jeweiligen Surfaces und zeichne sie dann so oft ich will im Draw-event. Funktioniert bei mir auch relativ gut. Zumindest mache ich dies so in meinem Projekt und hatte seither keinen einzigen "Trying to use non-existing surface" error bekommen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von LEWA ()

  • Ich danke euch vielmals für eure Überlegungen, denke wir kommen dem ganzen näher.

    Für mich ist folgendes warscheinlich zu hoch, aber vielleicht kann ja jemand von euch was damit anfangen. (... auf Irrenhaus3 und LEWA guck)
    Ich hab mal in ROT kommentiert.

    Entering main loop.
    **********************************.
    Application Surface created: w=640, h=480 // Letzte Zeile wenn das Spiel über den GM:S gestartet ist
    Pause event has been registered for this frame // Klick mit der Maus auf dem Rahmen um das Fenster zu ziehen
    Pause event has been unregistered // Loslassen des Fensters
    Pause event has been registered for this frame // Minimieren des Fensters
    Pause event has been unregistered // Maximieren des Fensters, ab hier der rest bis zur Fehlermeldung nach maximieren des Fensters
    Free all surfaces // OH OH, das hört sich gar nicht gut an oder?
    Graphics::Reset()
    --Reset Begin
    Restore Target
    Check Display Mode
    Free Screen Texture
    Toggle Fullscreen/windowed mode settings
    Execute Reset()
    WindowedMode: Setup window prefs
    --Reset End
    Graphics::Clear()
    D3D Settings Init
    Application Surface created: w=640, h=480
    ERROR!!! :: ############################################################################################
    ERROR in
    action number 1
    of Draw Event
    for object obj_login_server:


    Trying to use non-existing surface.
    at gml_Object_obj_login_server_DrawEvent_1 (line 78) - draw_surface(sf_log, 16, 91);
    ############################################################################################


    Scheint so als würde er beim minimieren wirklich alle Surfaces löschen oder wie seht ihr das?
    Das muss man doch irgendwo einstellen können den früher war das auch nicht so, erinnere mich nicht das ich beim minimieren je ein Problem hatte :(
  • Wie gesagt, surfaces können verloren gehen.
    Was du machen musst, ist diese nochmals zu erstellen, falls sie nicht mehr existieren.
    Bei mir schauen die Checks (im Step-Event eines beliebigen Objektes) etwa so aus:

    GML-Quellcode

    1. if(surface_exists(light_scattering_buffer) == false){
    2. light_scattering_buffer = surface_create(get_render_w(),get_render_h());
    3. }
    4. if(surface_exists(framebuffer) == false){
    5. framebuffer = surface_create(get_render_w(),get_render_h());
    6. }
    7. if(surface_exists(framebuffer_temp) == false){
    8. framebuffer_temp = surface_create(get_render_w(),get_render_h());
    9. }
    10. if(surface_exists(gui_framebuffer) == false){
    11. gui_framebuffer = surface_create(get_render_w(),get_render_h());
    12. }
    Alles anzeigen


    Das Step-Event wird vor dem Draw-Event ausgeführt. Das bedeutet, dass vor dem zeichen (bzw. verwenden der Surface) diese bereits im Speicher neu angelegt wurde. (was den error verhindert.)
    Funktioniert auch mit dem minimieren und maximieren des Fensters.

    /Edit:
    In deiner Consolenausgabe siehst du bereits, dass die Application Surface nach dem erneuten öffnen des Fensters erstellt wird:
    Application Surface created: w=640, h=480

    Das liegt daran dass die application surface fest in den GM integriert ist und dadurch der "surface_exists()" check vom GM automatisch (für die application_surface) gemacht wird.

    GML-Quellcode

    1. /*Solch eine überprüfung wird für die application_surface bereits intern im GM AUTOMATISCH gemacht.
    2. Für alle anderen "eigenen" Surfaces wirst du diese überprüfung selber machen müssen.*/
    3. if(surface_exists(application_surface) == false){
    4. application_surface = surface_create(get_render_w(),get_render_h());
    5. }


    Du verwendest aber noch weitere Surfaces welche von Studio nicht automatisch auf verfügbarkeit überprüft werden:
    Trying to use non-existing surface.
    at gml_Object_obj_login_server_DrawEvent_1 (line 78) - draw_surface(sf_log, 16, 91);

    Die "sf_log" surface wirst du daher selber (mit demselben Code wie ich dir oben gezeigt habe) auf verfügbarkeit prüfen- und gegebenenfalls neu erstellen müssen.

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von LEWA ()

  • Holy s...
    ich habe doch tatsächlich bisher immer eine Existenzabfrage vor dem Zeichnen aller Surfaces drin gehabt,
    habe es gerade getestet, und es läuft bei meinem Projekt problemlos, wenn ich die Abfrage nur im Step-Event drin habe.
    Tja, so lernt man immer dazu und kommt auf unnötige Performancebremsen drauf ...
  • NOTE: When working with surfaces there is the possibility that they can cease to exist at any time due to them being stored in texture memory. You should ALWAYS check that a surface exists using surface_exists before referencing them directly. For further information see Surfaces.


    So stehts in der Hilfe, sobald du das Spiel verlässt werden Surfaces ausm Speicher geschmissen :) deshalb immer eine Abfrage und notfalls neu erstellen lassen.

    EDIT: Nur 30Min zu spät :thumbsup:
    @7rust-dev
  • Danke euch vielmals

    Also bei meinem Login-Programm war es einfach mit der einen Abfrage im Step Event gelöst (danke Irrenhaus und LEWA) da es ja nur ein Surface besitzt.

    GML-Quellcode

    1. /// Überprüfe ob Surfaces noch existieren
    2. if(surface_exists(sf_log) == false)
    3. { sf_log = surface_create(305, 374);
    4. surface_set_target(sf_log);
    5. draw_clear_alpha(0,0);
    6. surface_reset_target();
    7. }



    Aber bei meinem Client-Programm könnte es etwas aufwendiger werden... da ich Objekte habe die selbstständig Surfaces erstellen und wieder löschen... aber das ist jetzt einfach nur ewas arbeit mich da durchzuwühlen, da ich ja jetzt weis woran es liegt.


    @Lucke
    Ach du bist überhaupt nicht zu spät, bin für jede info dankbar :)
    Jo mit Englisch hab ichs einfach nicht so (sagen wir der Google-Übersetzer kann das noch besser als ich) ich meide die Hilfe weitmöglichst deshalb leider auch.


    EDIT: (19:10)

    Wenn ich mehrere Surfaces habe brauche ich ja im Step-Event nur überprüfen zu lassen ob eines fehlt, da ja wenn alle gelöscht werden oder?
    Und wenn das nicht da ist lasse ich einfach alle erneut erstellen.

    Was haltet ihr davon?


    EDIT: (19:19)

    Surfaces sind ja Objektgebunden so wie Variablen oder?

    Wenn ich das Objekt lösche zu welchem ein Surface gehört, wird dieses dann automatisch auch gelöscht? bzw. wieder freigegeben?

    Muss ich glatt mal testen falls niemand spontan eine Antwort darauf hat.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von Balls of Steel ()

  • Wenn ich mehrere Surfaces habe brauche ich ja im Step-Event nur überprüfen zu lassen ob eines fehlt, da ja wenn alle gelöscht werden oder?
    Und wenn das nicht da ist lasse ich einfach alle erneut erstellen.

    Was haltet ihr davon?

    Jein. Manchmal verschwinden alle auf einmal, manchmal aber auch nur spezifische surfaces. (wenn z.B: der V-Ram zu ende geht könnte eine Surface verloren gehen.)
    Prüf sicherheitshalber jede existierende Surface ab.


    Surfaces sind ja Objektgebunden so wie Variablen oder?
    Wenn ich das Objekt lösche zu welchem ein Surface gehört, wird dieses dann automatisch auch gelöscht? bzw. wieder freigegeben?
    Muss ich glatt mal testen falls niemand spontan eine Antwort darauf hat.

    Die surfaces verbleiben im Speicher. (werden nicht automatisch gelöscht.) Das "unerwünschte" löschen passiert nur in "Sonderfällen" wie eben das minimieren des Fensters.
    Um also potenzielle memory leaks zu verhindern, lösche die surfaces beim zerstören der Isntanz mit "surface_free()".
    Ausserdem, ja, die surface-variablen sind Instanzgebunden (so wie alle anderen Variablen im GM). Wenn du auf eine Surface also von einem anderen Objekt aus zugreifen möchtest, machst du das wie folgt:

    GML-Quellcode

    1. surface_set_target(yourinstance.surfacename);
    2. //draw
    3. surface_reset_target();
  • Hey Super! :D Genau die Info die ich auch gebraucht habe.
    In meinem Fall gings schon nicht wenn ich versucht habe die Fenstergröße zu ändern oder einfach nur vom Fenstermodus auf Vollbildmodus umzuschalten.

    ancient-pixel.com
    youtube.com/user/SebastianMerkl <<< ich freu mich über einen Besuch ;)