committed patch:

[ 1942358 ] DX9 Blindside VBO Implementation plus SiO2 fix

to allow hardware buffers to be used by dx9, like openGL

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@1318 dfc29bdd-3216-0410-991c-e03cc46cb475
master
lukeph 2008-04-21 15:36:14 +00:00
parent 4325befbb1
commit 24202d861a
2 changed files with 317 additions and 18 deletions

View File

@ -806,6 +806,219 @@ const core::rect<s32>& CD3D9Driver::getViewPort() const
}
bool CD3D9Driver::updateVertexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer)
{
if (!HWBuffer)
return false;
const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer;
const void* vertices=mb->getVertices();
const u32 vertexCount=mb->getVertexCount();
const E_VERTEX_TYPE vType=mb->getVertexType();
const u32 vertexSize = getVertexPitchFromType(vType);
void* pLockedBuffer = 0;
if (!HWBuffer->vertexBuffer || vertexSize * vertexCount > HWBuffer->vertexBufferSize)
{
DWORD flags = 0;
u32 vertexSize;
DWORD FVF;
// Get the vertex sizes and cvf
switch (vType)
{
case EVT_STANDARD:
vertexSize = sizeof(S3DVertex);
FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1;
break;
case EVT_2TCOORDS:
vertexSize = sizeof(S3DVertex2TCoords);
FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2;
break;
case EVT_TANGENTS:
vertexSize = sizeof(S3DVertexTangents);
FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX3;
break;
default:
return false;
}
flags = D3DUSAGE_WRITEONLY; // SIO2: Default to D3DUSAGE_WRITEONLY
if(HWBuffer->Mapped != scene::EHM_STATIC)
flags |= D3DUSAGE_DYNAMIC;
pID3DDevice->CreateVertexBuffer(vertexCount * vertexSize, flags, FVF, D3DPOOL_DEFAULT, &HWBuffer->vertexBuffer, NULL);
if(!HWBuffer->vertexBuffer)
return false;
flags = 0; // SIO2: Reset flags before Lock
if(HWBuffer->Mapped != scene::EHM_STATIC)
flags = D3DLOCK_DISCARD;
HWBuffer->vertexBuffer->Lock(0, vertexCount * vertexSize, (void**)&pLockedBuffer, flags);
memcpy(pLockedBuffer, vertices, vertexCount * vertexSize);
HWBuffer->vertexBuffer->Unlock();
HWBuffer->vertexBufferSize = vertexCount * vertexSize;
}
else
{
HWBuffer->vertexBuffer->Lock(0, vertexCount * vertexSize, (void**)&pLockedBuffer, D3DLOCK_DISCARD);
memcpy(pLockedBuffer, vertices, vertexCount * vertexSize);
HWBuffer->vertexBuffer->Unlock();
}
return true;
}
bool CD3D9Driver::updateIndexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer)
{
if (!HWBuffer)
return false;
const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer;
const u16* indices=mb->getIndices();
const u32 indexCount=mb->getIndexCount();
const u32 indexSize = 2;
if (!HWBuffer->indexBuffer || indexSize * indexCount > HWBuffer->indexBufferSize)
{
D3DFORMAT idxFormat = D3DFMT_INDEX16;
DWORD flags = 0;
flags = D3DUSAGE_WRITEONLY; // SIO2: Default to D3DUSAGE_WRITEONLY
if(HWBuffer->Mapped != scene::EHM_STATIC)
flags |= D3DUSAGE_DYNAMIC; // SIO2: Add DYNAMIC flag for dynamic buffer data
if(FAILED(pID3DDevice->CreateIndexBuffer( indexCount * indexSize, flags, idxFormat, D3DPOOL_DEFAULT, &HWBuffer->indexBuffer, NULL)))
return false;
void* pIndices = 0;
flags = 0; // SIO2: Reset flags before Lock
if(HWBuffer->Mapped != scene::EHM_STATIC)
flags = D3DLOCK_DISCARD;
if(FAILED(HWBuffer->indexBuffer->Lock( 0, 0, (void**)&pIndices, flags)))
return false;
memcpy(pIndices, indices, indexCount * indexSize);
HWBuffer->indexBuffer->Unlock();
HWBuffer->indexBufferSize = indexCount * indexSize;
}
else
{
void* pIndices = 0;
if( SUCCEEDED(HWBuffer->indexBuffer->Lock( 0, 0, (void**)&pIndices, D3DLOCK_DISCARD)))
{
memcpy(pIndices, indices, indexCount * indexSize);
HWBuffer->indexBuffer->Unlock();
}
}
return true;
}
//! updates hardware buffer if needed
bool CD3D9Driver::updateHardwareBuffer(SHWBufferLink *HWBuffer)
{
if (!HWBuffer)
return false;
if (HWBuffer->ChangedID != HWBuffer->MeshBuffer->getChangedID()
|| !((SHWBufferLink_d3d9*)HWBuffer)->vertexBuffer
|| !((SHWBufferLink_d3d9*)HWBuffer)->indexBuffer)
{
HWBuffer->ChangedID = HWBuffer->MeshBuffer->getChangedID();
if (!updateVertexHardwareBuffer((SHWBufferLink_d3d9*)HWBuffer))
return false;
if (!updateIndexHardwareBuffer((SHWBufferLink_d3d9*)HWBuffer))
return false;
}
return true;
}
//! Create hardware buffer from meshbuffer
CD3D9Driver::SHWBufferLink *CD3D9Driver::createHardwareBuffer(const scene::IMeshBuffer* mb)
{
if (!mb || (mb->getHardwareMappingHint()==scene::EHM_NEVER))
return 0;
SHWBufferLink_d3d9 *HWBuffer=new SHWBufferLink_d3d9(mb);
//add to map
HWBufferMap.insert(HWBuffer->MeshBuffer, HWBuffer);
HWBuffer->ChangedID=HWBuffer->MeshBuffer->getChangedID();
HWBuffer->Mapped=mb->getHardwareMappingHint();
HWBuffer->LastUsed=0;
HWBuffer->vertexBuffer=0;
HWBuffer->indexBuffer=0;
HWBuffer->vertexBufferSize=0;
HWBuffer->indexBufferSize=0;
if (!updateHardwareBuffer(HWBuffer))
{
deleteHardwareBuffer(HWBuffer);
return 0;
}
return HWBuffer;
}
void CD3D9Driver::deleteHardwareBuffer(SHWBufferLink *_HWBuffer)
{
if (!_HWBuffer) return;
SHWBufferLink_d3d9 *HWBuffer=(SHWBufferLink_d3d9*)_HWBuffer;
if (HWBuffer->indexBuffer)
{
HWBuffer->indexBuffer->Release();
HWBuffer->indexBuffer = 0;
}
if (HWBuffer->vertexBuffer)
{
HWBuffer->vertexBuffer->Release();
HWBuffer->vertexBuffer = 0;
}
CNullDriver::deleteHardwareBuffer(_HWBuffer);
}
//! Draw hardware buffer
void CD3D9Driver::drawHardwareBuffer(SHWBufferLink *_HWBuffer)
{
if (!_HWBuffer)
return;
SHWBufferLink_d3d9 *HWBuffer=(SHWBufferLink_d3d9*)_HWBuffer;
updateHardwareBuffer(HWBuffer); //check if update is needed
HWBuffer->LastUsed=0;//reset count
const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer;
const E_VERTEX_TYPE vType = mb->getVertexType();
const u32 stride = getVertexPitchFromType(vType);
if (HWBuffer->vertexBuffer) pID3DDevice->SetStreamSource(0, HWBuffer->vertexBuffer, 0, stride);
if (HWBuffer->indexBuffer) pID3DDevice->SetIndices(HWBuffer->indexBuffer);
drawVertexPrimitiveList(0, mb->getVertexCount(), 0, mb->getIndexCount()/3, mb->getVertexType(), scene::EPT_TRIANGLES);
if (HWBuffer->vertexBuffer) pID3DDevice->SetStreamSource(0, 0, 0, 0);
if (HWBuffer->indexBuffer) pID3DDevice->SetIndices(0);
}
//! draws a vertex primitive list
void CD3D9Driver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const u16* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType)
@ -839,41 +1052,97 @@ void CD3D9Driver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount,
pID3DDevice->SetRenderState(D3DRS_POINTSIZE_MIN, *(DWORD*)(&tmp));
pID3DDevice->SetRenderState(D3DRS_POINTSCALE_A, *(DWORD*)(&tmp));
pID3DDevice->SetRenderState(D3DRS_POINTSCALE_B, *(DWORD*)(&tmp));
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_POINTLIST, 0, vertexCount,
primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride);
if (!vertices)
{
pID3DDevice->DrawIndexedPrimitive(D3DPT_POINTLIST, 0, 0, vertexCount, 0, primitiveCount);
}
else
{
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_POINTLIST, 0, vertexCount,
primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride);
}
pID3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);
if (pType==scene::EPT_POINT_SPRITES)
pID3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);
}
break;
case scene::EPT_LINE_STRIP:
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount,
primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride);
if(!vertices)
{
pID3DDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, 0, 0, vertexCount, 0, primitiveCount);
}
else
{
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount,
primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride);
}
break;
case scene::EPT_LINE_LOOP:
{
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount,
if(!vertices)
{
// TODO: Implement proper hardware support for this primitive type.
// (No looping occurs currently because this would require a way to
// draw the hardware buffer with a custom set of indices. We may even
// need to create a new mini index buffer specifically for this
// primitive type.)
pID3DDevice->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, vertexCount, 0, primitiveCount);
}
else
{
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount,
primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride);
u16 tmpIndices[] = {0, primitiveCount};
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount,
1, tmpIndices, D3DFMT_INDEX16, vertices, stride);
}
u16 tmpIndices[] = {0, primitiveCount};
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount,
1, tmpIndices, D3DFMT_INDEX16, vertices, stride);
}
break;
case scene::EPT_LINES:
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount,
primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride);
if(!vertices)
{
pID3DDevice->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, vertexCount, 0, primitiveCount);
}
else
{
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount,
primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride);
}
break;
case scene::EPT_TRIANGLE_STRIP:
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLESTRIP, 0, vertexCount,
primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride);
if(!vertices)
{
pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, 0, vertexCount, 0, primitiveCount);
}
else
{
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLESTRIP, 0, vertexCount,
primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride);
}
break;
case scene::EPT_TRIANGLE_FAN:
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLEFAN, 0, vertexCount,
primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride);
if(!vertices)
{
pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN, 0, 0, vertexCount, 0, primitiveCount);
}
else
{
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLEFAN, 0, vertexCount,
primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride);
}
break;
case scene::EPT_TRIANGLES:
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, vertexCount,
primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride);
if(!vertices)
{
pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, vertexCount, 0, primitiveCount);
}
else
{
pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, vertexCount,
primitiveCount, indexList, D3DFMT_INDEX16, vertices, stride);
}
break;
}
}
@ -2220,3 +2489,5 @@ IVideoDriver* createDirectX9Driver(const core::dimension2d<s32>& screenSize, HWN
} // end namespace irr

View File

@ -59,6 +59,32 @@ namespace video
//! gets the area of the current viewport
virtual const core::rect<s32>& getViewPort() const;
struct SHWBufferLink_d3d9 : public SHWBufferLink
{
SHWBufferLink_d3d9(const scene::IMeshBuffer *_MeshBuffer): SHWBufferLink(_MeshBuffer), vertexBuffer(0), indexBuffer(0){}
IDirect3DVertexBuffer9* vertexBuffer;
IDirect3DIndexBuffer9* indexBuffer;
u32 vertexBufferSize;
u32 indexBufferSize;
};
bool updateVertexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer);
bool updateIndexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer);
//! updates hardware buffer if needed
virtual bool updateHardwareBuffer(SHWBufferLink *HWBuffer);
//! Create hardware buffer from mesh
virtual SHWBufferLink *createHardwareBuffer(const scene::IMeshBuffer* mb);
//! Delete hardware buffer (only some drivers can)
virtual void deleteHardwareBuffer(SHWBufferLink *HWBuffer);
//! Draw hardware buffer
virtual void drawHardwareBuffer(SHWBufferLink *HWBuffer);
//! draws a vertex primitive list
virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const u16* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType);
@ -309,3 +335,5 @@ namespace video
#endif // __C_VIDEO_DIRECTX_8_H_INCLUDED__