Create VB. stringValue Lock memcpy

Started by
6 comments, last by Norman Barrows 10 years, 8 months ago
Hi~~~
Let's look source...
string strValue = "1.0123f,3.1389f,5.0125f,11.0123f,33.1389f,55.0125f,111.0123f,333.1389f,555.0125f";
strValue has 9 float value.(3 vertex)
I hope to draw 1 tri.
I will make 1 mesh with "memcpy" NO Loop.
struct st
{
D3DXVECTOR3 v;
};
st* pVerts = nullptr;
pMesh->LockVertexBuffer( 0, (void**)&pVerts );
::CopyMemory( pVerts, &strValue, sizeof(st) * 3 );
pMesh->UnlockVertexBuffer();
Is Right ?
Advertisement

For each value in your string, say "1.0123f", requires 7 bytes (one for each character including the decimal). A real float of the value 1.0123f is represented with 4 bytes.

so, no, unfortunately.

You can't just memcpy that string to get your values into your vertex buffer (that would even be wrong if you took e.g. strValue.c_str()). You need so called parsing to first split that string (according to the commas) and then convert the parts to floats. I don't use C++ very often but IIRC one can split and parse using strstream and the >> operator. *google* Yep, that's a start.

what you're doing is trying to copy the "text representation" of a floating point number to a vertex buffer, not the value its self.

you'd need to convert the strings to floats first.

what you want to do is create a RAM buffer the same size as your VB, initialize it with your floating point values, then lock and copy the whole shebang to your vb:

float buffer[9]

buffer[0]=1.0123f

buffer[1]=3.1389f

buffer[2]=5.0125f

buffer[3]=11.0123f

buffer[4]=33.1389f

buffer[5]=55.0125f

buffer[6]=111.0123f

buffer[7]=333.1389f

buffer[8]=555.0125f

then lock and copy.

here's a source code snippet from CAVEMAN with the desired operations.

it looks a little uglier than it is, because it does error checking for each step.

by now, its proven stable code, so in the final release version, i may turn off the error checks.


 
 
 
void copy_ground_mesh2(int b,int c)    // b is chunk #.   c is tex pass #  (0-3).
{
void *p;
HRESULT a;
int d;                  // mesh #
d=b*4+c+157;          // calculate index of the mesh (VB/IB) to copy to
a=mesh[d].mesh2.vb->Lock(0,0,&p,D3DLOCK_DISCARD);
if (a != D3D_OK) 
    {
    Zshowscene();
    msg("lock ground mesh vb error");
    Zbeginscene();
    return;
    }
memcpy(p,system_vb,sizeof(Zvertexrec)*system_vb_numverts);
a=mesh[d].mesh2.vb->Unlock();
if (a != D3D_OK) 
    {
    Zshowscene();
    msg("unlock ground mesh vb error");
    Zbeginscene();
    return;
    }
a=mesh[d].mesh2.ib->Lock(0,0,&p,D3DLOCK_DISCARD);
if (a != D3D_OK) 
    {
    Zshowscene();
    msg("lock ground mesh ib error");
    Zbeginscene();
    return;
    }
memcpy(p,system_ib,sizeof(unsigned short int)*system_vb_numtris*3);
a=mesh[d].mesh2.ib->Unlock();
if (a != D3D_OK) 
    {
    Zshowscene();
    msg("unlock ground mesh ib error");
    Zbeginscene();
    return;
    }
mesh[d].mesh2.numfaces=system_vb_numtris;
mesh[d].mesh2.numverts=system_vb_numverts;
}
 
 
 
 

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

note that lock returns a null pointer to the VB's or IB's data, which you then use as the destination for the memcpy.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

parsing and lock, copy <- I already know.

But this method take long~~~~~ time.

No way ?


Nope, that "shortcut" you wanna take is, well, wrong, so no way around it. Can't make useful suggestions performance-wise either (since I don't use C++). You might look into C alternatives like strtok and atof or the boost libraries like in that link I found for comparisons.

Edit: Why you need to parse vertex data anyway ? If you wanna fast loading meshes you rather go binary.


parsing and lock, copy <- I already know.

But this method take long~~~~~ time.

No way ?

buffer[0]=1.0123f

buffer[1]=3.1389f

buffer[2]=5.0125f

buffer[3]=11.0123f

buffer[4]=33.1389f

buffer[5]=55.0125f

buffer[6]=111.0123f

buffer[7]=333.1389f

buffer[8]=555.0125f

once you have your vertices initialized, nothing is faster than memcpy(). lock is required in all cases.

converting hard coded strings to floats to init your vertices will be slower than simply hard coding the floats directly.

so the above code is essentially as fast as it gets.

you can also init the verts when you declare them, but all that does is move the init code (and its overhead) from your code to the app's startup init code stub. probably no speed savings.

but init speed is not what you should be worrying about. anything that gets the float values into your array of floats (which is a RAM memory image of the VB on the GPU) in a reasonable amount of time is ok.

the problem is not that memcpy is slow. the problem is that dynamic buffers DRAW slow. MUCH slower than static. because the CPU must be able to update them quickly, they are stored in memory that the CPU can access relatively quickly, but which unfortunately the GPU can't read nearly as fast as the memory used for a static mesh. as a result, the performance hit for memcpy is low, at the cost of a performance hit in DrawIndexedPrimitive due to the slower memory used to store the dynamic VB/IB.

i actually switched from drawing a number of dynamic ground quad meshes per frame to assembling them into a big static mesh which changes much less frequently and draws much faster.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

This topic is closed to new replies.

Advertisement