Files
Leviathan/Client/Game/engine/Renderer/KResourceDXDynamic.cpp
T
2026-06-01 12:46:52 +02:00

401 lines
10 KiB
C++

#include "stdafx.h"
/*
KResourceDXDynamic.cpp
Software processing용 vertex buffer
Note: Resource는 아니지만 인터페이스 통일을 위해 상속함
Created 2006/04, by JiYoung
*/
#include "KResourceDXDynamic.h"
#include "KDeviceManager.h"
namespace {
// Vertex buffer creation 등등등용으로, 현재의 global rendering device를 얻어옴
K3DRenderDeviceDX * renderDevice = NULL;
K3DRenderDeviceDX *getCurrentRenderDevice()
{
/* if (renderDevice==NULL) {
renderDevice = (K3DRenderDeviceDX *)KDeviceManagerDX::GetDeviceManager()->GetRenderDevice();
}
return renderDevice;
*/ return (K3DRenderDeviceDX *)KDeviceManagerDX::GetDeviceManager()->GetRenderDevice();
}
}
//-------------------------------------------
// DynamicVertex vertex format declaration
//-------------------------------------------
/*
const D3DVERTEXELEMENT9 DynamicVertex_old::vertexDeclaration[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT3 , D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION , 0 },//size=12
{ 0, 12, D3DDECLTYPE_FLOAT3 , D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL , 0 },//size=12
{ 0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR , 0 },//size=4
{ 0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR , 1 },//size=4
{ 0, 32, D3DDECLTYPE_FLOAT2 , D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD , 0 },//size=8
{ 0, 40, D3DDECLTYPE_FLOAT2 , D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD , 1 },//size=8
{ 0, 48, D3DDECLTYPE_FLOAT2 , D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD , 2 },//size=8
{ 0, 56, D3DDECLTYPE_FLOAT2 , D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD , 3 },//size=8
D3DDECL_END()
};
*/
const D3DVERTEXELEMENT9 DynamicVertex::vertexDeclaration[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT3 , D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION , 0 },//size=12
{ 0, 12, D3DDECLTYPE_FLOAT3 , D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL , 0 },//size=12
{ 0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR , 0 },//size=4
{ 0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR , 1 },//size=4
{ 0, 32, D3DDECLTYPE_FLOAT2 , D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD , 0 },//size=8
{ 0, 40, D3DDECLTYPE_FLOAT2 , D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD , 1 },//size=8
{ 0, 48, D3DDECLTYPE_UBYTE4 , D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES , 0 },//size=4
{ 0, 52, D3DDECLTYPE_FLOAT3 , D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT , 0 },//size=12
D3DDECL_END()
};
//-------------------------------------------
// Vertex Buffer
//-------------------------------------------
KVertexBufferDX_dynamic::KVertexBufferDX_dynamic() : K3DVertexBufferDX()
{
m_bUseRecycle = false;
m_bufferSize=0;
vertexBuffer=NULL;
m_autoDataPreserve=false; // Device lost시 reload()되는 경우, 버퍼의 데이터를 자동으로 refresh한다
m_pDataPreserveBuffer=NULL; // m_autoDataPreserver==true인 경우 Lock()/Unlock()시에 여기다 데이터를 dump한다
m_pLockedPosition=NULL; // Lock()시 ppBuf에 return한 pointer. i.e. !=NULL이면 Lock()된 상태이다. Unlock()에서 NULL로 reset한다
m_bHaveToReloadBuffer=false;
}
KVertexBufferDX_dynamic::~KVertexBufferDX_dynamic()
{
clear();
}
// Inherited
void KVertexBufferDX_dynamic::Lock( void** ppBuf, int& size, DWORD flags)
{
assert(m_pLockedPosition==NULL); // 두 번 lock방지
if (vertexBuffer==NULL) {
*ppBuf=NULL;
return;
}
if ( FAILED( vertexBuffer->Lock( 0, size, ppBuf, flags ) ) ) {
*ppBuf=NULL;
return;
}
m_pLockedPosition=*ppBuf;
}
void KVertexBufferDX_dynamic::Unlock()
{
if (m_pLockedPosition==NULL) return; // Not locked
if (vertexBuffer!=NULL) {
vertexBuffer->Unlock();
if (m_autoDataPreserve) {
assert(m_pDataPreserveBuffer!=NULL);
// Copy buffer
memcpy(m_pDataPreserveBuffer, m_pLockedPosition, (size_t)m_bufferSize);
}
m_pLockedPosition=NULL;
}
}
bool KVertexBufferDX_dynamic::Reload()
{
K3DRenderDeviceDX *device=getCurrentRenderDevice();
if (device==NULL) return false;
if( FAILED( device->GetD3DDevice()->CreateVertexBuffer( m_bufferSize, m_usage, m_format, m_Pool, &vertexBuffer, NULL))) {
return false;
}
m_d3dvb=vertexBuffer;
if (m_autoDataPreserve) {
// Autopreserve buffer에서 데이터를 카피
void *pBuf;
int size=0;
Lock(&pBuf, size);
if (pBuf!=NULL) {
memcpy(pBuf, m_pDataPreserveBuffer, (size_t)m_bufferSize);
}
Unlock();
} else {
// Reload flag설정
m_bHaveToReloadBuffer=true;
}
return true;
}
bool KVertexBufferDX_dynamic::PreReload()
{
m_d3dvb = NULL;
// Note : m_d3dvb는 dynamic-vertex-buffer에서는 managed resource가 아니다. So just set to NULL.
// SAFE_RELEASE(m_d3dvb); // <- 이거 하면 큰일남 :)
if (vertexBuffer!=NULL) {
vertexBuffer->Release();
vertexBuffer=NULL;
}
return true;
}
// original
bool KVertexBufferDX_dynamic::create(UINT length, DWORD usage, DWORD FVF, D3DPOOL pool, bool autoPreserve) // See IDirect3DDevice9::CreateVertexBuffer() for parameters
{
//clear();
m_d3dvb=NULL;
if (vertexBuffer!=NULL) {
vertexBuffer->Release();
vertexBuffer=NULL;
}
K3DRenderDeviceDX *device=getCurrentRenderDevice();
if (device==NULL) return false;
if( FAILED( device->GetD3DDevice()->CreateVertexBuffer( length, usage, FVF, pool, &vertexBuffer, NULL))) {
return false;
}
m_bufferSize=length;
m_usage = usage;
m_format = FVF;
m_vtxStride = K3DVertexBuffer::CalcVertexStride( m_format );
m_vtxCount = length/sizeof(DynamicVertex);
m_Pool = pool;
// WORKAROUND : m_d3dvb는 리소스이지만, 이게 세팅되어 있지 않으면 렌더링이 안 된다
// 나중에 RELEASE()하지 말고 그냥 NULL세팅할 것
m_d3dvb=vertexBuffer;
// DeviceLost용 callback
device->AddLostVertexBuffer( this );
// Autopreserve buffer
if (autoPreserve) {
m_pDataPreserveBuffer=new char[m_bufferSize];
m_autoDataPreserve=true;
}
return true;
}
bool KVertexBufferDX_dynamic::clear() // Release();
{
K3DRenderDeviceDX *device=getCurrentRenderDevice();
if (device)
{
// DeviceLost용 callback chain에서 삭제
device->RemoveLostVertexBuffer( this );
}
// Free the vertex buffer
m_d3dvb=NULL;
if (vertexBuffer!=NULL) {
vertexBuffer->Release();
vertexBuffer=NULL;
}
// Free the AutoPreserve buffer
SAFE_DELETE(m_pDataPreserveBuffer);
m_autoDataPreserve=false;
m_pLockedPosition=NULL;
m_bHaveToReloadBuffer=false;
return true;
}
//-------------------------------------------
// Index Buffer
//-------------------------------------------
KIndexBufferDX_dynamic::KIndexBufferDX_dynamic() : K3DIndexBufferDX(NULL)
{
m_bufferSize=0;
indexBuffer=NULL;
m_autoDataPreserve=false; // Device lost시 reload()되는 경우, 버퍼의 데이터를 자동으로 refresh한다
m_pDataPreserveBuffer=NULL; // m_autoDataPreserver==true인 경우 Lock()/Unlock()시에 여기다 데이터를 dump한다
m_pLockedPosition=NULL; // Lock()시 ppBuf에 return한 pointer. i.e. !=NULL이면 Lock()된 상태이다. Unlock()에서 NULL로 reset한다
m_bHaveToReloadBuffer=false;
}
KIndexBufferDX_dynamic::~KIndexBufferDX_dynamic()
{
clear();
}
// Inherited
void KIndexBufferDX_dynamic::Lock( void** ppBuf, int& size, DWORD flags )
{
if (indexBuffer==NULL) {
*ppBuf=NULL;
return;
}
if ( FAILED( indexBuffer->Lock( 0, size, ppBuf, flags ) ) ) {
*ppBuf=NULL;
return;
}
m_pLockedPosition=*ppBuf;
}
void KIndexBufferDX_dynamic::Unlock()
{
if (m_pLockedPosition==NULL) return; // Not locked
if (indexBuffer!=NULL) {
indexBuffer->Unlock();
if (m_autoDataPreserve) {
assert(m_pDataPreserveBuffer!=NULL);
// Copy buffer
memcpy(m_pDataPreserveBuffer, m_pLockedPosition, (size_t)m_bufferSize);
}
m_pLockedPosition=NULL;
}
}
bool KIndexBufferDX_dynamic::Reload()
{
K3DRenderDeviceDX *device=getCurrentRenderDevice();
if (device==NULL) return false;
if( FAILED( device->GetD3DDevice()->CreateIndexBuffer( m_bufferSize, m_usage, (D3DFORMAT)m_format, m_Pool, &indexBuffer, NULL))) {
return false;
}
m_d3dib=indexBuffer;
if (m_autoDataPreserve) {
// Autopreserve buffer에서 데이터를 카피
void *pBuf;
int size=0;
Lock(&pBuf, size);
if (pBuf!=NULL) {
memcpy(pBuf, m_pDataPreserveBuffer, (size_t)m_bufferSize);
}
Unlock();
} else {
// Reload flag설정
m_bHaveToReloadBuffer=true;
}
return true;
}
bool KIndexBufferDX_dynamic::PreReload()
{
m_d3dib=NULL;
// Note : m_d3dib는 dynamic-indextex-buffer에서는 managed resource가 아니다. So just set to NULL.
// SAFE_RELEASE(m_d3dib); // <- 이거 하면 큰일남 :)
if (indexBuffer!=NULL) {
indexBuffer->Release();
indexBuffer=NULL;
}
return true;
}
// original
bool KIndexBufferDX_dynamic::create(UINT length, DWORD usage, D3DFORMAT format, D3DPOOL pool, bool autoPreserve) // See IDirect3DDevice9::CreateIndexBuffer() for parameters
{
// clear();
m_d3dib=NULL;
if (indexBuffer!=NULL) {
indexBuffer->Release();
indexBuffer=NULL;
}
K3DRenderDeviceDX *device=getCurrentRenderDevice();
if (device==NULL) return false;
if( FAILED( device->GetD3DDevice()->CreateIndexBuffer( length, usage, format, pool, &indexBuffer, NULL))) {
return false;
}
m_bufferSize= length;
m_vtxStride = sizeof(DWORD);
m_idxCount = length/sizeof(DWORD);
m_format = static_cast<K3DFORMAT>(format);
m_usage = usage;
m_Pool = pool;
// WORKAROUND : m_d3dib는 리소스이지만, 이게 세팅되어 있지 않으면 렌더링이 안 된다
// 나중에 RELEASE()하지 말고 그냥 NULL세팅할 것
m_d3dib=indexBuffer;
//DeviceLost용 callback chain에 register
device->AddLostIndexBuffer( this );
// Autopreserve buffer
if (autoPreserve) {
m_pDataPreserveBuffer=new char[m_bufferSize];
m_autoDataPreserve=true;
}
return true;
}
bool KIndexBufferDX_dynamic::clear() // Release();
{
K3DRenderDeviceDX *device=getCurrentRenderDevice();
if (device)
{
//DeviceLost용 callback chain에서 삭제
device->RemoveLostIndexBuffer( this );
}
m_d3dib=NULL;
if (indexBuffer!=NULL) {
indexBuffer->Release();
indexBuffer=NULL;
}
// Free the AutoPreserve buffer
SAFE_DELETE(m_pDataPreserveBuffer);
m_autoDataPreserve=false;
m_pLockedPosition=NULL;
m_bHaveToReloadBuffer=false;
return true;
}