I have a question realted to meemory usage by using
Dynamic ConstantBuffer vs Constant Buffer updated frequentlky(Using Defualt usagetype) vs Dynamic Vertex Buffer
I always Defined Constnat buffer usage as defualt and updated the changes in realtime like so
Eg 1
D3D11_BUFFER_DESC desc;
desc.Usage = D3D11_USAGE_DEFAULT;
// irrelevant code omitted
void Render()
{
WORLD = XMMatrixTranslation(x,y,z); // x,y,z are chaned dynamiclly
ConstantBuffer cb;
cb.world = WORLD;
devcon->UpdateSubResource(constantBuffer,0,0,&cb,0,0);
// Set the VSSetBuffer and PSSetBuffer
}
But Recently I came across a tutorial from rastertek that used
devcon->Map() and devcon->Unmap() to update them and he had defined the usage as Dynamic
Eg 2
void CreateBuffer(){
D3D11_BUFFER_DESC desc;
desc.Usage = D3D11_USAGE_DYNAMIC; // irrelkavant code ommited
}
void Render()
{
WORLD = XMMatrixTranslation(x,y,z); // x,y,z are chaned dynamiclly
D3D11_MAPPED_SUBRESOURCE mappedRes;
ConstantBuffer *cbPtr;
devcon->Map(constantBuffer,0,D3D11_MAP_WRITE_DISCARD,0,&mappedRes);
cbPtr = (ConstantBuffer*)mappedRes.pData;
cbPtr->World = WORLD;
devcon->UnMap(constantBuffer,0);
}
So the question is .
Is there any performance gain or hit by using Dynamic Constant buffer(eg2) over the the default ConstatnBuffer updatee at runtim(eg1) ??
Please do help me clear this doubt..
Thanks
The answer here like most performance advice is "It depends". Both are valid and it really depends on your content and rendering pattern.
The classic performance reference here is Windows to Reality: Getting the Most out of Direct3D 10 Graphics in Your Games from Gamefest 2007.
If you are dealing with lots of constants, Map of a DYNAMIC Constant Buffer is better if your data is scattered about and is collected as part of the update cycle. If all your constants are already laid out correctly in system memory, then UpdateSubResource is probably better. If you are reusing the same CB many times a frame and Map/Locking it, then you might run into 'rename' limits with Map/Lock that are less problematic with UpdateSuResource so "it depends' is really the answer here.
And of course, all of this goes out the window with DirectX 12 which has an entirely different mechanism for handling the equivalent of dynamic updates.
Related
I am trying to tie together a few different libraries for a project I'm working on. The code is for a Teensy 4.1 in VS Code and PlatformIO
I am trying to use lvgl https://lvgl.io/ (graphics library) and ILI9341_t3n LCD libraries https://github.com/KurtE/ILI9341_t3n.
The ILI9341_t3n library has functions that use DMA to asynchronously update the display. I would like to use it as my display driver.
The ILI9341_t3n library uses a framebuffer and the pointer is pointing to a uint16_t.
However, the lvgl library does things a bit differently. It uses a _lv_disp_draw_buf_t struct to hold several more variables, like fb size, which buffer to use (if double buffer) and other status indicators.
typedef struct _lv_disp_draw_buf_t {
void * buf1; /**< First display buffer.*/
void * buf2; /**< Second display buffer.*/
/*Internal, used by the library*/
void * buf_act;
uint32_t size; /*In pixel count*/
/*1: flushing is in progress. (It can't be a bit field because when it's cleared from IRQ Read-Modify-Write issue might occur)*/
volatile int flushing;
/*1: It was the last chunk to flush. (It can't be a bit field because when it's cleared from IRQ Read-Modify-Write issue might occur)*/
volatile int flushing_last;
volatile uint32_t last_area : 1; /*1: the last area is being rendered*/
volatile uint32_t last_part : 1; /*1: the last part of the current area is being rendered*/
} lv_disp_draw_buf_t;
The code to create and initialize a buffer is as follows.
static _lv_disp_draw_buf_t draw_buf;
static lv_color_t buf_1[MY_DISP_HOR_RES * 10]; /*A screen sized buffer*/
static lv_color_t buf_2[MY_DISP_HOR_RES * 10]; /*Another screen sized buffer*/
lv_disp_draw_buf_init(&draw_buf, buf_1, buf_2, MY_DISP_HOR_RES * 10); /*Initialize
The init code is:
void lv_disp_draw_buf_init(lv_disp_draw_buf_t * draw_buf, void * buf1, void * buf2, uint32_t
size_in_px_cnt)
{
lv_memset_00(draw_buf, sizeof(uint16_t));
draw_buf->buf1 = buf1;
draw_buf->buf2 = buf2;
draw_buf->buf_act = draw_buf->buf1;
draw_buf->size = size_in_px_cnt;
}
The ILI9341_t3n code for initializing the frame buffer is much more simple.
void ILI9341_t3n::setFrameBuffer(uint16_t *frame_buffer) {
#ifdef ENABLE_ILI9341_FRAMEBUFFER
_pfbtft = frame_buffer;
_dma_state &= ~ILI9341_DMA_INIT; // clear that we init the dma chain as our
// buffer has changed...
#endif
}
I would like to create a framebuffer like the lvgl library recommends, and then pass it into this function. I can modify the code so that the LCD library can do something like:
_pfbtft = draw_buf->buf1;
//or//
_pfbtft = draw_buf->buf2;
That way, I can use lvgl to update the framebuffer, and use the ILI9341 library just for handling the DMA transactions.
The problem is I don't know how to incorporate the _lv_disp_draw_buf_t data type into the ILI9341 library. I tried changing the uint16_t to _lv_disp_draw_buf_t just to see what would happen and it says it's an undefined variable type.
Is this a somewhat trivial task or will it require rewriting a lot of code?
Or maybe I dont need to incorporate it. If I call:
tft.setFrameBuffer(&frame_buffer);
Is there a way I could access the framebuffer pointer contained in the _lv_disp_draw_buf_t data type and pass it instead?
If it's not a simple answer, please advise some topics that I should study so that I can learn how to do this.
It's possible I'm going about this all wrong, so constructive criticism is appreciated.
I did several google searches to see if this has been answered before, but my search terms are limited by my knowledge of the terminology, so if it has I apologize.
I have followed a dirextX 9 tutorial on utube and i have tried to modify the program to display multiple triangles based on a set of points. I am using it as a sort of plotter. in my testing i generate a list of points within my plotter class. the plotter class then generates 3 vertices to create a small triangle around the point. the points are then passed to the directx device.
i have moved the code that generates the polygons into my update method, as i need to update the polygon list with fresh polygons.
The code works, but every now and then it will crash with the following error message
Unhandled exception at 0x010F6AF1 in DX3DPlotTest.exe: 0xC0000005: Access violation reading location 0x00000000.
im shure that the problem is to do with the memcpy command being called over and over. i've tried deleting pVert but that creates its own error as pVert is never initiated.
hear is my update version
`
void TestApp::Update(float dt)
{
void *pVerts;
plotter=new Plotter(MaxPoints,0.01f);
float x,y;
for(ULONG i=0;i<MaxPoints;i++)
{
x= (float)(distribution(generator)-2.0f);
y= (float)(distribution(generator)-2.0f);
plotter->Plot(x,y);
}
m_pDevice3D->CreateVertexBuffer(
plotter->listContentCount*sizeof(VertexPositionColor),
0,VertexPositionColor::FVF,
D3DPOOL_MANAGED,
&VB,
NULL
);
//d3d vertex buffer VB
VB -> Lock(0,sizeof(VertexPositionColor)*plotter->listContentCount, (void**)&pVerts, 0);
memcpy(pVerts,plotter->m_pVertexList,sizeof(VertexPositionColor)*plotter->listContentCount);
VB -> Unlock();
}
`
please can someone help me understand how to fix this problem? if been fiddling around with it for hours. It does work, but for a limited amount of time.
Thanks all.
EDIT:
OK now im shure its do to wich recreating my plotter instance
`
Plotter::Plotter(UINT PointCount,float pointsize)
{
listSize = PointCount*3;
listContentCount = 0;
bufferContentCount = 0;
Polycount = 0;
m_pStdtri = new VertexPositionColor[3];
m_pVertexList = new VertexPositionColor[listSize];
m_pStdtri[0] = VertexPositionColor(0.0f ,1.0f*pointsize ,d3dColors::Red);
m_pStdtri[1] = VertexPositionColor(1.0f*pointsize , -1.0f*pointsize ,d3dColors::Lime);
m_pStdtri[2] = VertexPositionColor(-1.0f*pointsize , -1.0f*pointsize ,d3dColors::Red);
}
Plotter::~Plotter()
{
delete(m_pStdtri);
delete(m_pVertexList);
}
void Plotter::Plot(float x, float y)
{
Polycount++;
m_pVertexList[listContentCount]=VertexPositionColor(x+m_pStdtri[0].x, y+m_pStdtri[0].y,d3dColors::Red);
listContentCount++;
m_pVertexList[listContentCount]=VertexPositionColor(x+m_pStdtri[1].x, y+m_pStdtri[1].y,d3dColors::Lime);
listContentCount++;
m_pVertexList[listContentCount]=VertexPositionColor(x+m_pStdtri[2].x, y+m_pStdtri[2].y,d3dColors::Blue);
listContentCount++;
}
`
There are a couple of things that can be wrong here. The plotter object seems to be never disposed, but it is potentially possible that it's done elsewhere. What bothers me, however, is your calling of CreateVertexBuffer over and over again, presumably without ever releasing the resource that you're using. So basically what happens in my opinion is: in every frame, you create a new VertexBuffer. As the memory on your GPU runs low, the command fails eventually, which you don't detect and try to use the "created" buffer, which is not really created. You need to know, that the buffer is not destroyed, even if you delete the object which holds the VB variable. The CreateVertexBuffer command occupies resources on GPU so they need to be explicitly freed when no longer needed. But let's return to the point. This function fails at some point. So it results in a NULL pointer error. My suggestion would be to create the buffer just once and then only update it in each frame. But first, make sure if it is the case.
I'm building a simple generic engine for my true start in the making of games, and I am trying to be somehow organized and decent in the making of my engine, meaning I don't want it to be something I throw to the side once I make what I'm planning to.
I add objects to be displayed, drawObjects, and these can either move, not move, and have an animation, or not have one.
In case they DO have an animation, I want to initialize a single animationSet, and this animationSet will have xxx animationComp inside of it. As I'm trying to be neat and have worked abit on "optimizations" towards memory and cpu usage (such as sharing already-loaded image pointers, and whatever came across my mind), I wanted to not ask for possibly unused memory in arrays.
So I had animationSetS* animationSet = NULL; initially, planning to do a animationSet = animationSetS[spacesINEED]; after, only on the objects that needed animation that I added, being those that aren't animations a NULL and therefore not using memory (correct?).
And then this question popped up! (title)
struct animationComp {
SDL_Rect* clip;
int clipsize;
};
struct animationSetS {
animationComp* animation;
int currentFrame;
int currentAnimation;
int animationNumber;
};
struct drawObject { // Um objecto.
char* name;
SDL_Surface* surface;
bool draw = true;
float xPos;
float yPos;
bool willMove = false; // 0 - Won't move, 10 - Moves alot, TO IMPLEMENT
bool isSprite = false;
animationSetS* animationSet;
};
I dabble alot in my questions, sorry for that. For any clarifications reply here, I'll reply within 10 minutes for the next... 1 hour perhaps? Or more.
Thanks!
Setting the pointer to NULL means that you'll be able to add ASSERT(ptr != NULL); and KNOW that your pointer does not accidentally contain some rubbish value from whatever happens to be in the memory it was using.
So, if for some reason, you end up using the object before it's been properly set up, you can detect it.
It also helps if you sometimes don't use a field, you can still call delete stuff; [assuming it's allocated in the first place].
Note that leaving a variable uninitialized means that it can have ANY value within it's valid range [and for some types, outside the valid range - e.g. pointers and floating point values can be "values that are not allowed by the processor"]. This means that it's impossible to "tell" within the code if it has been initialized or not - but things will go horribly wrong if you don't initialize things!
If this should be really implemented in C++ (as you write), why don't you use the C++ Standard Library? Like
struct animationSetS {
std::vector< std::shared_ptr<animationComp> > animation;
// ...
}
Hi i'm working with shaders and i've just got a quick question about whether or not i can do something here. When mapping data to a buffer i normally see it done like this. Define class or struct to represent whats in the buffer.
class MatrixBuffer
{
public:
D3DXMATRIX worldMatrix;
D3DXMATRIX viewMatrix;
D3DXMATRIX projectionMatrix;
}
then set up a input element description when you make when you create the input layout, i got all that. Now, when i see people update the buffers before rendering, i see it mostly done like this:
MatrixBuffer * dataPtr;
if(FAILED(deviceContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource)))
return false;
dataPtr = (MatrixBuffer *) mappedResource.pData;
dataPtr->world = worldMatrix;
dataPtr->view = viewMatrix;
dataPtr->projection = projectionMatrix;
deviceContext->Unmap(m_matrixBuffer, 0);
where the values assigned are actually valid D3DXMATRIX's. seeing as that's okay, would anything go wrong if i just did it like this?
MatrixBuffer* dataPtr;
if(FAILED(deviceContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource)))
return false;
dataPtr = (MatrixBuffer *) mappedResource.pData;
*dataPtr = matrices;
deviceContext->Unmap(m_matrixBuffer, 0);
where matrices is a valid filled out MatrixBuffer object? Would there be dire consequences later because of some special direct X handles this or is it fine?
I don't see anything wrong with your version, from a technical perspective.
It might be slightly harder to grasp what actually gets copied there, and from a theoretical viewpoint the resulting code should be pretty much the same -- I would expect that any decent optimizer would notice that the "long" version just copies several successive items, and lump them all into one larger copy.
Try avoiding using mapping as it stalls the pipeline. For stuff that gets updated once a frame it's better to have D3D11_USAGE_DEFAULT buffer and then use UpdateSubresource method to push new data in.
More on that here: http://blogs.msdn.com/b/shawnhar/archive/2008/04/14/stalling-the-pipeline.aspx
Assume that I need to render static picture (100 stars).
I generate star data (position, color, size) to std::vector stars;
Then I create a class for D3D rendering, which consist a buffer:
CGalaxyMapRenderer
{
…
CComPtr<ID3D11Buffer> m_spStarBuffer;
}
In ctor I initialize it in this way:
CGalaxyMapRenderer::CGalaxyMapRenderer(const std::vector<SStarData>& vecData)
{
…
const CD3D11_BUFFER_DESC vertexBuffDescr((UINT)(sizeof(SStarData)*stars.size()), D3D11_BIND_VERTEX_BUFFER); //Constant buffer?
D3D11_SUBRESOURCE_DATA initVertexData = {0};
initVertexData.pSysMem = &stars[0];
spDevice->CreateBuffer(&vertexBuffDescr, &initVertexData, &m_spStarBuffer);
…
}
After that I may destroy std::vector, as it is no longer needed.
The questions are:
spDevice->CreateBuffer(&vertexBuffDescr, &initVertexData, &m_spStarBuffer));
Where memory allocation will take place for this peace of code?
Will it be graphic memory or current process memory?
When I no longer need to render a galaxy map (for example, when I want to move to next level, where no galaxy map required), I am going to destroy CGalaxyMapRenderer.
There will be automatic destruction of m_spStarBuffer in dtor.
The question is: is it enough to clear all the buffer resources?
Or should I make some additional steps in order to make memory free?
As to first question it should be on the process heap graphic memory is only used when needed in general: http://msdn.microsoft.com/en-us/library/ff476501(v=vs.85).aspx
As to second question I'm hoping by automatic destruction you mean that m_spStarBuffer is a smart pointer. Here's a simple example of creating a vertex buffer: http://msdn.microsoft.com/en-us/library/ff476899(v=VS.85).aspx