Jump to content

  • Log In with Google      Sign In   
  • Create Account


C++ DX API, help me get it?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
14 replies to this topic

#1 ranakor   Members   -  Reputation: 439

Like
1Likes
Like

Posted 08 July 2013 - 08:23 PM

Ok so i'm coming from a .net background (multiple years of professional development).

I'm checking out microsoft DX11 samples and i just don't get it, am i missing something obvious & there's actually beauty there i'm not seeing? Or is this actually just flat ugly hard code for no reason? Is it legacy or are you actually supposed to write & consume APIs this way?

(just to be clear, this is half rant, half question, i'd be more than happy to learn my rant is unfounded & have this transition from a rant to an answered question, also i'm not saying i'm having a hard time, just to be clear i understand the sample perfectly fine, i just find it painstakingly hard for no reason).

 

Shed some light on all this for me

1) Why the hell is this so damn long & hard? I expected getting a DX11 window up & running (and rendering) with nothing inside to be a 10liner or so, maybe 20 tops, but not 250 like in the sample!

2) Why the typedefs? Seems to be adding confusion for no reason especially on simple types, am i missing something or is this just useless? typedef float               FLOAT

3) Why no constructors? Objects are just declared and initialized element by element, meaning you remove 1 line you don't get a default, you don't even get an exception, you get a nice access violation!

4) Why all the if(failed(bla)) ? Why isn't code throwing?

5) Probably the same as 3 but, why no sensible default values for everything? Declaring any directX object seems to be a full time job & a 10 liner!

6) Why is everything taking a pointer? I get the point for large (or medium) objects but why for example does something like the feature level, which isn't a large object nor an array, and that you're likely to be using once (or hell, maybe twice!) in your whole application get passed by pointer? I'm new at C++ but unless i get it wrong it means you must create a (local or global) variable, assign a value to it, and pass a pointer to it, if it was by reference you could just pass in D3D_FEATURE_LEVEL_11_0 for example

7) Typedef question again, it's confusing enough for float => FLOAT, but hell LPVOID*, i can't believe people starting with C++ make it through this!

8) __uuidof, so you even need custom keywords to get a simple directX sample app going on???

 

I'm not trying to bash C++ here, the only things i can't bare in it are header files and compilation speed, but i just don't get that API design, is it flaws in the API or in the sample? Or am i just getting it wrong? Because if this is the right way to do it this sounds just horrible to me, 250 lines to do nothing, 3X that much for a rotating cube (out of which only 60 lines are rendering, and about 300 setting up the device . . . ). I just don't get it! Hell SharpDX didn't feel that way at all.

 

I'm waiting, please enlighten me!



Sponsor:

#2 jrh2365   Members   -  Reputation: 602

Like
2Likes
Like

Posted 08 July 2013 - 09:01 PM

Allow me to pick off part of #6:

 

D3D11CreateDeviceAndSwapChain has two parameters that accept pointers to D3D_FEATURE_LEVEL. The first one is a pointer because it is actually looking for an array of D3D_FEATURE_LEVEL (and the parameter following that one is the number of elements in the array). The second one is a pointer because it is an output parameter to where the feature level that was actually selected can be stored.

 

http://msdn.microsoft.com/en-us/library/windows/desktop/ff476083(v=vs.85).aspx

 

[EDIT]

Also, I expect that a lot of the reasons for the API being structured how it is are due to http://en.wikipedia.org/wiki/Component_Object_Model


Edited by jrh2365, 08 July 2013 - 09:05 PM.


#3 NumberXaero   Prime Members   -  Reputation: 1371

Like
0Likes
Like

Posted 08 July 2013 - 09:55 PM

1) Short version, modern languages and frameworks tend to do a lot of the work for you. This is the raw api.

2) typedef float FLOAT, might become typedef double FLOAT in the future, dont need to change as much later you can redefine FLOAT.

3) Windows has a long history with C, it tends to be the main focus when extending the windows apis, C has no constructors

4) see 3

5) see 3

6) see 3

7) see 3

8) see 3



#4 MJP   Moderators   -  Reputation: 10659

Like
6Likes
Like

Posted 08 July 2013 - 11:17 PM

1) A lot of the setup in the simple tutorials is just getting a window going. That's just the way it is in Win32: it's a crusty old C API that takes a lot of boilerplate just for basic functionality. There's no reason not to use a framework to handle this for you, whether it's an existing one like SDL or one of your own design.

 

2) It's inherited from the Windows API. Almost all API's do something like this, since C/C++ only makes loose guarantees about the size of types. Using typedefs can ensure that the API is always working with the same size type. This isn't really much of an issue for x86 Windows platforms, so you can usually ignore them and using native types or the types from stdint.h

 

3) D3D uses a light-weight form of COM. Supporting COM requires C compatibility, which means you're mostly limited to functionality exposed in C (before C99). This is why  you have things like pointers instead of references for function parameters, and structs with no methods. However there are actually "C++" versions of some of the structures that have constructors defined. They're named the same with a "C" in front of them, for instance CD3D11_TEXTURE2D_DESC. It's also possible to make your own extension structures if you want.

4) Mostly because the older samples are written in more of a "C with classes" style as opposed to modern C++. The newer samples written for the Windows 8 SDK actually make heavy use of exceptions, smart pointers, and C++11 features. In my home codebase I just made a wrapper macro for D3D calls that checks the HRESULT for failure, and if it fails converts it to a string error message and stuffs it in an exception.

5) This is indeed the same reasoning as #3. It can definitely be pretty ugly at times.

6) Also the same as #3

7) Yeah that stuff is rooted in the Win32 API, and it's seriously ugly. I never use the typedefs in my own code.

8) This comes from D3D being a COM API. DXGI actually happens to be even heavier on the COM compared to D3D, hence it taking the interface GUID as a function parameter. However I'm pretty sure you don't have to use __uuidof if you don't want, it's just a convenience.

The reason SharpDX doesn't "feel" the same is because they wrap all of this in types and functions that convert the COM/Win32 idioms into patterns that are typical to C#. You can certainly do the same except with modern C++ concepts, if that's how you'd like to do it.


Edited by MJP, 09 July 2013 - 01:01 AM.


#5 AvengerDr   Members   -  Reputation: 685

Like
0Likes
Like

Posted 09 July 2013 - 02:04 AM

That's why I keep my distance from C++! Even in C# you need to write a lot of code just to set up a device. It is certainly nicer to look at, less * and & :D But once you begin writing your engine you can abstract away all that. In my own engine everything boils down to a call to DeviceManager.Initialize where I pass my own settings structure... and that's that.


--Avengers UTD Chronicles - My game development blog

#6 Jason Z   Crossbones+   -  Reputation: 4875

Like
3Likes
Like

Posted 09 July 2013 - 04:58 AM

As the others have already mentioned, you are comparing two different things.  C++ has direct access to the D3D API, and hence has to do the heavy lifting to get anything going.  But SharpDX is actually just a library that sits between you and the API to make things easier.  Most people don't start from scratch in C++ either - for example, in the Hieroglyph 3 application framework, you just inherit from a class and your window setup, device setup, and all the other goodies are done without any additional code.



#7 SiCrane   Moderators   -  Reputation: 9500

Like
2Likes
Like

Posted 09 July 2013 - 05:16 AM

One thing not a lot of people realize is that most of the Windows API samples are written so that non-C and C++ programmers will understand them. For instance, when initializing structs the API samples will use ZeroMemory() despite the fact that = {} will do the same thing. However, non-C or C++ programmers won't necessarily understand that, so the explicit ZeroMemory() call is used instead.



#8 ranakor   Members   -  Reputation: 439

Like
0Likes
Like

Posted 09 July 2013 - 06:02 AM

Ok so as i expected most of it is to be blamed on legacy or COM, actually makes me quite happy to hear that.

 

Is there any library on the C++ side that does the same as SharpDX for .net? (keep the same low level API access, but wrap it in namespaced classes with default constructors etc, something that would feel more "modern C++ish" without being an engine but that would be a good base for starting one without doing my own wrappers on everything?)



#9 imoogiBG   Members   -  Reputation: 1087

Like
0Likes
Like

Posted 09 July 2013 - 07:27 AM

4) Why all the if(failed(bla)) ? Why isn't code throwing? 

 

 NEVER use exceptions in C++! I love HRESULT error codes
 

6) Why is everything taking a pointer? I get the point for large (or medium) objects but why for example does something like the feature level, which isn't a large object nor an array, and that you're likely to be using once (or hell, maybe twice!) in your whole application get passed by pointer? I'm new at C++ but unless i get it wrong it means you must create a (local or global) variable, assign a value to it, and pass a pointer to it, if it was by reference you could just pass in D3D_FEATURE_LEVEL_11_0 for example

 

 Use CComPtr(atlbase.h) if you dont like pointers...

 

LPVOID

 

well.... i really dont care about PVOID LPVOID FLOAT ect...


D3D is designed for performance and user-control.. If you dont like that then you can use something like irrlicht/ogre/panda/whatever



#10 ranakor   Members   -  Reputation: 439

Like
0Likes
Like

Posted 09 July 2013 - 08:23 AM

 

4) Why all the if(failed(bla)) ? Why isn't code throwing? 

 

 NEVER use exceptions in C++! I love HRESULT error codes
 

6) Why is everything taking a pointer? I get the point for large (or medium) objects but why for example does something like the feature level, which isn't a large object nor an array, and that you're likely to be using once (or hell, maybe twice!) in your whole application get passed by pointer? I'm new at C++ but unless i get it wrong it means you must create a (local or global) variable, assign a value to it, and pass a pointer to it, if it was by reference you could just pass in D3D_FEATURE_LEVEL_11_0 for example

 

 Use CComPtr(atlbase.h) if you dont like pointers...

 

LPVOID

 

well.... i really dont care about PVOID LPVOID FLOAT ect...


D3D is designed for performance and user-control.. If you dont like that then you can use something like irrlicht/ogre/panda/whatever

 

None of this relates to performance at all, unless you consider "setting up directx" a performance critical part of any application where it's important to saveup nanoseconds in object instantiation and saving 4 bytes copies here & there? Performance is no reason here (i could get it if it was in per frame actions, but just not here), nor does it relate to user control at all. Anyway i already had my answers earlier on this thread, it's just com limitations & legacy code.

 

So now just looking for a thin wrapper around it, NOT an engine, something like a directX for actual C++ and not com/C.

Anyone could recommand such a thing? Something very thin where i could still refer to DX documentation, but just use it in a more "modern C++" way, C++11 is fine (within visual studio 2013's limitations)



#11 Matt-D   Crossbones+   -  Reputation: 1431

Like
4Likes
Like

Posted 09 July 2013 - 09:20 AM


So now just looking for a thin wrapper around it, NOT an engine, something like a directX for actual C++ and not com/C.

Anyone could recommand such a thing? Something very thin where i could still refer to DX documentation, but just use it in a more "modern C++" way, C++11 is fine (within visual studio 2013's limitations)

 

 

Take a look at "A Modern C++ Library for DirectX Programming" by Kenny Kerr:

http://msdn.microsoft.com/en-us/magazine/dn201741.aspx

http://dx.codeplex.com/

 

Seems to be exactly what you're describing:

I didn’t want to produce yet another heavy wrapper around DirectX. Instead, I decided to leverage C++11 to produce a simpler API for DirectX without imposing any space and time overheard to the core DirectX API.

 

If you'd like to have something on a yet higher level, check out SFML (Simple and Fast Multimedia Library):

http://www.sfml-dev.org/


Edited by Matt-D, 09 July 2013 - 09:26 AM.


#12 ATEFred   Members   -  Reputation: 1037

Like
2Likes
Like

Posted 09 July 2013 - 09:21 AM


None of this relates to performance at all

 

Exceptions have a noticeable performance impact, which is one of the reasons many game projects at least do not use them. From that perspective it makes sense from an API point of view to not rely on them (in addition to C legacy)

 

I don't know of any wrappers like that you are describing, but you could take just the API abstraction layer of any openly available engine and start with that instead of interfacing directly with d3d if you really wanted to. It would be better to use it natively if you want to learn how it works though I think.
 



#13 imoogiBG   Members   -  Reputation: 1087

Like
0Likes
Like

Posted 09 July 2013 - 10:01 AM

Jason Z's (http://hieroglyph3.codeplex.com/) has really good wrappers!



#14 uglybdavis   Members   -  Reputation: 901

Like
0Likes
Like

Posted 09 July 2013 - 05:23 PM


None of this relates to performance at all, unless you consider "setting up directx" a performance critical part of any application where it's important to saveup nanoseconds in object instantiation and saving 4 bytes copies here & there? Performance is no reason here (i could get it if it was in per frame actions, but just not here), nor does it relate to user control at all. Anyway i already had my answers earlier on this thread, it's just com limitations & legacy code.

 

Setting up DirectX can be a "performance critical" part. Just depends whom you work for. 

Some places have STRICT requirements on startup times.

Last company i worked at our game window had to be up and displaying something in under three seconds or all hell broke loose.



#15 Jason Z   Crossbones+   -  Reputation: 4875

Like
0Likes
Like

Posted 09 July 2013 - 05:32 PM

Jason Z's (http://hieroglyph3.codeplex.com/) has really good wrappers!

 

Like he said, Hieroglyph 3 is a layered framework that can be used at a high level or at a lower level.  At the very least, you can take a look at it and see if it does what you want.  There are lots of sample applications, ranging from very simple (just clearing the window to a different color) all the way up to volume rendering, Kinect integration, and deferred/light pre-pass rendering.

 

If you want something very light, you can grab pieces of the framework and use them as you see fit - it is licensed under MIT, so it is quite liberal for you to use.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS