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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
|
/*
* Copyright 2011-2019 Branimir Karadzic. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/
#ifndef BGFX_RENDERER_D3D9_H_HEADER_GUARD
#define BGFX_RENDERER_D3D9_H_HEADER_GUARD
#define BGFX_CONFIG_RENDERER_DIRECT3D9EX BX_PLATFORM_WINDOWS
#if BX_PLATFORM_WINDOWS
# include <sal.h>
# include <d3d9.h>
#endif // BX_PLATFORM_
#ifndef D3DSTREAMSOURCE_INDEXEDDATA
# define D3DSTREAMSOURCE_INDEXEDDATA (1<<30)
#endif// D3DSTREAMSOURCE_INDEXEDDATA
#ifndef D3DSTREAMSOURCE_INSTANCEDATA
# define D3DSTREAMSOURCE_INSTANCEDATA (2<<30)
#endif // D3DSTREAMSOURCE_INSTANCEDATA
#include "renderer.h"
#include "renderer_d3d.h"
#include "nvapi.h"
#define BGFX_D3D9_PROFILER_BEGIN(_view, _abgr) \
BX_MACRO_BLOCK_BEGIN \
PIX_BEGINEVENT(_abgr, s_viewNameW[_view]); \
BGFX_PROFILER_BEGIN(s_viewName[view], _abgr); \
BX_MACRO_BLOCK_END
#define BGFX_D3D9_PROFILER_BEGIN_LITERAL(_name, _abgr) \
BX_MACRO_BLOCK_BEGIN \
PIX_BEGINEVENT(_abgr, L"" # _name); \
BGFX_PROFILER_BEGIN_LITERAL("" # _name, _abgr); \
BX_MACRO_BLOCK_END
#define BGFX_D3D9_PROFILER_END() \
BX_MACRO_BLOCK_BEGIN \
BGFX_PROFILER_END(); \
PIX_ENDEVENT(); \
BX_MACRO_BLOCK_END
namespace bgfx { namespace d3d9
{
# if defined(D3D_DISABLE_9EX)
# define D3DFMT_S8_LOCKABLE D3DFORMAT( 85)
# define D3DFMT_A1 D3DFORMAT(118)
# endif // defined(D3D_DISABLE_9EX)
# ifndef D3DFMT_ATI1
# define D3DFMT_ATI1 ( (D3DFORMAT)BX_MAKEFOURCC('A', 'T', 'I', '1') )
# endif // D3DFMT_ATI1
# ifndef D3DFMT_ATI2
# define D3DFMT_ATI2 ( (D3DFORMAT)BX_MAKEFOURCC('A', 'T', 'I', '2') )
# endif // D3DFMT_ATI2
# ifndef D3DFMT_ATOC
# define D3DFMT_ATOC ( (D3DFORMAT)BX_MAKEFOURCC('A', 'T', 'O', 'C') )
# endif // D3DFMT_ATOC
# ifndef D3DFMT_DF16
# define D3DFMT_DF16 ( (D3DFORMAT)BX_MAKEFOURCC('D', 'F', '1', '6') )
# endif // D3DFMT_DF16
# ifndef D3DFMT_DF24
# define D3DFMT_DF24 ( (D3DFORMAT)BX_MAKEFOURCC('D', 'F', '2', '4') )
# endif // D3DFMT_DF24
# ifndef D3DFMT_INST
# define D3DFMT_INST ( (D3DFORMAT)BX_MAKEFOURCC('I', 'N', 'S', 'T') )
# endif // D3DFMT_INST
# ifndef D3DFMT_INTZ
# define D3DFMT_INTZ ( (D3DFORMAT)BX_MAKEFOURCC('I', 'N', 'T', 'Z') )
# endif // D3DFMT_INTZ
# ifndef D3DFMT_NULL
# define D3DFMT_NULL ( (D3DFORMAT)BX_MAKEFOURCC('N', 'U', 'L', 'L') )
# endif // D3DFMT_NULL
# ifndef D3DFMT_RESZ
# define D3DFMT_RESZ ( (D3DFORMAT)BX_MAKEFOURCC('R', 'E', 'S', 'Z') )
# endif // D3DFMT_RESZ
# ifndef D3DFMT_RAWZ
# define D3DFMT_RAWZ ( (D3DFORMAT)BX_MAKEFOURCC('R', 'A', 'W', 'Z') )
# endif // D3DFMT_RAWZ
# ifndef D3DFMT_S8_LOCKABLE
# define D3DFMT_S8_LOCKABLE ( (D3DFORMAT)85)
# endif // D3DFMT_S8_LOCKABLE
# ifndef D3DFMT_A1
# define D3DFMT_A1 ( (D3DFORMAT)118)
# endif // D3DFMT_A1
struct ExtendedFormat
{
enum Enum
{
Ati1,
Ati2,
Df16,
Df24,
Inst,
Intz,
Null,
Resz,
Rawz,
Atoc,
Count,
};
D3DFORMAT m_fmt;
DWORD m_usage;
D3DRESOURCETYPE m_type;
bool m_supported;
};
struct Msaa
{
D3DMULTISAMPLE_TYPE m_type;
DWORD m_quality;
};
struct IndexBufferD3D9
{
IndexBufferD3D9()
: m_ptr(NULL)
, m_dynamic(NULL)
, m_size(0)
, m_flags(BGFX_BUFFER_NONE)
{
}
void create(uint32_t _size, void* _data, uint16_t _flags);
void update(uint32_t _offset, uint32_t _size, void* _data, bool _discard = false)
{
if (NULL != m_dynamic
&& _data != m_dynamic)
{
bx::memCopy(&m_dynamic[_offset], _data, _size);
}
void* buffer;
DX_CHECK(m_ptr->Lock(_offset
, _size
, &buffer
, _discard || (m_dynamic && 0 == _offset && m_size == _size) ? D3DLOCK_DISCARD : 0
) );
bx::memCopy(buffer, _data, _size);
DX_CHECK(m_ptr->Unlock() );
}
void destroy()
{
if (NULL != m_ptr)
{
DX_RELEASE(m_ptr, 0);
if (NULL != m_dynamic)
{
BX_FREE(g_allocator, m_dynamic);
m_dynamic = NULL;
}
}
}
void preReset();
void postReset();
IDirect3DIndexBuffer9* m_ptr;
uint8_t* m_dynamic;
uint32_t m_size;
uint16_t m_flags;
};
struct VertexBufferD3D9
{
VertexBufferD3D9()
: m_ptr(NULL)
, m_dynamic(NULL)
, m_size(0)
{
}
void create(uint32_t _size, void* _data, VertexLayoutHandle _layoutHandle);
void update(uint32_t _offset, uint32_t _size, void* _data, bool _discard = false)
{
if (NULL != m_dynamic
&& _data != m_dynamic)
{
bx::memCopy(&m_dynamic[_offset], _data, _size);
}
void* buffer;
DX_CHECK(m_ptr->Lock(_offset
, _size
, &buffer
, _discard || (m_dynamic && 0 == _offset && m_size == _size) ? D3DLOCK_DISCARD : 0
) );
bx::memCopy(buffer, _data, _size);
DX_CHECK(m_ptr->Unlock() );
}
void destroy()
{
if (NULL != m_ptr)
{
DX_RELEASE(m_ptr, 0);
if (NULL != m_dynamic)
{
BX_FREE(g_allocator, m_dynamic);
m_dynamic = NULL;
}
}
}
void preReset();
void postReset();
IDirect3DVertexBuffer9* m_ptr;
uint8_t* m_dynamic;
uint32_t m_size;
VertexLayoutHandle m_layoutHandle;
};
struct ShaderD3D9
{
ShaderD3D9()
: m_vertexShader(NULL)
, m_constantBuffer(NULL)
, m_numPredefined(0)
, m_type(0)
{
}
void create(const Memory* _mem);
void destroy()
{
if (NULL != m_constantBuffer)
{
UniformBuffer::destroy(m_constantBuffer);
m_constantBuffer = NULL;
}
m_numPredefined = 0;
switch (m_type)
{
case 0: DX_RELEASE(m_vertexShader, 0); BX_FALLTHROUGH;
default: DX_RELEASE(m_pixelShader, 0);
}
}
union
{
// X360 doesn't have interface inheritance (can't use IUnknown*).
IDirect3DVertexShader9* m_vertexShader;
IDirect3DPixelShader9* m_pixelShader;
};
UniformBuffer* m_constantBuffer;
PredefinedUniform m_predefined[PredefinedUniform::Count];
uint8_t m_numPredefined;
uint8_t m_type;
};
struct ProgramD3D9
{
void create(const ShaderD3D9* _vsh, const ShaderD3D9* _fsh)
{
m_vsh = _vsh;
m_fsh = _fsh;
bx::memCopy(&m_predefined[0], _vsh->m_predefined, _vsh->m_numPredefined*sizeof(PredefinedUniform) );
m_numPredefined = _vsh->m_numPredefined;
if (NULL != _fsh)
{
bx::memCopy(&m_predefined[_vsh->m_numPredefined], _fsh->m_predefined, _fsh->m_numPredefined*sizeof(PredefinedUniform) );
m_numPredefined += _fsh->m_numPredefined;
}
}
void destroy()
{
m_numPredefined = 0;
m_vsh = NULL;
m_fsh = NULL;
}
const ShaderD3D9* m_vsh;
const ShaderD3D9* m_fsh;
PredefinedUniform m_predefined[PredefinedUniform::Count*2];
uint8_t m_numPredefined;
};
struct TextureD3D9
{
enum Enum
{
Texture2D,
Texture3D,
TextureCube,
};
TextureD3D9()
: m_ptr(NULL)
, m_surface(NULL)
, m_staging(NULL)
, m_textureFormat(TextureFormat::Unknown)
{
}
void createTexture(uint32_t _width, uint32_t _height, uint8_t _numMips);
void createVolumeTexture(uint32_t _width, uint32_t _height, uint32_t _depth, uint8_t _numMips);
void createCubeTexture(uint32_t _width, uint8_t _numMips);
uint8_t* lock(uint8_t _side, uint8_t _lod, uint32_t& _pitch, uint32_t& _slicePitch, const Rect* _rect = NULL);
void unlock(uint8_t _side, uint8_t _lod);
void dirty(uint8_t _side, const Rect& _rect, uint16_t _z, uint16_t _depth);
IDirect3DSurface9* getSurface(uint8_t _side = 0, uint8_t _mip = 0) const;
void create(const Memory* _mem, uint64_t _flags, uint8_t _skip);
void destroy(bool _resize = false)
{
if (0 == (m_flags & BGFX_SAMPLER_INTERNAL_SHARED) )
{
if (_resize)
{
// BK - at the time of resize there might be one reference held by frame buffer
// surface. This frame buffer will be recreated later, and release reference
// to existing surface. That's why here we don't care about ref count.
m_ptr->Release();
}
else
{
DX_RELEASE(m_ptr, 0);
}
}
DX_RELEASE(m_surface, 0);
DX_RELEASE(m_staging, 0);
m_textureFormat = TextureFormat::Unknown;
}
void overrideInternal(uintptr_t _ptr)
{
destroy();
m_flags |= BGFX_SAMPLER_INTERNAL_SHARED;
m_ptr = (IDirect3DBaseTexture9*)_ptr;
}
void updateBegin(uint8_t _side, uint8_t _mip);
void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem);
void updateEnd();
void commit(uint8_t _stage, uint32_t _flags, const float _palette[][4]);
void resolve(uint8_t _resolve) const;
void preReset();
void postReset();
union
{
IDirect3DBaseTexture9* m_ptr;
IDirect3DTexture9* m_texture2d;
IDirect3DVolumeTexture9* m_texture3d;
IDirect3DCubeTexture9* m_textureCube;
};
IDirect3DSurface9* m_surface;
union
{
IDirect3DBaseTexture9* m_staging;
IDirect3DTexture9* m_staging2d;
IDirect3DVolumeTexture9* m_staging3d;
IDirect3DCubeTexture9* m_stagingCube;
};
uint64_t m_flags;
uint32_t m_width;
uint32_t m_height;
uint32_t m_depth;
uint8_t m_numMips;
uint8_t m_type;
uint8_t m_requestedFormat;
uint8_t m_textureFormat;
};
struct FrameBufferD3D9
{
FrameBufferD3D9()
: m_hwnd(NULL)
, m_denseIdx(UINT16_MAX)
, m_num(0)
, m_numTh(0)
, m_dsIdx(UINT8_MAX)
, m_needResolve(false)
, m_needPresent(false)
{
}
void create(uint8_t _num, const Attachment* _attachment);
void create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat);
uint16_t destroy();
HRESULT present();
void resolve() const;
void preReset();
void postReset();
void createNullColorRT();
void set();
IDirect3DSurface9* m_surface[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1];
IDirect3DSwapChain9* m_swapChain;
HWND m_hwnd;
uint32_t m_width;
uint32_t m_height;
Attachment m_attachment[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS];
uint16_t m_denseIdx;
uint8_t m_num;
uint8_t m_numTh;
uint8_t m_dsIdx;
bool m_needResolve;
bool m_needPresent;
};
struct TimerQueryD3D9
{
TimerQueryD3D9()
: m_control(BX_COUNTOF(m_query) )
{
}
void postReset();
void preReset();
uint32_t begin(uint32_t _resultIdx);
void end(uint32_t _idx);
bool update();
struct Query
{
IDirect3DQuery9* m_disjoint;
IDirect3DQuery9* m_begin;
IDirect3DQuery9* m_end;
IDirect3DQuery9* m_freq;
uint32_t m_resultIdx;
bool m_ready;
};
struct Result
{
void reset()
{
m_begin = 0;
m_end = 0;
m_frequency = 1;
m_pending = 0;
}
uint64_t m_begin;
uint64_t m_end;
uint64_t m_frequency;
uint32_t m_pending;
};
Result m_result[BGFX_CONFIG_MAX_VIEWS+1];
Query m_query[BGFX_CONFIG_MAX_VIEWS*4];
bx::RingBufferControl m_control;
};
struct OcclusionQueryD3D9
{
OcclusionQueryD3D9()
: m_control(BX_COUNTOF(m_query) )
{
}
void postReset();
void preReset();
void begin(Frame* _render, OcclusionQueryHandle _handle);
void end();
void resolve(Frame* _render, bool _wait = false);
void invalidate(OcclusionQueryHandle _handle);
struct Query
{
IDirect3DQuery9* m_ptr;
OcclusionQueryHandle m_handle;
};
Query m_query[BGFX_CONFIG_MAX_OCCLUSION_QUERIES];
bx::RingBufferControl m_control;
};
} /* namespace d3d9 */ } // namespace bgfx
#endif // BGFX_RENDERER_D3D9_H_HEADER_GUARD
|