mirror of https://github.com/AxioDL/boo.git
Windows sync
This commit is contained in:
parent
fa45c6750a
commit
25fadc7348
|
@ -89,10 +89,14 @@ class VulkanDataFactory : public IGraphicsDataFactory
|
||||||
uint32_t m_drawSamples;
|
uint32_t m_drawSamples;
|
||||||
static ThreadLocalPtr<struct VulkanData> m_deferredData;
|
static ThreadLocalPtr<struct VulkanData> m_deferredData;
|
||||||
std::unordered_set<struct VulkanData*> m_committedData;
|
std::unordered_set<struct VulkanData*> m_committedData;
|
||||||
|
std::unordered_set<struct VulkanPool*> m_committedPools;
|
||||||
std::mutex m_committedMutex;
|
std::mutex m_committedMutex;
|
||||||
std::vector<int> m_texUnis;
|
std::vector<int> m_texUnis;
|
||||||
void destroyData(IGraphicsData*);
|
void destroyData(IGraphicsData*);
|
||||||
|
void destroyPool(IGraphicsBufferPool*);
|
||||||
void destroyAllData();
|
void destroyAllData();
|
||||||
|
IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool *pool, BufferUse use,
|
||||||
|
size_t stride, size_t count);
|
||||||
public:
|
public:
|
||||||
VulkanDataFactory(IGraphicsContext* parent, VulkanContext* ctx, uint32_t drawSamples);
|
VulkanDataFactory(IGraphicsContext* parent, VulkanContext* ctx, uint32_t drawSamples);
|
||||||
~VulkanDataFactory() {destroyAllData();}
|
~VulkanDataFactory() {destroyAllData();}
|
||||||
|
@ -121,7 +125,8 @@ public:
|
||||||
bool enableShaderColorBinding, bool enableShaderDepthBinding);
|
bool enableShaderColorBinding, bool enableShaderDepthBinding);
|
||||||
|
|
||||||
bool bindingNeedsVertexFormat() const {return false;}
|
bool bindingNeedsVertexFormat() const {return false;}
|
||||||
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements);
|
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
|
||||||
|
size_t baseVert = 0, size_t baseInst = 0);
|
||||||
|
|
||||||
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
|
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
|
||||||
std::vector<unsigned int>& vertBlobOut, std::vector<unsigned int>& fragBlobOut,
|
std::vector<unsigned int>& vertBlobOut, std::vector<unsigned int>& fragBlobOut,
|
||||||
|
@ -146,10 +151,12 @@ public:
|
||||||
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
|
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
|
||||||
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
|
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
|
||||||
const size_t* ubufOffs, const size_t* ubufSizes,
|
const size_t* ubufOffs, const size_t* ubufSizes,
|
||||||
size_t texCount, ITexture** texs);
|
size_t texCount, ITexture** texs,
|
||||||
|
size_t baseVert = 0, size_t baseInst = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
GraphicsDataToken commitTransaction(const FactoryCommitFunc&);
|
GraphicsDataToken commitTransaction(const FactoryCommitFunc&);
|
||||||
|
GraphicsBufferPoolToken newBufferPool();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,25 @@ struct D3D11Data : IGraphicsData
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct D3D11Pool : IGraphicsBufferPool
|
||||||
|
{
|
||||||
|
size_t m_deleteCountdown = 4;
|
||||||
|
std::vector<std::unique_ptr<class D3D11GraphicsBufferD>> m_DBufs;
|
||||||
|
|
||||||
|
bool decref()
|
||||||
|
{
|
||||||
|
if (!m_deleteCountdown)
|
||||||
|
Log.report(logvisor::Fatal, "Can't decrement 0-data");
|
||||||
|
--m_deleteCountdown;
|
||||||
|
if (!m_deleteCountdown)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static const D3D11_BIND_FLAG USE_TABLE[] =
|
static const D3D11_BIND_FLAG USE_TABLE[] =
|
||||||
{
|
{
|
||||||
D3D11_BIND_VERTEX_BUFFER,
|
D3D11_BIND_VERTEX_BUFFER,
|
||||||
|
@ -425,13 +444,14 @@ struct D3D11VertexFormat : IVertexFormat
|
||||||
{
|
{
|
||||||
size_t m_elementCount;
|
size_t m_elementCount;
|
||||||
std::unique_ptr<D3D11_INPUT_ELEMENT_DESC[]> m_elements;
|
std::unique_ptr<D3D11_INPUT_ELEMENT_DESC[]> m_elements;
|
||||||
|
size_t m_stride = 0;
|
||||||
|
size_t m_instStride = 0;
|
||||||
|
|
||||||
D3D11VertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
|
D3D11VertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
|
||||||
: m_elementCount(elementCount),
|
: m_elementCount(elementCount),
|
||||||
m_elements(new D3D11_INPUT_ELEMENT_DESC[elementCount])
|
m_elements(new D3D11_INPUT_ELEMENT_DESC[elementCount])
|
||||||
{
|
{
|
||||||
memset(m_elements.get(), 0, elementCount * sizeof(D3D11_INPUT_ELEMENT_DESC));
|
memset(m_elements.get(), 0, elementCount * sizeof(D3D11_INPUT_ELEMENT_DESC));
|
||||||
size_t offset = 0;
|
|
||||||
size_t instOffset = 0;
|
|
||||||
for (size_t i=0 ; i<elementCount ; ++i)
|
for (size_t i=0 ; i<elementCount ; ++i)
|
||||||
{
|
{
|
||||||
const VertexElementDescriptor* elemin = &elements[i];
|
const VertexElementDescriptor* elemin = &elements[i];
|
||||||
|
@ -445,14 +465,14 @@ struct D3D11VertexFormat : IVertexFormat
|
||||||
elem.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
|
elem.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
|
||||||
elem.InstanceDataStepRate = 1;
|
elem.InstanceDataStepRate = 1;
|
||||||
elem.InputSlot = 1;
|
elem.InputSlot = 1;
|
||||||
elem.AlignedByteOffset = instOffset;
|
elem.AlignedByteOffset = m_instStride;
|
||||||
instOffset += SEMANTIC_SIZE_TABLE[semantic];
|
m_instStride += SEMANTIC_SIZE_TABLE[semantic];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
elem.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
elem.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||||
elem.AlignedByteOffset = offset;
|
elem.AlignedByteOffset = m_stride;
|
||||||
offset += SEMANTIC_SIZE_TABLE[semantic];
|
m_stride += SEMANTIC_SIZE_TABLE[semantic];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -483,11 +503,14 @@ static const D3D11_BLEND BLEND_FACTOR_TABLE[] =
|
||||||
class D3D11ShaderPipeline : public IShaderPipeline
|
class D3D11ShaderPipeline : public IShaderPipeline
|
||||||
{
|
{
|
||||||
friend class D3D11DataFactory;
|
friend class D3D11DataFactory;
|
||||||
|
friend struct D3D11ShaderDataBinding;
|
||||||
|
const D3D11VertexFormat* m_vtxFmt;
|
||||||
|
|
||||||
D3D11ShaderPipeline(D3D11Context* ctx, ID3DBlob* vert, ID3DBlob* pixel,
|
D3D11ShaderPipeline(D3D11Context* ctx, ID3DBlob* vert, ID3DBlob* pixel,
|
||||||
const D3D11VertexFormat* vtxFmt,
|
const D3D11VertexFormat* vtxFmt,
|
||||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||||
bool depthTest, bool depthWrite, bool backfaceCulling)
|
bool depthTest, bool depthWrite, bool backfaceCulling)
|
||||||
: m_topology(PRIMITIVE_TABLE[int(prim)])
|
: m_vtxFmt(vtxFmt), m_topology(PRIMITIVE_TABLE[int(prim)])
|
||||||
{
|
{
|
||||||
ThrowIfFailed(ctx->m_dev->CreateVertexShader(vert->GetBufferPointer(), vert->GetBufferSize(), nullptr, &m_vShader));
|
ThrowIfFailed(ctx->m_dev->CreateVertexShader(vert->GetBufferPointer(), vert->GetBufferSize(), nullptr, &m_vShader));
|
||||||
ThrowIfFailed(ctx->m_dev->CreatePixelShader(pixel->GetBufferPointer(), pixel->GetBufferSize(), nullptr, &m_pShader));
|
ThrowIfFailed(ctx->m_dev->CreatePixelShader(pixel->GetBufferPointer(), pixel->GetBufferSize(), nullptr, &m_pShader));
|
||||||
|
@ -549,13 +572,14 @@ struct D3D11ShaderDataBinding : IShaderDataBinding
|
||||||
std::unique_ptr<bool[]> m_pubufs;
|
std::unique_ptr<bool[]> m_pubufs;
|
||||||
size_t m_texCount;
|
size_t m_texCount;
|
||||||
std::unique_ptr<ITexture*[]> m_texs;
|
std::unique_ptr<ITexture*[]> m_texs;
|
||||||
|
UINT m_baseOffsets[2];
|
||||||
|
|
||||||
D3D11ShaderDataBinding(D3D11Context* ctx,
|
D3D11ShaderDataBinding(D3D11Context* ctx,
|
||||||
IShaderPipeline* pipeline,
|
IShaderPipeline* pipeline,
|
||||||
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbuf, IGraphicsBuffer* ibuf,
|
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbuf, IGraphicsBuffer* ibuf,
|
||||||
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
|
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
|
||||||
const size_t* ubufOffs, const size_t* ubufSizes,
|
const size_t* ubufOffs, const size_t* ubufSizes,
|
||||||
size_t texCount, ITexture** texs)
|
size_t texCount, ITexture** texs, size_t baseVert, size_t baseInst)
|
||||||
: m_pipeline(static_cast<D3D11ShaderPipeline*>(pipeline)),
|
: m_pipeline(static_cast<D3D11ShaderPipeline*>(pipeline)),
|
||||||
m_vbuf(vbuf),
|
m_vbuf(vbuf),
|
||||||
m_instVbuf(instVbuf),
|
m_instVbuf(instVbuf),
|
||||||
|
@ -565,6 +589,9 @@ struct D3D11ShaderDataBinding : IShaderDataBinding
|
||||||
m_texCount(texCount),
|
m_texCount(texCount),
|
||||||
m_texs(new ITexture*[texCount])
|
m_texs(new ITexture*[texCount])
|
||||||
{
|
{
|
||||||
|
m_baseOffsets[0] = UINT(baseVert * m_pipeline->m_vtxFmt->m_stride);
|
||||||
|
m_baseOffsets[1] = UINT(baseInst * m_pipeline->m_vtxFmt->m_instStride);
|
||||||
|
|
||||||
if (ubufStages)
|
if (ubufStages)
|
||||||
{
|
{
|
||||||
m_pubufs.reset(new bool[ubufCount]);
|
m_pubufs.reset(new bool[ubufCount]);
|
||||||
|
@ -605,7 +632,6 @@ struct D3D11ShaderDataBinding : IShaderDataBinding
|
||||||
|
|
||||||
ID3D11Buffer* bufs[2] = {};
|
ID3D11Buffer* bufs[2] = {};
|
||||||
UINT strides[2] = {};
|
UINT strides[2] = {};
|
||||||
UINT offsets[2] = {0,0};
|
|
||||||
|
|
||||||
if (m_vbuf)
|
if (m_vbuf)
|
||||||
{
|
{
|
||||||
|
@ -639,7 +665,7 @@ struct D3D11ShaderDataBinding : IShaderDataBinding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->IASetVertexBuffers(0, 2, bufs, strides, offsets);
|
ctx->IASetVertexBuffers(0, 2, bufs, strides, m_baseOffsets);
|
||||||
|
|
||||||
if (m_ibuf)
|
if (m_ibuf)
|
||||||
{
|
{
|
||||||
|
@ -808,7 +834,7 @@ struct D3D11CommandQueue : IGraphicsCommandQueue
|
||||||
ComPtr<ID3D11CommandList> m_cmdLists[3];
|
ComPtr<ID3D11CommandList> m_cmdLists[3];
|
||||||
D3D11TextureR* m_workDoPresent[3];
|
D3D11TextureR* m_workDoPresent[3];
|
||||||
|
|
||||||
std::mutex m_dynamicLock;
|
std::recursive_mutex m_dynamicLock;
|
||||||
void ProcessDynamicLoads(ID3D11DeviceContext* ctx);
|
void ProcessDynamicLoads(ID3D11DeviceContext* ctx);
|
||||||
static void RenderingWorker(D3D11CommandQueue* self)
|
static void RenderingWorker(D3D11CommandQueue* self)
|
||||||
{
|
{
|
||||||
|
@ -1042,7 +1068,7 @@ void D3D11GraphicsBufferD::update(ID3D11DeviceContext* ctx, int b)
|
||||||
}
|
}
|
||||||
void D3D11GraphicsBufferD::load(const void* data, size_t sz)
|
void D3D11GraphicsBufferD::load(const void* data, size_t sz)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(m_q->m_dynamicLock);
|
std::unique_lock<std::recursive_mutex> lk(m_q->m_dynamicLock);
|
||||||
size_t bufSz = std::min(sz, m_cpuSz);
|
size_t bufSz = std::min(sz, m_cpuSz);
|
||||||
memcpy(m_cpuBuf.get(), data, bufSz);
|
memcpy(m_cpuBuf.get(), data, bufSz);
|
||||||
m_validSlots = 0;
|
m_validSlots = 0;
|
||||||
|
@ -1075,7 +1101,7 @@ void D3D11TextureD::update(ID3D11DeviceContext* ctx, int b)
|
||||||
}
|
}
|
||||||
void D3D11TextureD::load(const void* data, size_t sz)
|
void D3D11TextureD::load(const void* data, size_t sz)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(m_q->m_dynamicLock);
|
std::unique_lock<std::recursive_mutex> lk(m_q->m_dynamicLock);
|
||||||
size_t bufSz = std::min(sz, m_cpuSz);
|
size_t bufSz = std::min(sz, m_cpuSz);
|
||||||
memcpy(m_cpuBuf.get(), data, bufSz);
|
memcpy(m_cpuBuf.get(), data, bufSz);
|
||||||
m_validSlots = 0;
|
m_validSlots = 0;
|
||||||
|
@ -1100,8 +1126,10 @@ class D3D11DataFactory : public ID3DDataFactory
|
||||||
static thread_local D3D11Data* m_deferredData;
|
static thread_local D3D11Data* m_deferredData;
|
||||||
struct D3D11Context* m_ctx;
|
struct D3D11Context* m_ctx;
|
||||||
std::unordered_set<D3D11Data*> m_committedData;
|
std::unordered_set<D3D11Data*> m_committedData;
|
||||||
|
std::unordered_set<D3D11Pool*> m_committedPools;
|
||||||
std::mutex m_committedMutex;
|
std::mutex m_committedMutex;
|
||||||
std::unordered_set<D3D11Data*> m_deletedData;
|
std::unordered_set<D3D11Data*> m_deletedData;
|
||||||
|
std::unordered_set<D3D11Pool*> m_deletedPools;
|
||||||
uint32_t m_sampleCount;
|
uint32_t m_sampleCount;
|
||||||
|
|
||||||
void destroyData(IGraphicsData* d)
|
void destroyData(IGraphicsData* d)
|
||||||
|
@ -1117,27 +1145,52 @@ class D3D11DataFactory : public ID3DDataFactory
|
||||||
std::unique_lock<std::mutex> lk(m_committedMutex);
|
std::unique_lock<std::mutex> lk(m_committedMutex);
|
||||||
for (IGraphicsData* data : m_committedData)
|
for (IGraphicsData* data : m_committedData)
|
||||||
m_deletedData.insert(static_cast<D3D11Data*>(data));
|
m_deletedData.insert(static_cast<D3D11Data*>(data));
|
||||||
|
for (IGraphicsBufferPool* pool : m_committedPools)
|
||||||
|
m_deletedPools.insert(static_cast<D3D11Pool*>(pool));
|
||||||
m_committedData.clear();
|
m_committedData.clear();
|
||||||
|
m_committedPools.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroyPool(IGraphicsBufferPool* p)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lk(m_committedMutex);
|
||||||
|
D3D11Pool* pool = static_cast<D3D11Pool*>(p);
|
||||||
|
m_committedPools.erase(pool);
|
||||||
|
m_deletedPools.insert(pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<D3D11Data*> m_toDelete;
|
|
||||||
void procDeletes()
|
void procDeletes()
|
||||||
{
|
{
|
||||||
if (m_deletedData.size())
|
for (auto it = m_deletedData.begin(); it != m_deletedData.end();)
|
||||||
{
|
{
|
||||||
for (IGraphicsData* data : m_deletedData)
|
D3D11Data* cdata = static_cast<D3D11Data*>(*it);
|
||||||
{
|
|
||||||
D3D11Data* cdata = static_cast<D3D11Data*>(data);
|
|
||||||
if (cdata->decref())
|
if (cdata->decref())
|
||||||
m_toDelete.push_back(cdata);
|
|
||||||
}
|
|
||||||
if (m_toDelete.size())
|
|
||||||
{
|
{
|
||||||
for (D3D11Data* data : m_toDelete)
|
it = m_deletedData.erase(it);
|
||||||
m_deletedData.erase(data);
|
continue;
|
||||||
m_toDelete.clear();
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
for (auto it = m_deletedPools.begin(); it != m_deletedPools.end();)
|
||||||
|
{
|
||||||
|
D3D11Pool* cpool = static_cast<D3D11Pool*>(*it);
|
||||||
|
if (cpool->decref())
|
||||||
|
{
|
||||||
|
it = m_deletedPools.erase(it);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool* p, BufferUse use,
|
||||||
|
size_t stride, size_t count)
|
||||||
|
{
|
||||||
|
D3D11CommandQueue* q = static_cast<D3D11CommandQueue*>(m_parent->getCommandQueue());
|
||||||
|
D3D11Pool* pool = static_cast<D3D11Pool*>(p);
|
||||||
|
D3D11GraphicsBufferD* retval = new D3D11GraphicsBufferD(q, use, m_ctx, stride, count);
|
||||||
|
pool->m_DBufs.emplace_back(retval);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -1207,7 +1260,8 @@ public:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
|
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
|
||||||
|
size_t baseVert, size_t baseInst)
|
||||||
{
|
{
|
||||||
D3D11CommandQueue* q = static_cast<D3D11CommandQueue*>(m_parent.m_parent->getCommandQueue());
|
D3D11CommandQueue* q = static_cast<D3D11CommandQueue*>(m_parent.m_parent->getCommandQueue());
|
||||||
D3D11VertexFormat* retval = new struct D3D11VertexFormat(elementCount, elements);
|
D3D11VertexFormat* retval = new struct D3D11VertexFormat(elementCount, elements);
|
||||||
|
@ -1262,11 +1316,13 @@ public:
|
||||||
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibuf,
|
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibuf,
|
||||||
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
|
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
|
||||||
const size_t* ubufOffs, const size_t* ubufSizes,
|
const size_t* ubufOffs, const size_t* ubufSizes,
|
||||||
size_t texCount, ITexture** texs)
|
size_t texCount, ITexture** texs,
|
||||||
|
size_t baseVert, size_t baseInst)
|
||||||
{
|
{
|
||||||
D3D11ShaderDataBinding* retval =
|
D3D11ShaderDataBinding* retval =
|
||||||
new D3D11ShaderDataBinding(m_parent.m_ctx, pipeline, vbuf, instVbo, ibuf,
|
new D3D11ShaderDataBinding(m_parent.m_ctx, pipeline, vbuf, instVbo, ibuf,
|
||||||
ubufCount, ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs);
|
ubufCount, ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs,
|
||||||
|
baseVert, baseInst);
|
||||||
static_cast<D3D11Data*>(m_deferredData)->m_SBinds.emplace_back(retval);
|
static_cast<D3D11Data*>(m_deferredData)->m_SBinds.emplace_back(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -1293,6 +1349,14 @@ public:
|
||||||
lk.unlock();
|
lk.unlock();
|
||||||
return GraphicsDataToken(this, retval);
|
return GraphicsDataToken(this, retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GraphicsBufferPoolToken newBufferPool()
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lk(m_committedMutex);
|
||||||
|
D3D11Pool* retval = new D3D11Pool;
|
||||||
|
m_committedPools.insert(retval);
|
||||||
|
return GraphicsBufferPoolToken(this, retval);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
thread_local D3D11Data* D3D11DataFactory::m_deferredData;
|
thread_local D3D11Data* D3D11DataFactory::m_deferredData;
|
||||||
|
@ -1328,7 +1392,7 @@ void D3D11CommandQueue::execute()
|
||||||
void D3D11CommandQueue::ProcessDynamicLoads(ID3D11DeviceContext* ctx)
|
void D3D11CommandQueue::ProcessDynamicLoads(ID3D11DeviceContext* ctx)
|
||||||
{
|
{
|
||||||
D3D11DataFactory* gfxF = static_cast<D3D11DataFactory*>(m_parent->getDataFactory());
|
D3D11DataFactory* gfxF = static_cast<D3D11DataFactory*>(m_parent->getDataFactory());
|
||||||
std::unique_lock<std::mutex> lk(m_dynamicLock);
|
std::unique_lock<std::recursive_mutex> lk(m_dynamicLock);
|
||||||
std::unique_lock<std::mutex> datalk(gfxF->m_committedMutex);
|
std::unique_lock<std::mutex> datalk(gfxF->m_committedMutex);
|
||||||
|
|
||||||
for (D3D11Data* d : gfxF->m_committedData)
|
for (D3D11Data* d : gfxF->m_committedData)
|
||||||
|
@ -1338,6 +1402,11 @@ void D3D11CommandQueue::ProcessDynamicLoads(ID3D11DeviceContext* ctx)
|
||||||
for (std::unique_ptr<D3D11TextureD>& t : d->m_DTexs)
|
for (std::unique_ptr<D3D11TextureD>& t : d->m_DTexs)
|
||||||
t->update(ctx, m_drawBuf);
|
t->update(ctx, m_drawBuf);
|
||||||
}
|
}
|
||||||
|
for (D3D11Pool* p : gfxF->m_committedPools)
|
||||||
|
{
|
||||||
|
for (std::unique_ptr<D3D11GraphicsBufferD>& b : p->m_DBufs)
|
||||||
|
b->update(ctx, m_drawBuf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IGraphicsCommandQueue* _NewD3D11CommandQueue(D3D11Context* ctx, D3D11Context::Window* windowCtx, IGraphicsContext* parent)
|
IGraphicsCommandQueue* _NewD3D11CommandQueue(D3D11Context* ctx, D3D11Context::Window* windowCtx, IGraphicsContext* parent)
|
||||||
|
|
|
@ -55,6 +55,18 @@ struct D3D12Data : IGraphicsData
|
||||||
ComPtr<ID3D12Heap> m_texHeap;
|
ComPtr<ID3D12Heap> m_texHeap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct D3D12Pool : IGraphicsBufferPool
|
||||||
|
{
|
||||||
|
struct Buffer
|
||||||
|
{
|
||||||
|
ComPtr<ID3D12Heap> m_bufHeap;
|
||||||
|
std::unique_ptr<class D3D12GraphicsBufferD> m_buf;
|
||||||
|
Buffer(ComPtr<ID3D12Heap>&& heap, class D3D12GraphicsBufferD* buf)
|
||||||
|
: m_bufHeap(std::move(heap)), m_buf(buf) {}
|
||||||
|
};
|
||||||
|
std::vector<Buffer> m_DBufs;
|
||||||
|
};
|
||||||
|
|
||||||
static const D3D12_RESOURCE_STATES USE_TABLE[] =
|
static const D3D12_RESOURCE_STATES USE_TABLE[] =
|
||||||
{
|
{
|
||||||
D3D12_RESOURCE_STATE_COMMON,
|
D3D12_RESOURCE_STATE_COMMON,
|
||||||
|
@ -569,13 +581,14 @@ struct D3D12VertexFormat : IVertexFormat
|
||||||
{
|
{
|
||||||
size_t m_elementCount;
|
size_t m_elementCount;
|
||||||
std::unique_ptr<D3D12_INPUT_ELEMENT_DESC[]> m_elements;
|
std::unique_ptr<D3D12_INPUT_ELEMENT_DESC[]> m_elements;
|
||||||
|
size_t m_stride = 0;
|
||||||
|
size_t m_instStride = 0;
|
||||||
|
|
||||||
D3D12VertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
|
D3D12VertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
|
||||||
: m_elementCount(elementCount),
|
: m_elementCount(elementCount),
|
||||||
m_elements(new D3D12_INPUT_ELEMENT_DESC[elementCount])
|
m_elements(new D3D12_INPUT_ELEMENT_DESC[elementCount])
|
||||||
{
|
{
|
||||||
memset(m_elements.get(), 0, elementCount * sizeof(D3D12_INPUT_ELEMENT_DESC));
|
memset(m_elements.get(), 0, elementCount * sizeof(D3D12_INPUT_ELEMENT_DESC));
|
||||||
size_t offset = 0;
|
|
||||||
size_t instOffset = 0;
|
|
||||||
for (size_t i=0 ; i<elementCount ; ++i)
|
for (size_t i=0 ; i<elementCount ; ++i)
|
||||||
{
|
{
|
||||||
const VertexElementDescriptor* elemin = &elements[i];
|
const VertexElementDescriptor* elemin = &elements[i];
|
||||||
|
@ -589,14 +602,14 @@ struct D3D12VertexFormat : IVertexFormat
|
||||||
elem.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
|
elem.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
|
||||||
elem.InstanceDataStepRate = 1;
|
elem.InstanceDataStepRate = 1;
|
||||||
elem.InputSlot = 1;
|
elem.InputSlot = 1;
|
||||||
elem.AlignedByteOffset = instOffset;
|
elem.AlignedByteOffset = m_instStride;
|
||||||
instOffset += SEMANTIC_SIZE_TABLE[semantic];
|
m_instStride += SEMANTIC_SIZE_TABLE[semantic];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
elem.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
|
elem.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
|
||||||
elem.AlignedByteOffset = offset;
|
elem.AlignedByteOffset = m_stride;
|
||||||
offset += SEMANTIC_SIZE_TABLE[semantic];
|
m_stride += SEMANTIC_SIZE_TABLE[semantic];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -627,11 +640,14 @@ static const D3D12_BLEND BLEND_FACTOR_TABLE[] =
|
||||||
class D3D12ShaderPipeline : public IShaderPipeline
|
class D3D12ShaderPipeline : public IShaderPipeline
|
||||||
{
|
{
|
||||||
friend class D3D12DataFactory;
|
friend class D3D12DataFactory;
|
||||||
|
friend struct D3D12ShaderDataBinding;
|
||||||
|
const D3D12VertexFormat* m_vtxFmt;
|
||||||
|
|
||||||
D3D12ShaderPipeline(D3D12Context* ctx, ID3DBlob* vert, ID3DBlob* pixel, ID3DBlob* pipeline,
|
D3D12ShaderPipeline(D3D12Context* ctx, ID3DBlob* vert, ID3DBlob* pixel, ID3DBlob* pipeline,
|
||||||
const D3D12VertexFormat* vtxFmt,
|
const D3D12VertexFormat* vtxFmt,
|
||||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||||
bool depthTest, bool depthWrite, bool backfaceCulling)
|
bool depthTest, bool depthWrite, bool backfaceCulling)
|
||||||
: m_topology(PRIMITIVE_TABLE[int(prim)])
|
: m_vtxFmt(vtxFmt), m_topology(PRIMITIVE_TABLE[int(prim)])
|
||||||
{
|
{
|
||||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {};
|
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {};
|
||||||
desc.pRootSignature = ctx->m_rs.Get();
|
desc.pRootSignature = ctx->m_rs.Get();
|
||||||
|
@ -700,22 +716,22 @@ static UINT64 PlaceTextureForGPU(ITexture* tex, D3D12Context* ctx, ID3D12Heap* g
|
||||||
}
|
}
|
||||||
|
|
||||||
static ID3D12Resource* GetBufferGPUResource(const IGraphicsBuffer* buf, int idx,
|
static ID3D12Resource* GetBufferGPUResource(const IGraphicsBuffer* buf, int idx,
|
||||||
D3D12_VERTEX_BUFFER_VIEW& descOut)
|
D3D12_VERTEX_BUFFER_VIEW& descOut, size_t offset)
|
||||||
{
|
{
|
||||||
if (buf->dynamic())
|
if (buf->dynamic())
|
||||||
{
|
{
|
||||||
const D3D12GraphicsBufferD* cbuf = static_cast<const D3D12GraphicsBufferD*>(buf);
|
const D3D12GraphicsBufferD* cbuf = static_cast<const D3D12GraphicsBufferD*>(buf);
|
||||||
descOut.SizeInBytes = cbuf->m_count * cbuf->m_stride;
|
descOut.SizeInBytes = cbuf->m_count * cbuf->m_stride - offset;
|
||||||
descOut.StrideInBytes = cbuf->m_stride;
|
descOut.StrideInBytes = cbuf->m_stride;
|
||||||
descOut.BufferLocation = cbuf->m_gpuBufs[idx]->GetGPUVirtualAddress();
|
descOut.BufferLocation = cbuf->m_gpuBufs[idx]->GetGPUVirtualAddress() + offset;
|
||||||
return cbuf->m_gpuBufs[idx].Get();
|
return cbuf->m_gpuBufs[idx].Get();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const D3D12GraphicsBufferS* cbuf = static_cast<const D3D12GraphicsBufferS*>(buf);
|
const D3D12GraphicsBufferS* cbuf = static_cast<const D3D12GraphicsBufferS*>(buf);
|
||||||
descOut.SizeInBytes = cbuf->m_count * cbuf->m_stride;
|
descOut.SizeInBytes = cbuf->m_count * cbuf->m_stride - offset;
|
||||||
descOut.StrideInBytes = cbuf->m_stride;
|
descOut.StrideInBytes = cbuf->m_stride;
|
||||||
descOut.BufferLocation = cbuf->m_gpuBuf->GetGPUVirtualAddress();
|
descOut.BufferLocation = cbuf->m_gpuBuf->GetGPUVirtualAddress() + offset;
|
||||||
return cbuf->m_gpuBuf.Get();
|
return cbuf->m_gpuBuf.Get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -909,13 +925,15 @@ struct D3D12ShaderDataBinding : IShaderDataBinding
|
||||||
std::unique_ptr<ITexture*[]> m_texs;
|
std::unique_ptr<ITexture*[]> m_texs;
|
||||||
D3D12_VERTEX_BUFFER_VIEW m_vboView[2][2] = {{},{}};
|
D3D12_VERTEX_BUFFER_VIEW m_vboView[2][2] = {{},{}};
|
||||||
D3D12_INDEX_BUFFER_VIEW m_iboView[2];
|
D3D12_INDEX_BUFFER_VIEW m_iboView[2];
|
||||||
|
size_t m_vertOffset, m_instOffset;
|
||||||
|
|
||||||
D3D12ShaderDataBinding(D3D12Context* ctx,
|
D3D12ShaderDataBinding(D3D12Context* ctx,
|
||||||
IShaderPipeline* pipeline,
|
IShaderPipeline* pipeline,
|
||||||
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbuf, IGraphicsBuffer* ibuf,
|
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbuf, IGraphicsBuffer* ibuf,
|
||||||
size_t ubufCount, IGraphicsBuffer** ubufs,
|
size_t ubufCount, IGraphicsBuffer** ubufs,
|
||||||
const size_t* ubufOffs, const size_t* ubufSizes,
|
const size_t* ubufOffs, const size_t* ubufSizes,
|
||||||
size_t texCount, ITexture** texs)
|
size_t texCount, ITexture** texs,
|
||||||
|
size_t baseVert, size_t baseInst)
|
||||||
: m_pipeline(static_cast<D3D12ShaderPipeline*>(pipeline)),
|
: m_pipeline(static_cast<D3D12ShaderPipeline*>(pipeline)),
|
||||||
m_vbuf(vbuf),
|
m_vbuf(vbuf),
|
||||||
m_instVbuf(instVbuf),
|
m_instVbuf(instVbuf),
|
||||||
|
@ -925,6 +943,9 @@ struct D3D12ShaderDataBinding : IShaderDataBinding
|
||||||
m_texCount(texCount),
|
m_texCount(texCount),
|
||||||
m_texs(new ITexture*[texCount])
|
m_texs(new ITexture*[texCount])
|
||||||
{
|
{
|
||||||
|
m_vertOffset = baseVert * m_pipeline->m_vtxFmt->m_stride;
|
||||||
|
m_instOffset = baseInst * m_pipeline->m_vtxFmt->m_instStride;
|
||||||
|
|
||||||
if (ubufOffs && ubufSizes)
|
if (ubufOffs && ubufSizes)
|
||||||
{
|
{
|
||||||
m_ubufOffs.reserve(ubufCount);
|
m_ubufOffs.reserve(ubufCount);
|
||||||
|
@ -967,9 +988,9 @@ struct D3D12ShaderDataBinding : IShaderDataBinding
|
||||||
CD3DX12_CPU_DESCRIPTOR_HANDLE handle(m_descHeap[b]->GetCPUDescriptorHandleForHeapStart());
|
CD3DX12_CPU_DESCRIPTOR_HANDLE handle(m_descHeap[b]->GetCPUDescriptorHandleForHeapStart());
|
||||||
|
|
||||||
if (m_vbuf)
|
if (m_vbuf)
|
||||||
GetBufferGPUResource(m_vbuf, b, m_vboView[b][0]);
|
GetBufferGPUResource(m_vbuf, b, m_vboView[b][0], m_vertOffset);
|
||||||
if (m_instVbuf)
|
if (m_instVbuf)
|
||||||
GetBufferGPUResource(m_instVbuf, b, m_vboView[b][1]);
|
GetBufferGPUResource(m_instVbuf, b, m_vboView[b][1], m_instOffset);
|
||||||
if (m_ibuf)
|
if (m_ibuf)
|
||||||
GetBufferGPUResource(m_ibuf, b, m_iboView[b]);
|
GetBufferGPUResource(m_ibuf, b, m_iboView[b]);
|
||||||
if (m_ubufOffs.size())
|
if (m_ubufOffs.size())
|
||||||
|
@ -1511,6 +1532,7 @@ class D3D12DataFactory : public ID3DDataFactory
|
||||||
static thread_local D3D12Data* m_deferredData;
|
static thread_local D3D12Data* m_deferredData;
|
||||||
struct D3D12Context* m_ctx;
|
struct D3D12Context* m_ctx;
|
||||||
std::unordered_set<D3D12Data*> m_committedData;
|
std::unordered_set<D3D12Data*> m_committedData;
|
||||||
|
std::unordered_set<D3D12Pool*> m_committedPools;
|
||||||
std::mutex m_committedMutex;
|
std::mutex m_committedMutex;
|
||||||
uint32_t m_sampleCount;
|
uint32_t m_sampleCount;
|
||||||
|
|
||||||
|
@ -1527,8 +1549,47 @@ class D3D12DataFactory : public ID3DDataFactory
|
||||||
std::unique_lock<std::mutex> lk(m_committedMutex);
|
std::unique_lock<std::mutex> lk(m_committedMutex);
|
||||||
for (IGraphicsData* data : m_committedData)
|
for (IGraphicsData* data : m_committedData)
|
||||||
delete static_cast<D3D12Data*>(data);
|
delete static_cast<D3D12Data*>(data);
|
||||||
|
for (IGraphicsBufferPool* pool : m_committedPools)
|
||||||
|
delete static_cast<D3D12Pool*>(pool);
|
||||||
m_committedData.clear();
|
m_committedData.clear();
|
||||||
|
m_committedPools.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void destroyPool(IGraphicsBufferPool* p)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lk(m_committedMutex);
|
||||||
|
D3D12Pool* pool = static_cast<D3D12Pool*>(p);
|
||||||
|
m_committedPools.erase(pool);
|
||||||
|
delete pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool* p, BufferUse use,
|
||||||
|
size_t stride, size_t count)
|
||||||
|
{
|
||||||
|
D3D12CommandQueue* q = static_cast<D3D12CommandQueue*>(m_parent->getCommandQueue());
|
||||||
|
D3D12Pool* pool = static_cast<D3D12Pool*>(p);
|
||||||
|
D3D12GraphicsBufferD* retval = new D3D12GraphicsBufferD(q, use, m_ctx, stride, count);
|
||||||
|
|
||||||
|
/* Gather resource descriptions */
|
||||||
|
D3D12_RESOURCE_DESC bufDescs[2];
|
||||||
|
bufDescs[0] = retval->m_bufs[0]->GetDesc();
|
||||||
|
bufDescs[1] = retval->m_bufs[1]->GetDesc();
|
||||||
|
|
||||||
|
/* Create heap */
|
||||||
|
ComPtr<ID3D12Heap> bufHeap;
|
||||||
|
D3D12_RESOURCE_ALLOCATION_INFO bufAllocInfo =
|
||||||
|
m_ctx->m_dev->GetResourceAllocationInfo(0, 2, bufDescs);
|
||||||
|
ThrowIfFailed(m_ctx->m_dev->CreateHeap(&CD3DX12_HEAP_DESC(bufAllocInfo,
|
||||||
|
D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS),
|
||||||
|
__uuidof(ID3D12Heap), &bufHeap));
|
||||||
|
|
||||||
|
/* Place resources */
|
||||||
|
PlaceBufferForGPU(retval, m_ctx, bufHeap.Get(), 0);
|
||||||
|
|
||||||
|
pool->m_DBufs.emplace_back(std::move(bufHeap), retval);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
D3D12DataFactory(IGraphicsContext* parent, D3D12Context* ctx, uint32_t sampleCount)
|
D3D12DataFactory(IGraphicsContext* parent, D3D12Context* ctx, uint32_t sampleCount)
|
||||||
: m_parent(parent), m_ctx(ctx), m_sampleCount(sampleCount)
|
: m_parent(parent), m_ctx(ctx), m_sampleCount(sampleCount)
|
||||||
|
@ -1614,7 +1675,8 @@ public:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
|
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
|
||||||
|
size_t baseVert, size_t baseInst)
|
||||||
{
|
{
|
||||||
D3D12VertexFormat* retval = new struct D3D12VertexFormat(elementCount, elements);
|
D3D12VertexFormat* retval = new struct D3D12VertexFormat(elementCount, elements);
|
||||||
static_cast<D3D12Data*>(m_deferredData)->m_VFmts.emplace_back(retval);
|
static_cast<D3D12Data*>(m_deferredData)->m_VFmts.emplace_back(retval);
|
||||||
|
@ -1673,11 +1735,13 @@ public:
|
||||||
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbuf, IGraphicsBuffer* ibuf,
|
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbuf, IGraphicsBuffer* ibuf,
|
||||||
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
|
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
|
||||||
const size_t* ubufOffs, const size_t* ubufSizes,
|
const size_t* ubufOffs, const size_t* ubufSizes,
|
||||||
size_t texCount, ITexture** texs)
|
size_t texCount, ITexture** texs,
|
||||||
|
size_t baseVert, size_t baseInst)
|
||||||
{
|
{
|
||||||
D3D12ShaderDataBinding* retval =
|
D3D12ShaderDataBinding* retval =
|
||||||
new D3D12ShaderDataBinding(m_parent.m_ctx, pipeline, vbuf, instVbuf, ibuf,
|
new D3D12ShaderDataBinding(m_parent.m_ctx, pipeline, vbuf, instVbuf, ibuf,
|
||||||
ubufCount, ubufs, ubufOffs, ubufSizes, texCount, texs);
|
ubufCount, ubufs, ubufOffs, ubufSizes, texCount, texs,
|
||||||
|
baseVert, baseInst);
|
||||||
static_cast<D3D12Data*>(m_deferredData)->m_SBinds.emplace_back(retval);
|
static_cast<D3D12Data*>(m_deferredData)->m_SBinds.emplace_back(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -1800,6 +1864,14 @@ public:
|
||||||
lk.unlock();
|
lk.unlock();
|
||||||
return GraphicsDataToken(this, retval);
|
return GraphicsDataToken(this, retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GraphicsBufferPoolToken newBufferPool()
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lk(m_committedMutex);
|
||||||
|
D3D12Pool* retval = new D3D12Pool;
|
||||||
|
m_committedPools.insert(retval);
|
||||||
|
return GraphicsBufferPoolToken(this, retval);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
thread_local D3D12Data* D3D12DataFactory::m_deferredData;
|
thread_local D3D12Data* D3D12DataFactory::m_deferredData;
|
||||||
|
@ -1819,6 +1891,11 @@ void D3D12CommandQueue::execute()
|
||||||
for (std::unique_ptr<D3D12TextureD>& t : d->m_DTexs)
|
for (std::unique_ptr<D3D12TextureD>& t : d->m_DTexs)
|
||||||
t->update(m_fillBuf);
|
t->update(m_fillBuf);
|
||||||
}
|
}
|
||||||
|
for (D3D12Pool* p : gfxF->m_committedPools)
|
||||||
|
{
|
||||||
|
for (D3D12Pool::Buffer& b : p->m_DBufs)
|
||||||
|
b.m_buf->update(m_fillBuf);
|
||||||
|
}
|
||||||
datalk.unlock();
|
datalk.unlock();
|
||||||
|
|
||||||
/* Perform dynamic uploads */
|
/* Perform dynamic uploads */
|
||||||
|
|
|
@ -677,6 +677,27 @@ struct VulkanData : IGraphicsData
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VulkanPool : IGraphicsBufferPool
|
||||||
|
{
|
||||||
|
VulkanContext* m_ctx;
|
||||||
|
struct Buffer
|
||||||
|
{
|
||||||
|
VkDeviceMemory m_bufMem = VK_NULL_HANDLE;
|
||||||
|
std::unique_ptr<class VulkanGraphicsBufferD> m_buffer;
|
||||||
|
Buffer(VkDeviceMemory mem, class VulkanGraphicsBufferD* buf)
|
||||||
|
: m_bufMem(mem), m_buffer(buf) {}
|
||||||
|
};
|
||||||
|
std::vector<Buffer> m_DBufs;
|
||||||
|
bool m_dead = false;
|
||||||
|
VulkanPool(VulkanContext* ctx) : m_ctx(ctx) {}
|
||||||
|
~VulkanPool()
|
||||||
|
{
|
||||||
|
for (Buffer& buf : m_DBufs)
|
||||||
|
if (buf.m_bufMem)
|
||||||
|
vk::FreeMemory(m_ctx->m_dev, buf.m_bufMem, nullptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static const VkBufferUsageFlagBits USE_TABLE[] =
|
static const VkBufferUsageFlagBits USE_TABLE[] =
|
||||||
{
|
{
|
||||||
VkBufferUsageFlagBits(0),
|
VkBufferUsageFlagBits(0),
|
||||||
|
@ -1631,6 +1652,9 @@ struct VulkanVertexFormat : IVertexFormat
|
||||||
VkVertexInputBindingDescription m_bindings[2];
|
VkVertexInputBindingDescription m_bindings[2];
|
||||||
std::unique_ptr<VkVertexInputAttributeDescription[]> m_attributes;
|
std::unique_ptr<VkVertexInputAttributeDescription[]> m_attributes;
|
||||||
VkPipelineVertexInputStateCreateInfo m_info;
|
VkPipelineVertexInputStateCreateInfo m_info;
|
||||||
|
size_t m_stride = 0;
|
||||||
|
size_t m_instStride = 0;
|
||||||
|
|
||||||
VulkanVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
|
VulkanVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
|
||||||
: m_attributes(new VkVertexInputAttributeDescription[elementCount])
|
: m_attributes(new VkVertexInputAttributeDescription[elementCount])
|
||||||
{
|
{
|
||||||
|
@ -1642,8 +1666,6 @@ struct VulkanVertexFormat : IVertexFormat
|
||||||
m_info.vertexAttributeDescriptionCount = elementCount;
|
m_info.vertexAttributeDescriptionCount = elementCount;
|
||||||
m_info.pVertexAttributeDescriptions = m_attributes.get();
|
m_info.pVertexAttributeDescriptions = m_attributes.get();
|
||||||
|
|
||||||
size_t offset = 0;
|
|
||||||
size_t instOffset = 0;
|
|
||||||
for (size_t i=0 ; i<elementCount ; ++i)
|
for (size_t i=0 ; i<elementCount ; ++i)
|
||||||
{
|
{
|
||||||
const VertexElementDescriptor* elemin = &elements[i];
|
const VertexElementDescriptor* elemin = &elements[i];
|
||||||
|
@ -1654,28 +1676,28 @@ struct VulkanVertexFormat : IVertexFormat
|
||||||
if ((elemin->semantic & boo::VertexSemantic::Instanced) != boo::VertexSemantic::None)
|
if ((elemin->semantic & boo::VertexSemantic::Instanced) != boo::VertexSemantic::None)
|
||||||
{
|
{
|
||||||
attribute.binding = 1;
|
attribute.binding = 1;
|
||||||
attribute.offset = instOffset;
|
attribute.offset = m_instStride;
|
||||||
instOffset += SEMANTIC_SIZE_TABLE[semantic];
|
m_instStride += SEMANTIC_SIZE_TABLE[semantic];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
attribute.binding = 0;
|
attribute.binding = 0;
|
||||||
attribute.offset = offset;
|
attribute.offset = m_stride;
|
||||||
offset += SEMANTIC_SIZE_TABLE[semantic];
|
m_stride += SEMANTIC_SIZE_TABLE[semantic];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset)
|
if (m_stride)
|
||||||
{
|
{
|
||||||
m_bindings[0].binding = 0;
|
m_bindings[0].binding = 0;
|
||||||
m_bindings[0].stride = offset;
|
m_bindings[0].stride = m_stride;
|
||||||
m_bindings[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
m_bindings[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
++m_info.vertexBindingDescriptionCount;
|
++m_info.vertexBindingDescriptionCount;
|
||||||
}
|
}
|
||||||
if (instOffset)
|
if (m_instStride)
|
||||||
{
|
{
|
||||||
m_bindings[m_info.vertexBindingDescriptionCount].binding = 1;
|
m_bindings[m_info.vertexBindingDescriptionCount].binding = 1;
|
||||||
m_bindings[m_info.vertexBindingDescriptionCount].stride = instOffset;
|
m_bindings[m_info.vertexBindingDescriptionCount].stride = m_instStride;
|
||||||
m_bindings[m_info.vertexBindingDescriptionCount].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
|
m_bindings[m_info.vertexBindingDescriptionCount].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
|
||||||
++m_info.vertexBindingDescriptionCount;
|
++m_info.vertexBindingDescriptionCount;
|
||||||
}
|
}
|
||||||
|
@ -1707,8 +1729,10 @@ static const VkBlendFactor BLEND_FACTOR_TABLE[] =
|
||||||
class VulkanShaderPipeline : public IShaderPipeline
|
class VulkanShaderPipeline : public IShaderPipeline
|
||||||
{
|
{
|
||||||
friend class VulkanDataFactory;
|
friend class VulkanDataFactory;
|
||||||
|
friend struct VulkanShaderDataBinding;
|
||||||
VulkanContext* m_ctx;
|
VulkanContext* m_ctx;
|
||||||
VkPipelineCache m_pipelineCache;
|
VkPipelineCache m_pipelineCache;
|
||||||
|
const VulkanVertexFormat* m_vtxFmt;
|
||||||
VulkanShaderPipeline(VulkanContext* ctx,
|
VulkanShaderPipeline(VulkanContext* ctx,
|
||||||
VkShaderModule vert,
|
VkShaderModule vert,
|
||||||
VkShaderModule frag,
|
VkShaderModule frag,
|
||||||
|
@ -1716,7 +1740,7 @@ class VulkanShaderPipeline : public IShaderPipeline
|
||||||
const VulkanVertexFormat* vtxFmt,
|
const VulkanVertexFormat* vtxFmt,
|
||||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||||
bool depthTest, bool depthWrite, bool backfaceCulling)
|
bool depthTest, bool depthWrite, bool backfaceCulling)
|
||||||
: m_ctx(ctx), m_pipelineCache(pipelineCache)
|
: m_ctx(ctx), m_pipelineCache(pipelineCache), m_vtxFmt(vtxFmt)
|
||||||
{
|
{
|
||||||
VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE] = {};
|
VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE] = {};
|
||||||
VkPipelineDynamicStateCreateInfo dynamicState = {};
|
VkPipelineDynamicStateCreateInfo dynamicState = {};
|
||||||
|
@ -1945,6 +1969,9 @@ struct VulkanShaderDataBinding : IShaderDataBinding
|
||||||
VkDescriptorPool m_descPool = VK_NULL_HANDLE;
|
VkDescriptorPool m_descPool = VK_NULL_HANDLE;
|
||||||
VkDescriptorSet m_descSets[2];
|
VkDescriptorSet m_descSets[2];
|
||||||
|
|
||||||
|
size_t m_vertOffset;
|
||||||
|
size_t m_instOffset;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
/* Debugging aids */
|
/* Debugging aids */
|
||||||
bool m_committed = false;
|
bool m_committed = false;
|
||||||
|
@ -1955,7 +1982,8 @@ struct VulkanShaderDataBinding : IShaderDataBinding
|
||||||
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbuf, IGraphicsBuffer* ibuf,
|
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbuf, IGraphicsBuffer* ibuf,
|
||||||
size_t ubufCount, IGraphicsBuffer** ubufs,
|
size_t ubufCount, IGraphicsBuffer** ubufs,
|
||||||
const size_t* ubufOffs, const size_t* ubufSizes,
|
const size_t* ubufOffs, const size_t* ubufSizes,
|
||||||
size_t texCount, ITexture** texs)
|
size_t texCount, ITexture** texs,
|
||||||
|
size_t baseVert, size_t baseInst)
|
||||||
: m_ctx(ctx),
|
: m_ctx(ctx),
|
||||||
m_pipeline(static_cast<VulkanShaderPipeline*>(pipeline)),
|
m_pipeline(static_cast<VulkanShaderPipeline*>(pipeline)),
|
||||||
m_vbuf(vbuf),
|
m_vbuf(vbuf),
|
||||||
|
@ -1966,6 +1994,9 @@ struct VulkanShaderDataBinding : IShaderDataBinding
|
||||||
m_texCount(texCount),
|
m_texCount(texCount),
|
||||||
m_texs(new ITexture*[texCount])
|
m_texs(new ITexture*[texCount])
|
||||||
{
|
{
|
||||||
|
m_vertOffset = baseVert * m_pipeline->m_vtxFmt->m_stride;
|
||||||
|
m_instOffset = baseInst * m_pipeline->m_vtxFmt->m_instStride;
|
||||||
|
|
||||||
if (ubufOffs && ubufSizes)
|
if (ubufOffs && ubufSizes)
|
||||||
{
|
{
|
||||||
m_ubufOffs.reserve(ubufCount);
|
m_ubufOffs.reserve(ubufCount);
|
||||||
|
@ -2036,13 +2067,13 @@ struct VulkanShaderDataBinding : IShaderDataBinding
|
||||||
{
|
{
|
||||||
const VkDescriptorBufferInfo* vbufInfo = GetBufferGPUResource(m_vbuf, b);
|
const VkDescriptorBufferInfo* vbufInfo = GetBufferGPUResource(m_vbuf, b);
|
||||||
m_vboBufs[b][0] = vbufInfo->buffer;
|
m_vboBufs[b][0] = vbufInfo->buffer;
|
||||||
m_vboOffs[b][0] = vbufInfo->offset;
|
m_vboOffs[b][0] = vbufInfo->offset + m_vertOffset;
|
||||||
}
|
}
|
||||||
if (m_instVbuf)
|
if (m_instVbuf)
|
||||||
{
|
{
|
||||||
const VkDescriptorBufferInfo* vbufInfo = GetBufferGPUResource(m_instVbuf, b);
|
const VkDescriptorBufferInfo* vbufInfo = GetBufferGPUResource(m_instVbuf, b);
|
||||||
m_vboBufs[b][1] = vbufInfo->buffer;
|
m_vboBufs[b][1] = vbufInfo->buffer;
|
||||||
m_vboOffs[b][1] = vbufInfo->offset;
|
m_vboOffs[b][1] = vbufInfo->offset + m_instOffset;
|
||||||
}
|
}
|
||||||
if (m_ibuf)
|
if (m_ibuf)
|
||||||
{
|
{
|
||||||
|
@ -2769,12 +2800,23 @@ void VulkanDataFactory::destroyData(IGraphicsData* d)
|
||||||
data->m_dead = true;
|
data->m_dead = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VulkanDataFactory::destroyPool(IGraphicsBufferPool* p)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lk(m_committedMutex);
|
||||||
|
VulkanPool* pool = static_cast<VulkanPool*>(p);
|
||||||
|
m_committedPools.erase(pool);
|
||||||
|
delete pool;
|
||||||
|
}
|
||||||
|
|
||||||
void VulkanDataFactory::destroyAllData()
|
void VulkanDataFactory::destroyAllData()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(m_committedMutex);
|
std::unique_lock<std::mutex> lk(m_committedMutex);
|
||||||
for (IGraphicsData* data : m_committedData)
|
for (IGraphicsData* data : m_committedData)
|
||||||
delete static_cast<VulkanData*>(data);
|
delete static_cast<VulkanData*>(data);
|
||||||
|
for (IGraphicsBufferPool* pool : m_committedPools)
|
||||||
|
delete static_cast<VulkanPool*>(pool);
|
||||||
m_committedData.clear();
|
m_committedData.clear();
|
||||||
|
m_committedPools.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanDataFactory::VulkanDataFactory(IGraphicsContext* parent, VulkanContext* ctx, uint32_t drawSamples)
|
VulkanDataFactory::VulkanDataFactory(IGraphicsContext* parent, VulkanContext* ctx, uint32_t drawSamples)
|
||||||
|
@ -3003,7 +3045,9 @@ ITextureR* VulkanDataFactory::Context::newRenderTexture(size_t width, size_t hei
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
IVertexFormat* VulkanDataFactory::Context::newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
|
IVertexFormat* VulkanDataFactory::Context::newVertexFormat(size_t elementCount,
|
||||||
|
const VertexElementDescriptor* elements,
|
||||||
|
size_t baseVert, size_t baseInst)
|
||||||
{
|
{
|
||||||
VulkanVertexFormat* retval = new struct VulkanVertexFormat(elementCount, elements);
|
VulkanVertexFormat* retval = new struct VulkanVertexFormat(elementCount, elements);
|
||||||
static_cast<VulkanData*>(m_deferredData.get())->m_VFmts.emplace_back(retval);
|
static_cast<VulkanData*>(m_deferredData.get())->m_VFmts.emplace_back(retval);
|
||||||
|
@ -3015,11 +3059,13 @@ IShaderDataBinding* VulkanDataFactory::Context::newShaderDataBinding(IShaderPipe
|
||||||
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbuf, IGraphicsBuffer* ibuf,
|
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbuf, IGraphicsBuffer* ibuf,
|
||||||
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* /*ubufStages*/,
|
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* /*ubufStages*/,
|
||||||
const size_t* ubufOffs, const size_t* ubufSizes,
|
const size_t* ubufOffs, const size_t* ubufSizes,
|
||||||
size_t texCount, ITexture** texs)
|
size_t texCount, ITexture** texs,
|
||||||
|
size_t baseVert, size_t baseInst)
|
||||||
{
|
{
|
||||||
VulkanShaderDataBinding* retval =
|
VulkanShaderDataBinding* retval =
|
||||||
new VulkanShaderDataBinding(m_parent.m_ctx, pipeline, vbuf, instVbuf, ibuf,
|
new VulkanShaderDataBinding(m_parent.m_ctx, pipeline, vbuf, instVbuf, ibuf,
|
||||||
ubufCount, ubufs, ubufOffs, ubufSizes, texCount, texs);
|
ubufCount, ubufs, ubufOffs, ubufSizes, texCount, texs,
|
||||||
|
baseVert, baseInst);
|
||||||
static_cast<VulkanData*>(m_deferredData.get())->m_SBinds.emplace_back(retval);
|
static_cast<VulkanData*>(m_deferredData.get())->m_SBinds.emplace_back(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -3147,6 +3193,46 @@ GraphicsDataToken VulkanDataFactory::commitTransaction
|
||||||
return GraphicsDataToken(this, retval);
|
return GraphicsDataToken(this, retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IGraphicsBufferD* VulkanDataFactory::newPoolBuffer(IGraphicsBufferPool* p, BufferUse use,
|
||||||
|
size_t stride, size_t count)
|
||||||
|
{
|
||||||
|
VulkanPool* pool = static_cast<VulkanPool*>(p);
|
||||||
|
VulkanCommandQueue* q = static_cast<VulkanCommandQueue*>(m_parent->getCommandQueue());
|
||||||
|
VulkanGraphicsBufferD* retval = new VulkanGraphicsBufferD(q, use, m_ctx, stride, count);
|
||||||
|
|
||||||
|
/* size up resources */
|
||||||
|
uint32_t bufMemTypeBits = ~0;
|
||||||
|
VkDeviceSize bufMemSize = retval->sizeForGPU(m_ctx, bufMemTypeBits, 0);
|
||||||
|
|
||||||
|
/* allocate memory */
|
||||||
|
VkDeviceMemory bufMem = VK_NULL_HANDLE;
|
||||||
|
if (bufMemSize)
|
||||||
|
{
|
||||||
|
VkMemoryAllocateInfo memAlloc = {};
|
||||||
|
memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||||
|
memAlloc.allocationSize = bufMemSize;
|
||||||
|
ThrowIfFalse(MemoryTypeFromProperties(m_ctx, bufMemTypeBits,
|
||||||
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||||
|
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||||
|
&memAlloc.memoryTypeIndex));
|
||||||
|
ThrowIfFailed(vk::AllocateMemory(m_ctx->m_dev, &memAlloc, nullptr, &bufMem));
|
||||||
|
|
||||||
|
/* place resources */
|
||||||
|
retval->placeForGPU(m_ctx, bufMem);
|
||||||
|
}
|
||||||
|
|
||||||
|
pool->m_DBufs.emplace_back(bufMem, retval);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsBufferPoolToken VulkanDataFactory::newBufferPool()
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lk(m_committedMutex);
|
||||||
|
VulkanPool* retval = new VulkanPool(m_ctx);
|
||||||
|
m_committedPools.insert(retval);
|
||||||
|
return GraphicsBufferPoolToken(this, retval);
|
||||||
|
}
|
||||||
|
|
||||||
ThreadLocalPtr<struct VulkanData> VulkanDataFactory::m_deferredData;
|
ThreadLocalPtr<struct VulkanData> VulkanDataFactory::m_deferredData;
|
||||||
|
|
||||||
void VulkanCommandQueue::execute()
|
void VulkanCommandQueue::execute()
|
||||||
|
@ -3164,6 +3250,11 @@ void VulkanCommandQueue::execute()
|
||||||
for (std::unique_ptr<VulkanTextureD>& t : d->m_DTexs)
|
for (std::unique_ptr<VulkanTextureD>& t : d->m_DTexs)
|
||||||
t->update(m_fillBuf);
|
t->update(m_fillBuf);
|
||||||
}
|
}
|
||||||
|
for (VulkanPool* p : gfxF->m_committedPools)
|
||||||
|
{
|
||||||
|
for (VulkanPool::Buffer& b : p->m_DBufs)
|
||||||
|
b.m_buffer->update(m_fillBuf);
|
||||||
|
}
|
||||||
datalk.unlock();
|
datalk.unlock();
|
||||||
|
|
||||||
/* Perform dynamic uploads */
|
/* Perform dynamic uploads */
|
||||||
|
|
|
@ -5,6 +5,10 @@
|
||||||
#include <winver.h>
|
#include <winver.h>
|
||||||
#include <Dbt.h>
|
#include <Dbt.h>
|
||||||
|
|
||||||
|
#if _WIN32_WINNT_WINBLUE
|
||||||
|
PFN_GetScaleFactorForMonitor MyGetScaleFactorForMonitor = nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if _DEBUG
|
#if _DEBUG
|
||||||
#define D3D11_CREATE_DEVICE_FLAGS D3D11_CREATE_DEVICE_DEBUG
|
#define D3D11_CREATE_DEVICE_FLAGS D3D11_CREATE_DEVICE_DEBUG
|
||||||
#else
|
#else
|
||||||
|
@ -453,6 +457,21 @@ int ApplicationRun(IApplication::EPlatformType platform,
|
||||||
platform != IApplication::EPlatformType::Auto)
|
platform != IApplication::EPlatformType::Auto)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
#if _WIN32_WINNT_WINBLUE
|
||||||
|
/* HI-DPI support */
|
||||||
|
HMODULE shcoreLib = LoadLibraryW(L"Shcore.dll");
|
||||||
|
if (shcoreLib)
|
||||||
|
{
|
||||||
|
PFN_SetProcessDpiAwareness MySetProcessDpiAwareness =
|
||||||
|
(PFN_SetProcessDpiAwareness)GetProcAddress(shcoreLib, "SetProcessDpiAwareness");
|
||||||
|
if (MySetProcessDpiAwareness)
|
||||||
|
MySetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE);
|
||||||
|
|
||||||
|
MyGetScaleFactorForMonitor =
|
||||||
|
(PFN_GetScaleFactorForMonitor)GetProcAddress(shcoreLib, "GetScaleFactorForMonitor");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
WIN32_CURSORS.m_arrow = LoadCursor(nullptr, IDC_ARROW);
|
WIN32_CURSORS.m_arrow = LoadCursor(nullptr, IDC_ARROW);
|
||||||
WIN32_CURSORS.m_hResize = LoadCursor(nullptr, IDC_SIZEWE);
|
WIN32_CURSORS.m_hResize = LoadCursor(nullptr, IDC_SIZEWE);
|
||||||
WIN32_CURSORS.m_vResize = LoadCursor(nullptr, IDC_SIZENS);
|
WIN32_CURSORS.m_vResize = LoadCursor(nullptr, IDC_SIZENS);
|
||||||
|
|
|
@ -16,6 +16,13 @@ extern DWORD g_mainThreadId;
|
||||||
|
|
||||||
namespace boo {class IWindow;}
|
namespace boo {class IWindow;}
|
||||||
|
|
||||||
|
#if _WIN32_WINNT_WINBLUE
|
||||||
|
#include <ShellScalingApi.h>
|
||||||
|
typedef HRESULT (WINAPI* PFN_SetProcessDpiAwareness)( _In_ PROCESS_DPI_AWARENESS );
|
||||||
|
typedef HRESULT (WINAPI* PFN_GetScaleFactorForMonitor)( _In_ HMONITOR, _Out_ DEVICE_SCALE_FACTOR *);
|
||||||
|
extern PFN_GetScaleFactorForMonitor MyGetScaleFactorForMonitor;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if _WIN32_WINNT_WIN10
|
#if _WIN32_WINNT_WIN10
|
||||||
#include <dxgi1_4.h>
|
#include <dxgi1_4.h>
|
||||||
#include <d3d12.h>
|
#include <d3d12.h>
|
||||||
|
|
|
@ -1092,7 +1092,18 @@ public:
|
||||||
|
|
||||||
float getVirtualPixelFactor() const
|
float getVirtualPixelFactor() const
|
||||||
{
|
{
|
||||||
return 1.0;
|
#if _WIN32_WINNT_WINBLUE
|
||||||
|
if (MyGetScaleFactorForMonitor)
|
||||||
|
{
|
||||||
|
DEVICE_SCALE_FACTOR Factor;
|
||||||
|
HMONITOR mon = MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTOPRIMARY);
|
||||||
|
MyGetScaleFactorForMonitor(mon, &Factor);
|
||||||
|
if (Factor == DEVICE_SCALE_FACTOR_INVALID)
|
||||||
|
return 1.f;
|
||||||
|
return Factor / 100.f;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFullscreen() const
|
bool isFullscreen() const
|
||||||
|
|
Loading…
Reference in New Issue