diff options
Diffstat (limited to 'LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_Util.cpp')
-rw-r--r-- | LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_Util.cpp | 758 |
1 files changed, 758 insertions, 0 deletions
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_Util.cpp b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_Util.cpp new file mode 100644 index 0000000..36f1de0 --- /dev/null +++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_Util.cpp @@ -0,0 +1,758 @@ +/************************************************************************************ + +Filename : CAPI_D3D11_Util.cpp +Content : D3DX11 utility classes for rendering +Created : September 10, 2012 +Authors : Andrew Reisse + +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.2 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#include "CAPI_D3D11_Util.h" + +namespace OVR { namespace CAPI { namespace D3D11 { + + +//------------------------------------------------------------------------------------- +// ***** ShaderFill + +void ShaderFill::Set(PrimitiveType prim) const +{ + Shaders->Set(prim); + + for(int i = 0; i < 8; ++i) + { + if ( VsTextures[i] != NULL ) + { + VsTextures[i]->Set(i, Shader_Vertex); + } + } + + for(int i = 0; i < 8; ++i) + { + if ( CsTextures[i] != NULL ) + { + CsTextures[i]->Set(i, Shader_Compute); + } + } + + for(int i = 0; i < 8; ++i) + { + if ( PsTextures[i] != NULL ) + { + PsTextures[i]->Set(i, Shader_Fragment); + } + } +} + + +//------------------------------------------------------------------------------------- +// ***** Buffer + +Buffer::~Buffer() +{ +} + +bool Buffer::Data(int use, const void *buffer, size_t size, int computeBufferStride /*=-1*/) +{ + HRESULT hr; + + if (D3DBuffer && Size >= size) + { + if (Dynamic) + { + if (!buffer) + return true; + + void* v = Map(0, size, Map_Discard); + if (v) + { + memcpy(v, buffer, size); + Unmap(v); + return true; + } + } + else + { + OVR_ASSERT (!(use & Buffer_ReadOnly)); + pParams->pContext->UpdateSubresource(D3DBuffer, 0, NULL, buffer, 0, 0); + return true; + } + } + if (D3DBuffer) + { + D3DBuffer = NULL; + Size = 0; + Use = 0; + Dynamic = false; + } + D3DSrv = NULL; + D3DUav = NULL; + + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(desc)); + if (use & Buffer_ReadOnly) + { + desc.Usage = D3D11_USAGE_IMMUTABLE; + desc.CPUAccessFlags = 0; + } + else + { + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + Dynamic = true; + } + + switch(use & Buffer_TypeMask) + { + case Buffer_Vertex: desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; break; + case Buffer_Index: desc.BindFlags = D3D11_BIND_INDEX_BUFFER; break; + case Buffer_Uniform: + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + size = ((size + 15) & ~15); + break; + case Buffer_Compute: + // There's actually a bunch of options for buffers bound to a CS. + // Right now this is the most appropriate general-purpose one. Add more as needed. + + // NOTE - if you want D3D11_(CPU_ACCESS_WRITE), it MUST be either D3D11_(USAGE_DYNAMIC) or D3D11_(USAGE_STAGING). + // TODO: we want a resource that is rarely written to, in which case we'd need two surfaces - one a STAGING + // that the CPU writes to, and one a DEFAULT, and we CopyResource from one to the other. Hassle! + // Setting it as D3D11_(USAGE_DYNAMIC) will get the job done for now. + // Also for fun - you can't have a D3D11_(USAGE_DYNAMIC) buffer that is also a D3D11_(BIND_UNORDERED_ACCESS). + OVR_ASSERT ( !(use & Buffer_ReadOnly) ); + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + OVR_ASSERT ( computeBufferStride > 0 ); + desc.StructureByteStride = computeBufferStride; // sizeof(DistortionComputePin); + + Dynamic = true; + size = ((size + 15) & ~15); + break; + } + + desc.ByteWidth = (unsigned)size; + + D3D11_SUBRESOURCE_DATA sr; + sr.pSysMem = buffer; + sr.SysMemPitch = 0; + sr.SysMemSlicePitch = 0; + + D3DBuffer = NULL; + hr = pParams->pDevice->CreateBuffer(&desc, buffer ? &sr : NULL, &D3DBuffer.GetRawRef()); + OVR_D3D_CHECK_RET_FALSE(hr); + + Use = 0; + Size = 0; + + if ( ( use & Buffer_TypeMask ) == Buffer_Compute ) + { + hr = pParams->pDevice->CreateShaderResourceView ( D3DBuffer, NULL, &D3DSrv.GetRawRef() ); + OVR_D3D_CHECK_RET_FALSE(hr); + +#if 0 // Right now we do NOT ask for UAV access (see flags above). + hr = Ren->Device->CreateUnorderedAccessView ( D3DBuffer, NULL, &D3DUav.GetRawRef() ); + OVR_D3D_CHECK_RET_FALSE(hr); +#endif + } + + Use = use; + Size = desc.ByteWidth; + + return true; + +} + +void* Buffer::Map(size_t start, size_t size, int flags) +{ + OVR_UNUSED(size); + + D3D11_MAP mapFlags = D3D11_MAP_WRITE; + if (flags & Map_Discard) + mapFlags = D3D11_MAP_WRITE_DISCARD; + if (flags & Map_Unsynchronized) + mapFlags = D3D11_MAP_WRITE_NO_OVERWRITE; + + D3D11_MAPPED_SUBRESOURCE map; + if (SUCCEEDED(pParams->pContext->Map(D3DBuffer, 0, mapFlags, 0, &map))) + return ((char*)map.pData) + start; + + return NULL; +} + +bool Buffer::Unmap(void *m) +{ + OVR_UNUSED(m); + + pParams->pContext->Unmap(D3DBuffer, 0); + return true; +} + + +//------------------------------------------------------------------------------------- +// Shaders + +template<> bool ShaderImpl<Shader_Vertex, ID3D11VertexShader>::Load(void* shader, size_t size) +{ + HRESULT hr = pParams->pDevice->CreateVertexShader(shader, size, nullptr, &D3DShader); + OVR_D3D_CHECK_RET_FALSE(hr); + return true; +} +template<> bool ShaderImpl<Shader_Pixel, ID3D11PixelShader>::Load(void* shader, size_t size) +{ + HRESULT hr = pParams->pDevice->CreatePixelShader(shader, size, nullptr, &D3DShader); + OVR_D3D_CHECK_RET_FALSE(hr); + return true; +} +template<> bool ShaderImpl<Shader_Compute, ID3D11ComputeShader>::Load(void* shader, size_t size) +{ + HRESULT hr = pParams->pDevice->CreateComputeShader(shader, size, nullptr, &D3DShader); + OVR_D3D_CHECK_RET_FALSE(hr); + return true; +} + +template<> void ShaderImpl<Shader_Vertex, ID3D11VertexShader>::Set(PrimitiveType) const +{ + pParams->pContext->VSSetShader(D3DShader, nullptr, 0); +} +template<> void ShaderImpl<Shader_Pixel, ID3D11PixelShader>::Set(PrimitiveType) const +{ + pParams->pContext->PSSetShader(D3DShader, nullptr, 0); +} +template<> void ShaderImpl<Shader_Compute, ID3D11ComputeShader>::Set(PrimitiveType) const +{ + pParams->pContext->CSSetShader(D3DShader, nullptr, 0); +} + +template<> void ShaderImpl<Shader_Vertex, ID3D11VertexShader>::SetUniformBuffer(Buffer* buffer, int i) +{ + pParams->pContext->VSSetConstantBuffers(i, 1, &((Buffer*)buffer)->D3DBuffer.GetRawRef()); +} +template<> void ShaderImpl<Shader_Pixel, ID3D11PixelShader>::SetUniformBuffer(Buffer* buffer, int i) +{ + pParams->pContext->PSSetConstantBuffers(i, 1, &((Buffer*)buffer)->D3DBuffer.GetRawRef()); +} +template<> void ShaderImpl<Shader_Compute, ID3D11ComputeShader>::SetUniformBuffer(Buffer* buffer, int i) +{ + pParams->pContext->CSSetConstantBuffers(i, 1, &((Buffer*)buffer)->D3DBuffer.GetRawRef()); +} + +//------------------------------------------------------------------------------------- +// ***** Shader Base + +ShaderBase::ShaderBase(RenderParams* rp, ShaderStage stage) : + Shader(stage), + pParams(rp), + UniformData(NULL), + UniformsSize(0), + UniformRefl(NULL), + UniformReflSize(0) +{ +} + +ShaderBase::~ShaderBase() +{ + if (UniformData) + { + OVR_FREE(UniformData); + UniformData = NULL; + } + + // UniformRefl does not need to be freed + UniformRefl = NULL; +} + +bool ShaderBase::SetUniform(const char* name, int n, const float* v) +{ + for(unsigned i = 0; i < UniformReflSize; i++) + { + if (!strcmp(UniformRefl[i].Name, name)) + { + memcpy(UniformData + UniformRefl[i].Offset, v, n * sizeof(float)); + return 1; + } + } + return 0; +} + +bool ShaderBase::SetUniformBool(const char* name, int n, const bool* v) +{ + OVR_UNUSED(n); + for(unsigned i = 0; i < UniformReflSize; i++) + { + if (!strcmp(UniformRefl[i].Name, name)) + { + memcpy(UniformData + UniformRefl[i].Offset, v, UniformRefl[i].Size); + return 1; + } + } + return 0; +} + +void ShaderBase::InitUniforms(const Uniform* refl, size_t reflSize) +{ + UniformsSize = 0; + if (UniformData) + { + OVR_FREE(UniformData); + UniformData = 0; + } + + if (!refl) + { + UniformRefl = NULL; + UniformReflSize = 0; + return; // no reflection data + } + + UniformRefl = refl; + UniformReflSize = reflSize; + + UniformsSize = UniformRefl[UniformReflSize-1].Offset + UniformRefl[UniformReflSize-1].Size; + UniformData = (unsigned char*)OVR_ALLOC(UniformsSize); +} + +void ShaderBase::UpdateBuffer(Buffer* buf) +{ + if (UniformsSize) + { + buf->Data(Buffer_Uniform, UniformData, UniformsSize); + } +} + + +//------------------------------------------------------------------------------------- +// ***** Texture +// +Texture::Texture(RenderParams* rp, int fmt, const Sizei texSize, + ID3D11SamplerState* sampler, int samples) + : pParams(rp), Tex(NULL), TexSv(NULL), TexRtv(NULL), TexDsv(NULL), + TextureSize(texSize), + Sampler(sampler), + Samples(samples) +{ + OVR_UNUSED(fmt); +} + + +Texture::Texture(RenderParams* rp, int format, const Sizei texSize, + ID3D11SamplerState* sampler, const void* data, int mipcount) + : pParams(rp), Tex(NULL), TexSv(NULL), TexRtv(NULL), TexDsv(NULL), + TextureSize(texSize), + Sampler(sampler), + Samples(1) +{ + OVR_ASSERT(rp->pDevice != NULL); + + OVR_UNUSED(mipcount); + + //if (format == Texture_DXT1 || format == Texture_DXT3 || format == Texture_DXT5) + //{ + // int convertedFormat; + // switch (format) + // { + // case Texture_DXT1: convertedFormat = DXGI_FORMAT_BC1_UNORM; break; + // case Texture_DXT3: convertedFormat = DXGI_FORMAT_BC2_UNORM; break; + // case Texture_DXT5: + // default: convertedFormat = DXGI_FORMAT_BC3_UNORM; break; + // } + // unsigned largestMipWidth = 0; + // unsigned largestMipHeight = 0; + // unsigned effectiveMipCount = mipcount; + // unsigned textureSize = 0; + + // D3D11_SUBRESOURCE_DATA* subresData = + // (D3D11_SUBRESOURCE_DATA*) OVR_ALLOC(sizeof(D3D11_SUBRESOURCE_DATA) * mipcount); + // GenerateSubresourceData(width, height, convertedFormat, imageDimUpperLimit, data, subresData, largestMipWidth, + // largestMipHeight, textureSize, effectiveMipCount); + // TotalTextureMemoryUsage += textureSize; + + // if (!Device || !subresData) + // { + // return NULL; + // } + + // Texture* NewTex = new Texture(this, format, largestMipWidth, largestMipHeight); + // // BCn/DXTn - no AA. + // Samples = 1; + + // D3D11_TEXTURE2D_DESC desc; + // desc.Width = largestMipWidth; + // desc.Height = largestMipHeight; + // desc.MipLevels = effectiveMipCount; + // desc.ArraySize = 1; + // desc.Format = static_cast<DXGI_FORMAT>(convertedFormat); + // desc.SampleDesc.Count = 1; + // desc.SampleDesc.Quality = 0; + // desc.Usage = D3D11_USAGE_DEFAULT; + // desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + // desc.CPUAccessFlags = 0; + // desc.MiscFlags = 0; + + // Tex = NULL; + // HRESULT hr = Device->CreateTexture2D(&desc, static_cast<D3D11_SUBRESOURCE_DATA*>(subresData), + // &Tex.GetRawRef()); + // OVR_FREE(subresData); + // if (FAILED(hr)) + // { + // OVR_LOG_COM_ERROR(hr); + // } + + // if (SUCCEEDED(hr) && NewTex != 0) + // { + // D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; + // memset(&SRVDesc, 0, sizeof(SRVDesc)); + // SRVDesc.Format = static_cast<DXGI_FORMAT>(format); + // SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D; + // SRVDesc.Texture2D.MipLevels = desc.MipLevels; + + // TexSv = NULL; + // hr = Device->CreateShaderResourceView(Tex, NULL, &TexSv.GetRawRef()); + + // if (FAILED(hr)) + // { + // OVR_LOG_COM_ERROR(hr); + // Release(); + // return NULL; + // } + // return NewTex; + // } + + // return NULL; + //} + //else + { + int samples = (format & Texture_SamplesMask); + if (samples < 1) + { + samples = 1; + } + + bool createDepthSrv = (format & Texture_SampleDepth) > 0; + + DXGI_FORMAT d3dformat; + int bpp; + switch(format & Texture_TypeMask) + { + //case Texture_BGRA: + // bpp = 4; + // d3dformat = (format & Texture_SRGB) ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : DXGI_FORMAT_B8G8R8A8_UNORM; + // break; + case Texture_RGBA: + bpp = 4; + //d3dformat = (format & Texture_SRGB) ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM; + d3dformat = DXGI_FORMAT_R8G8B8A8_UNORM; + break; + //case Texture_R: + // bpp = 1; + // d3dformat = DXGI_FORMAT_R8_UNORM; + // break; + //case Texture_A: + // bpp = 1; + // d3dformat = DXGI_FORMAT_A8_UNORM; + // break; + case Texture_Depth: + bpp = 0; + d3dformat = createDepthSrv ? DXGI_FORMAT_R32_TYPELESS : DXGI_FORMAT_D32_FLOAT; + break; + default: + bpp = 4; + d3dformat = DXGI_FORMAT_R8G8B8A8_UNORM; + OVR_ASSERT(0); + } + + D3D11_TEXTURE2D_DESC dsDesc; + dsDesc.Width = texSize.w; + dsDesc.Height = texSize.h; + dsDesc.MipLevels = (format == (Texture_RGBA | Texture_GenMipmaps) && data) ? GetNumMipLevels(texSize.w, texSize.h) : 1; + dsDesc.ArraySize = 1; + dsDesc.Format = d3dformat; + dsDesc.SampleDesc.Count = samples; + dsDesc.SampleDesc.Quality = 0; + dsDesc.Usage = D3D11_USAGE_DEFAULT; + dsDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + dsDesc.CPUAccessFlags = 0; + dsDesc.MiscFlags = 0; + + if (format & Texture_RenderTarget) + { + if ((format & Texture_TypeMask) == Texture_Depth) + { + dsDesc.BindFlags = createDepthSrv ? (dsDesc.BindFlags | D3D11_BIND_DEPTH_STENCIL) : D3D11_BIND_DEPTH_STENCIL; + } + else + { + dsDesc.BindFlags |= D3D11_BIND_RENDER_TARGET; + } + } + + Tex = NULL; + HRESULT hr = rp->pDevice->CreateTexture2D(&dsDesc, NULL, &Tex.GetRawRef()); + if (FAILED(hr)) + { + OVR_ASSERT(0); + //OVR_DEBUG_LOG_TEXT(("Failed to create 2D D3D texture.")); + Release(); + return; + } + if (dsDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE) + { + if((dsDesc.BindFlags & D3D11_BIND_DEPTH_STENCIL) > 0 && createDepthSrv) + { + D3D11_SHADER_RESOURCE_VIEW_DESC depthSrv; + depthSrv.Format = DXGI_FORMAT_R32_FLOAT; + depthSrv.ViewDimension = samples > 1 ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D; + depthSrv.Texture2D.MostDetailedMip = 0; + depthSrv.Texture2D.MipLevels = dsDesc.MipLevels; + TexSv = NULL; + hr = rp->pDevice->CreateShaderResourceView(Tex, &depthSrv, &TexSv.GetRawRef()); + if (FAILED(hr)) + { + OVR_ASSERT(0); + } + } + else + { + TexSv = NULL; + hr = rp->pDevice->CreateShaderResourceView(Tex, NULL, &TexSv.GetRawRef()); + if (FAILED(hr)) + { + OVR_ASSERT(0); + } + } + } + + if (data) + { + rp->pContext->UpdateSubresource(Tex, 0, NULL, data, texSize.w * bpp, texSize.w * texSize.h * bpp); + if (format == (Texture_RGBA | Texture_GenMipmaps)) + { + int srcw = texSize.w, srch = texSize.h; + int level = 0; + uint8_t* mipmaps = NULL; + do + { + level++; + int mipw = srcw >> 1; + if (mipw < 1) + { + mipw = 1; + } + int miph = srch >> 1; + if (miph < 1) + { + miph = 1; + } + if (mipmaps == NULL) + { + mipmaps = (uint8_t*)OVR_ALLOC(mipw * miph * 4); + } + FilterRgba2x2(level == 1 ? (const uint8_t*)data : mipmaps, srcw, srch, mipmaps); + rp->pContext->UpdateSubresource(Tex, level, NULL, mipmaps, mipw * bpp, miph * bpp); + srcw = mipw; + srch = miph; + } + while(srcw > 1 || srch > 1); + + if (mipmaps != NULL) + { + OVR_FREE(mipmaps); + } + } + } + + if (format & Texture_RenderTarget) + { + if ((format & Texture_TypeMask) == Texture_Depth) + { + D3D11_DEPTH_STENCIL_VIEW_DESC depthDsv; + ZeroMemory(&depthDsv, sizeof(depthDsv)); + depthDsv.Format = DXGI_FORMAT_D32_FLOAT; + depthDsv.ViewDimension = samples > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D; + depthDsv.Texture2D.MipSlice = 0; + TexDsv = NULL; + hr = rp->pDevice->CreateDepthStencilView(Tex, createDepthSrv ? &depthDsv : NULL, &TexDsv.GetRawRef()); + if (FAILED(hr)) + { + OVR_ASSERT(0); + } + } + else + { + TexRtv = NULL; + hr = rp->pDevice->CreateRenderTargetView(Tex, NULL, &TexRtv.GetRawRef()); + if (FAILED(hr)) + { + OVR_ASSERT(0); + } + } + } + } +} + +Texture::~Texture() +{ +} + +void Texture::Set(int slot, ShaderStage stage) const +{ + ID3D11ShaderResourceView* texSv = TexSv.GetPtr(); + + switch(stage) + { + case Shader_Fragment: + pParams->pContext->PSSetShaderResources(slot, 1, &texSv); + pParams->pContext->PSSetSamplers(slot, 1, &Sampler.GetRawRef()); + break; + + case Shader_Vertex: + pParams->pContext->VSSetShaderResources(slot, 1, &texSv); + pParams->pContext->VSSetSamplers(slot, 1, &Sampler.GetRawRef()); + break; + + case Shader_Compute: + pParams->pContext->CSSetShaderResources(slot, 1, &texSv); + pParams->pContext->CSSetSamplers(slot, 1, &Sampler.GetRawRef()); + break; + + default: OVR_ASSERT ( false ); break; + } +} + + +//------------------------------------------------------------------------------------- +// ***** GpuTimer +// +#define D3DQUERY_EXEC(_context_, _query_, _command_, ...) _context_->_command_(_query_, __VA_ARGS__) + + +void GpuTimer::Init(ID3D11Device* device, ID3D11DeviceContext* content) +{ + D3dDevice = device; + Context = content; +} + +void GpuTimer::BeginQuery() +{ + HRESULT hr; + + if(GotoNextFrame(LastQueuedFrame) == LastTimedFrame) + { + OVR_ASSERT(false); // too many queries queued + return; + } + + LastQueuedFrame = GotoNextFrame(LastQueuedFrame); + + GpuQuerySets& newQuerySet = QuerySets[LastQueuedFrame]; + if(newQuerySet.DisjointQuery == NULL) + { + // Create the queries + D3D11_QUERY_DESC desc; + desc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT; + desc.MiscFlags = 0; + hr = D3dDevice->CreateQuery(&desc, &newQuerySet.DisjointQuery); + OVR_D3D_CHECK_RET(hr); + + desc.Query = D3D11_QUERY_TIMESTAMP; + hr = D3dDevice->CreateQuery(&desc, &newQuerySet.TimeStartQuery); + OVR_D3D_CHECK_RET(hr); + hr = D3dDevice->CreateQuery(&desc, &newQuerySet.TimeEndQuery); + OVR_D3D_CHECK_RET(hr); + } + + OVR_ASSERT(!newQuerySet.QueryStarted); + OVR_ASSERT(!newQuerySet.QueryAwaitingTiming); + + + D3DQUERY_EXEC(Context, QuerySets[LastQueuedFrame].DisjointQuery, Begin, ); // First start a disjoint query + D3DQUERY_EXEC(Context, QuerySets[LastQueuedFrame].TimeStartQuery, End, ); // Insert start timestamp + + newQuerySet.QueryStarted = true; + newQuerySet.QueryAwaitingTiming = false; + //newQuerySet.QueryTimed = false; +} + +void GpuTimer::EndQuery() +{ + if(LastQueuedFrame > 0 && !QuerySets[LastQueuedFrame].QueryStarted) + return; + + GpuQuerySets& doneQuerySet = QuerySets[LastQueuedFrame]; + OVR_ASSERT(doneQuerySet.QueryStarted); + OVR_ASSERT(!doneQuerySet.QueryAwaitingTiming); + + // Insert the end timestamp + D3DQUERY_EXEC(Context, doneQuerySet.TimeEndQuery, End, ); + + // End the disjoint query + D3DQUERY_EXEC(Context, doneQuerySet.DisjointQuery, End, ); + + doneQuerySet.QueryStarted = false; + doneQuerySet.QueryAwaitingTiming = true; +} + +float GpuTimer::GetTiming(bool blockUntilValid) +{ + float time = -1.0f; + + // loop until we hit a query that is not ready yet, or we have read all queued queries + while(LastTimedFrame != LastQueuedFrame) + { + int timeTestFrame = GotoNextFrame(LastTimedFrame); + + GpuQuerySets& querySet = QuerySets[timeTestFrame]; + + OVR_ASSERT(!querySet.QueryStarted && querySet.QueryAwaitingTiming); + + UINT64 startTime = 0; + UINT64 endTime = 0; + D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjointData; + + if(blockUntilValid) + { + while(D3DQUERY_EXEC(Context, querySet.TimeStartQuery, GetData, &startTime, sizeof(startTime), 0) != S_OK); + while(D3DQUERY_EXEC(Context, querySet.TimeEndQuery, GetData, &endTime, sizeof(endTime), 0) != S_OK); + while(D3DQUERY_EXEC(Context, querySet.DisjointQuery, GetData, &disjointData, sizeof(disjointData), 0) != S_OK); + } + else + { +// Early return if we fail to get data for any of these + if(D3DQUERY_EXEC(Context, querySet.TimeStartQuery, GetData, &startTime, sizeof(startTime), 0) != S_OK) return time; + if(D3DQUERY_EXEC(Context, querySet.TimeEndQuery, GetData, &endTime, sizeof(endTime), 0) != S_OK) return time; + if(D3DQUERY_EXEC(Context, querySet.DisjointQuery, GetData, &disjointData, sizeof(disjointData), 0) != S_OK) return time; + } + + querySet.QueryAwaitingTiming = false; + LastTimedFrame = timeTestFrame; // successfully retrieved the timing data + + if(disjointData.Disjoint == false) + { + UINT64 delta = endTime - startTime; + float frequency = (float)(disjointData.Frequency); + time = (delta / frequency); + } + } + + return time; +} + +}}} // OVR::CAPI::D3D11 |