Implementation Suggestions for Managed DirectX Rendering menu

User Tag List

Results 1 to 8 of 8
  1. #1
    Harland's Avatar Member
    Reputation
    8
    Join Date
    Oct 2007
    Posts
    50
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Implementation Suggestions for Managed DirectX Rendering

    Yo Mmowned-ers,

    I've been looking into rewriting my C++ library that handles drawing pretty boxes and lines (Mind you it's looks like shit and needs some heavy reworking). I've made the change to write most of my bot framework in C#. I thought hey I can check out the managed DirectX courtesy of Micro$oft, only to realise how incomplete it is. Anyways I have been trying to weigh up my options:

    1. Should I dive into C++/CLI and export my C++ dll Drawing Functions to be made available in my C# App?

    2. Write my own lightweight wrapper for DirectX to do most of my rendering logic from C#, although i don't feel like wrestling with the Marshaller, especially if I'm just reinventing the wheel.

    3. Grit my teeth and use the SlimDX Wrapper (the framework looks a bit too heavy for my liking, it seems to wrap too many version of DirectX).

    If anyone else in the managed world has performed any DirectX rendering and perhaps have some suggestions, that'd be excellent. I haven't seen many people performing managed DirectX Rendering, which leads me to believe Option 1 will be the choice.

    Cheers for your input.

    Implementation Suggestions for Managed DirectX Rendering
  2. #2
    JuJuBoSc's Avatar Banned for scamming CoreCoins Purchaser
    Reputation
    1019
    Join Date
    May 2007
    Posts
    922
    Thanks G/R
    1/3
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I started using MDX 1.1, and moved to SlimDX since few day, it's really pretty easy and SlimDX work almost as MDX, so you can still follow doc for MDX with SlimDX.
    You can use Device.FromPointer() to use SlimDX Device class and do your writing by hooking the EndScene.

    I only tried drawing simple text and line, but it work pretty good

    http://s2.noelshack.com/old/up/d3d_wow-8c643c5928.jpg

  3. #3
    adaephon's Avatar Active Member
    Reputation
    76
    Join Date
    May 2009
    Posts
    167
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You can also use XNA. It's a bit more work to get the XNA device to use WoW's device (or the other way around) but definitely possible.

  4. #4
    Harland's Avatar Member
    Reputation
    8
    Join Date
    Oct 2007
    Posts
    50
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yuck I can't stand these managed versions of DirectX. I think i'm just going to keep my C++ Library and Export everything. Damn resistance to change!

    ---------- Post added at 07:58 AM ---------- Previous post was at 06:36 AM ----------

    I have now encountered a problem after importing a couple of the methods from my Rendering Library. .Net seems to keep a handle open to the newly imported method. This means when I want to unload the library containing the method it silently fails. By silent I mean Windows says the library was successfully ejected but process explorer shows otherwise.

    Is there such a method that disposes of any references created by the DllImport. Google keeps spitting out results for FreeLibrary, yet again asking Mr Google the wrong questions.

  5. #5
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1356
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You have two options:
    1. Don't use DllImport directly on your lib, use LoadLibrary and GetProcAddress. <-- Preferred solution.
    2. Remember that modules are ref counted. Just call FreeLibrary in a loop until the refcount hits zero. <-- Disgusting solution, but should still work.

    There's probably a better way of doing it, but in Hades I just used option 1 because my C# is awful and I needed to whip together something quickly for my interop. Maybe someone else has a better idea?

  6. #6
    Shenlok's Avatar Active Member
    Reputation
    15
    Join Date
    Jul 2008
    Posts
    42
    Thanks G/R
    6/2
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think you should give SlimDX a try, it's a pretty good wrapper with a decent userbase.

    Out of curiosity, how exactly do you get the XNA device to use WoW's device? Looking over the XNA API briefly I don't see any obvious way of doing it.

  7. #7
    adaephon's Avatar Active Member
    Reputation
    76
    Join Date
    May 2009
    Posts
    167
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Brief answer: ugly reflection unsafe code and some smart hooking and caching. I'll check my code and give a less brief answer tomorrow

    Edit: Longer answer:

    I do this from process start (start suspended).

    1. Inject and hook Direct3DCreate9
    2. When Direct3DCreate9 is called, my hook calls the original and stores the returned pointer
    3. Using the returned pointer, I hook IDirect3D9::CreateDevice
    4. When IDirect3D9::CreateDevice is called, I check whether this call is coming from XNA or WoW (first call will be WoW).
    4.a. If it's not XNA, I convert the pPresentationParameters structure to an XNA appropriate structure and cache the behavior flags (see below), set the IsXnaCreateDeviceCall flag to true and then call the standard XNA device constructor (new GraphicsDevice(GraphicsAdapter.DefaultAdapter, (DeviceType)deviceType, hFocusWindow, presentationParameters) ). Internally this calls IDirect3D9::CreateDevice again, so my hook is hit again.
    4.b. If it is an XNA call (this will be the second call), I call the original function (IDirect3D9::CreateDevice). The XNA constructor doesn't give you access to behavior flags and there is one (from memory) that WoW sets that XNA doesn't, that's why I preserved it previously and pass that in. Return the value that the original function returned.
    4.c. Back in the non-xna call, after calling the XNA GraphicsDevice constructor, we should now have a proper XNA GraphicsDevice. Using reflection you can get the internal pointer (look for "pComPtr" in GraphicsDevice in reflector). Using unsafe code you can get the value of pComPtr and store it in the ppReturnedDeviceInterface parameter.

    In a nutshell, that's it. Haven't really looked into injecting it after WoW has already started, but if you knew what the presentation parameters were you could probably do it - hook IDirect3D9::CreateDevice and return your WoW pointer when XNA calls it. You'd probably need to make sure your XNA constructor was called with appropriate parameters or something. Might look into it later.
    Last edited by adaephon; 07-23-2010 at 08:52 PM. Reason: Less brief answer

  8. #8
    Harland's Avatar Member
    Reputation
    8
    Join Date
    Oct 2007
    Posts
    50
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I appreciate that advice Cypher, yeah Option 1 does sound slightly cleaner, rather than the brute force approach. I'll keep hunting for some other solutions, and post back if I actually find anything of interest (though my late night googling did not yield anything promising).

    EDIT:
    Bah I'm really too lazy, Option 1 works like a charm I'll leave it as it is.

    EDIT:
    Oh for those that want the C/P sample Export/Import Code for inprocess C++/C# library calling:

    C++ DLL:
    Code:
    //Just a random function I made to accept a list of lines and render them
    //Sorry no code on rendering lines here, plenty of other forum topics cover this.
    extern "C" {
          __declspec(dllexport)void __cdecl DrawLines(IDirect3DDevice9* pDevice, LINEVECTOR lineList[], int lineCount);
    }
    C# Assembly:
    Code:
    static class DXDraw
    {
    //Delegate to handle the exported function signature.
    //LINEVECTOR is a custom struct that describes a line (start/end vertex and colour)
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    private delegate void DrawLinesDelegate(IntPtr pDevice, [MarshalAs(UnmanagedType.LPArray)] LINEVECTOR[] lineList, int lineCount);
    
    //Holds the marshaled function
    static DrawLinesDelegate DrawLines;
    
    //Constructor
    static DXDraw()
    {
          //Get Reference to our inprocess assembly location
          //I keep all my libraries/assemblies in the same folder for ease of updating
          string appDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
          string filename = Path.Combine(appDir, "BootstrapLib.dll");
    
          //Load our Library
          IntPtr dllPtr = NativeMethods.LoadLibrary(filename);
    
          if (dllPtr== IntPtr.Zero)
          {
                throw new NullReferenceException("LoadLibrary Failed");
          }
    
          //Obtain a pointer to our function
          IntPtr funcPtr= NativeMethods.GetProcAddress(dllPtr, "DrawLines");
    
          if (funcPtr== IntPtr.Zero)
          {
               throw new NullReferenceException("DrawLines Failed");
          }
    
          //Marshal the address of the function to the delegate above this constructor
          DrawLines= (DrawLinesDelegate)Marshal.GetDelegateForFunctionPointer(funcPtr, typeof(DrawLinesDelegate));
    
          //Drop reference count by 1....just a note BootstrapLib.dll is actually loaded previously to begin the .Net Runtime.
          NativeMethods.FreeLibrary(dllPtr);       
    }
    
    //Just a stub for testing in my pulse
    static void test(IntPtr pDevice)
    {
         ColorARGB green = new ColorARGB();
         green.Alpha = 100;
         green.Red = 0;
         green.Green = 255;
         green.Blue = 0;
    
         float startZ = 94.55733f;
    
         LINEVECTOR[] lineList = new LINEVECTOR[9];
    
         //Setup line list.
         for (int i = 0; i < 9; i++)
         {
               lineList[i].X = -140.43083f;
               lineList[i].Y = 1865.19995f;
               lineList[i].Z = startZ;
               lineList[i].X2 = -140.43083f;
               lineList[i].Y2 = 1865.19995f;
               lineList[i].Z2 = startZ+10;
               lineList[i].Color = green;
               startZ += 10;
          }
    
          //Yay vertical lines!
          DrawLines(pDevice, lineList, 9);
    }
    Last edited by Harland; 07-24-2010 at 02:55 AM.

Similar Threads

  1. Suggestions for a new server
    By Decapitate in forum World of Warcraft General
    Replies: 3
    Last Post: 04-13-2009, 12:43 PM
  2. Need suggestion for account.
    By gaithead in forum WoW Scam Prevention
    Replies: 6
    Last Post: 06-28-2008, 09:26 PM
  3. A suggestion for posting Emu-Servers
    By Arylion in forum Suggestions
    Replies: 1
    Last Post: 11-14-2007, 10:01 PM
  4. [Suggestion for me] I wanne have perm ban
    By Thallia in forum World of Warcraft General
    Replies: 8
    Last Post: 10-06-2007, 12:39 PM
All times are GMT -5. The time now is 09:44 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search