• Advertisement
  • Popular Tags

  • Popular Now

  • Advertisement
  • Similar Content

    • By fleissi
      Hey guys!

      I'm new here and I recently started developing my own rendering engine. It's open source, based on OpenGL/DirectX and C++.
      The full source code is hosted on github:
      https://github.com/fleissna/flyEngine

      I would appreciate if people with experience in game development / engine desgin could take a look at my source code. I'm looking for honest, constructive criticism on how to improve the engine.
      I'm currently writing my master's thesis in computer science and in the recent year I've gone through all the basics about graphics programming, learned DirectX and OpenGL, read some articles on Nvidia GPU Gems, read books and integrated some of this stuff step by step into the engine.

      I know about the basics, but I feel like there is some missing link that I didn't get yet to merge all those little pieces together.

      Features I have so far:
      - Dynamic shader generation based on material properties
      - Dynamic sorting of meshes to be renderd based on shader and material
      - Rendering large amounts of static meshes
      - Hierarchical culling (detail + view frustum)
      - Limited support for dynamic (i.e. moving) meshes
      - Normal, Parallax and Relief Mapping implementations
      - Wind animations based on vertex displacement
      - A very basic integration of the Bullet physics engine
      - Procedural Grass generation
      - Some post processing effects (Depth of Field, Light Volumes, Screen Space Reflections, God Rays)
      - Caching mechanisms for textures, shaders, materials and meshes

      Features I would like to have:
      - Global illumination methods
      - Scalable physics
      - Occlusion culling
      - A nice procedural terrain generator
      - Scripting
      - Level Editing
      - Sound system
      - Optimization techniques

      Books I have so far:
      - Real-Time Rendering Third Edition
      - 3D Game Programming with DirectX 11
      - Vulkan Cookbook (not started yet)

      I hope you guys can take a look at my source code and if you're really motivated, feel free to contribute :-)
      There are some videos on youtube that demonstrate some of the features:
      Procedural grass on the GPU
      Procedural Terrain Engine
      Quadtree detail and view frustum culling

      The long term goal is to turn this into a commercial game engine. I'm aware that this is a very ambitious goal, but I'm sure it's possible if you work hard for it.

      Bye,

      Phil
    • By tj8146
      I have attached my project in a .zip file if you wish to run it for yourself.
      I am making a simple 2d top-down game and I am trying to run my code to see if my window creation is working and to see if my timer is also working with it. Every time I run it though I get errors. And when I fix those errors, more come, then the same errors keep appearing. I end up just going round in circles.  Is there anyone who could help with this? 
       
      Errors when I build my code:
      1>Renderer.cpp 1>c:\users\documents\opengl\game\game\renderer.h(15): error C2039: 'string': is not a member of 'std' 1>c:\program files (x86)\windows kits\10\include\10.0.16299.0\ucrt\stddef.h(18): note: see declaration of 'std' 1>c:\users\documents\opengl\game\game\renderer.h(15): error C2061: syntax error: identifier 'string' 1>c:\users\documents\opengl\game\game\renderer.cpp(28): error C2511: 'bool Game::Rendering::initialize(int,int,bool,std::string)': overloaded member function not found in 'Game::Rendering' 1>c:\users\documents\opengl\game\game\renderer.h(9): note: see declaration of 'Game::Rendering' 1>c:\users\documents\opengl\game\game\renderer.cpp(35): error C2597: illegal reference to non-static member 'Game::Rendering::window' 1>c:\users\documents\opengl\game\game\renderer.cpp(36): error C2597: illegal reference to non-static member 'Game::Rendering::window' 1>c:\users\documents\opengl\game\game\renderer.cpp(43): error C2597: illegal reference to non-static member 'Game::Rendering::window' 1>Done building project "Game.vcxproj" -- FAILED. ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========  
       
      Renderer.cpp
      #include <GL/glew.h> #include <GLFW/glfw3.h> #include "Renderer.h" #include "Timer.h" #include <iostream> namespace Game { GLFWwindow* window; /* Initialize the library */ Rendering::Rendering() { mClock = new Clock; } Rendering::~Rendering() { shutdown(); } bool Rendering::initialize(uint width, uint height, bool fullscreen, std::string window_title) { if (!glfwInit()) { return -1; } /* Create a windowed mode window and its OpenGL context */ window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL); if (!window) { glfwTerminate(); return -1; } /* Make the window's context current */ glfwMakeContextCurrent(window); glViewport(0, 0, (GLsizei)width, (GLsizei)height); glOrtho(0, (GLsizei)width, (GLsizei)height, 0, 1, -1); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glfwSwapInterval(1); glEnable(GL_SMOOTH); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glEnable(GL_TEXTURE_2D); glLoadIdentity(); return true; } bool Rendering::render() { /* Loop until the user closes the window */ if (!glfwWindowShouldClose(window)) return false; /* Render here */ mClock->reset(); glfwPollEvents(); if (mClock->step()) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glfwSwapBuffers(window); mClock->update(); } return true; } void Rendering::shutdown() { glfwDestroyWindow(window); glfwTerminate(); } GLFWwindow* Rendering::getCurrentWindow() { return window; } } Renderer.h
      #pragma once namespace Game { class Clock; class Rendering { public: Rendering(); ~Rendering(); bool initialize(uint width, uint height, bool fullscreen, std::string window_title = "Rendering window"); void shutdown(); bool render(); GLFWwindow* getCurrentWindow(); private: GLFWwindow * window; Clock* mClock; }; } Timer.cpp
      #include <GL/glew.h> #include <GLFW/glfw3.h> #include <time.h> #include "Timer.h" namespace Game { Clock::Clock() : mTicksPerSecond(50), mSkipTics(1000 / mTicksPerSecond), mMaxFrameSkip(10), mLoops(0) { mLastTick = tick(); } Clock::~Clock() { } bool Clock::step() { if (tick() > mLastTick && mLoops < mMaxFrameSkip) return true; return false; } void Clock::reset() { mLoops = 0; } void Clock::update() { mLastTick += mSkipTics; mLoops++; } clock_t Clock::tick() { return clock(); } } TImer.h
      #pragma once #include "Common.h" namespace Game { class Clock { public: Clock(); ~Clock(); void update(); bool step(); void reset(); clock_t tick(); private: uint mTicksPerSecond; ufloat mSkipTics; uint mMaxFrameSkip; uint mLoops; uint mLastTick; }; } Common.h
      #pragma once #include <cstdio> #include <cstdlib> #include <ctime> #include <cstring> #include <cmath> #include <iostream> namespace Game { typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; typedef float ufloat; }  
      Game.zip
    • By Ty Typhoon
      Before read everything i am honest:
      Payment after release you get your percentage lifetime for that project.
       
      Second:
      i dont need your inspirations, ideas, music or designs.
      My head is full with that.
      I need workers who i can trust.
       
       
       
      Please let us talk in discord.
      I got a lot of stuff planned, there is much work to do.
       
      But first my team and me try to start with a small mini game and we need maybe exactly you.
      Planned for more than pc, like ps4, xbox one and mobile - so its very important to us to hopefully welcome a programmer.
       
      The mini game will be part of the planned big game. There will be never before seen guns and gameplay, you will get deeper info if youre a safe part of the team.
       
      I need:
      Programmers
      Animators
      Zbrush pros
       
      Join here please:
      https://discord.gg/YtjE3sV
       
      You find me here:
      Joerg Federmann Composing#2898
       
       
    • By Ty Typhoon
      I like to build my A - Team now.
       
      I need loyal people who can trust and believe in a dream.
      If you got time and no need for direct pay please contact me now.
       
      We cant pay now, you will recieve a lifetime percentage if the released game will give earnings. 
      If I get the best people together for a team, everything should be possible.
       
       
      What i need:
      - Programmer c++
      - Unity / Unreal - we must check whats possible, please share your experience with me.
      - Sculpter, 3D Artist
      - Animator
      - Marketing / Promotion 
       
       
      What i do:
      - Studio Owner
      - Director
      - Recruit exactly you
      - Sounddesign
      - Main theme composing
      - Vocals
      - Game design
      - Gun, swords, shields and weapon design
      - Character, plants and animal design
       
       
      Please dont ask about the Name of the Game, about Designs or Screenshots.
      The game will be defintitly affected about our and your skills if you join the team.
       
       
      Planned for the big Game:
      - 1st person shooter
      - online multiplayer
      - character manipulation
      - complete big open world with like lifetime actions and reactions
      - gunstore with many items to buy
      - many upgrades for players
      - specials like mini games
       
      So if you are interested in joining a team with a nearly complete game idea, contact me now and tell me what you can do.
       
      discord:
      joerg federmann composing#2898
       
       
    • By codelyoko373
      I wasn't sure if this would be the right place for a topic like this so sorry if it isn't.
      I'm currently working on a project for Uni using FreeGLUT to make a simple solar system simulation. I've got to the point where I've implemented all the planets and have used a Scene Graph to link them all together. The issue I'm having with now though is basically the planets and moons orbit correctly at their own orbit speeds.
      I'm not really experienced with using matrices for stuff like this so It's likely why I can't figure out how exactly to get it working. This is where I'm applying the transformation matrices, as well as pushing and popping them. This is within the Render function that every planet including the sun and moons will have and run.
      if (tag != "Sun") { glRotatef(orbitAngle, orbitRotation.X, orbitRotation.Y, orbitRotation.Z); } glPushMatrix(); glTranslatef(position.X, position.Y, position.Z); glRotatef(rotationAngle, rotation.X, rotation.Y, rotation.Z); glScalef(scale.X, scale.Y, scale.Z); glDrawElements(GL_TRIANGLES, mesh->indiceCount, GL_UNSIGNED_SHORT, mesh->indices); if (tag != "Sun") { glPopMatrix(); } The "If(tag != "Sun")" parts are my attempts are getting the planets to orbit correctly though it likely isn't the way I'm meant to be doing it. So I was wondering if someone would be able to help me? As I really don't have an idea on what I would do to get it working. Using the if statement is truthfully the closest I've got to it working but there are still weird effects like the planets orbiting faster then they should depending on the number of planets actually be updated/rendered.
  • Advertisement
  • Advertisement
Sign in to follow this  

C++ MSVC - Function argument evaluation order (bug?)

Recommended Posts

Hi,

So yesterday I had this really weird bug, which fortunately I managed to work around, but I'd still like to know whats going on in the first place.

So here's the deal: For my script-systems C++-function-bindings, I (variadic) templates like this:

template<typename Return, typename Class, typename... Args>
using Function = Return (Class::*)(Args...);

template<typename Return, CheckHasReturn<Return> = 0>
static void Call(size_t index, Class& object, Function func, CallState& state)
{
  auto value = (object.*func)(getAttribute<Args>(index, state)...);

  returnValue<Return>(0, state, value);
}

This allows for me to call a function-pointer from a bunch of arguments stored continuously in memory. In case you aren't familiar with variadic templates (or didn't know this was possible): getAttribute<Args>()... inserts the getAttribute-function for each individual template argument, like that:

void test(int, float)
{
}

Call(&test) => 

	index = 1;

	func(getAttribute<int>(index), getAttribute<float>(index)); 

Now here's the important part: Since I'm using the (default) cdecl/thiscall calling order, attributes are evaluted right-to-left, so index starts at the maximum value and is decremented in getAttribute().

And now to the bug:

Inside my plugin-projects, getAttribute would sometimes get called out of order. An example of such a function would be:

void ShowOptions(event::CallState& state, const std::vector<core::LocalizedString*>& vOptions, int selection, bool allowCancel, bool playSounds);

Now here's what happened: Instead of calling getAttribute<bool>(3), getAttribute<bool>(2), ... it was calling getAttribute<const std::vector<core::LocalizedString*>&>(3) first, which resulted in an misinterpretation of the last "bool" argument as a vector-type (it was still being inserted into the correct argument-slot, kind of obvious since there likely would've been a compile-error otherwise). After that, it would resume to calling the leftover getAttribute-functions in the "correct" order (in reality though, this resulted in an early crash).

Now my question is: How can this happen? Is there any clause in the C++-standard that allows for argument-evaluation to happen out-of-order under certain circumstances, maybe just in conjunction with the variadic-function unpacking "trick" I've used here? Or could it be a compiler-bug (in which case I'd be tempted to smack MSVC finally; that thing is just getting messier and messier)? You'd probably need to know what else I tried to pin down the exact problem in order to know for sure, so here:

- Since it only happens inside the plugin-projects (loaded via DLL), I've made sure that all compiler-settings match.

- I've also found out that under no circumstances, neigther in the plugin projects nor the main engine codebase, any such bug could be directly reproduced. As in, I've tried to reduce the involved code for the function-binding (which is quite a lot) to a minimal working example, but all attempts failed to yield a similar result - all the arguments/functions were evaluted/called in the required order.

- What I've been able to do is pinpoint the problem to (appearently) the getAttribute<>-function. Long story short, I'm supporting const vector<>& and similar constructs via an specialized templated class inside getAttribute:

namespace detail
{
	template<typename Arg>
	struct AttributeHelper
	{
		static Arg Call(size_t& index, CallState& state)
		{
			return state.GetAttribute<core::CleanType<Arg>>(index--);
		}
	};

	template<typename Arg>
	struct AttributeHelper<const std::vector<Arg>&>
	{
		static std::vector<Arg> Call(size_t& index, CallState& state)
		{
			return state.GetAttribute<std::vector<Arg>>(index--);
		}
	};
}

template<typename Arg>
decltype(auto) getAttribute(size_t& index, CallState& state)
{
	return detail::AttributeHelper<Arg>::Call(index, state);
}

The actual code is a lot more complicated, but as I've seen, the "bug" is triggered when one of the AttributeHelper specializations are being choosen. Now again, I couldn't reduce this problem to a more simplified version of the code, but it seems thats the root of the problem here.

I've actually been able to workaround the issue by using an std::index_sequence instead of manually counting the index (which imposes a few additional limiations, but oh well). The issue still remains though, and I still don't have any damn clue whats exactly going on or why.
I know this is probably a deeply complicated technical issue, and I don't require immediate help, but I'd still like to know if the experienced behaviour (out-of-order evaluation of function arguments under specific circumstances) is actually valid or just another microsoft-related bug. Any ideas?

Thanks!

Share this post


Link to post
Share on other sites
Advertisement
17 minutes ago, Juliean said:

Is there any clause in the C++-standard that allows for argument-evaluation to happen out-of-order under certain circumstances

Most definitely.  In fact all of Annex C of the ISO/IEC 9899 C language standard deals with clarifying exactly where the sequence points in evaluating expressions are.  Section [6.5.2.2][10] also explicitly states the following.

Quote

10 The order of evaluation of the function designator, the actual arguments, and
subexpressions within the actual arguments is unspecified, but there is a sequence point
before the actual call.

Section [5.1.2.3] clearly specifies that the value of objects between sequence points may not be relied on. Paragraph 2 of that section defines what a sequence point is, and the rest of the section goes to great lengths in standardese to describe what a sequence point is not.

Quote

2 Accessing a volatile object, modifying an object, modifying a file, or calling a function
that does any of those operations are all side effects, 11) which are changes in the state of
the execution environment. Evaluation of an expression may produce side effects. At
certain specified points in the execution sequence called sequence points, all side effects
of previous evaluations shall be complete and no side effects of subsequent evaluations
shall have taken place. (A summary of the sequence points is given in annex C.)

Section [1.2] of the ISO C++ standard explicitly includes the C language standard as a normative reference (that is to say, it extends the C language standard).

In other words, any program that relies on the order of evaluation of arguments to a function is malformed, because anything between the start of the function call and the actual execution of the function itself lacks a sequence point and the compiler could emit code to evaluate the arguments in any order, at any time, for any number of reasons.  It doesn't matter what calling conventions you're using, because that affects only the way data are passed and received -- which only happens after arguments are evaluated and their side effects complete.

You can not rely on the order in which arguments are evaluated in C or C++.  Ever.  Ever ever. 

Share this post


Link to post
Share on other sites

Thanks, makes a lot more sense now. I somehow mistake the right-to-left argument passing to evaluation order, oh well. Still strange that this problem only shows up now and in such a specific case, but oh well, thats what you get when you rely on unspecified behaviour.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Advertisement