Jump to content

  • Log In with Google      Sign In   
  • Create Account

DirectX 11 Jerky rendering


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

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

#1 RythBlade   Members   -  Reputation: 152

Like
0Likes
Like

Posted 03 April 2012 - 11:16 AM

Hi folks,
I'm still in the process of debugging this problem but I've got no idea what the problem really is. Basically I have a simple direct x 11 simulation running - 3 balls that spin.

Basically it mostly runs incredibly fast as you'd expect - how ever every 1 or seconds it seems to stick or jump. Varying from quite small to very large jumps.

I'm not aware of any extra work that I'm doing in between these frames - generally after initialisation the workload is constant.

I just wanted to try brainstorm a few potential causes for my problems.

The only thing I thought it might be is that I'm writing a parallel game engine that uses a deferred shader and deferred DirectX contexts.
My engine is broken up into tasks using the Intel Threaded building blocks API. I have an input, asset, update and graphics task. The update task relies on both input and assets tasks and the graphics task relies on update the update task.

I've profiled in sampling and instrumentation mode and can't seem to find a trouble spot if its some mystery blocking function or something but nothing stands out.

DXUT seems to think I'm running at a consistent 500 frames per second - but I added a few getTickCounts() and I can see a few spikes appearing in the frame time.

Any help or ideas with this would be fantastic!!
I've got a new blog!! I post details of my projects, useful things I find around and about the place and some tutorials on various technologies I'm experimenting with.

Sponsor:

#2 mhagain   Crossbones+   -  Reputation: 7979

Like
0Likes
Like

Posted 03 April 2012 - 01:10 PM

Sounds like a timer problem - you mentioned that you're using GetTickCount for profiling, so I'm curious if you're using it for your main timer too. If so you need to be aware that it's quite unsuitable for this job; you need a higher resolution timer (like QueryPerformanceCounter) instead.

It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.


#3 Hornsj3   Members   -  Reputation: 191

Like
0Likes
Like

Posted 03 April 2012 - 07:35 PM

I'd like to see how you are calculating the spin angle. It could be error caused by concatenation of rotations.

#4 RythBlade   Members   -  Reputation: 152

Like
0Likes
Like

Posted 04 April 2012 - 02:09 AM

Hi folks, thanks for the responses!!

@mhagain
I'm not aware of any timers that I'm using. I'm running it as fast as it can go and my animation is a constant step per frame - so the higher the frame rate, the faster the animation. Might be DXUT trying to impose a timer of some sort??

@Hornsj3
My animation is based on a "centred camera" sort of like you'd find a 3d modelling package. It specifies vertical (from the positive y axis) and horizontal (from the positive x axis) rotation along with a radius (the camera's distance from the origin).
Also my cameras are implemented as a wrapper around a basic camera to give it some specialised functionality.
For completeness I've include the animation code and the basic and centred camera class implementations.

The 'updateCameraVectors()' in the centred camera class is where I do the rotational calculations and the set rotation functions clip the angle to be between 0 and 360 degrees for the horizontal rotation and 0 and 180 degrees for the vertical rotation.

Here's the animation code:
ICameraManager* cameras = taskData->m_pRenderingService->getCameraManager();
ICentredCamera* camera = cameras->getCentredCamera();
// horizontal rotation animation
camera->setHorizontalRotation(camera->getHorizontalRotation() + 0.01);
// camera zoom animation
if(camera->getRadius() >= 30.0f)
{
camera->setRadius(10.0f);
}
else
{
camera->setRadius(camera->getRadius() + 0.01f);
}

And here is the centred camera class:
#include "CentredCameraWrapper.h"
namespace GEngine_Graphics
{
CentredCameraWrapper::CentredCameraWrapper(Camera* cameraToWrap)
{
  GEngineNonZeroAssert(cameraToWrap, L"No camera passed to CentredCameraWrapper constructor", L"No Camera");
  m_pWrappedCamera = cameraToWrap;
  m_horizontalRotation = 0.0f;
  m_verticalRotation = D3DX_PI / 2.0f;
  m_radius = 1.0f;
}
CentredCameraWrapper::~CentredCameraWrapper()
{
}
void CentredCameraWrapper::setMatrices()
{
  m_pWrappedCamera->setMatrices();
}
D3DXVECTOR3* CentredCameraWrapper::getCameraPosition()
{
  return m_pWrappedCamera->getCameraPosition();
}
D3DXMATRIXA16* CentredCameraWrapper::getViewMatrix()
{
  return m_pWrappedCamera->getViewMatrix();
}
D3DXMATRIXA16* CentredCameraWrapper::getProjectionMatrix()
{
  return m_pWrappedCamera->getProjectionMatrix();
}
void CentredCameraWrapper::setAsActive()
{
  VectorUtilities::setVector(m_pWrappedCamera->getCameraTarget(), 0.0f, 0.0f, 0.0f);
  VectorUtilities::setVector(m_pWrappedCamera->getCameraUp(), 0.0f, 1.0f, 0.0f);
  updateCameraVectors();
}
/*
  sets the horizontal rotation of the camera
  Parameter list
   rotation:  to horizontal rotation of the camera
  */
void CentredCameraWrapper::setHorizontalRotation(float rotation)
{
  m_horizontalRotation = fmod(rotation, 2.0f * (float)D3DX_PI);
  updateCameraVectors();
}
/*
  sets the vertical rotation of the camera
  Parameter list
   rotation:  to vertical rotation of the camera
  */
void CentredCameraWrapper::setVerticalRotation(float rotation)
{
  m_verticalRotation = rotation;
  if (m_verticalRotation > D3DX_PI)
  {
   m_verticalRotation = D3DX_PI;
  }
  else if (m_verticalRotation < 0.0f)
  {
   m_verticalRotation = 0.0f;
  }
  updateCameraVectors();
}
void CentredCameraWrapper::setRadius(float radius)
{
  m_radius = radius;
  // do not let the radius equal 0!!! If the camera position is the same as it's lookat position the view matrix will break!!
  if (m_radius <= 1.0f)
  {
   m_radius = 1.0f;
  }
  updateCameraVectors();
}
float CentredCameraWrapper::getHorizontalRotation()
{
  return m_horizontalRotation;
}
float CentredCameraWrapper::getVerticalRotation()
{
  return m_verticalRotation;
}
float CentredCameraWrapper::getRadius()
{
  return m_radius;
}
/*
  recalculates and updates the camera vectors
  */
void CentredCameraWrapper::updateCameraVectors()
{
  D3DXVECTOR3 forward(sinf(m_horizontalRotation), cosf(m_verticalRotation), cosf(m_horizontalRotation));
  D3DXVec3Normalize(&forward, &forward);
  VectorUtilities::setVector(
   m_pWrappedCamera->getCameraPosition(),
   m_radius * forward.x,
   m_radius * forward.y,
   m_radius * forward.z);
}
}

Finally here's the basic camera that the centred camera wraps up:
// LCCREDIT start of 3DGraph1
#include  "Camera.h"
/*----------------------------------------------------------------------------\
*	  Initialisation and Clean up					   |
*----------------------------------------------------------------------------*/

#define DEFAULT_CAMERA_FOV	D3DX_PI / 4.0f
#define DEFAULT_CAMERA_NEAR_PLANE  1.0f
#define DEFAULT_CAMERA_FAR_PLANE  1000.0f
#define SCREEN_WIDTH	 800
#define SCREEN_HEIGHT	 600

namespace GEngine_Graphics
{
/*
   Constructs and initialises a camera object
   */
Camera::Camera()
{
  m_cameraPosition = D3DXVECTOR3( 0.0f, 0.0f, -1.0f );
  m_cameraTarget = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  m_cameraUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  m_nearPlane = DEFAULT_CAMERA_NEAR_PLANE;
  m_farPlane = DEFAULT_CAMERA_FAR_PLANE;
  m_fieldOfView = DEFAULT_CAMERA_FOV;
  m_aspectRatio = (float)SCREEN_WIDTH / (float)SCREEN_HEIGHT;
  setMatrices();
}
/*
  Destructs a camera object
  */
Camera::~Camera()
{
}
/*----------------------------------------------------------------------------\
  *	  Transformation pipeline code		|
  *----------------------------------------------------------------------------*/
/*
   Sets the view and projection transformation matrices.
   */
void Camera::setMatrices()
{
  setViewMatrix();
  setProjectionMatrix();
}
/*
   Sets the view transformation matrix.
   */
void Camera::setViewMatrix()
{
  D3DXMatrixLookAtLH( &m_viewMatrix, &m_cameraPosition, &m_cameraTarget, &m_cameraUp );
}
/*
   Sets the projection transformation matrix.
   */
void Camera::setProjectionMatrix()
{
  D3DXMatrixPerspectiveFovLH( &m_projectionMatrix, m_fieldOfView, m_aspectRatio, m_nearPlane, m_farPlane );
}
D3DXMATRIXA16* Camera::getViewMatrix()
{
  return &m_viewMatrix;
}
D3DXMATRIXA16* Camera::getProjectionMatrix()
{
  return &m_projectionMatrix;
}
D3DXVECTOR3* Camera::getCameraPosition()
{
  return &m_cameraPosition;
}
D3DXVECTOR3* Camera::getCameraTarget()
{
  return &m_cameraTarget;
}
D3DXVECTOR3* Camera::getCameraUp()
{
  return &m_cameraUp;
}

float Camera::getNearClipPlane()
{
  return m_nearPlane;
}
float Camera::getFarClipPlane()
{
  return m_farPlane;
}	
float Camera::getFieldOfView()
{
  return m_fieldOfView;
}
void Camera::setNearClipPlane(float value)
{
  m_nearPlane = value;
}
void Camera::setFarClipPlane(float value)
{
  m_farPlane = value;
}
void Camera::setFieldOfView(float value)
{
  m_fieldOfView = value;
}
}
// end of 3DGraph1


Any tips???

Thanks very much!

[Edit] I'll give the higher resolution timer a try and see what happens if I time the different sections of code. It's a performance thing - I'll expect to find group of functions that oddly take ages every now and again. Hopefully the timer can show this.
I've got a new blog!! I post details of my projects, useful things I find around and about the place and some tutorials on various technologies I'm experimenting with.

#5 Hodgman   Moderators   -  Reputation: 30388

Like
1Likes
Like

Posted 04 April 2012 - 04:36 AM

At 500hz, your frame time is just 2ms, so small jitter values will have a large impact. Windows thread scheduling granularity defaults to 15ms.
If you've got other programs running, it could be that your thread called Sleep, and another program got the CPU for 15ms, resulting in one frame that's 7 times longer than the surrounding ones.
Do you have a virus scanner running?

Also, at 500hz, assuming you've got a regular 60hz monitor, then your monitor is only displaying every 8(and a 3rd)th frame. If your rotation speed is fixed per frame, this means that you'll have three frames where you see "rotation*8" movement, but the fourth frame you'll see "rotation*9" movement.

If there's some jitter in your frame time (which you should expect a small amount of), and for some reason your frame times are between 1.5 and 2.5ms, instead of a solid 2ms, then:
1.5ms == 666hz == every 11.1th frame displayed == movement per refresh: 11,11,11,11,11,11,11,11,11,12,...
2ms == 500hz == every 8.3th frame displayed == movement per refresh: 8,8,8,9,8,8,8,9,8...
2.5ms == 400hz == every 6.6th frame displayed == movement per refresh: 6,7,6,8,7...

So with such low frame-times, frame-rates higher than the display rate, and with non frame-rate independent movement, you should expect some jitter.
If you vsync'ed to 60, you probably wouldn't be noticing these issues right now Posted Image

I would start by implementing frame-rate independent movement - where your rotations take into account the actual time passed.

#6 RythBlade   Members   -  Reputation: 152

Like
0Likes
Like

Posted 04 April 2012 - 06:04 AM

Hi Hodgman!
Thanks for the advice. I think I ended up discounting VSync because I thought it was pausing elsewhere in the application but I've just switched it on and its definitely alleviating the problem.
If full screen mode I can now only see a jerk every few seconds rather than quite constantly - but its still quite bad in windowed mode!

Although I know of VSync I've never had any problems that have meant I had to worry about it. The pre-cursor to this engine was a sample framework I put together with no VSync and all the animations where constant step. It ran at a few hundred fps and never had any trouble with stuttering animations.....

I've read a bit about vsyc and I think I understand what it's all about - but I don't understand why it's suddenly a problem for me when other projects have been fine with no vsync and didn't display any sort of visible stammer problems. I've had them all running fine on this machine with an identical set-up.

Yeah, there is an anti-virus app running in the background and could possibly be causing me a problem...but I can't switch it off - its all in German :(
I don't think I should need to worry about windows thread scheduling stuff too much. Threaded building blocks works with a thread pool idea. It sets up a thread for each available hardware thread and just keeps pushing tasks into them.
I've got a new blog!! I post details of my projects, useful things I find around and about the place and some tutorials on various technologies I'm experimenting with.

#7 RythBlade   Members   -  Reputation: 152

Like
0Likes
Like

Posted 04 April 2012 - 07:50 AM

Ok I think I've tracked down more of my problem - I had quite a lot of debug messages printing. As soon as I removed them the stammering reduced further. So I've compiled it under release mode and now its barely noticeable.
I'm still unsure as to why it suddenly became an issue for me though considering in my past experience its not been much of a problem....
I've got a new blog!! I post details of my projects, useful things I find around and about the place and some tutorials on various technologies I'm experimenting with.




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



PARTNERS