Ok! Also hier wird der Thread und die Pipe erstellt:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
|
//Pipe erstellen
if(!(::CreatePipe(&m_hPipeR, &m_hPipeW, NULL, NULL)))
OG_ERROR(L"Pipe konnte nicht erstellt werden", OG_ERROR);
//Thread erstellen
m_iQueueLength = 0;
m_hThread = ::CreateThread(NULL, 0, TextureLoadingThread, &m_hPipeR, 0, &m_dwThreadID);
::SetThreadPriority(m_hThread, THREAD_PRIORITY_NORMAL);
|
Wenn ein neuer Auftrag reinkommt, wird jener in die Pipe geschrieben:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
ogResult CCache::LoadTexture(const UINT iSector, const UINT iLOD, IDirect3DTexture9** ppTexPointer)
{
if(!m_bActive) return OG_CANCEL;
//Im Falle von Vorausladen, ist der Texture-Pointer gleich NULL, dann wird direkt
//in das 2D-Texture-Array geladen: Also für den Thread entspricht das einem
//ppTexPointer von &(m_pppTextures[iSector][iLOD]);
if(ppTexPointer)
{
//Wenn die Texture bereits geladen worden ist, direkt richtigen Pointer einsetzten
if(m_pppTextures[iSector][iLOD])
{
*ppTexPointer = m_pppTextures[iSector][iLOD];
return OG_OK;
}
//Zwischenzeitlich niederauflösende Texture laden
*ppTexPointer = m_pppTextures[iSector][m_iStdLOD];
}
else
{
//Wenn schon geladen, dann abbrechen, sonst Texture einfach vorrausladen!
if(m_pppTextures[iSector][iLOD]) return OG_OK;
else ppTexPointer = &(m_pppTextures[iSector][iLOD]);
}
//Über PIPE den Auftrag speichern... (APPENDING)
DWORD dwBytesWritten = 0;
SPipePackage Data = SPipePackage(iSector, iLOD, ppTexPointer);
if(!(::WriteFile(m_hPipeW, &Data, sizeof(SPipePackage), &dwBytesWritten, NULL)) ||
(dwBytesWritten != sizeof(SPipePackage)))
{
OG_ERROR(L"Daten konnten nicht in die Pipe geschrieben werden!", OG_ERROR);
}
++m_iQueueLength;
return OG_OK;
}
|
m_pppTextures ist ein 2D-Array mit TexturePointern, wobei gilt: [SektorAufDerMap][LOD_Stufe], höchste LOD ist 0, niederste zugleich auch StdLOD = 3!
==============================================
Wenn alle Aufträge abgeliefert worden sind, wird diese Funktion aufgerufen, sie startet ev. den Thread:
|
C-/C++-Quelltext
|
1
2
3
4
5
|
void WorkDownQueue()
{
//Einfach den Thread starten, wenn Aufträge vorhanden
if(m_iQueueLength > 0) ::ResumeThread(m_hThread);
}
|
==============================================
Und dies hier ist der Thread selbst!
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
//LoadingThread
DWORD WINAPI TextureLoadingThread(void* pParam)
{
const bool bDebugOutput = true;
HANDLE hPipe = *(static_cast<HANDLE*>(pParam));
SPipePackage aData[500];
wchar_t awcMainPath[256] = L"data\\textures\\planet1\\";
while(true)
{
//Thread stoppen (solange nichts zu tun ist, soll er keine Performance rauben!)
if(CCache::Instance().m_iQueueLength <= 0) ::SuspendThread(CCache::Instance().m_hThread);
//Zwischenspeichern
const UINT iRecordCount = CCache::Instance().m_iQueueLength;
//Zuviele Records?
if(iRecordCount > 500)
{
OG_WARNING(L"Zu viele Aufträge in der Queue, werden einfach ignoriert!");
CCache::Instance().m_iQueueLength = 0;
continue;
}
//Thread wurde wieder gestartet --> Pipe auslesen
DWORD dwBytesRead = 0;
DWORD dwDataSize = sizeof(SPipePackage) * iRecordCount;
if(!(::ReadFile(hPipe, aData, dwDataSize, &dwBytesRead, NULL)) || (dwBytesRead != dwDataSize))
{
OG_WARNING(L"Pipe konnte nicht ausgelesen werden! Queue wird auf 0 gesetzt");
CCache::Instance().m_iQueueLength = 0;
continue;
}
//Alle Texturen nacheinander laden
HRESULT hResult;
for(UINT i = 0; i < iRecordCount; ++i)
{
if(!(aData[i].ppTexPointer))
{
OG_WARNING(L"Achtung! NULL-Pointer zum Texture-laden! Überspringe!");
continue;
}
//Texture schon geladen?
if(CCache::Instance().m_pppTextures[aData[i].iSector][aData[i].iLOD])
{
*(aData[i].ppTexPointer) = CCache::Instance().m_pppTextures[aData[i].iSector][aData[i].iLOD];
continue;
}
//Dateinamen zusammenstellen
wchar_t awcFileName[256] = L"";
if(aData[i].iLOD != 0)
::swprintf_s(awcFileName, 255, L"%sCache\\%d_%d.png", awcMainPath, (aData[i].iSector + 1), aData[i].iLOD);
else
::swprintf_s(awcFileName, 255, L"%s%d.png", awcMainPath, (aData[i].iSector + 1));
//Texture laden
if(FAILED(hResult = D3DXCreateTextureFromFileExW(ogDirect3D::Instance().GetD3DDevice(),
awcFileName,
D3DX_DEFAULT,
D3DX_DEFAULT,
1,
0,
D3DFMT_UNKNOWN,
D3DPOOL_MANAGED,
D3DX_DEFAULT,
D3DX_DEFAULT,
NULL,
NULL,
NULL,
&(CCache::Instance().m_pppTextures[aData[i].iSector][aData[i].iLOD]))))
{
//Fehler
OG_ERROR_DIRECTX(L"D3DXCreateTextureFromFileEx()", hResult, OG_ERROR);
}
//TexturePointer kopieren (zur Verfügung stellen)
*(aData[i].ppTexPointer) = CCache::Instance().m_pppTextures[aData[i].iSector][aData[i].iLOD];
}
//Queue länge um abgearbeitete Recs kürzen
CCache::Instance().m_iQueueLength -= iRecordCount;
} //while(true)
return 0;
}
|
==============================================
Wenn eine Texture eines bestimmten Sektors wieder freigegeben werden soll, wird das so gemacht:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
//Texture wieder freigeben
ogResult CCache::UnloadTexture(const UINT iSector, const UINT iLOD, IDirect3DTexture9** ppTexPointer)
{
if(((*ppTexPointer) == NULL) || (iLOD == m_iStdLOD))
{
//Auf Std Texture setzten
(*ppTexPointer) = m_pppTextures[iSector][m_iStdLOD];
return OG_OK; //StdLOD kann NICHT freigegeben werden
}
//Texture freigeben
OG_SAFE_RELEASE(m_pppTextures[iSector][iLOD]);
//Auf Std Texture setzten
(*ppTexPointer) = m_pppTextures[iSector][m_iStdLOD];
return OG_OK;
}
//ODER
ogResult CCache::UnloadAllSectorTexture(const UINT iSector, IDirect3DTexture9** ppTexPointer)
{
//Auf STd setzten
(*ppTexPointer) = m_pppTextures[iSector][m_iStdLOD];
//Alle Tex dieses Sektors freigeben
for(UINT i = 0; i < m_iStdLOD; ++i)
{
OG_SAFE_RELEASE(m_pppTextures[iSector][i]);
}
return OG_OK;
}
|