People with DirectX knowledge wanted! (1 Viewer)

Frodo

Retired Team Member
  • Premium Supporter
  • April 22, 2004
    1,518
    121
    52
    The Netherlands
    Home Country
    Netherlands Netherlands
    Hi,
    As you all know MP is a nice product, but it needs a performance boost
    Although i'm busy with it , i really could use help on this topic
    I did some profiling and it seems that most time is spend in DirectX calls
    MP is using 1 vertexbuffer & 1 texture per GUI element (like buttons, text, list controls, thumbnails,...)
    Render all these objects seperately is causin MP to be slow.
    So If you have directx knowledge I would like to talk to you on how to improve this!
    Things i'm thinking of:
    - batching directx calls
    - using 1 vertex buffer instead of 1 per object
    - porting time-critical stuff to c++
    - using meshes

    but maybe you can tell me what really needs to be done to get a better performance


    frodo
     

    koniosis

    Portal Member
    January 21, 2005
    7
    0
    Have you thought about using Sprites? The Sprite object in MDX is actually a batching object used to draw sprites with. I've written a bunch of boiler plate code around sprites for an Engine I'm working on if you're interested I can send you the relevant stuff.

    As for porting to C++, you probably won't gain much performance increase in the DX region of code, since MDX just calls the C++ equivilant APIs anyway.

    Using a DirectX Mesh is the same as using a vertex and index buffer, so you won't gain any performance that way.

    What are you doing at the moment, are you using textured quads to draw to the screen, is there any 3D in it?

    How are you loading textures? TextureLoader.FromFile(device, filename) will load the texture and then create a bunch of mipmaps from the texture size down to 1x1 by a power of 2. You need to use the overloaded version of TextureLoader.FromFile() and specify that you want 0 mipmap levels otherwise your textures will be taking up a lot more memory than you think.

    Also consider using a resource cache if you aren't already. The MDX SDK comes with an example resource cache in the demos; take a look at that if you haven't already.

    Setting Device.Texture = ... is one of the most expensive (cycles) operation you can do, so batching your textures will be a great benefit (assuming the same texture is used more than once).
     

    Frodo

    Retired Team Member
  • Premium Supporter
  • April 22, 2004
    1,518
    121
    52
    The Netherlands
    Home Country
    Netherlands Netherlands
    >Have you thought about using Sprites?
    Yes, i did some tests, but i didnt see any performance improvements. Maybe i did it wrong

    >As for porting to C++, you probably won't gain much performance
    >increase in the DX region of code, since MDX just calls the C++
    >equivilant APIs anyway.
    Well it saves interop, so i do think it will help

    >What are you doing at the moment, are you using textured quads to
    >draw to the screen, is there any 3D in it?
    No 3d. All objects are 2D. Basicly MP only renders textures to the screen using trianglelists

    >How are you loading textures?
    I use the overloaded function and specify 1 for the mipsmaps parameter

    >Also consider using a resource cache if you aren't already.
    MP caches resources. It will only create 1 direct3d texture and give pointers to any code interested

    >Setting Device.Texture = ... is one of the most expensive (cycles)
    Indeed, and also locking vertex buffers seems 2b expensive

    frodo
     

    koniosis

    Portal Member
    January 21, 2005
    7
    0
    Locking Vertex buffers is a real performance hit, it's probably faster to just create a new vertex buffer. How much locking are you doing? Essential you will loose any performance beneift of using the GPUs RAM when you are locking and unlocking buffers since it has to drag the data out of the GPU across the AGP bus, down the pipeline to the RAM so you can work on it and then send the whole lot back once you are finished.

    Why are you locking buffers?
     

    Frodo

    Retired Team Member
  • Premium Supporter
  • April 22, 2004
    1,518
    121
    52
    The Netherlands
    Home Country
    Netherlands Netherlands
    Reason i'm locking vertexbuffers is to update the
    x,y tu,tv parameters. these parameters contain where the texture is rendered on screen

    frodo
     

    koniosis

    Portal Member
    January 21, 2005
    7
    0
    ACK! No, you should be using Matrix Transformations to move stuff around not adjust the x, y values. This is also why sprites are useful as you can easily apply transformations to them at little cost.

    When I get home I'll post some boiler code for the MDX sprite class.
     

    Frodo

    Retired Team Member
  • Premium Supporter
  • April 22, 2004
    1,518
    121
    52
    The Netherlands
    Home Country
    Netherlands Netherlands
    sounds good!!
    I already made some improvements myself:
    i'm now using 1 vertex buffer per texture. If a texture is rendered multiple times on the screen (like buttons) i now just need 1 vertexbuffer lock, update & unlock

    frodo
     

    koniosis

    Portal Member
    January 21, 2005
    7
    0
    Ideally you want to create the vertex buffer for your button with the correct dimensions and then use that buffer for the remainder of the application run and never lock it again. Your vertex buffers are going to contain I'm assuming four points for each corner of the image. It'll be more efficient to just keep hold of the vertex buffer throughout the life of the program, even if you leave a screen which contains buttons, just keep the vertex buffer for when the user returns to the screen with buttons.

    This way you shouldn't ever have to lock the buffer. Without needing to lock the buffer you can create the vertex buffer with the WriteOnly property so that DirectX places the buffer in the correct memory location, usually AGP memory (though not always) where it can be accessed with maximum performance. e.g:

    VertexBuffer vb = new VertexBuffer(..., ..., ..., Usage.WriteOnly, ..., ...);
    vb.SetData(..., ..., LockFlags.None);

    Note that if you do create a vertex buffer like this you CANNOT lock it; which you shouldn't do anyway! You only need to lock vertex buffers when doing custom vertex data otherwise just use the SetData() function (which essential locks the buffer for you).
     

    Frodo

    Retired Team Member
  • Premium Supporter
  • April 22, 2004
    1,518
    121
    52
    The Netherlands
    Home Country
    Netherlands Netherlands
    Ok, here's what we do now:
    1. I create 1 big vertexbuffer per texture (lets say a button)
    2. I update the vertex buffer with all positions of all buttons onscreen
    3. I render the screen (no updates/locks here)
    4. goto 3

    Now when something changes, say position or color of a button changes then I update the position of the changed button in the vertex buffer ( 1 lock) This can happen for example when you scroll through a thumbnail list and then go back to step 3

    So at the moment i only do a few vertexbuffer locks when something changed (coordinates or color of a texture)
    For the rest i just do

    Foreach (Texture tex in onscreentextures)
    DX9Device.SetTexture(tex )
    DX9Device.SetStreamSource(tex )
    DX9Device.DrawPrimitive(...)
    Next


    Vertex buffer/textures are created with Usage.None & placed in Pool.Managed.
    Reason for this is that the resources stay valid when the user resizes the screen ( windowed<->fullscreen)
    I tried Usage.Dynamic & Pool.Default, but it didnt give me a better performance

    Frodo
     

    Users who are viewing this thread

    Top Bottom