Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: Please help me find a bug (DX9 Direct3D)

  1. #1

    Please help me find a bug (DX9 Direct3D)

    Hello,

    in my Game demo one of my Beta testers has a bug in a 3D sequence, the screens freezes, but in the background it continues.

    I cannot reproduze this error myself, everything fine here.

    I build in some error messages to find out where the errors come from.
    They are coming from my 3D Particles. I included them from the SDK sample.

    So here is the code how I render those particles (please not exceptionmsg is a function that writes the string into a textfile):

    Code:
    function CParticleSystem.Render(pd3dDevice: IDirect3DDevice9;nsize: single): HResult; 
    var 
      p_Particle: P3DParticle; 
      pVertices: PPointVertex; 
      dwNumParticlesToRender: DWord; 
      Flags: DWord; 
      vPos, vVel: TD3DXVector3; 
      fLengthSq: Single; 
      dwSteps: DWord; 
      clrDiffuse: TD3DXColor; 
      dwDiffuse: DWORD; 
      i: Integer; 
    begin 
      try 
      // Set the render states for using point sprites 
      pd3dDevice.SetRenderState(D3DRS_POINTSPRITEENABLE, iTRUE); 
      pd3dDevice.SetRenderState(D3DRS_POINTSCALEENABLE,  iTRUE); 
      pd3dDevice.SetRenderState(D3DRS_POINTSIZE,     FtoDW(nsize));   //GrA¬?AYe Partikel 
      pd3dDevice.SetRenderState(D3DRS_POINTSIZE_MIN, FtoDW(0.01)); 
      pd3dDevice.SetRenderState(D3DRS_POINTSCALE_A,  FtoDW(0.01)); 
      pd3dDevice.SetRenderState(D3DRS_POINTSCALE_B,  FtoDW(0.01)); 
      pd3dDevice.SetRenderState(D3DRS_POINTSCALE_C,  FtoDW(1.00)); 
      // Set up the vertex buffer to be rendered 
      pd3dDevice.SetStreamSource(0, m_pVB, SizeOf(TPointVertex),SizeOf(TPointVertex));    //dx9 letzter Param size in byte 
      pd3dDevice.SetFVF(D3DFVF_POINTVERTEX); 
      if m_pParticles=nil then exit; 
      p_Particle := m_pParticles; 
      if p_particle=nil then exit; 
      dwNumParticlesToRender := 0; 
      // Lock the vertex buffer.  We fill the vertex buffer in small 
      // chunks, using D3DLOCK_NOOVERWRITE.  When we are done filling 
      // each chunk, we call DrawPrim, and lock the next chunk.  When 
      // we run out of space in the vertex buffer, we start over at 
      // the beginning, using D3DLOCK_DISCARD. 
      Inc(m_dwBase, m_dwFlush); 
      if (m_dwBase >= m_dwDiscard) then m_dwBase:= 0; 
      if m_dwBase = 0 then Flags:= D3DLOCK_DISCARD else Flags:= D3DLOCK_NOOVERWRITE; 
      if m_pvb=nil then exit; 
      if failed(m_pVB.Lock(m_dwBase * SizeOf(TPointVertex), m_dwFlush * SizeOf(TPointVertex), 
       Pointer(pVertices), Flags)) then begin 
        commandoform.ExceptionMsg('ParticleLock'); 
        exit; 
      end; 
      // Render each particle 
      while Assigned(p_Particle) do 
      begin 
        vPos:= p_Particle.m_vPos; 
        vVel:= p_Particle.m_vVel; 
        fLengthSq := D3DXVec3LengthSq(vVel); 
        if &#40;fLengthSq < 1.0&#41;        then dwSteps &#58;= 2 
        else if &#40;fLengthSq <  4.00&#41; then dwSteps &#58;= 3 
        else if &#40;fLengthSq <  9.00&#41; then dwSteps &#58;= 4 
        else if &#40;fLengthSq < 12.25&#41; then dwSteps &#58;= 5 
        else if &#40;fLengthSq < 16.00&#41; then dwSteps &#58;= 6 
        else if &#40;fLengthSq < 20.25&#41; then dwSteps &#58;= 7 
        else                             dwSteps &#58;= 8; 
        D3DXVec3Scale&#40;vVel, vVel, -0.04 / dwSteps&#41;; 
        D3DXColorLerp&#40;clrDiffuse, p_Particle.m_clrFade, p_Particle.m_clrDiffuse, p_Particle.m_fFade&#41;; 
        dwDiffuse&#58;= D3DXColorToDWord&#40;clrDiffuse&#41;; 
        // Render each particle a bunch of times to get a blurring effect 
        for i&#58;= 0 to dwSteps - 1 do 
        begin 
          pVertices.v     &#58;= vPos; 
          pVertices.color &#58;= dwDiffuse; 
          Inc&#40;pVertices&#41;; 
          Inc&#40;dwNumParticlesToRender&#41;; 
          if &#40;dwNumParticlesToRender = m_dwFlush&#41; then 
          begin 
            // Done filling this chunk of the vertex buffer.  Lets unlock and 
            // draw this portion so we can begin filling the next chunk. 
            if failed&#40;m_pVB.Unlock&#41; then begin 
              commandoform.exceptionmsg&#40;'ParticleUnLock'&#41;; 
              exit; 
            end; 
            Result&#58;= pd3dDevice.DrawPrimitive&#40;D3DPT_POINTLIST, m_dwBase, dwNumParticlesToRender&#41;; 
            if FAILED&#40;Result&#41; then begin 
              commandoform.exceptionmsg&#40;'Rendererror DrawPrimitive'&#41;; 
              Exit; 
            end; 
            // Lock the next chunk of the vertex buffer.  If we are at the 
            // end of the vertex buffer, DISCARD the vertex buffer and start 
            // at the beginning.  Otherwise, specify NOOVERWRITE, so we can 
            // continue filling the VB while the previous chunk is drawing. 
            Inc&#40;m_dwBase, m_dwFlush&#41;; 
            if &#40;m_dwBase >= m_dwDiscard&#41; then m_dwBase&#58;= 0; 
            if m_dwBase = 0 then Flags&#58;= D3DLOCK_DISCARD else Flags&#58;= D3DLOCK_NOOVERWRITE; 
            if failed&#40;m_pVB.Lock&#40;m_dwBase * SizeOf&#40;TPointVertex&#41;, m_dwFlush * SizeOf&#40;TPointVertex&#41;, 
             Pointer&#40;pVertices&#41;, Flags&#41;&#41; then begin 
               commandoform.exceptionmsg&#40;'ParticleLock2'&#41;; 
               exit; 
            end; 
            dwNumParticlesToRender &#58;= 0; 
          end; 
          D3DXVec3Add&#40;vPos, vPos, vVel&#41;; 
        end; 
        if p_Particle.m_pNext=nil then exit; 
        p_Particle &#58;= p_Particle.m_pNext; 
      end; 
      // Unlock the vertex buffer 
      m_pVB.Unlock; 
      // Render any remaining particles 
      if &#40;dwNumParticlesToRender <> 0&#41; then 
      begin 
        Result&#58;= pd3dDevice.DrawPrimitive&#40;D3DPT_POINTLIST, m_dwBase, dwNumParticlesToRender&#41;; 
        if FAILED&#40;Result&#41; then Exit; 
      end; 
      // Reset render states 
      pd3dDevice.SetRenderState&#40;D3DRS_POINTSPRITEENABLE, iFALSE&#41;; 
      pd3dDevice.SetRenderState&#40;D3DRS_POINTSCALEENABLE,  iFALSE&#41;; 
      Result &#58;= S_OK; 
      except 
        commandoform.exceptionmsg&#40;'Rendererror Particles'&#41;; 
      end; 
    end;
    My betatester reports the error is Particlelock and then it freezes.

    Here is the code I use to render the particles:

    Code:
    //fA¼r partikel setzen 
        setrenderstate&#40;d3drs_alphablendenable,dword&#40;true&#41;&#41;; 
        setrenderstate&#40;d3drs_srcblend,d3dblend_srcalpha&#41;; 
        setrenderstate&#40;d3drs_destblend,d3dblend_destalpha&#41;; 
        setmaterial&#40;m_pParticleMaterial&#41;; 
        try 
        if m_pParticleTexture<>nil then SetTexture&#40;0, m_pParticleTexture &#41; 
        else exceptionmsg&#40;'3D Particle Nil'&#41;; 
        except 
          exceptionmsg&#40;'3D Particle Error'&#41;; 
        end; 
        setTextureStageState&#40;0, D3DTSS_COLORARG1, D3DTA_Texture&#41;; 
        setTextureStageState&#40;0, D3DTSS_COLOROP, D3DTOP_selectarg1&#41;; 
        setTextureStageState&#40;1, D3DTSS_COLOROP, D3DTOP_disable&#41;; 
        m_pParticleSystem.Render&#40;XenScreen.Device,0.3&#41;; 
        setrenderstate&#40;d3drs_alphablendenable,dword&#40;false&#41;&#41;; 
        setrenderstate&#40;d3drs_specularenable,dword&#40;false&#41;&#41;; 
        //fA¼r skybox setzen 
        setTextureStageState&#40;0, D3DTSS_COLOROP, d3dtop_modulate&#41;; 
        setTextureStageState&#40;1, D3DTSS_COLOROP, d3dtop_modulate&#41;; 
        setRenderState&#40;D3DRS_NORMALIZENORMALS, 0&#41;; 
        setTextureStageState&#40;1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU or 1&#41;; 
        setTextureStageState&#40;1, D3DTSS_COLOROP, D3DTOP_DISABLE&#41;;
    So do you have any idea, how to fix that bug?

    I have a htm file with the devicecaps of my testers graficx card here:

    http://www.ericbehme.de/download/DeviceCaps.htm

    Any idea how to fix that error or at least make the screen not freeze or what to do next?

    Thanks a lot,
    Firle

  2. #2

    Please help me find a bug (DX9 Direct3D)

    I don't see the problem right away, but is there any reason why are you using D3DLOCK_NOOVERWRITE and update vertex buffer slowly rather than using dynamic vertex buffer and fill it in a single shot?

  3. #3

    Please help me find a bug (DX9 Direct3D)

    Seems this:
    [pascal]pd3dDevice.SetStreamSource(0, m_pVB, SizeOf(TPointVertex),SizeOf(TPointVertex)); [/pascal]
    should be:
    [pascal]pd3dDevice.SetStreamSource(0, m_pVB, 0, SizeOf(TPointVertex)); [/pascal]

    So you rendering starts from 0 item, not 1st. Your code can generate AV (trying to read from other's process memory).

    Have you looked at mine conversion of PointSprites from DirectX9 SDK? Link to near download all Direct3D 9.0 samples (summer 2003) for Delphi item
    There are only 10 types of people in this world; those who understand binary and those who don't.

  4. #4

    Please help me find a bug (DX9 Direct3D)

    Hi Lifepower,

    thanks a lot for replying. Could you perhaps give me a piece of code, like replace this with that sutff here....

    I have that particles form an older sample, if you can tell me how to improve that this would be great, and perhaps it also fixes my hard-to-find bug?

    Thanks,
    Firle

  5. #5

    Please help me find a bug (DX9 Direct3D)

    Hi Clootie,

    thanks a lot! I'll try that and take a look at your link, thank you
    Seems we posted the same time.

    Firle

  6. #6

    Please help me find a bug (DX9 Direct3D)

    Hi Clootie,

    yes I guess it was an older version of that Pointsprite sample I used first, right! And I now see the error, you're absolutley right!

    Maybe this is the bug, I'll change that and let my beta tester test it, thanks!

    Firle

  7. #7

    Please help me find a bug (DX9 Direct3D)

    Quote Originally Posted by Firlefanz
    Hi Lifepower,

    thanks a lot for replying. Could you perhaps give me a piece of code, like replace this with that sutff here....

    I have that particles form an older sample, if you can tell me how to improve that this would be great, and perhaps it also fixes my hard-to-find bug?

    Thanks,
    Firle
    Here's a *very quick* example:
    [pascal]
    type
    TVertexCacheClass = class
    private
    Buffer: Pointer;
    Index : Integer;

    public
    procedure AddVertex(const p: TPointVertex);
    procedure FlushCache();

    constructor Create();
    destructor Destroy(); override;
    end;


    const
    CacheSize = 200;

    constructor TVertexCacheClass.Create();
    begin
    inherited;

    Buffer:= AllocMem(CacheSize * SizeOf(TPointVertex));
    end;

    destructor TVertexCacheClass.Destroy();
    begin
    FreeMem(Buffer);
    inherited;
    end;

    procedure TVertexCacheClass.AddVertex(const p: TPointVertex);
    begin
    if (Index >= CacheSize) then FlushCache();
    PPointVertex(Integer(Buffer) + (Index * SizeOf(TPointVertex)))^:= p;
    Inc(Index);
    end;

    procedure TVertexCacheClass.FlushCache();
    begin
    if (Index > 0) then
    begin
    pd3dDevice.DrawPrimitiveUP(D3DPT_POINTLIST, Index, Buffer, SizeOf(TPointVertex));
    Index:= 0;
    end;
    end;
    [/pascal]
    It doesn't explicitly use dynamic Vertex Buffers (Direct3D uses its internal dynamic vertex buffers for DrawPrimitiveUP), but it renders all your point sprites in one call (or few calls). Of course, you have to put all render states and everything to make it work. Creating and using your own vertex buffers might be *slightly* faster than using DrawPrimitiveUP, but it's rather under debate and depends on how many points you are actually drawing.

  8. #8

    Please help me find a bug (DX9 Direct3D)

    I wouldn't recommend using DPUP.
    Because:
    1) It's not recommended by NVIDIA and ATI (less tested, more prone to bugs, etc.).
    2) There is too much work going on behind your code and before HW: if your data is small Direct3D runtime tries to embed it into command stream (data send to video-driver); if it's large D3D tries to draw your data with pre-created (by D3D runtime at startup) VB, but if your data size is not equal to size of D3D internal buffer -> more draw call's will reach video driver.

    So, if you draw particle system of measurable size - DON'T use DPUP!
    There are only 10 types of people in this world; those who understand binary and those who don't.

  9. #9

    Please help me find a bug (DX9 Direct3D)

    Hi!

    @Lifepower: Thanks a lot for your sample! But if Clootie says this may cause other Bugs, I think I leave it the way it is now, I only have <100 Particles in count. And because...

    ...it works now!

    @Clootie: Thanks a lot, this little bug caused my problems!

    Thank you both very much for helping me out, good job!

    Firle

  10. #10

    Please help me find a bug (DX9 Direct3D)

    Actually, I agree with Clootie. Although DrawPrimitiveUP might be useful for some GUI stuff, using dynamic VBs is a proven way

Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •