Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Andreas

Frischling

  • »Andreas« ist der Autor dieses Themas

Beiträge: 77

Beruf: Schüler

  • Private Nachricht senden

1

28.01.2008, 22:07

Genauigkeitsproblem durch Direct3D

Hallo,
ich häng jetzt schon seit einer Woche an einem Problem, dass große double Werte (im 500000-Bereich) nur sehr ungenau subtrahiert werden, während es in einem kleinen Test-Projekt viel genauer war.

Ich hab jetzt die Ursache gefunden:

In der Tribase wird das Direct3D-Device folgendermaßen erstellt:

C-/C++-Quelltext

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
// Präsentationsstruktur ausfüllen

    ZeroMemory(&PresentParams, sizeof(D3DPRESENT_PARAMETERS));
    PresentParams.BackBufferWidth               = pConfig->Direct3D.VideoMode.Width;
    PresentParams.BackBufferHeight              = pConfig->Direct3D.VideoMode.Height;
    PresentParams.BackBufferFormat              = pConfig->Direct3D.BackBufferFormat;
    PresentParams.BackBufferCount               = 1;
    PresentParams.MultiSampleType               = pConfig->Direct3D.MultiSamplingType;
    PresentParams.MultiSampleQuality            = pConfig->Direct3D.dwMultiSamplingQuality;
    PresentParams.SwapEffect                    = D3DSWAPEFFECT_DISCARD;
    PresentParams.hDeviceWindow                 = m_hWindow;
    PresentParams.Windowed                      = pConfig->Direct3D.bWindowed;
    PresentParams.EnableAutoDepthStencil        = TRUE;
    PresentParams.AutoDepthStencilFormat        = pConfig->Direct3D.ZStencilBufferFormat;
    PresentParams.Flags                         = pConfig->Direct3D.ZStencilBufferFormat != D3DFMT_D16_LOCKABLE ? D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL : 0;
    PresentParams.FullScreen_RefreshRateInHz    = pConfig->Direct3D.bWindowed ? D3DPRESENT_RATE_DEFAULT : pConfig->Direct3D.VideoMode.RefreshRate;
    PresentParams.PresentationInterval          = pConfig->Direct3D.bVSync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
        
    // Und nun die Geräteschnittstelle generieren

    if(FAILED(hResult = m_pD3D->CreateDevice(pConfig->Direct3D.iAdapter,
                                             pConfig->Direct3D.DeviceType,
                                             m_hWindow,
                                             pConfig->Direct3D.dwFlags | D3DCREATE_MULTITHREADED,
                                             &PresentParams,
                                             &m_pD3DDevice)))
    {
        // Fehler beim Generieren der Schnittstelle!

        TB_ERROR_DIRECTX("m_pD3D->CreateDevice", hResult, TB_ERROR);
    }


Ich hab jetzt schon stundenlang debugged bis ich diese Stelle als Fehlerursache gefunden hatte.
Ich hab jetzt vor und nach der Initialisierung eine kleine Rechnung eingebaut:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    double dummy12 = 500000.7328123456798187;
    dummy12 -=      0.11994317919015884;    // Und nun die Geräteschnittstelle generieren

    if(FAILED(hResult = m_pD3D->CreateDevice(pConfig->Direct3D.iAdapter,
                                             pConfig->Direct3D.DeviceType,
                                             m_hWindow,
                                             pConfig->Direct3D.dwFlags | D3DCREATE_MULTITHREADED,
                                             &PresentParams,
                                             &m_pD3DDevice)))
    {
        // Fehler beim Generieren der Schnittstelle!

        TB_ERROR_DIRECTX("m_pD3D->CreateDevice", hResult, TB_ERROR);
    }
    
    double dummy13 = 500000.7328123456798187;
    dummy13 -=      0.11994317919015884;


Beim debuggen kam dann folgendes raus (ich benutze VC 2005):

[list]vor der ersten Ausführung:

dummy12 -9.2559631349317831e+061 double
dummy13 -9.2559631349317831e+061 double

nach der 1. Subtraktion (bei dummy12):
dummy12 500000.61286916648 double
dummy13 -9.2559631349317831e+061 double

nach der 2. Subtraktion (bei dummy13):
dummy12 500000.61286916648 double
dummy13 500000.62500000000 double[/list]
Für mich bedeutet das, dass die Genauigkeit während der Initialisierungsmethode rapide herabgesetzt wird, was zwar normal verständlich ist, da diese Art der Rechnung bestimmt schneller geht, allerdings für mich das ganze ziemlich unbrauchbar macht.

Hat jemand mit sowas schon Erfahrung, weiß jemand wie man die Genauigkeit wieder herstellt, das wäre echt nett!!!!!

Viele Grüße
Andreas

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

28.01.2008, 22:53

hm. schau dir evtl. mal die funktionen _controlfp bzw. _control87 an...mag sein dass d3d was am status word der FPU ändert...

oh, noch was. ich hab jetzt nicht nachgerechnet, aber bist du dir sicher, dass das was du da machst im rahmen von double überhaupt möglich ist?

Helmut

5x Contest-Sieger

Beiträge: 692

Wohnort: Bielefeld

  • Private Nachricht senden

3

28.01.2008, 23:02

Es gibt ein Flag für die Funktion, um zu Verhindern, dass die Genauigkeit herabgesetzt wird.

ciao
Sei stets geduldig gegenüber Leuten, die nicht mit dir übereinstimmen. Sie haben ein Recht auf ihren Standpunkt - trotz ihrer lächerlichen Meinung. (F. Hollaender)

Andreas

Frischling

  • »Andreas« ist der Autor dieses Themas

Beiträge: 77

Beruf: Schüler

  • Private Nachricht senden

4

28.01.2008, 23:47

Hallo,
erstmal vielen Dank für die schnellen Antworten!!!

Zitat

oh, noch was. ich hab jetzt nicht nachgerechnet, aber bist du dir sicher, dass das was du da machst im rahmen von double überhaupt möglich ist?


Die Anfangszahl geht zwar etwas über die Genauigkeit hinaus, das sieht man ja auch an der Ausgabe, dass nicht alle Nachkommastellen übernommen werden, aber vom double erwarte ich schon, dass er mehr als die vierte Nachkommastelle schafft, welches ja auch vor der Initialisierung möglich war.

Auf jeden Fall vielen Dank für die Hilfe, ich hab D3DCREATE_FPU_PRESERVE bei der Erstellung mitangegeben und jetzt funktionierts!!!!

Vielen Dank, viele Grüße
Andreas

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

5

28.01.2008, 23:52

Zitat von »"Andreas"«

Die Anfangszahl geht zwar etwas über die Genauigkeit hinaus, das sieht man ja auch an der Ausgabe, dass nicht alle Nachkommastellen übernommen werden, aber vom double erwarte ich schon, dass er mehr als die vierte Nachkommastelle schafft, welches ja auch vor der Initialisierung möglich war.


hehe, sry ich war leicht verwirrt. ich dachte irgendwie du versuchtest 0.11994317919015884 von -9.2559631349317831e+061 abzuziehen...

anyway, double ist gleitkomma. sowas wie die "vierte nachkommastelle" gibts da nicht unbedingt immer ;)

Werbeanzeige