diff options
Diffstat (limited to 'LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.cpp')
-rw-r--r-- | LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.cpp | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.cpp b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.cpp new file mode 100644 index 0000000..501a8e3 --- /dev/null +++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.cpp @@ -0,0 +1,416 @@ +/************************************************************************************ + +Filename : CAPI_D3D1X_Util.cpp +Content : D3DX10 utility classes for rendering +Created : September 10, 2012 +Authors : Andrew Reisse + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (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.1 + +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_D3D1X_Util.h" + +#include <d3dcompiler.h> + +namespace OVR { namespace CAPI { namespace D3D_NS { + + +//------------------------------------------------------------------------------------- +// ***** ShaderFill + +void ShaderFill::Set(PrimitiveType prim) const +{ + Shaders->Set(prim); + for(int i = 0; i < 8; i++) + { + if(Textures[i]) + { + Textures[i]->Set(i); + } + } +} + + +//------------------------------------------------------------------------------------- +// ***** Buffer + +Buffer::~Buffer() +{ +} + +bool Buffer::Data(int use, const void *buffer, size_t size) +{ + 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 + { + pParams->pContext->UpdateSubresource(D3DBuffer, 0, NULL, buffer, 0, 0); + return true; + } + } + if (D3DBuffer) + { + D3DBuffer = NULL; + Size = 0; + Use = 0; + Dynamic = 0; + } + + D3D1X_(BUFFER_DESC) desc; + memset(&desc, 0, sizeof(desc)); + if (use & Buffer_ReadOnly) + { + desc.Usage = D3D1X_(USAGE_IMMUTABLE); + desc.CPUAccessFlags = 0; + } + else + { + desc.Usage = D3D1X_(USAGE_DYNAMIC); + desc.CPUAccessFlags = D3D1X_(CPU_ACCESS_WRITE); + Dynamic = 1; + } + + switch(use & Buffer_TypeMask) + { + case Buffer_Vertex: desc.BindFlags = D3D1X_(BIND_VERTEX_BUFFER); break; + case Buffer_Index: desc.BindFlags = D3D1X_(BIND_INDEX_BUFFER); break; + case Buffer_Uniform: + desc.BindFlags = D3D1X_(BIND_CONSTANT_BUFFER); + size += ((size + 15) & ~15) - size; + break; + } + + desc.ByteWidth = (unsigned)size; + + D3D1X_(SUBRESOURCE_DATA) sr; + sr.pSysMem = buffer; + sr.SysMemPitch = 0; + sr.SysMemSlicePitch = 0; + + HRESULT hr = pParams->pDevice->CreateBuffer(&desc, buffer ? &sr : NULL, &D3DBuffer.GetRawRef()); + if (SUCCEEDED(hr)) + { + Use = use; + Size = desc.ByteWidth; + return 1; + } + return 0; +} + +void* Buffer::Map(size_t start, size_t size, int flags) +{ + OVR_UNUSED(size); + + D3D1X_(MAP) mapFlags = D3D1X_(MAP_WRITE); + if (flags & Map_Discard) + mapFlags = D3D1X_(MAP_WRITE_DISCARD); + if (flags & Map_Unsynchronized) + mapFlags = D3D1X_(MAP_WRITE_NO_OVERWRITE); + +#if (OVR_D3D_VERSION == 10) + void* map; + if (SUCCEEDED(D3DBuffer->Map(mapFlags, 0, &map))) + return ((char*)map) + start; +#else + D3D11_MAPPED_SUBRESOURCE map; + if (SUCCEEDED(pParams->pContext->Map(D3DBuffer, 0, mapFlags, 0, &map))) + return ((char*)map.pData) + start; +#endif + + return NULL; +} + +bool Buffer::Unmap(void *m) +{ + OVR_UNUSED(m); + + D3DSELECT_10_11( D3DBuffer->Unmap(), + pParams->pContext->Unmap(D3DBuffer, 0) ); + return true; +} + + +//------------------------------------------------------------------------------------- +// Shaders + +template<> bool ShaderImpl<Shader_Vertex, ID3D1xVertexShader>::Load(void* shader, size_t size) +{ + return SUCCEEDED(pParams->pDevice->CreateVertexShader(shader, size D3D11_COMMA_0, &D3DShader)); +} +template<> bool ShaderImpl<Shader_Pixel, ID3D1xPixelShader>::Load(void* shader, size_t size) +{ + return SUCCEEDED(pParams->pDevice->CreatePixelShader(shader, size D3D11_COMMA_0, &D3DShader)); +} + +template<> void ShaderImpl<Shader_Vertex, ID3D1xVertexShader>::Set(PrimitiveType) const +{ + pParams->pContext->VSSetShader(D3DShader D3D11_COMMA_0 D3D11_COMMA_0 ); +} +template<> void ShaderImpl<Shader_Pixel, ID3D1xPixelShader>::Set(PrimitiveType) const +{ + pParams->pContext->PSSetShader(D3DShader D3D11_COMMA_0 D3D11_COMMA_0 ) ; +} + +template<> void ShaderImpl<Shader_Vertex, ID3D1xVertexShader>::SetUniformBuffer(Buffer* buffer, int i) +{ + pParams->pContext->VSSetConstantBuffers(i, 1, &((Buffer*)buffer)->D3DBuffer.GetRawRef()); +} +template<> void ShaderImpl<Shader_Pixel, ID3D1xPixelShader>::SetUniformBuffer(Buffer* buffer, int i) +{ + pParams->pContext->PSSetConstantBuffers(i, 1, &((Buffer*)buffer)->D3DBuffer.GetRawRef()); +} + + +//------------------------------------------------------------------------------------- +// ***** Shader Base + +ShaderBase::ShaderBase(RenderParams* rp, ShaderStage stage) + : Shader(stage), pParams(rp), UniformData(0) +{ +} +ShaderBase::~ShaderBase() +{ + if (UniformData) + OVR_FREE(UniformData); +} + +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) +{ + if(!refl) + { + UniformRefl = NULL; + UniformReflSize = 0; + + UniformsSize = 0; + if (UniformData) + { + OVR_FREE(UniformData); + UniformData = 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, + ID3D1xSamplerState* sampler, int samples) + : pParams(rp), Tex(NULL), TexSv(NULL), TexRtv(NULL), TexDsv(NULL), + TextureSize(texSize), + Sampler(sampler), + Samples(samples) +{ + OVR_UNUSED(fmt); +} + +Texture::~Texture() +{ +} + +void Texture::Set(int slot, ShaderStage stage) const +{ + ID3D1xShaderResourceView* 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); + break; + } +} + + +//------------------------------------------------------------------------------------- +// ***** GpuTimer +// +#if (OVR_D3D_VERSION == 11) +#define D3DQUERY_EXEC(_context_, _query_, _command_, ...) _context_->_command_(_query_, __VA_ARGS__) +#else +#define D3DQUERY_EXEC(_context_, _query_, _command_, ...) _query_->_command_(__VA_ARGS__) +#endif + + +void GpuTimer::Init(ID3D1xDevice* device, ID3D1xDeviceContext* content) +{ + D3dDevice = device; + Context = content; +} + +void GpuTimer::BeginQuery() +{ + 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 + D3D1x_QUERY_DESC desc; + desc.Query = D3D1X_(QUERY_TIMESTAMP_DISJOINT); + desc.MiscFlags = 0; + VERIFY_HRESULT(D3dDevice->CreateQuery(&desc, &newQuerySet.DisjointQuery)); + + desc.Query = D3D1X_(QUERY_TIMESTAMP); + VERIFY_HRESULT(D3dDevice->CreateQuery(&desc, &newQuerySet.TimeStartQuery)); + VERIFY_HRESULT(D3dDevice->CreateQuery(&desc, &newQuerySet.TimeEndQuery)); + } + + 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; + D3D1X_(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::D3DX |