Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


Juliean

Member Since 29 Jun 2010
Offline Last Active Today, 06:03 PM

#5237596 Why no Constant Buffer offsets like for Vertex Buffers?

Posted by Juliean on 29 June 2015 - 07:14 PM


Did you originally come from a OpenGL background Juliean? I think the hardware abstraction layer optimizes the draw calls. You may have a bottleneck in ur render loop. Dont do any updates in the render but on a separate thread.

 

No, I started out with DirectX, and only recently adopted an OpenGL4 renderer. I gotta say I can't make much sense of what you are implying with your post right now, so if you could elaborate on that in more detail I'd be very grateful. What I was implying with in my post is that

 

a) in order to achieve what the OP wants on Draw-Call level, each draw call has to have eigther 1) 5 additional parameters merely for cbuffer offsets for each shader stage or 2) a double array for each shader stage and all bound buffers. This is not so much even a problem on performance end, but more for the API bloat it imposes.

 

It is a strict fact that you get more performance if you map one 128 MB Cbuffer and copy data to it in one pass than you would if you mapped an amount of say 1024 buffers of the same size seperately though. Thats why what I was saying is that i definately makes sense in what DirectX11.1 proposes, but having offsets being passes in into the drawcall doesn't gain much, and can make matters worse on an architectural level.




#5237535 Why no Constant Buffer offsets like for Vertex Buffers?

Posted by Juliean on 29 June 2015 - 12:22 PM

It was simply not available at this point in time. With DirectX11.1, you have access to this kind of functionality, via ID3D11DeviceContext1::VSSetConstantBuffers1 and equivalents. pFirstConstant does just what you described. I can't recall the requirements for DirectX11.1, but I suppose you need a pretty new GPU and Windows 8. So if you are still at DirectX10, it seems you are out of luck.

 

EDIT: Pardon, I linked the wrong MSDN page, should be fixed now




#5237338 Memory management patterns in C++

Posted by Juliean on 28 June 2015 - 04:15 PM

Well, I do agree to a certain point that memory management via gargabe collection and/or reference counting should not be part of the inner workings of an engine.

 

As soon as you step into high-level territory with scripts and front-end game logic, having eigther of those can be highly beneficial for productivity. There is no real need for performance on this end anyways. As soon as you start using scripting, you want

 

- fast startup/development cycles without having to recompile (the whole application)

- quick prototyping using simplified and special structures (ranging from typeless languages, to python-style closures, etc...)

- a sandbox environment where no matter what you do, there will never be a fatal type of crash (if any crash at all)

 

Performance is your least worry in such an environment. If there ever turns out to be a performance oriented problem with logic that is implemented in a script, you move it over to C++. Having to perform manual memory management in a script however is a huge waste of time and hurts you in all the above points (minus the first, ofc). There is no "lots of bugs" inherent to reference counting. I know of one where objects A and B each reference each other, and thus won't get deleted. This is solved by garbage collection. To put it mildly, there is certainly no more bugs than you can (and will) run into when using manual memory management.

 

In the low-level engine department, advanced/good memory management usually involves custom memory allocators, where you grab a huge chunk of memory from your system at startup, and then deploy this memory instead of regular new/delete using different structures of memory managers. You pretty much need to do this when developing for consoles, but its a good choice on PC nevertheless.

 

Depending of your goals, the scope of your project and the fact you are still learning (getting this right is not an easy task since it forces you to make a huge number of difficult design decisions), it might be enough to employ std::unique_ptr wherever feasable (there is no downside to doing this in terms of performance, but lots of upsides in usability). You just pass around such an object by raw pointer, in case you can assure that whoever uses such an object won't outlife the owner of it. If you really need shared ownership, use a std::shared_ptr, preferbly pass std::weak_ptr to using objects. Do so sparecly - while the performance overhead is not THAT high, you won't want to reference-count thousands of pointers in like an inner loop of your renderer.

 

I'd strongly advice against developing an own solution, chances are very high it won't be nearly as usable as you want it to be. Also, since you mentioned you want to outperform std::shared_ptr, without very careful considerations regarding memory layouts I can't imagine your solution to be any better. I did the same thing a while ago. I thought I was clever and made a custom shared_ptr that I thought was going to be better, but in the end I just ended up with 2 additional dereferencations to random memory locations and yeah, thats not good for performance at all. If you want to improve shared_ptr performance, pass it by (const) reference until the point you really need to store it to extend its lifetime. Better yet, pass it by raw pointer for functions that are guaranteed to be finished as long as the object lives, and don't need to store it.




#5237127 register keyword in HLSL?

Posted by Juliean on 27 June 2015 - 12:02 PM


What is cb0 or c0 or something like that? What does c/cb mean?

 

You can read on their exact definition on the MSDN, which should be your go-to-instantly for any such questions about shaders:

 

https://msdn.microsoft.com/en-us/library/windows/desktop/dd607359%28v=vs.85%29.aspx

 

In short, the letter marks the type of register/resource you are specifying, and the number the slot. so c0 is first constant-buffer, t3 is fourth texture, s7 is eight sampler unit... For usage, consider my first reply.




#5237126 If-else coding style

Posted by Juliean on 27 June 2015 - 11:59 AM

Are you sure the "very misleading" part is strictly talking about how you ordered your if/else's? I'm assuming it said that by the way you are talking about it, but without the exact wording, it sounds a little weird to me. I really don't see whats "misleading" about that at all, granted that this is the whole code (and there were not ie. 20 ifs followed by an else).

I could imagine it was rather talking about that its not really clear what you get when calling the function based on the condition, but yeah... if they did really see an immantent problem with the if/else-part, I'd sure love for someone else to show me what it could be.




#5237066 register keyword in HLSL?

Posted by Juliean on 27 June 2015 - 04:48 AM


Also, what do these numbers mean in register keyword? like register(b0), register(cb0), etc. I used to use effects11 before and at that time, I didn't had to bother with these things.

 

Every shader-resource in DirectX11 is bound to a certain slot, with calls like PSSetShaderResource, etc... . Ususally in the shader, resources are assigned to slots in the order they are declared, like first cbuffer would be 0, second would be 1. With register() you can make sure that a certain resource always has a fixed slot. This can be mandatory if e.g. your application defines a global camera c-buffer which is always bound to slot 3. If a shader uses only this cbuffer, without register it would be assumed at slot 0.




#5236996 GenerateMipmaps and staging textures

Posted by Juliean on 26 June 2015 - 03:47 PM


I'm stuck with these textures in a non-dds texture format. Is there no way to generate mipmaps with directx 11 and then read them back to the CPU?

 

You can always copy _any_ texture to a STAGING marked texture using ID3D11Device::CopyResource. So you can just GenerateMipmaps on a regular texture that is able to be bound, then you create a seperate staging texture, copy the originals content to that and read its buffer back to the CPU.




#5236542 Using OpenGL/DirectX to build GUI

Posted by Juliean on 24 June 2015 - 05:40 AM


It's a huge waste of time because modern platform native windowing toolkits already use accelerated graphics libraries like Direct3D (Windows) and OpenGL (Mac, now moving to Metal). You won't even see a performance benefit for all your work.

 

Its even way worse than that. By manually rendering the UI, you will tie your editors performance to the game "views" performance. So if your game runs very slowly at some point (debug mode, debug information like terrain-wireframe/collision boxes/etc..., unoptimized 4k-texture bloat by artists), your editor will also run as slow and become extremely unresponsive. I have the same issue, and as far as all the information I've been able to gather, the only way to solve this via heavy multithreading ground up, so that your editor and game basically run in their own thread. I don't have to mention that this is a huge overkill in terms of how you will have to design your entire application.

 

I really forget to mention this point, so thanks for Oluseyi for bringing it up.




#5236141 WTH boost error is this.?

Posted by Juliean on 22 June 2015 - 06:02 AM

Shouldn't the compiler been telling you the source line from which the error originated, in this case your CurrentDownLoads.erase(ir); line? For as weird and cryptic template errors are, MSVC usually points you to the right line... unless you are using this obnoxious error-list-view instead of regular output, that is.

 

This is what I mean:

    std::unordered_map<std::wstring, float*> mTest;
    mTest.emplace(1.0f);
//produces this output:

1>t:\programme (x86)\microsoft visual studio 12.0\vc\include\xmemory0(600): error C2664: 'std::pair<const _Kty,_Ty>::pair(const std::pair<const _Kty,_Ty> &)' : Konvertierung von Argument 1 von 'float' in 'const std::pair<const _Kty,_Ty> &' nicht möglich
1>          with
1>          [
1>              _Kty=std::wstring
1>  ,            _Ty=float *
1>          ]
1>          Ursache: Konvertierung von 'float' in 'const std::pair<const _Kty,_Ty>' nicht möglich
1>          with
1>          [
1>              _Kty=std::wstring
1>  ,            _Ty=float *
1>          ]
1>          Quelltyp konnte von keinem Konstruktor angenommen werden, oder die Überladungsauflösung des Konstruktors ist mehrdeutig
1>          t:\programme (x86)\microsoft visual studio 12.0\vc\include\xmemory0(723): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void std::allocator<_Other>::construct<_Objty,_Ty>(_Objty *,_Ty &&)".
1>          with
1>          [
1>              _Other=std::_List_node<std::pair<const std::wstring,float *>,void *>
1>  ,            _Objty=std::pair<const std::wstring,float *>
1>  ,            _Ty=float
1>          ]
1>          t:\programme (x86)\microsoft visual studio 12.0\vc\include\xmemory0(723): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void std::allocator<_Other>::construct<_Objty,_Ty>(_Objty *,_Ty &&)".
1>          with
1>          [
1>              _Other=std::_List_node<std::pair<const std::wstring,float *>,void *>
1>  ,            _Objty=std::pair<const std::wstring,float *>
1>  ,            _Ty=float
1>          ]
1>          t:\programme (x86)\microsoft visual studio 12.0\vc\include\xmemory0(872): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void std::allocator_traits<_Alloc>::construct<_Ty,float>(std::allocator<_Other> &,_Objty *,float &&)".
1>          with
1>          [
1>              _Alloc=std::allocator<std::_List_node<std::pair<const std::wstring,float *>,void *>>
1>  ,            _Ty=std::pair<const std::wstring,float *>
1>  ,            _Other=std::_List_node<std::pair<const std::wstring,float *>,void *>
1>  ,            _Objty=std::pair<const std::wstring,float *>
1>          ]
1>          t:\programme (x86)\microsoft visual studio 12.0\vc\include\xmemory0(872): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void std::allocator_traits<_Alloc>::construct<_Ty,float>(std::allocator<_Other> &,_Objty *,float &&)".
1>          with
1>          [
1>              _Alloc=std::allocator<std::_List_node<std::pair<const std::wstring,float *>,void *>>
1>  ,            _Ty=std::pair<const std::wstring,float *>
1>  ,            _Other=std::_List_node<std::pair<const std::wstring,float *>,void *>
1>  ,            _Objty=std::pair<const std::wstring,float *>
1>          ]
1>          t:\programme (x86)\microsoft visual studio 12.0\vc\include\list(835): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void std::_Wrap_alloc<std::allocator<_Other>>::construct<_Ty,float>(_Ty *,float &&)".
1>          with
1>          [
1>              _Other=std::_List_node<std::pair<const std::wstring,float *>,void *>
1>  ,            _Ty=std::pair<const std::wstring,float *>
1>          ]
1>          t:\programme (x86)\microsoft visual studio 12.0\vc\include\list(835): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void std::_Wrap_alloc<std::allocator<_Other>>::construct<_Ty,float>(_Ty *,float &&)".
1>          with
1>          [
1>              _Other=std::_List_node<std::pair<const std::wstring,float *>,void *>
1>  ,            _Ty=std::pair<const std::wstring,float *>
1>          ]
1>          t:\programme (x86)\microsoft visual studio 12.0\vc\include\list(1062): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "std::_List_node<std::pair<const _Kty,_Ty>,void *> *std::_List_buy<std::pair<const _Kty,_Ty>,_Alloc>::_Buynode<float>(std::_List_node<std::pair<const _Kty,_Ty>,void *> *,std::_List_node<std::pair<const _Kty,_Ty>,void *> *,float &&)".
1>          with
1>          [
1>              _Kty=std::wstring
1>  ,            _Ty=float *
1>  ,            _Alloc=std::allocator<std::pair<const std::wstring,float *>>
1>          ]
1>          t:\programme (x86)\microsoft visual studio 12.0\vc\include\list(1062): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "std::_List_node<std::pair<const _Kty,_Ty>,void *> *std::_List_buy<std::pair<const _Kty,_Ty>,_Alloc>::_Buynode<float>(std::_List_node<std::pair<const _Kty,_Ty>,void *> *,std::_List_node<std::pair<const _Kty,_Ty>,void *> *,float &&)".
1>          with
1>          [
1>              _Kty=std::wstring
1>  ,            _Ty=float *
1>  ,            _Alloc=std::allocator<std::pair<const std::wstring,float *>>
1>          ]
1>          t:\programme (x86)\microsoft visual studio 12.0\vc\include\list(1034): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void std::list<std::pair<const _Kty,_Ty>,std::allocator<std::pair<const _Kty,_Ty>>>::_Insert<float>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<std::pair<const _Kty,_Ty>>>,std::_Iterator_base0>,float &&)".
1>          with
1>          [
1>              _Kty=std::wstring
1>  ,            _Ty=float *
1>          ]
1>          t:\programme (x86)\microsoft visual studio 12.0\vc\include\list(1034): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void std::list<std::pair<const _Kty,_Ty>,std::allocator<std::pair<const _Kty,_Ty>>>::_Insert<float>(std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<std::pair<const _Kty,_Ty>>>,std::_Iterator_base0>,float &&)".
1>          with
1>          [
1>              _Kty=std::wstring
1>  ,            _Ty=float *
1>          ]
1>          t:\programme (x86)\microsoft visual studio 12.0\vc\include\xhash(394): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void std::list<std::pair<const _Kty,_Ty>,std::allocator<std::pair<const _Kty,_Ty>>>::emplace_front<float>(float &&)".
1>          with
1>          [
1>              _Kty=std::wstring
1>  ,            _Ty=float *
1>          ]
1>          t:\programme (x86)\microsoft visual studio 12.0\vc\include\xhash(394): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void std::list<std::pair<const _Kty,_Ty>,std::allocator<std::pair<const _Kty,_Ty>>>::emplace_front<float>(float &&)".
1>          with
1>          [
1>              _Kty=std::wstring
1>  ,            _Ty=float *
1>          ]
1>          c:\acclimate engine\repo\testing\main.cpp(34): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "std::pair<std::_List_iterator<std::_List_val<std::_List_simple_types<std::pair<const _Kty,_Ty>>>>,bool> std::_Hash<std::_Umap_traits<_Kty,_Ty,std::_Uhash_compare<_Kty,_Hasher,_Keyeq>,_Alloc,false>>::emplace<float>(float &&)".
1>          with
1>          [
1>              _Kty=std::wstring
1>  ,            _Ty=float *
1>  ,            _Hasher=std::hash<std::wstring>
1>  ,            _Keyeq=std::equal_to<std::wstring>
1>  ,            _Alloc=std::allocator<std::pair<const std::wstring,float *>>
1>          ]
1>          c:\acclimate engine\repo\testing\main.cpp(34): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "std::pair<std::_List_iterator<std::_List_val<std::_List_simple_types<std::pair<const _Kty,_Ty>>>>,bool> std::_Hash<std::_Umap_traits<_Kty,_Ty,std::_Uhash_compare<_Kty,_Hasher,_Keyeq>,_Alloc,false>>::emplace<float>(float &&)".
1>          with
1>          [
1>              _Kty=std::wstring
1>  ,            _Ty=float *
1>  ,            _Hasher=std::hash<std::wstring>
1>  ,            _Keyeq=std::equal_to<std::wstring>
1>  ,            _Alloc=std::allocator<std::pair<const std::wstring,float *>>
1>          ]

Ignoring the german error messages, if you click on the last line "c:\acclimate engine\repo\testing\main.cpp(34): ..." it puts you right at the line from which the error originated.




#5235858 std::unordered_map random insertion infinity loop

Posted by Juliean on 20 June 2015 - 08:52 AM


My mistake - I use a different compiler, and am inexperienced with Visual Studio's offerings. I've read in passing before that you can run in debug mode and have iterator checking disabled, which I thought you might've accidentally been doing since the callstack says std::_List_unchecked_iterator.

 

I certainly havn't changed anything about iterator checking from the project that got generated by VS; and my STL-containers are certainly slow enough in debug mode that I can say with certainty it shouldn't be disabled.

 


Verified it in the hex editor view? Or does Visual Studio's debugger visually show you if invisible characters are caught in your strings?



Must be nice to use a debugger you can actually trust. laugh.png

MinGW's port of GDB has several times over the years displayed the wrong value for a variable I'm trying to debug - though I haven't had that occur with more recent versions.

 

Yeah, I really love MSVC debugger. I didn't use other C++-debuggers that much, but even pythons etc... really suck compared to that. I fear the day I will have to port to linux and POSIX ;) Unfortunately it got some issues in the last time too, like not being able to debug an STL container of a class when viewing the class from outside, in which case it will just show ??? and garbage data for all the STL containers. Only when I look at the member container from within a call of the same class, I see the data. Kind of weird, but I hope 2015 version will fix it.

 

As for the question: Yes, Visual Studio does show invisible characters, but only if I open up the dropdown-menu on the string... you know what, next time it happens I might actually want to do that, didn't think of it really.

 


I'm probably misreading your callstack, but it looks like you are inside of std::hash, as it's iterating over the std::wstring for comparison, before it gets to _Destroy_range(). If so, you might be able to reduce the problem down to std::hash instead of std::unsigned_map's calling of std::hash.

 

The thing I'm uncertain about this is, what tells me that std::hash is not working? I've stepped a while through this whole mess of a callstack and it appeared not to be hanging directly in std::hash, but now you say it, this callstack really looks suspicous. I havn't been able to reproduce the error as of today, but I'll investigate it further. Might as well just put the code you gave me in before the application starts, might really be able to reproduce the problem.

 


It'd also be good to know if your smart pointer really does handle copying and/or moving properly, and isn't accidentally double-deleting when std::unordered_map is moving it around. (Edit: Posted at the same time as your previous post)

 

Did I miss out on writing in the original post that I used raw pointers before? I'm pretty sure I didn't, I mean its a very fair assumption that my own smart pointer implementation might be faulty, though it cannot be addressed to this issue due what I already explained, aside from I'm using this smart-pointer althrough my application and (aside from the first day or so) it has never had any issues... though same can be said for the std::unordered_map/has, so meh...




#5235854 std::unordered_map random insertion infinity loop

Posted by Juliean on 20 June 2015 - 08:36 AM


Try running Application Verifier against this code with all the bells and whistles for memory poisoning turned on. It smells like a memory bug due to the nature of how it repros.

 

I usually run application verifier with all flags in the "Basics" section set (Heap, Memory, ...), is there something else I should turn on in order to detect this?

 

 

 


Is your sys pointer a literal typedef for unique_ptr, or something of your own devising?

 

Its my own type, but it is in no way related to the error, since I used raw pointers until just about a few days ago, and the issue happened like one year ago for the first time, before I even had my sys::Pointer type.

 

 

 


Don't suppress warnings, especially not level 1 warnings, especially not warnings about DLL boundaries!

https://msdn.microsoft.com/en-us/library/esew7y1w.aspx


I will bet you a large sandwich and a nice beer that you're doing something naughty with those DLLs.

 

Ah, thats the kind of thing I was hoping for that I overlooked. Well, I am doing this all the time for private usage of STL-classes, as suggested in some stackoverflow threads like this here:

http://stackoverflow.com/questions/2132747/warning-c4251-when-building-a-dll-that-exports-a-class-containing-an-atlcstrin

 

 

If the members in question are not accessible to the clients, make them private and #pragma away the warning for that member/class. If the members are accessible and used by clients, then you will need to provide indirect access to the members through accessors and mutators.

 

Would you say that there is still a chance of the DLLs screwing things up here? What I'm doing with the DLL is pretty simple, the main engine is a DLL, and then I have plugins which are themselves DLLs (loaded with LoadLibary), that use the Engine's Dll. The faulty method here is also called by the main application from within the engine, and not one of the plugins, so technically I shouldn't be even crossing DLL boundaries here.

 

So what would your suggestion be? Exporting the std::unordered_map symbols instead of pragma-ing the warning away? It would be still weird since I'm doing this for all private STL containers throught my codebase. In this case I have to take a close look at whats needed, I originally decided not to export the symbols for private STL-containers since they have a huge ton of depending symbols that I all have to export to totally get rid of the warnings, might write a macro for that though...




#5235829 Using OpenGL/DirectX to build GUI

Posted by Juliean on 20 June 2015 - 04:46 AM


What I meant by child windows are window components like buttons and edit box(they're child windows in MFC). I personally think it's better just to render the components, instead of creating child windows for them. Actually, what is point of that? That allows other programs to easily analyze my GUI. What do you think?

 

As I said, I think it is perfectly fine to render buttons, etc.. directly instead of creating seperate window elements for them. I wouldn't worry about the other way around though, whats the problem with programs analyzing your UI? The one advantage over having seperate windows is if you really have a window that pops up, like an asset editor, and you want the user to be able to tab between it and your editor. THEN is the time to pop up a seperate window.

 

But again, if you are planning on using this for an editor, I once again like to urge my opinion: DON'T. I did it myself, and its a path of no joy. Do you want to do this as a learning experience? Thats is fine, in this case keep going. Do you want to be productive and create a future-rich editor in no time? Then stop with this approach, and just get Qt. You'll have most of your editor in like 6 months compared to 2 years of pain. I did this myself, and yeah, I still to this day sometimes cringe over the bugs and flaws of the UI system, and having to write a new sort of advanced widget type is always a pain (next up would be allowing windows to be reinserted into the docking structures for me, ugh). Don't worry about factors like external applications being able to analyze your UI then, its a non-issue, since literally every other UI application is built that way, only very few do their UIs themselfes (Unreal Engine it appears, but their manpower/knowledge behind this is also much better).

 


Are there any disadvantage if I use OpenGL to make GUI for editors/tools? I think the two disadvantages I mentioned above are not really disadvantages. What do you guys think?

 

To put more emphasise on it, the main disadvantage is that its awefully unproductive, even if you need to learn QT, its like 4-16 times faster. Learning a QT widget is like maximum of few hours of reading the (good) documentary and trying it out, writing the same widget can take days, and you'll spend even more time fixing bugs, and polishing. Again, if you are in for the learning experience, its fine, but don't expect to gain anything from doing it other than that.

 


What I meant by screenshot is the case when other programs try to screenshot my GUI, such as remote desktop. Some of those program uses GDI to screenshot so..

 

I still don't think you have to worry about this. Remote desktop manages to capture all 3D game applications so far (I once was foolish enough to try playing highend games over the internet on my phone, lol). The point is, its regardless of what those applications use, they will most likely capture the content of the framebuffer, and don't even care what application is visible, so you don't need to care eigther. If in doubt, try it. Just render a colored quad in OpenGL and pop in your target capturing program, and see if it works (it should).




#5235828 std::unordered_map random insertion infinity loop

Posted by Juliean on 20 June 2015 - 04:37 AM

Thanks for all the responses!

 


Are you doing any threading? Is this map accessed from multiple threads?

 

No, I'm in a strictly single threaded environment, aside from XAudio which creates a thread and an encapsulated thread for streaming audio data (the bug happend before I introduced that, so not part of the issue).

 


You should probably copy the text of the stack trace into the forum - the image isn't really helpful as the lines are cut off so we can't see what function it is necessarily looping on.

 

How do I copy the text of the stack trace? I know I can copy single lines by right-clicking on them, but can I just select the whole callstack and ctrl+c & ctrl+v? If so, I'll try it the next time this is happening to me.

 


My blind guess is that I wonder what happens when you change stName to a value parameter instead of a reference. Whatever multi-thread issue you have, if you have one, might be messing with your asset names.

 

I might try changing that. But from debugging the name seems to be fine. I even forgot to mention, but when I look at the callstack outside of the hanging loop function, the item appears already inserted as second element in the map with its correct name. The function is still doing this weird infinite insertion code though.

 


I also wonder what happens if you try to reproduce the problem in a single source file instead of using DLLs. It's really easy to get really strange bugs when you are living dangerously with DLL boundaries.

 

Seeing how its not that trivial to reproduce, and that I can't just change my engine from DLL to static lib all of the sudden while keeping the same test environment, I might see if I can reproduce the error by isolating the faulty method and run it in a static-libary environment with artifical test data. The bad thing is, I won't even be able to tell you if it is working or not unless I run it like 200 times, as sometimes I don't get the error for a really, really long time.

 


I am also curious about the rest of the code in the OnLoad function. You return a raw pointer from AddHandler. You say that sys::Pointer is a unique_ptr. How are you turning that raw pointer into a unique_ptr when your Handler is owned by that unordered_map?

 

In the emplace-line, I call sys::toPointer, which assigns the raw pointer to a sys::Pointer. I would normally call sys::makePointer which would create the object directly in sys::Pointer, but in this case I would have to do another unnecessary map lookup.

 


My guess is that it's the input string that is causing the hash function to crash in some circumstance. It's hard for me to read those errors, but it sounds like, in release mode, it's crashing when std::hash is iterating over the std::wstring. It also sounds like running it in debug mode with bounds-checking iterators enabled might catch it.

 

Did I forget to mention I was running in debug mode? Apologies, I thought it was clear. Should have put more emphasise on that I am fully being able to debug the issue when it arrises due to it, so I go the names of which element is crashing not by analysing my input data but because the debugger told me. In fact I can't even remember having this issue in release mode, though I am running the application significantly more in debug mode than in release.

 


Do you have any invisible characters accidentally getting inside your std::wstring? I'm not sure how that'd crash the hash function though!

 

Not really, and as I said I verified that the string itself is not broken inside the debugger.

 


Print out the name of the key string each time that function is called. Each time it crashes, check what the last string was.

 

Again, I don't even have to do this, I can just check with the debugger.

 


Run that until it crashes and see where it crashes. If it IS crashing on the std::hash() + std::wstring() combo, either the bug is with std::wstring() or the bug is with std::hash(). If with std::hash, you can write your own non-broken hash implementation for std::wstring. If for std::wstring, you'll have to do a bit more work replacing it. But if you can figure out why it's crashing, maybe you can sanitize your input enough that it won't be a problem.

 

I'll try that out, though I have no great hope that it will show the cause of the error, since there is no real crash, but just this weird infinity-loop thingy, which I imagine won't be reproducable by just calling hash in isolation.

 

Thanks for all the suggestions though, the next time this happens, I'll be trying to get the callstack as plaintext and post it here. In the meanwhile I'll try out some of the suggestions to identifiy the problem, if you have any more input, keep it coming.




#5235666 Using OpenGL/DirectX to build GUI

Posted by Juliean on 19 June 2015 - 05:38 AM

What are your plans for using this UI? Do you want to use it for ingame UIs, or for editors/tools? I'm asking since you are talking about "child windows". For a game, it is indeed tolerable, if not wanted, to not have a seperate window if ie. an options menu pops up. Imagine this would be a seperate window, you'd have to tab around to get back to your regular game. For editors, its usually wanted/preferred to have a seperate window pop up when you e.g. open an asset editing window. You can bypass this by creating a seperate OS window in this case, with a seperate DirectX-device, and rendering to this instead, if it ever becomes an issue, so this should not be a showstopper. However, if you are planning on really using this for editor-like applications and not for ingame graphics, I'd strongly suggest you use an already existing libary like QT, since the complexity required for building a custom-rendered UI capable of simulating all the widgets needed for editors (window docks, tables, trees, ...) is overwhelming. For ingame UIs, there is nothing wrong with writing the UI renderer yourself, and in this case you should not have an issue with that everything is "one element" and cannot be inspected from outside.

 

Regarding the screenshot problem, I can't really follow. Whats the issue again? I have no problem making screenshots of my own DX/OpenGL-renderer UI. In fact if this was a problem than screenshotting wouldn't work in games at all, which it does 100% of the time. Well thinking about it, I think OpenGL on windows didn't work, but thats a different story... you don't need to fallback to GDI in that case eigther, since you can always just capture the content of the backbuffer at the end of thre frame and output that, just search for the different ways this can be done via google.




#5235656 Virtual base classes vs templates for multi-platform

Posted by Juliean on 19 June 2015 - 04:34 AM

Lets look at requirements first. Having virtual base classes is (mostly) unncessary, since being able to change the API at runtime is not required anymore as fo today. You will always have one certain build for each platform. Having a templated class is also not the best solution, as you have mentione. So you can do this:

 

// some file called OSTypes.h

#ifdef WIN32 // we assume every OS has a predestined API; there is no need for OpenGL on windows

#include "Win32Window.h"
#include "D3D11Device.h"

using WindowType = Win32Window; // typedef pre c++11
using DeviceType = D3D11Device;

#elif defined(LINUX)

#include "Win32Window.h"
#include "OpenGLDevice.h"

using WindowType = Win32Window;
using DeviceTyp = OpenGLDevice;

#end

And then you use the "WindowType" typedef wherever a window is needed, and based on compile switches this becomes the correct version when built.
 






PARTNERS