mirror of https://github.com/mamedev/mame.git
582 lines
15 KiB
C++
582 lines
15 KiB
C++
/*
|
|
* Copyright 2011-2022 Branimir Karadzic. All rights reserved.
|
|
* License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
|
|
*/
|
|
|
|
#ifndef BGFX_RENDERER_D3D12_H_HEADER_GUARD
|
|
#define BGFX_RENDERER_D3D12_H_HEADER_GUARD
|
|
|
|
#define USE_D3D12_DYNAMIC_LIB (BX_PLATFORM_WINDOWS || BX_PLATFORM_LINUX)
|
|
|
|
#include <sal.h>
|
|
#include <unknwn.h>
|
|
|
|
#if BX_PLATFORM_LINUX || BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT
|
|
# include <d3d12.h>
|
|
#else
|
|
# if !BGFX_CONFIG_DEBUG
|
|
# define D3DCOMPILE_NO_DEBUG 1
|
|
# endif // !BGFX_CONFIG_DEBUG
|
|
# include <d3d12_x.h>
|
|
#endif // BX_PLATFORM_XBOXONE
|
|
|
|
#if defined(__MINGW32__) // BK - temp workaround for MinGW until I nuke d3dx12 usage.
|
|
extern "C++" {
|
|
# if defined(__cpp_constexpr) && __cpp_constexpr >= 200704L \
|
|
&& defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L
|
|
__extension__ template<typename Ty>
|
|
constexpr const GUID& __mingw_uuidof();
|
|
# else
|
|
__extension__ template<typename Ty>
|
|
const GUID& __mingw_uuidof();
|
|
# endif // __cpp_*
|
|
|
|
template<>
|
|
const GUID& __mingw_uuidof<ID3D12Device>()
|
|
{
|
|
static const GUID IID_ID3D12Device0 = { 0x189819f1, 0x1db6, 0x4b57, { 0xbe, 0x54, 0x18, 0x21, 0x33, 0x9b, 0x85, 0xf7 } };
|
|
return IID_ID3D12Device0;
|
|
}
|
|
}
|
|
#endif // defined(__MINGW32__)
|
|
|
|
#include "renderer.h"
|
|
#include "renderer_d3d.h"
|
|
#include "shader_dxbc.h"
|
|
#include "debug_renderdoc.h"
|
|
#include "nvapi.h"
|
|
#include "dxgi.h"
|
|
|
|
#if BGFX_CONFIG_DEBUG_ANNOTATION && !BX_PLATFORM_LINUX
|
|
# if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT
|
|
typedef struct PIXEventsThreadInfo* (WINAPI* PFN_PIX_GET_THREAD_INFO)();
|
|
typedef uint64_t (WINAPI* PFN_PIX_EVENTS_REPLACE_BLOCK)(bool _getEarliestTime);
|
|
|
|
extern PFN_PIX_GET_THREAD_INFO bgfx_PIXGetThreadInfo;
|
|
extern PFN_PIX_EVENTS_REPLACE_BLOCK bgfx_PIXEventsReplaceBlock;
|
|
|
|
# define PIXGetThreadInfo bgfx_PIXGetThreadInfo
|
|
# define PIXEventsReplaceBlock bgfx_PIXEventsReplaceBlock
|
|
# else
|
|
extern "C" struct PIXEventsThreadInfo* WINAPI bgfx_PIXGetThreadInfo();
|
|
extern "C" uint64_t WINAPI bgfx_PIXEventsReplaceBlock(bool _getEarliestTime);
|
|
# endif // BX_PLATFORM_WINDOWS
|
|
|
|
# include <pix3.h>
|
|
|
|
# define _PIX3_BEGINEVENT(_commandList, _color, _name) PIXBeginEvent(_commandList, _color, _name)
|
|
# define _PIX3_SETMARKER(_commandList, _color, _name) PIXSetMarker(_commandList, _color, _name)
|
|
# define _PIX3_ENDEVENT(_commandList) PIXEndEvent(_commandList)
|
|
|
|
# define PIX3_BEGINEVENT(_commandList, _color, _name) _PIX3_BEGINEVENT(_commandList, _color, _name)
|
|
# define PIX3_SETMARKER(_commandList, _color, _name) _PIX3_SETMARKER(_commandList, _color, _name)
|
|
# define PIX3_ENDEVENT(_commandList) _PIX3_ENDEVENT(_commandList)
|
|
#else
|
|
# define PIX3_BEGINEVENT(_commandList, _color, _name) BX_UNUSED(_commandList, _color, _name)
|
|
# define PIX3_SETMARKER(_commandList, _color, _name) BX_UNUSED(_commandList, _color, _name)
|
|
# define PIX3_ENDEVENT(_commandList) BX_UNUSED(_commandList)
|
|
#endif // BGFX_CONFIG_DEBUG_ANNOTATION
|
|
|
|
#define BGFX_D3D12_PROFILER_BEGIN(_view, _abgr) \
|
|
BX_MACRO_BLOCK_BEGIN \
|
|
PIX3_BEGINEVENT(m_commandList, _abgr, s_viewName[_view]); \
|
|
BGFX_PROFILER_BEGIN(s_viewName[view], _abgr); \
|
|
BX_MACRO_BLOCK_END
|
|
|
|
#define BGFX_D3D12_PROFILER_BEGIN_LITERAL(_name, _abgr) \
|
|
BX_MACRO_BLOCK_BEGIN \
|
|
PIX3_BEGINEVENT(m_commandList, _abgr, "" _name); \
|
|
BGFX_PROFILER_BEGIN_LITERAL("" _name, _abgr); \
|
|
BX_MACRO_BLOCK_END
|
|
|
|
#define BGFX_D3D12_PROFILER_END() \
|
|
BX_MACRO_BLOCK_BEGIN \
|
|
BGFX_PROFILER_END(); \
|
|
PIX3_ENDEVENT(m_commandList); \
|
|
BX_MACRO_BLOCK_END
|
|
|
|
namespace bgfx { namespace d3d12
|
|
{
|
|
typedef HRESULT (WINAPI* PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES)(uint32_t _numFeatures, const IID* _iids, void* _configurationStructs, uint32_t* _configurationStructSizes);
|
|
|
|
struct Rdt
|
|
{
|
|
enum Enum
|
|
{
|
|
Sampler,
|
|
SRV,
|
|
CBV,
|
|
UAV,
|
|
|
|
Count
|
|
};
|
|
};
|
|
|
|
class ScratchBufferD3D12
|
|
{
|
|
public:
|
|
ScratchBufferD3D12()
|
|
{
|
|
}
|
|
|
|
~ScratchBufferD3D12()
|
|
{
|
|
}
|
|
|
|
void create(uint32_t _size, uint32_t _maxDescriptors);
|
|
void destroy();
|
|
void reset(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle);
|
|
|
|
void allocEmpty(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle);
|
|
|
|
void* allocCbv(D3D12_GPU_VIRTUAL_ADDRESS& _gpuAddress, uint32_t _size);
|
|
|
|
void allocSrv(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, struct TextureD3D12& _texture, uint8_t _mip = 0);
|
|
void allocSrv(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, struct BufferD3D12& _buffer);
|
|
|
|
void allocUav(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, struct TextureD3D12& _texture, uint8_t _mip = 0);
|
|
void allocUav(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, struct BufferD3D12& _buffer);
|
|
|
|
ID3D12DescriptorHeap* getHeap()
|
|
{
|
|
return m_heap;
|
|
}
|
|
|
|
private:
|
|
ID3D12DescriptorHeap* m_heap;
|
|
ID3D12Resource* m_upload;
|
|
D3D12_GPU_VIRTUAL_ADDRESS m_gpuVA;
|
|
D3D12_CPU_DESCRIPTOR_HANDLE m_cpuHandle;
|
|
D3D12_GPU_DESCRIPTOR_HANDLE m_gpuHandle;
|
|
uint32_t m_incrementSize;
|
|
uint8_t* m_data;
|
|
uint32_t m_size;
|
|
uint32_t m_pos;
|
|
};
|
|
|
|
class DescriptorAllocatorD3D12
|
|
{
|
|
public:
|
|
DescriptorAllocatorD3D12()
|
|
: m_numDescriptorsPerBlock(1)
|
|
{
|
|
}
|
|
|
|
~DescriptorAllocatorD3D12()
|
|
{
|
|
}
|
|
|
|
void create(D3D12_DESCRIPTOR_HEAP_TYPE _type, uint16_t _maxDescriptors, uint16_t _numDescriptorsPerBlock = 1);
|
|
void destroy();
|
|
|
|
uint16_t alloc(ID3D12Resource* _ptr, const D3D12_SHADER_RESOURCE_VIEW_DESC* _desc);
|
|
uint16_t alloc(const uint32_t* _flags, uint32_t _num, const float _palette[][4]);
|
|
void free(uint16_t _handle);
|
|
void reset();
|
|
|
|
D3D12_GPU_DESCRIPTOR_HANDLE get(uint16_t _handle);
|
|
|
|
ID3D12DescriptorHeap* getHeap()
|
|
{
|
|
return m_heap;
|
|
}
|
|
|
|
private:
|
|
ID3D12DescriptorHeap* m_heap;
|
|
bx::HandleAlloc* m_handleAlloc;
|
|
D3D12_CPU_DESCRIPTOR_HANDLE m_cpuHandle;
|
|
D3D12_GPU_DESCRIPTOR_HANDLE m_gpuHandle;
|
|
uint32_t m_incrementSize;
|
|
uint16_t m_numDescriptorsPerBlock;
|
|
};
|
|
|
|
struct BufferD3D12
|
|
{
|
|
BufferD3D12()
|
|
: m_ptr(NULL)
|
|
, m_state(D3D12_RESOURCE_STATE_COMMON)
|
|
, m_size(0)
|
|
, m_flags(BGFX_BUFFER_NONE)
|
|
, m_dynamic(false)
|
|
{
|
|
}
|
|
|
|
void create(uint32_t _size, void* _data, uint16_t _flags, bool _vertex, uint32_t _stride = 0);
|
|
void update(ID3D12GraphicsCommandList* _commandList, uint32_t _offset, uint32_t _size, void* _data, bool _discard = false);
|
|
void destroy();
|
|
|
|
D3D12_RESOURCE_STATES setState(ID3D12GraphicsCommandList* _commandList, D3D12_RESOURCE_STATES _state);
|
|
|
|
D3D12_SHADER_RESOURCE_VIEW_DESC m_srvd;
|
|
D3D12_UNORDERED_ACCESS_VIEW_DESC m_uavd;
|
|
ID3D12Resource* m_ptr;
|
|
D3D12_GPU_VIRTUAL_ADDRESS m_gpuVA;
|
|
D3D12_RESOURCE_STATES m_state;
|
|
uint32_t m_size;
|
|
uint16_t m_flags;
|
|
bool m_dynamic;
|
|
};
|
|
|
|
struct VertexBufferD3D12 : public BufferD3D12
|
|
{
|
|
void create(uint32_t _size, void* _data, VertexLayoutHandle _layoutHandle, uint16_t _flags);
|
|
|
|
VertexLayoutHandle m_layoutHandle;
|
|
};
|
|
|
|
struct ShaderD3D12
|
|
{
|
|
ShaderD3D12()
|
|
: m_code(NULL)
|
|
, m_constantBuffer(NULL)
|
|
, m_hash(0)
|
|
, m_numUniforms(0)
|
|
, m_numPredefined(0)
|
|
{
|
|
}
|
|
|
|
void create(const Memory* _mem);
|
|
|
|
void destroy()
|
|
{
|
|
if (NULL != m_constantBuffer)
|
|
{
|
|
UniformBuffer::destroy(m_constantBuffer);
|
|
m_constantBuffer = NULL;
|
|
}
|
|
|
|
m_numPredefined = 0;
|
|
|
|
if (NULL != m_code)
|
|
{
|
|
release(m_code);
|
|
m_code = NULL;
|
|
m_hash = 0;
|
|
}
|
|
}
|
|
|
|
const Memory* m_code;
|
|
UniformBuffer* m_constantBuffer;
|
|
|
|
PredefinedUniform m_predefined[PredefinedUniform::Count];
|
|
uint16_t m_attrMask[Attrib::Count];
|
|
|
|
uint32_t m_hash;
|
|
uint16_t m_numUniforms;
|
|
uint16_t m_size;
|
|
uint8_t m_numPredefined;
|
|
};
|
|
|
|
struct ProgramD3D12
|
|
{
|
|
ProgramD3D12()
|
|
: m_vsh(NULL)
|
|
, m_fsh(NULL)
|
|
{
|
|
}
|
|
|
|
void create(const ShaderD3D12* _vsh, const ShaderD3D12* _fsh)
|
|
{
|
|
BX_ASSERT(NULL != _vsh->m_code, "Vertex shader doesn't exist.");
|
|
m_vsh = _vsh;
|
|
bx::memCopy(&m_predefined[0], _vsh->m_predefined, _vsh->m_numPredefined*sizeof(PredefinedUniform));
|
|
m_numPredefined = _vsh->m_numPredefined;
|
|
|
|
if (NULL != _fsh)
|
|
{
|
|
BX_ASSERT(NULL != _fsh->m_code, "Fragment shader doesn't exist.");
|
|
m_fsh = _fsh;
|
|
bx::memCopy(&m_predefined[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 ShaderD3D12* m_vsh;
|
|
const ShaderD3D12* m_fsh;
|
|
|
|
PredefinedUniform m_predefined[PredefinedUniform::Count * 2];
|
|
uint8_t m_numPredefined;
|
|
};
|
|
|
|
struct TextureD3D12
|
|
{
|
|
enum Enum
|
|
{
|
|
Texture2D,
|
|
Texture3D,
|
|
TextureCube,
|
|
};
|
|
|
|
TextureD3D12()
|
|
: m_ptr(NULL)
|
|
, m_singleMsaa(NULL)
|
|
, m_directAccessPtr(NULL)
|
|
, m_state(D3D12_RESOURCE_STATE_COMMON)
|
|
, m_numMips(0)
|
|
{
|
|
bx::memSet(&m_srvd, 0, sizeof(m_srvd) );
|
|
bx::memSet(&m_uavd, 0, sizeof(m_uavd) );
|
|
}
|
|
|
|
void* create(const Memory* _mem, uint64_t _flags, uint8_t _skip);
|
|
void destroy();
|
|
void overrideInternal(uintptr_t _ptr);
|
|
void update(ID3D12GraphicsCommandList* _commandList, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem);
|
|
void resolve(ID3D12GraphicsCommandList* _commandList, uint8_t _resolve, uint32_t _layer, uint32_t _numLayers, uint32_t _mip);
|
|
D3D12_RESOURCE_STATES setState(ID3D12GraphicsCommandList* _commandList, D3D12_RESOURCE_STATES _state);
|
|
|
|
D3D12_SHADER_RESOURCE_VIEW_DESC m_srvd;
|
|
D3D12_UNORDERED_ACCESS_VIEW_DESC m_uavd;
|
|
ID3D12Resource* m_ptr;
|
|
ID3D12Resource* m_singleMsaa;
|
|
void* m_directAccessPtr;
|
|
D3D12_RESOURCE_STATES m_state;
|
|
uint64_t m_flags;
|
|
uint32_t m_width;
|
|
uint32_t m_height;
|
|
uint32_t m_depth;
|
|
uint32_t m_numLayers;
|
|
uint16_t m_samplerIdx;
|
|
uint8_t m_type;
|
|
uint8_t m_requestedFormat;
|
|
uint8_t m_textureFormat;
|
|
uint8_t m_numMips;
|
|
};
|
|
|
|
struct FrameBufferD3D12
|
|
{
|
|
FrameBufferD3D12()
|
|
: m_swapChain(NULL)
|
|
, m_nwh(NULL)
|
|
, m_width(0)
|
|
, m_height(0)
|
|
, m_denseIdx(UINT16_MAX)
|
|
, m_num(0)
|
|
, m_numTh(0)
|
|
, m_state(D3D12_RESOURCE_STATE_PRESENT)
|
|
, m_needPresent(false)
|
|
{
|
|
m_depth.idx = bgfx::kInvalidHandle;
|
|
}
|
|
|
|
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(uint32_t _syncInterval, uint32_t _flags);
|
|
void preReset();
|
|
void postReset();
|
|
void resolve();
|
|
void clear(ID3D12GraphicsCommandList* _commandList, const Clear& _clear, const float _palette[][4], const D3D12_RECT* _rect = NULL, uint32_t _num = 0);
|
|
D3D12_RESOURCE_STATES setState(ID3D12GraphicsCommandList* _commandList, uint8_t _idx, D3D12_RESOURCE_STATES _state);
|
|
|
|
TextureHandle m_texture[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS];
|
|
TextureHandle m_depth;
|
|
Dxgi::SwapChainI* m_swapChain;
|
|
void* m_nwh;
|
|
uint32_t m_width;
|
|
uint32_t m_height;
|
|
uint16_t m_denseIdx;
|
|
uint8_t m_num;
|
|
uint8_t m_numTh;
|
|
Attachment m_attachment[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS];
|
|
D3D12_RESOURCE_STATES m_state;
|
|
bool m_needPresent;
|
|
};
|
|
|
|
struct CommandQueueD3D12
|
|
{
|
|
CommandQueueD3D12()
|
|
: m_currentFence(0)
|
|
, m_completedFence(0)
|
|
, m_control(BX_COUNTOF(m_commandList) )
|
|
{
|
|
BX_STATIC_ASSERT(BX_COUNTOF(m_commandList) == BX_COUNTOF(m_release) );
|
|
}
|
|
|
|
void init(ID3D12Device* _device);
|
|
void shutdown();
|
|
ID3D12GraphicsCommandList* alloc();
|
|
uint64_t kick();
|
|
void finish(uint64_t _waitFence = UINT64_MAX, bool _finishAll = false);
|
|
bool tryFinish(uint64_t _waitFence);
|
|
void release(ID3D12Resource* _ptr);
|
|
bool consume(uint32_t _ms = UINT32_MAX);
|
|
|
|
struct CommandList
|
|
{
|
|
ID3D12GraphicsCommandList* m_commandList;
|
|
ID3D12CommandAllocator* m_commandAllocator;
|
|
HANDLE m_event;
|
|
};
|
|
|
|
ID3D12CommandQueue* m_commandQueue;
|
|
uint64_t m_currentFence;
|
|
uint64_t m_completedFence;
|
|
ID3D12Fence* m_fence;
|
|
CommandList m_commandList[256];
|
|
typedef stl::vector<ID3D12Resource*> ResourceArray;
|
|
ResourceArray m_release[256];
|
|
bx::RingBufferControl m_control;
|
|
};
|
|
|
|
struct BatchD3D12
|
|
{
|
|
enum Enum
|
|
{
|
|
Draw,
|
|
DrawIndexed,
|
|
|
|
Count
|
|
};
|
|
|
|
BatchD3D12()
|
|
: m_currIndirect(0)
|
|
, m_maxDrawPerBatch(0)
|
|
, m_minIndirect(0)
|
|
, m_flushPerBatch(0)
|
|
{
|
|
bx::memSet(m_num, 0, sizeof(m_num) );
|
|
}
|
|
|
|
~BatchD3D12()
|
|
{
|
|
}
|
|
|
|
void create(uint32_t _maxDrawPerBatch);
|
|
void destroy();
|
|
|
|
template<typename Ty>
|
|
Ty& getCmd(Enum _type);
|
|
|
|
uint32_t draw(ID3D12GraphicsCommandList* _commandList, D3D12_GPU_VIRTUAL_ADDRESS _cbv, const RenderDraw& _draw);
|
|
|
|
void flush(ID3D12GraphicsCommandList* _commandList, Enum _type);
|
|
void flush(ID3D12GraphicsCommandList* _commandList, bool _clean = false);
|
|
|
|
void begin();
|
|
void end(ID3D12GraphicsCommandList* _commandList);
|
|
|
|
void setSeqMode(bool _enabled)
|
|
{
|
|
m_flushPerBatch = _enabled ? 1 : m_maxDrawPerBatch;
|
|
}
|
|
|
|
void setIndirectMode(bool _enabled)
|
|
{
|
|
m_minIndirect = _enabled ? 64 : UINT32_MAX;
|
|
}
|
|
|
|
ID3D12CommandSignature* m_commandSignature[Count];
|
|
uint32_t m_num[Count];
|
|
void* m_cmds[Count];
|
|
|
|
struct DrawIndirectCommand
|
|
{
|
|
D3D12_VERTEX_BUFFER_VIEW vbv[BGFX_CONFIG_MAX_VERTEX_STREAMS + 1 /* instanced buffer */];
|
|
D3D12_GPU_VIRTUAL_ADDRESS cbv;
|
|
D3D12_DRAW_ARGUMENTS args;
|
|
};
|
|
|
|
struct DrawIndexedIndirectCommand
|
|
{
|
|
D3D12_VERTEX_BUFFER_VIEW vbv[BGFX_CONFIG_MAX_VERTEX_STREAMS + 1 /* instanced buffer */];
|
|
D3D12_INDEX_BUFFER_VIEW ibv;
|
|
D3D12_GPU_VIRTUAL_ADDRESS cbv;
|
|
D3D12_DRAW_INDEXED_ARGUMENTS args;
|
|
};
|
|
|
|
struct Stats
|
|
{
|
|
uint32_t m_numImmediate[Count];
|
|
uint32_t m_numIndirect[Count];
|
|
};
|
|
|
|
BufferD3D12 m_indirect[32];
|
|
uint32_t m_currIndirect;
|
|
DrawIndexedIndirectCommand m_current;
|
|
|
|
Stats m_stats;
|
|
uint32_t m_maxDrawPerBatch;
|
|
uint32_t m_minIndirect;
|
|
uint32_t m_flushPerBatch;
|
|
};
|
|
|
|
struct TimerQueryD3D12
|
|
{
|
|
TimerQueryD3D12()
|
|
: m_control(BX_COUNTOF(m_query) )
|
|
{
|
|
}
|
|
|
|
void init();
|
|
void shutdown();
|
|
uint32_t begin(uint32_t _resultIdx, uint32_t _frameNum);
|
|
void end(uint32_t _idx);
|
|
bool update();
|
|
|
|
struct Query
|
|
{
|
|
uint32_t m_resultIdx;
|
|
uint32_t m_frameNum;
|
|
uint64_t m_fence;
|
|
bool m_ready;
|
|
};
|
|
|
|
struct Result
|
|
{
|
|
void reset()
|
|
{
|
|
m_begin = 0;
|
|
m_end = 0;
|
|
m_pending = 0;
|
|
m_frameNum = 0;
|
|
}
|
|
|
|
uint64_t m_begin;
|
|
uint64_t m_end;
|
|
uint32_t m_pending;
|
|
uint32_t m_frameNum;
|
|
};
|
|
|
|
uint64_t m_frequency;
|
|
|
|
Result m_result[BGFX_CONFIG_MAX_VIEWS+1];
|
|
Query m_query[BGFX_CONFIG_MAX_VIEWS*4];
|
|
|
|
ID3D12Resource* m_readback;
|
|
ID3D12QueryHeap* m_queryHeap;
|
|
uint64_t* m_queryResult;
|
|
bx::RingBufferControl m_control;
|
|
};
|
|
|
|
struct OcclusionQueryD3D12
|
|
{
|
|
OcclusionQueryD3D12()
|
|
: m_control(BX_COUNTOF(m_handle) )
|
|
{
|
|
}
|
|
|
|
void init();
|
|
void shutdown();
|
|
void begin(ID3D12GraphicsCommandList* _commandList, Frame* _render, OcclusionQueryHandle _handle);
|
|
void end(ID3D12GraphicsCommandList* _commandList);
|
|
void invalidate(OcclusionQueryHandle _handle);
|
|
|
|
ID3D12Resource* m_readback;
|
|
ID3D12QueryHeap* m_queryHeap;
|
|
OcclusionQueryHandle m_handle[BGFX_CONFIG_MAX_OCCLUSION_QUERIES];
|
|
uint64_t* m_result;
|
|
bx::RingBufferControl m_control;
|
|
};
|
|
|
|
} /* namespace d3d12 */ } // namespace bgfx
|
|
|
|
#endif // BGFX_RENDERER_D3D12_H_HEADER_GUARD
|