Skip to content

Instantly share code, notes, and snippets.

@minh0722
Forked from stoyannk/Data_oriented_example.cpp
Created March 17, 2016 14:46
Show Gist options
  • Save minh0722/a3900bc0d53d9e659661 to your computer and use it in GitHub Desktop.
Save minh0722/a3900bc0d53d9e659661 to your computer and use it in GitHub Desktop.
Sample that shows different approaces in the desing of a problem. For the HPC course in FMI 2015.
// Data-oriented variant for drawing moving shapes
struct Positions
{
unsigned Count;
float* Xs; // Simplify SIMD-ification
float* Ys;
};
struct ShapePositions
{
unsigned ImmobileCount; // [0..Immobile Count are not moving)
Positions Pos; // Conatins both immobile and moving (the state is implied)
};
void MoveShapes(float timeSinceStart,
ShapePositions positions,
Positions target)
{
// Move only the needed ones
// Trivial to parallelize; SIMD-ify whatever
}
struct Circles
{
unsigned Count;
float* Radii;
ShapePositions Pos;
};
Circles AllCircles;
Positions CircleTargets;
struct Rectangles
{
unsigned Count;
float* SizeX;
float* SizeY;
ShapePositions Pos;
};
Rectangles AllRects;
Positions RectTargets;
// Variant 1: Keep a table of what will have to be drawn
struct CirclesToDraw // Existance-based state. If not here - than we don't draw it
{
unsigned Count;
unsigned* IDs; // Have this one sorted by ID
// Additional arrays w/ draw-specific stuff
};
// Variant 2: A "gather" step can collect all needed draw info and send it
// for further processing down the pipeline.
void Update(float timeSinceStart)
{
MoveShapes(timeSinceStart, AllCircles.Pos, CircleTargets);
MoveShapes(timeSinceStart, AllRects.Pos, RectTargets);
}
void DrawCircles()
{
// ..
}
// ..
// "Textbook" example of OOP code for drawing moving shapes.
// The sample highlights all defciencies of the OOP design
// regarding performance and coupling.
struct float2 {};
class Shape
{
public:
virtual ~Shape() {}
virtual void Update(float timeSinceStart) = 0;
virtual void Draw(class IRenderer* renderer) = 0;
};
class TransfShape : public Shape
{
public:
virtual ~TransfShape() {}
float2 GetPosition() { return m_Position; }
virtual void SetTargetPosition(float2 target) { /*.. */}
virtual void Update(float timeSinceStart) override
{
if (!m_IsMoving) // branch!
return;
// Move
}
private:
float2 m_Position;
float2 m_TargetPosition;
bool m_IsMoving; // Some wasted memory here due to padding! State!
};
class Circle : public TransfShape
{
public:
virtual void Draw(class IRenderer* renderer) override
{
if (!m_IsVisible) // branch!
return;
const auto position = GetPosition();
renderer->SetShader(..);
renderer->SetBuffers(..);
renderer->DrawIndexed(..);
}
private:
IBuffer vb;
// .. Additional data (might span more than 1 cache line)
};
class Rectangle : public TransfShape
{
/*..*/
};
void UpdateApp(const gsl::span<Shape*>& shapes, float timeSinceStart)
{
for (auto sh : shapes)
{
sh->Update(timeSinceStart); // jump all over the place
}
}
void DrawApp(const gsl::span<Shape*>& shapes, IRenderer* renderer)
{
for (auto sh : shapes)
{
sh->Draw(renderer); // again - jump all over the place
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment