Welcome, Guest. Please login or register. Did you miss your activation email?

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Josh

Pages: [1] 2
1
Graphics / Re: Random spikes in time taken to draw objects
« on: March 13, 2013, 08:01:33 am »
Now today I just traced this back to it's source, which is why Google found this thread for me. It has to do with the glContext. As you may know, each FBO have their own sf::Context. Upon calling sf::RenderTarget::clear or draw, eventually you'll get down to WglContext::makeCurrent and wglMakeCurrent, which is the root cause of the huge lag spikes. There could be other causes as well, but I've yet to work around this issue. If there is any way to implement an FBO without using additional Contexts, I'd like to know.

Wow, very in depth investigation. I was having trouble fully understanding various profiling software, so I kind of gave up.

However, before I did give up, I noticed one thing which significantly reduced my lag spikes, in my game. I had been using 5 sf::RenderTextures, and was getting huge spikes (like taking 60-100ms for one frame). I rearranged the way they were used, so that now I can just use a single sf::RenderTexture. I still clear/display that one texture 5 times per frame (More now, in fact, because of other additions to the game), and yet, the spikes are nowhere near as big (From memory, my biggest ones after that were around 20ms, still ridiculous, but significantly better than 100+ms) as when I was using 5 separate textures.

Also, it feels awesome to know that the problem is not just with my game/computer/compiler/etc, and that someone else is experiencing it.

2
Graphics / Re: Random spikes in time taken to draw objects
« on: February 20, 2013, 03:20:26 am »
Haha, whoops, didn't notice the last graph's scale was at 0.1ms. Was 3am when I made that post and I had been staring at the numbers for a while. And yeah, when it's that small, probably just regular interruptions. Additionally, I removed timers from my game and it still spiked around.

I'll have a look a look at CodeAnalyst.

Edit: So I ran download CodeAnalyst and updated my system32 symbol cache. Ran the render test program and here is the result:

Process -> Pid -> ModuleTimer SamplesNumber of Samples
SFMLRenderBenchmark.exe26.351347
PID : 990426.351347
Unknown Kernel Samples14.13722
C:\Windows\SysWOW64\nvoglv32.dll6.36325
C:\Windows\SysWOW64\ntdll.dll2.11108
C:\Windows\SysWOW64\wow64cpu.dll1.4172
C:\Windows\SysWOW64\wow64win.dll0.736
C:\Windows\SysWOW64\wow64.dll0.5528
unknown module pid (9904)0.4724
C:\Windows\SysWOW64\kernel32.dll0.2714
C:\Windows\SysWOW64\opengl32.dll0.126
C:\Windows\SysWOW64\user32.dll0.126
C:\Windows\SysWOW64\guard32.dll0.084
C:\Windows\SysWOW64\imm32.dll0.021
F:\Data\Projects\SFMLRenderBenchmark\sfml-graphics-2.dll0.021

Not sure what the Unknown Kernel Samples are. Are there other symbols I have to have access to?

I also have windbg, gdebugger and xperf installed, but to be honest, I don't really know my way around any of them to do much profiling

3
Graphics / Re: Random spikes in time taken to draw objects
« on: February 19, 2013, 04:54:29 pm »
I'm using SFML 2. I can't remember the exact commit, but my own repository notes say I last updated 5th Dec 2012. Looking at all the commits since then, there shouldn't be anything that would affect this, but I guess I can update it just to see.

I am using VS Express 2008 on Win 7 64 bit.

Narrowing it down? I removed the render texture drawing, so now the main loop JUST clears and displays.

This is my pc, constantly spiking over 1ms just to clear/display:


This is a different friend's pc with drawing on and then off:




So, the spikes, while not as big in the last image (averages around 0.7ms), they are still large, and regular.

Taking out the display and clear calls, but leaving in their timers, produces this:

So there are still spikes there, just not as many (Does same thing on friend's computer).

So, I guess it could be the timer blocking the process for short periods of time causing the spikes, although, maybe not, since the spikes get more prevalent when clearing and displaying. I will take all the timers out of my game and see if the spikes still happen.


Also, cheers for the heads up about _s functions being VS specific. Didn't realise. Was always more comfortable using printf over cout for some reason, so kinda stuck with it, and then moved on _s when the compiler kept recommending them. I should probably spend more time with c++ i/o.

4
Window / Re: video mode thingy
« on: February 18, 2013, 04:37:32 am »
If you check out the docs, getDesktopMode()'s definition is:

static VideoMode getDesktopMode ()

Initialising desktop like this invokes the copy constructor (Not the default constructor or the assignment operator), using the sf::VideoMode object returned by getDesktopMode() as the object to copy.

5
Graphics / Re: Random spikes in time taken to draw objects
« on: February 17, 2013, 11:58:53 am »
Ah cheers. I had a quick look but didn't see anything relevant. I'll have another search

Edit: I can't seem to find the post you're talking about. Going to sleep now, will have another look tomorrow.

6
Graphics / Random spikes in time taken to draw objects
« on: February 17, 2013, 10:56:48 am »
I've been noticing some stuttering in my game, which is kind of annoying. I did some profiling and it seemed to be centered around a section of code dealing with some render textures.

I've been able to form this minimal program:

#include <SFML/Graphics.hpp>
#include <stdio.h>

#define NUMLOOPS 2000

#define WIDTH 1600
#define HEIGHT 900

int main() {

    sf::RenderWindow  window( sf::VideoMode( WIDTH, HEIGHT, 32 ), "Lag Spikes" );

        sf::RenderTexture renderTexture;
        sf::Sprite renderSprite;
        renderTexture.create(WIDTH, HEIGHT);
        renderSprite.setTexture(renderTexture.getTexture());

        sf::VertexArray tileDetails;
        tileDetails.setPrimitiveType(sf::Triangles);

        sf::Clock deltaClock;

        FILE *fp;
        fopen_s(&fp, "timings.xls", "w");
        fprintf_s(fp, "Frame Time\tClear Time\tDraw Time\tDisplay Time\n");
        srand(0);

        float records[NUMLOOPS][4];
        for(int i = 0; i < NUMLOOPS; i++)
        {
                //Frame time for previous frame
                records[i][0] = deltaClock.restart().asSeconds();

                window.clear(sf::Color::Cyan);
                records[i][1] = deltaClock.getElapsedTime().asSeconds();

                //Draw to some render textures and draw them to screen
                for(int j = 0; j < 5; j++)
                {
                        renderTexture.clear(sf::Color::Transparent);
                        renderTexture.draw(tileDetails);
                        renderTexture.display();
                        window.draw(renderSprite);
                }
                records[i][2] = deltaClock.getElapsedTime().asSeconds();

                window.display();
                records[i][3] = deltaClock.getElapsedTime().asSeconds();
        }

        //Write out the times
        for(int i = 0; i < NUMLOOPS; i++)
                fprintf_s(fp, "%f\t%f\t%f\t%f\n", records[i][0], records[i][1], records[i][2] - records[i][1], records[i][3] - records[i][2]);
}
 


Essentially, opens a window, makes a render texture and then draws some data to the render texture. It keeps track of the time taken to clear, draw and display each frame and saves it to an excel file. Opening it up and making a graph shows tonnes of spikes in time taken for the draw step. The loop is there to exaggerate the lag spike. Also, my game requires 5 passes, due to some shaders, so I left it in in case it affects the answer.

Here are some example runs:
My pc:


Friend's pc


As you can see, every frame is dominated by the draw time, with occassional spikes in the display time. But then, sometimes this also happens:

Note from frame 1400 onwards, the display time jumps from almost 0ms to 0.7ms, and the draw time drops from around 1.4ms down to 0.7ms. I've noticed this behaviour in my game as well, where sometimes all the rendering time is reported under my render system, and window.display() happens almost instantaneously, and other times my render system renders faster, while the window.display() takes long enough to fill the gap.

Basically, I'm looking for reasons or explanations why both the spikes and the draw/display effect is happening. I'm guessing it might have something to do with interrupts to the graphics card, or some other hardware side effect that I won't have much control over. But figured I would post and see if anyone has any ideas.

7
Graphics / Re: Question About GL States
« on: January 02, 2013, 11:35:59 am »
1) Since the texture is a parameter of the shader, instead of being passed to the draw function, it is not bound to texture unit 0. Therefore, you mustn't use gl_TexCoord[0] but gl_TexCoord[1]. I know, you were not supposed to know that.

2) I've also managed to make it work the other way, by passing the texture to the draw call and associating sf::Shader::CurrentTexture to the shader parameter "shaderTex". The probleme in this case is your shader: the line which computes "pos" messes up the result, removing it solves the problem.

So, the first fix is just changing
vec2 truePos = gl_TexCoord[0].xy;
to
vec2 truePos = gl_TexCoord[1].xy;
Correct? If so, that doesn't work for me. The texture coordinates I'm passing in through the vertex array are being stored in gl_TexCoord[0] (If I don't draw the sprite and change the texture coordinates in the array, it definitely distorts the texture correctly). Whereas it seems to be just getting zeroes or something from gl_TexCoord[1].

Fix number 2 seems to work, as long as I only use one texture (and set the texture to repeat). As soon as I put it back to the three texture shader, it messes up, as I can't have 3 textures as the currentTexture. gl_TexCoord[1] and [2] both seem to be zeroed. Using gl_TexCoord[0] for all 3 textures draws the other two textures as the same dimensions as the first texture.

The reason I do the pos calculation is so that I can store a world position in the texture coordinate in each vertex. This world position and the texture dimensions are then used to grab "clip regions" of each three tiles as if they had been infinitely tiled across the game world. (Essentially a modulo calculation).

So unless there is some way to for me to store data in gl_TexCoord[1] and [2], using the same vertexarray, then it would appear neither of your fixes solve my original problem, only the reduced minimal code.

8
Graphics / Re: Checking an sf::image vector
« on: January 02, 2013, 09:24:00 am »
If you're using an std::vector, and iterating over it with a for loop like
for(unsigned int i = 0; i < myVector.size(); i++)
  //...code...

Having an empty vector will not cause any problems. It won't run any of the code inside the for loop.

Then, when you want to add a new texture, in your AddTexture function you .push_back() a new element into the vector and set it up

9
Graphics / Re: Question About GL States
« on: January 02, 2013, 08:20:27 am »
No worries. Hope this is minimal enough:

#include <SFML/Graphics.hpp>
#include <GL/glew.h>
#pragma comment(lib, "opengl32.lib")

int main() {

        //Render window
    sf::RenderWindow  window( sf::VideoMode( 800, 600, 32 ), "GL States Issue" );

        //Texture to draw with shader
        sf::Texture shaderTex;
        shaderTex.loadFromFile("prime1.png");

        //Multisample shader
        sf::Shader multisamplerShader;
        multisamplerShader.loadFromFile("multisampler.sfx", sf::Shader::Fragment);
        //multisamplerShader.loadFromFile("vertexshader.sfx", "multisampler.sfx"); //Fixing the coordinates via the vertex shader

        sf::Vector2f size;
        multisamplerShader.setParameter("shaderTex", shaderTex);
        size.x = 1.0f / shaderTex.getSize().x;
        size.y = 1.0f / shaderTex.getSize().y;
        multisamplerShader.setParameter("shaderTexSize", size);

        //Random extra sprite to draw
    sf::Sprite proj;
        sf::Texture projTex;
        projTex.loadFromFile("randomsprite.png");
        proj.setTexture(projTex);

        //Vertex array that will be used with the shader
        sf::VertexArray shaderArray;
        shaderArray.setPrimitiveType(sf::Triangles);
        shaderArray.append(sf::Vertex(sf::Vector2f(0.0f, 0.0f), sf::Vector2f(0.0f,0.0f)));
        shaderArray.append(sf::Vertex(sf::Vector2f(0.0f, 500.0f), sf::Vector2f(0.0f,500.0f)));
        shaderArray.append(sf::Vertex(sf::Vector2f(500.0f, 500.0f), sf::Vector2f(500.0f,500.0f)));
        bool run = true;

        while(run)
        {
                window.clear(sf::Color::Cyan);

                window.draw(proj); //Drawing this messes things up

                window.draw(shaderArray, &multisamplerShader);
               
                window.display();
               
                sf::Event Event;
               
                while (window.pollEvent(Event))
                {
                        if ((Event.type == sf::Event::KeyPressed && (Event.key.code == sf::Keyboard::Escape)))  {run = false; }
                }
        }
}
 

My fragment shader:
//The textures to combine for the tile
uniform sampler2D shaderTex;
//Inverse size of each texture
uniform vec2 shaderTexSize;

void main()
{
        //Position of the current fragment
        vec2 truePos = gl_TexCoord[0].xy;
       
        //Grab the decimal part of the texture coordinate
        vec2 pos = vec2((truePos * shaderTexSize) - vec2(ivec2(truePos * shaderTexSize)));
               
        //Get the pixel data from texture
        vec4 fragment = texture2D(shaderTex, pos);
       
        gl_FragColor = vec4(fragment.rgb, 1.0);
}
 

And I'll include the vertex shader that I now use, for the sake of completeness:
void main(){
    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_FrontColor = gl_Color;
}

10
Graphics / Re: Question About GL States
« on: January 02, 2013, 02:47:51 am »
 I tried using your suggestion, however, that ignores the texture coordinates passed through in the vertex array. Additionally, it stretches all three of the textures so they're as big as the screen, which defeats the point of the multisampler. (The multisampler essentially infinitely tiles 3 prime sized textures over the game world, then the tiles act as a clipping mask. The reason for using prime sized textures is so that their lowest common denominator is the product of their dimensions, and thus won't get repetition for many, many pixels. Stretching the textures to be the screen size obviously destroys this behaviour)

However, I tried your suggestion of using the vertex shader, which worked.

This is the shader I used:
void main(){
    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_FrontColor = gl_Color;
}

So, basically just had to stop it multiplying the texcoord by gl_TextureMatrix[0].

Cheers


However, still kind of curious why drawing an extra object, using only SFML, requires me to mess around with resetting the texture coordinates. (i.e my original program, if I don't draw proj, then I don't need to reset the texture matrix). I was under the impression that one of the design goals for SFML was that if a user only used SFML (no custom opengl), then it would take care of all that lower level stuff for them, but clearly it's not taking care of something, since not drawing the proj sprite lets it work perfectly.

11
Graphics / Question About GL States
« on: January 01, 2013, 04:00:24 pm »
I'm using an sf::VertexArray and a multisample shader to draw the tile map in my game. This works fine, unless I try to draw something before it. When I do so, it messes with the texture coordinates in the multisampler. I found this page, which mentions differing coordinates. Sure, enough, when I manually reset the GL_TEXTURE matrix before the shader, it works perfectly. However, I don't do any custom openGL rendering in my program, so why does SFML not handle the states properly itself? I'm happy to manually reset the texture matrix, but was just curious as to why I have to.

Aditionally I can call push/popGLState around each draw call and it works as well, however, calling resetGLStates does not work.

I also tried the fix listed here, saying I should use sf::Shader::CurrentTexture, but that also did not work.

Also, should mention, I'm using one of the latest versions of SFML (Checking commits since my copy and they're all API updates, or irrelevant).

Anyway, here is a minimal app that demonstrates the issue (full app including shader attached):
#include <SFML/Graphics.hpp>

//Only included/linked to manually set GL_TEXTURE matrix to identity
#include <GL/glew.h>
#pragma comment(lib, "opengl32.lib")

int main() {

        //Render window
    sf::RenderWindow  window( sf::VideoMode( 800, 600, 32 ), "GL States Issue" );

        //Multisampler textures
        sf::Texture prime1Tex;
        sf::Texture prime2Tex;
        sf::Texture prime3Tex;
        prime1Tex.loadFromFile("prime1.png");
        prime2Tex.loadFromFile("prime2.png");
        prime3Tex.loadFromFile("prime3.png");

        //Mutlisample shader - Samples from 3 repeating prime textures to significantly reduce tiling patterns
        sf::Shader multisamplerShader;
        multisamplerShader.loadFromFile("multisampler.sfx", sf::Shader::Fragment);
        sf::Vector2f size;
        multisamplerShader.setParameter("prime1Tex", prime1Tex);//sf::Shader::CurrentTexture);
        size.x = 1.0f / prime1Tex.getSize().x;
        size.y = 1.0f / prime1Tex.getSize().y;
        multisamplerShader.setParameter("prime1Size", size);
        multisamplerShader.setParameter("prime2Tex", prime2Tex);
        size.x = 1.0f / prime2Tex.getSize().x;
        size.y = 1.0f / prime2Tex.getSize().y;
        multisamplerShader.setParameter("prime2Size", size);
        multisamplerShader.setParameter("prime3Tex", prime3Tex);
        size.x = 1.0f / prime3Tex.getSize().x;
        size.y = 1.0f / prime3Tex.getSize().y;
        multisamplerShader.setParameter("prime3Size", size);

        //Random extra sprite to draw
    sf::Sprite proj;
        sf::Texture projTex;
        projTex.loadFromFile("randomsprite.png");
        proj.setTexture(projTex);

        //Vertex array storing tile data.
        sf::VertexArray tileDetails;
        tileDetails.setPrimitiveType(sf::Triangles);
        tileDetails.append(sf::Vertex(sf::Vector2f(20.0f, 20.0f), sf::Vector2f(20.0f,20.0f)));
        tileDetails.append(sf::Vertex(sf::Vector2f(20.0f, 500.0f), sf::Vector2f(20.0f,500.0f)));
        tileDetails.append(sf::Vertex(sf::Vector2f(500.0f, 500.0f), sf::Vector2f(500.0f,500.0f)));

        bool run = true;
        while(run)
        {
                window.clear(sf::Color::Cyan);

                //Removing all these push/popGLState calls causes the multisample shader to mess up
                //window.pushGLStates();
                window.draw(proj);
                //window.popGLStates();

                //Just using this works
                glMatrixMode(GL_TEXTURE);
                glLoadIdentity();
               
                //Just using this does not work
                //window.resetGLStates();

                //window.pushGLStates();
                //Even trying the fix of setting the first texture in the shader to sf::Shader::CurrentTexture, and
                //then passing it in through sf::RenderStates does not work. It changes how the shader messes up however
                sf::RenderStates states;
                //states.texture = &prime1Tex;
                states.shader = &multisamplerShader;
                window.draw(tileDetails, states);
                //window.popGLStates();
               
                window.display();
               
                sf::Event Event;
               
                while (window.pollEvent(Event))
                {
                        if ((Event.type == sf::Event::KeyPressed && (Event.key.code == sf::Keyboard::Escape)))  {run = false; }
                }
        }
}
 

[attachment deleted by admin]

12
Seems to work fine for me with or without the lines being drawn.

Could you try commenting all the lines for the windowDebug? I've found some weird things were if I render to another window it will stop the bug from occuring.

Cheers

13
So I've been fiddling with it a bit more, and made a minimal project that does it. However, the minimal project doesn't fix up with the transparent line being drawn after every projectile.

Anyway, the source code, shaders and png are attached.

Edit: For a short while, the attached example would work fine if I drew a black texture to the sf::RenderTexture first and then all the projectiles, but that seems to have stopped working.

Additionally, if I call display() (or glFlush()) on the render texture in the projectile rendering loop before drawing each projectile, rather than just once afterward, it works fine. This also works in my game. However, the problem is, this adds about 6ms to my render cycle, rather than the <1ms I get without the individual display()/glFlush() calls. So I'm guessing that the sf::RenderTexture isn't being updated in time for my next projectile or something. Are there any work arounds for this, or do I just need to cop the hit?

[attachment deleted by admin]

14
Hrmmm, now I'm having another issue. If I only draw to the sf::RenderTexture, it ends up with garbage all over the texture, but if I do any drawing to the sf::RenderWindow, it works fine.

In my projectile manager:
sf::Shader* projectileShader = ShaderManager::Get()->getEffect(blendShaderIndex); //The blend shader is loaded earlier and then accessed using an index
if(projectileShader )
        projectileShader ->setParameter("bgtex", projTexture->getTexture()); //projTexture is the sf::RenderTexture

sf::Vertex line[2] = {a, b};
line[0].color = sf::Color::Transparent;
line[1].color = sf::Color::Transparent;

for(unsigned int i = 0; i < projectiles.size(); i++)
{
        projectiles[i]->render(); //Renders all projectiles onto the projTexture
        //RenderWindow.draw(line, 2, sf::Lines); //Works when this line is uncommented
}

//Render projTexture onto game screen using threshold shader
 

In projectiles:
void Projectile::render()
{
        sf::Shader* shader = ShaderManager::Get()->getEffect(blendShaderIndex);

        if(shader)
        {
                //sf::Sprite projectile, defined elsewhere. Position, scaling, etc set here

                shader->setParameter("projectiletex", sf::Shader::CurrentTexture);

                sf::RenderStates state;
                state.blendMode = sf::BlendNone;
                state.shader = shader;
                projTexture->draw(projectile, state);
        }
}
 

So, now the problem is when the draw(sf::Lines) is not done, the projTexture gets garbage over it, but when draw(sf::Lines) is done, it works fine (but at a framerate cost).

Here is an example of what I mean:

The one on the left is with the draw(sf::Lines) in, and is how it is supposed to look (The different colours are from different threshold values). The one on the right is when I remove draw(sf::Lines).

Any help would be appreciated

15
Brilliant, that worked! Thanks a bunch.

As for what is happening with the projectile texture, it gets drawn where a projectile object is in game. The red values all get blended together, to create a kind of stream, brightest near center and weakest along the edge. So basically, the render texture becomes a heatmap of projectil intensity. Then the threshold shader takes that and sets output colors based on the intensity and the green channel tag.

There is a good pictorial example in the first link I posted (2nd picture down). The projectile texture lets me make the blurred scene in the second frame.

Pages: [1] 2