• Advertisement
  • Popular Tags

  • Popular Now

  • Advertisement
  • Similar Content

    • By isu diss
      How do I fill the gap between sky and terrain? Scaling the terrain or procedural terrain rendering?

    • By Jiraya
      For a 2D game, does using a float2 for position increases performance in any way?
      I know that in the end the vertex shader will have to return a float4 anyway, but does using a float2 decreases the amount of data that will have to be sent from the CPU to the GPU?
       
    • By ucfchuck
      I am feeding in 16 bit unsigned integer data to process in a compute shader and i need to get a standard deviation.
      So I read in a series of samples and push them into float arrays
      float vals1[9], vals2[9], vals3[9], vals4[9]; int x = 0,y=0; for ( x = 0; x < 3; x++) { for (y = 0; y < 3; y++) { vals1[3 * x + y] = (float) (asuint(Input1[threadID.xy + int2(x - 1, y - 1)].x)); vals2[3 * x + y] = (float) (asuint(Input2[threadID.xy + int2(x - 1, y - 1)].x)); vals3[3 * x + y] = (float) (asuint(Input3[threadID.xy + int2(x - 1, y - 1)].x)); vals4[3 * x + y] = (float) (asuint(Input4[threadID.xy + int2(x - 1, y - 1)].x)); } } I can send these values out directly and the data is as expected

                             
      Output1[threadID.xy] = (uint) (vals1[4] ); Output2[threadID.xy] = (uint) (vals2[4] ); Output3[threadID.xy] = (uint) (vals3[4] ); Output4[threadID.xy] = (uint) (vals4[4] ); however if i do anything to that data it is destroyed.
      If i add a
      vals1[4] = vals1[4]/2; 
      or a
      vals1[4] = vals[1]-vals[4];
      the data is gone and everything comes back 0.
       
       
      How does one go about converting a uint to a float and performing operations on it and then converting back to a rounded uint?
    • 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
  • Advertisement
  • Advertisement

DX11 Binding buffers and then updating them

Recommended Posts

I got a quick question about buffers when it comes to DirectX 11. If I bind a buffer using a command like:

IASetVertexBuffers
IASetIndexBuffer
VSSetConstantBuffers
PSSetConstantBuffers

 and then later on I update that bound buffer's data using commands like Map/Unmap or any of the other update commands.

Do I need to rebind the buffer again in order for my update to take effect? If I dont rebind is that really bad as in I get a performance hit? My thought process behind this is that if the buffer is already bound why do I need to rebind it? I'm using that same buffer it is just different data

 

Share this post


Link to post
Share on other sites
Advertisement

You don't need to rebind. There may be a hit if you Map a buffer that is still in use by the GPU, depending on the flags. Choose wisely between Discard and No Overwrite. Discard will only stall if you Map it a lot without letting frames complete. It's a good choice if you only Map that buffer once a frame. No Overwrite should not stall, but may corrupt if you overwrite in-use data. It's good for streaming purposes where you never go backwards. Remember that this still counts across frames, you should Discard once before No Overwrite, or else set GPU fences.

If you're lost at this stage, take a look here: https://msdn.microsoft.com/en-us/library/windows/desktop/dn508285(v=vs.85).aspx

Share this post


Link to post
Share on other sites
16 hours ago, Promit said:

Discard will only stall if you Map it a lot without letting frames complete. It's a good choice if you only Map that buffer once a frame. No Overwrite should not stall, but may corrupt if you overwrite in-use data. It's good for streaming purposes where you never go backwards. Remember that this still counts across frames, you should Discard once before No Overwrite, or else set GPU fences.

In the article you linked there is a part where they go over using D3D11_MAP_WRITE_NO_OVERWRITE and D3D11_MAP_WRITE_DISCARD when mapping. Where you use D3D11_MAP_WRITE_DISCARD starting off and then successive map/unmap calls should use D3D11_MAP_WRITE_NO_OVERWRITE until your buffer becomes full again and you switch back to the D3D11_MAP_WRITE_DISCARD flag.

So now that has me wondering should I be placing everything in one large buffer? That way I don't have keep rebinding all these different buffers. Something like:

//The big buffer was already bound at this point (the intialization point)
for(std::vector<Renderable>::iterator renderable = renderables.begin(); renderable != renderables.end(); ++renderable)
{
	if(bigBufferIsNotFull)
	{
		D3D11_MAPPED_SUBRESOURCE resource = Map(bigBuffer, D3D11_MAP_WRITE_NO_OVERWRITE)
		memcpy(resource.pData, (*renderable).data, (*renderable).dataSize); //(*renderable).data in this case is a vector or array of vertex data
		Unmap();
	}
	else //Our big buffer is full
	{
		D3D11_MAPPED_SUBRESOURCE resource = Map(bigBuffer, D3D11_MAP_WRITE_DISCARD)
		memcpy(resource.pData, (*renderable).data, (*renderable).dataSize); //(*renderable).data in this case is a vector or array of vertex data
		Unmap();
	}
	Draw((*renderable).vertexCount);
}

Opposed to:

for(std::vector<Renderable>::iterator renderable = renderables.begin(); renderable != renderables.end(); ++renderable)
{
  	//(*renderable).buffer is a ID3D11Buffer and at some point (renderable creation) the buffer was mapped with the needed data
  	BindVertexBuffer((*renderable).buffer); 
  	Draw((*renderable).vertexCount);
}

 

Share this post


Link to post
Share on other sites
41 minutes ago, noodleBowl said:

So now that has me wondering should I be placing everything in one large buffer? That way I don't have keep rebinding all these different buffers.

Yes, with caveats. You can only Discard a buffer so many times* before the driver stalls. Think of it like this: when you are doing this, your buffer is actually three buffers internally. Each time you discard, it switches from buffer 0 to 1, 1 to 2, 2 to 3, 3 to 0. But if that switch to 0 arrives while 0 is still in use, you're going to stall. So the buffer has to be big enough that you don't do this more than once or maybe twice a frame in order for the GPU to clear pending operations. It's best to make the buffer big enough to accommodate an entire frame's rendering in one go with the occasional spill. 

* The limit doesn't apply to constant buffers, which are magical buffers that can service thousands of discards per frame.

Share this post


Link to post
Share on other sites
2 hours ago, Promit said:

Yes, with caveats

What is kind of tripping me up is how this big buffer exists. In the sense that I could have multiple vertex types like this

class VertexTypeA
{
	Vector3 pos;
	Color color;
}

class VertexTypeB
{
	Vector3 pos;
	Color color;
	Vector2 texCoord
}

class VertexTypeC
{
	//Some data to represent VertexTypeC
}

But surly these can't go all into the same buffer. I would need a VertexTypeA buffer, VertexTypeB buffer, VertexTypeC buffer, etc right? 

In the real world, are there renders that solely focus on one object to render? EG: You have a SpriteRenderer and its only job is to render sprites, then you have a CarRenderer and its only ever going to render cars, a CharacterRenderer that only renders characters so on and so forth. Or is there some single renderer entity that does everything (I really don't think this is the case)?

Maybe a combo, where everything is fed into single renderer but then its really delegated out to the sub renderers (SpriteRenderer, CarRenderer, etc) to handle what you are actually wanting to draw?

Share this post


Link to post
Share on other sites
4 hours ago, noodleBowl said:

In the real world, are there renders that solely focus on one object to render? EG: You have a SpriteRenderer and its only job is to render sprites, then you have a CarRenderer and its only ever going to render cars, a CharacterRenderer that only renders characters so on and so forth. Or is there some single renderer entity that does everything (I really don't think this is the case)?

You can partition your objects based on what data you need in your vertices. Like you said, sprites will probably be different from static objects: sprite vertices can have a position, pair of texture coordinates and color, whereas a static object vertex could have a position, pair of texture coordinates and normal. In the end, you will have few partitions. You could use some kind of "subrenderer" for each partition like you described it or at least for the partitions which are very different. Partitions which use for instance a different vertex shader, but the same pixel shader (the same lighting calculations for instance) could be handled by the same "subrenderer" which just switches the vertex shader or sorts based on the vertex shader beforehand.

Note, however, that a dynamic rigid (or deformable) object is more abstract than a concrete "car". So if the car is not the main focus by itself in your game, you do not necessarily need special car-only treatment in your game engine.

Edited by matt77hias

Share this post


Link to post
Share on other sites
15 hours ago, matt77hias said:

You can partition your objects based on what data you need in your vertices ... In the end, you will have few partitions. You could use some kind of "subrenderer" for each partition like you described it or at least for the partitions which are very different. 

Note, however, that a dynamic rigid (or deformable) object is more abstract than a concrete "car". So if the car is not the main focus by itself in your game, you do not necessarily need special car-only treatment in your game engine.

So its not necessarily a renderer per thing (sprite, car, etc), but really a renderer per vertex type (VertexTypeA renderer, VertexTypeB renderer, or etc) and or task (lighting)

 

Previously I also I had some psudeo code like:

D3D11_MAPPED_SUBRESOURCE resource = Map(bigBuffer, D3D11_MAP_WRITE_NO_OVERWRITE)
memcpy(resource.pData, (*renderable).data, (*renderable).dataSize); //(*renderable).data in this case is a vector or array of vertex data
Unmap();

And the renderable's data was in a std::vector or array. But is it possible to have the vertex data already in a ID3D11Buffer and then copy this data directly into the big buffer owned by the renderer? Or would this be really bad because it could trigger a read from the GPU and that in turn would be super slow and cause stalling

How should I be copying data over into the renderer's big buffer? Is it really just a simple memcpy from a std::vector (renderable's vertex data) into the ID3D11Buffer (renderers buffer) using map/unmap

Edited by noodleBowl

Share this post


Link to post
Share on other sites
8 hours ago, noodleBowl said:

So its not necessarily a renderer per thing (sprite, car, etc), but really a renderer per vertex type (VertexTypeA renderer, VertexTypeB renderer, or etc) and or task (lighting)

Sort of. You can render static objects, skeleton animated objects, sprites, etc.

For static objects you can use a single vertex layout or a few vertex layouts (if you want to pre-compute tangents for some of them for instance). Your renderer for static objects knows which layouts are supported for static objects and is capable of selecting the appropriate one for each static object. Then you can for example sort static objects based on the layout and render all static objects with the same layout consecutively.

Share this post


Link to post
Share on other sites
11 hours ago, matt77hias said:

For static objects you can use a single vertex layout or a few vertex layouts (if you want to pre-compute tangents for some of them for instance). Your renderer for static objects knows which layouts are supported for static objects and is capable of selecting the appropriate one for each static object. Then you can for example sort static objects based on the layout and render all static objects with the same layout consecutively.

Maybe I'm missing something here, but wouldn't a different input layout essentially mean a different vertex type?

//Vertex Type 1
D3D11_INPUT_ELEMENT_DESC layout1[] =
{
    {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
    {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
};

//Vertex Type 2
D3D11_INPUT_ELEMENT_DESC layout1[] =
{
    {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
    {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
    {"TEXCOORDS", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0},
};

 

Share this post


Link to post
Share on other sites

You can have a single vertex shader that takes positions + colours as inputs, but create three different input layouts so that you can use that one shader with three different storage formats, e.g.

D3D11_INPUT_ELEMENT_DESC layout1[] =
{
    {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
    {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
//maps to:
struct Layout1Stream0 { float posiion[3]; float color[4]; };


D3D11_INPUT_ELEMENT_DESC layout2[] =
{
    {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
    {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
//maps to:
struct Layout2Stream0 { float posiion[3]; };
struct Layout2Stream1 { float color[4]; };


D3D11_INPUT_ELEMENT_DESC layout3[] =
{
    {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
    {"COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
//maps to:
struct Layout3Stream0 { float posiion[3]; unsigned char color[4]; };

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


  • Advertisement