diff options
Diffstat (limited to 'LibOVR/Src/CAPI/D3D1X')
-rw-r--r-- | LibOVR/Src/CAPI/D3D1X/CAPI_D3D10_DistortionRenderer.cpp | 29 | ||||
-rw-r--r-- | LibOVR/Src/CAPI/D3D1X/CAPI_D3D10_DistortionRenderer.h | 34 | ||||
-rw-r--r-- | LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_DistortionRenderer.cpp | 30 | ||||
-rw-r--r-- | LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_DistortionRenderer.h | 34 | ||||
-rw-r--r-- | LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.cpp | 773 | ||||
-rw-r--r-- | LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.h | 131 | ||||
-rw-r--r-- | LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.cpp | 416 | ||||
-rw-r--r-- | LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.h | 505 | ||||
-rw-r--r-- | LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.cpp | 251 | ||||
-rw-r--r-- | LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.h | 120 | ||||
-rw-r--r-- | LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_Util.cpp | 317 |
11 files changed, 2640 insertions, 0 deletions
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D10_DistortionRenderer.cpp b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D10_DistortionRenderer.cpp new file mode 100644 index 0000000..d1ea4dc --- /dev/null +++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D10_DistortionRenderer.cpp @@ -0,0 +1,29 @@ +/************************************************************************************ + +Filename : CAPI_D3D10_DistortionRenderer.cpp +Content : Distortion renderer instantiation for D3D10 +Created : November 11, 2013 +Authors : Volga Aksoy, Michael Antonov + +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. + +************************************************************************************/ + +#define OVR_D3D_VERSION 10 +#include "CAPI_D3D1X_Util.cpp" +#include "CAPI_D3D1X_DistortionRenderer.cpp" diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D10_DistortionRenderer.h b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D10_DistortionRenderer.h new file mode 100644 index 0000000..bb56cb4 --- /dev/null +++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D10_DistortionRenderer.h @@ -0,0 +1,34 @@ +/************************************************************************************ + +Filename : CAPI_D3D10_DistortionRenderer.h +Content : Distortion renderer header for D3D10 +Created : November 11, 2013 +Authors : Michael Antonov + +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. + +************************************************************************************/ + +#ifndef INC_CAPI_D3D10_DistortionRenderer_h +#define INC_CAPI_D3D10_DistortionRenderer_h + +#define OVR_D3D_VERSION 10 +#include "CAPI_D3D1X_DistortionRenderer.h" +#undef OVR_D3D_VERSION + +#endif
\ No newline at end of file diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_DistortionRenderer.cpp b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_DistortionRenderer.cpp new file mode 100644 index 0000000..1184df8 --- /dev/null +++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_DistortionRenderer.cpp @@ -0,0 +1,30 @@ +/************************************************************************************ + +Filename : CAPI_D3D11_DistortionRenderer.cpp +Content : Distortion renderer instantiation for D3D11 +Created : November 11, 2013 +Authors : Volga Aksoy, Michael Antonov + +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. + +************************************************************************************/ + +#define OVR_D3D_VERSION 11 +#include "CAPI_D3D1X_Util.cpp" +#include "CAPI_D3D1X_DistortionRenderer.cpp" + diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_DistortionRenderer.h b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_DistortionRenderer.h new file mode 100644 index 0000000..8b9863b --- /dev/null +++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_DistortionRenderer.h @@ -0,0 +1,34 @@ +/************************************************************************************ + +Filename : CAPI_D3D11_DistortionRenderer.h +Content : Distortion renderer header for D3D11 +Created : November 11, 2013 +Authors : Michael Antonov + +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. + +************************************************************************************/ + +#ifndef INC_CAPI_D3D11_DistortionRenderer_h +#define INC_CAPI_D3D11_DistortionRenderer_h + +#define OVR_D3D_VERSION 11 +#include "CAPI_D3D1X_DistortionRenderer.h" +#undef OVR_D3D_VERSION + +#endif
\ No newline at end of file diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.cpp b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.cpp new file mode 100644 index 0000000..53f8948 --- /dev/null +++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.cpp @@ -0,0 +1,773 @@ +/************************************************************************************ + +Filename : CAPI_D3D1X_DistortionRenderer.cpp +Content : Experimental distortion renderer +Created : November 11, 2013 +Authors : Volga Aksoy, Michael Antonov + +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_DistortionRenderer.h" + +#include "../../OVR_CAPI_D3D.h" + +namespace OVR { namespace CAPI { namespace D3D_NS { + +#include "../Shaders/Distortion_vs.h" +#include "../Shaders/Distortion_vs_refl.h" +#include "../Shaders/Distortion_ps.h" +#include "../Shaders/Distortion_ps_refl.h" +#include "../Shaders/DistortionChroma_vs.h" +#include "../Shaders/DistortionChroma_vs_refl.h" +#include "../Shaders/DistortionChroma_ps.h" +#include "../Shaders/DistortionChroma_ps_refl.h" +#include "../Shaders/DistortionTimewarp_vs.h" +#include "../Shaders/DistortionTimewarp_vs_refl.h" +#include "../Shaders/DistortionTimewarpChroma_vs.h" +#include "../Shaders/DistortionTimewarpChroma_vs_refl.h" + +#include "../Shaders/SimpleQuad_vs.h" +#include "../Shaders/SimpleQuad_vs_refl.h" +#include "../Shaders/SimpleQuad_ps.h" +#include "../Shaders/SimpleQuad_ps_refl.h" + +// Distortion pixel shader lookup. +// Bit 0: Chroma Correction +// Bit 1: Timewarp + +enum { + DistortionVertexShaderBitMask = 3, + DistortionVertexShaderCount = DistortionVertexShaderBitMask + 1, + DistortionPixelShaderBitMask = 1, + DistortionPixelShaderCount = DistortionPixelShaderBitMask + 1 +}; + +struct PrecompiledShader +{ + const unsigned char* ShaderData; + size_t ShaderSize; + const ShaderBase::Uniform* ReflectionData; + size_t ReflectionSize; +}; + +// Do add a new distortion shader use these macros (with or w/o reflection) +#define PCS_NOREFL(shader) { shader, sizeof(shader), NULL, 0 } +#define PCS_REFL__(shader) { shader, sizeof(shader), shader ## _refl, sizeof( shader ## _refl )/sizeof(*(shader ## _refl)) } + + +static PrecompiledShader DistortionVertexShaderLookup[DistortionVertexShaderCount] = +{ + PCS_REFL__(Distortion_vs), + PCS_REFL__(DistortionChroma_vs), + PCS_REFL__(DistortionTimewarp_vs), + PCS_REFL__(DistortionTimewarpChroma_vs), +}; + +static PrecompiledShader DistortionPixelShaderLookup[DistortionPixelShaderCount] = +{ + PCS_NOREFL(Distortion_ps), + PCS_NOREFL(DistortionChroma_ps) +}; + +void DistortionShaderBitIndexCheck() +{ + OVR_COMPILER_ASSERT(ovrDistortion_Chromatic == 1); + OVR_COMPILER_ASSERT(ovrDistortion_TimeWarp == 2); +} + + + +struct DistortionVertex +{ + Vector2f Pos; + Vector2f TexR; + Vector2f TexG; + Vector2f TexB; + Color Col; +}; + + +// Vertex type; same format is used for all shapes for simplicity. +// Shapes are built by adding vertices to Model. +struct Vertex +{ + Vector3f Pos; + Color C; + float U, V; + Vector3f Norm; + + Vertex (const Vector3f& p, const Color& c = Color(64,0,0,255), + float u = 0, float v = 0, Vector3f n = Vector3f(1,0,0)) + : Pos(p), C(c), U(u), V(v), Norm(n) + {} + Vertex(float x, float y, float z, const Color& c = Color(64,0,0,255), + float u = 0, float v = 0) : Pos(x,y,z), C(c), U(u), V(v) + { } + + bool operator==(const Vertex& b) const + { + return Pos == b.Pos && C == b.C && U == b.U && V == b.V; + } +}; + + +//---------------------------------------------------------------------------- +// ***** D3D1X::DistortionRenderer + +DistortionRenderer::DistortionRenderer(ovrHmd hmd, FrameTimeManager& timeManager, + const HMDRenderState& renderState) + : CAPI::DistortionRenderer(ovrRenderAPI_D3D11, hmd, timeManager, renderState) +{ +} + +DistortionRenderer::~DistortionRenderer() +{ + destroy(); +} + +// static +CAPI::DistortionRenderer* DistortionRenderer::Create(ovrHmd hmd, + FrameTimeManager& timeManager, + const HMDRenderState& renderState) +{ + return new DistortionRenderer(hmd, timeManager, renderState); +} + + +bool DistortionRenderer::Initialize(const ovrRenderAPIConfig* apiConfig, + unsigned hmdCaps, unsigned distortionCaps) +{ + // TBD: Decide if hmdCaps are needed here or are a part of RenderState + OVR_UNUSED(hmdCaps); + + const ovrD3D1X(Config)* config = (const ovrD3D1X(Config)*)apiConfig; + + if (!config) + { + // Cleanup + pEyeTextures[0].Clear(); + pEyeTextures[1].Clear(); + memset(&RParams, 0, sizeof(RParams)); + return true; + } + + if (!config->D3D_NS.pDevice || !config->D3D_NS.pBackBufferRT) + return false; + + RParams.pDevice = config->D3D_NS.pDevice; + RParams.pContext = D3DSELECT_10_11(config->D3D_NS.pDevice, config->D3D_NS.pDeviceContext); + RParams.pBackBufferRT = config->D3D_NS.pBackBufferRT; + RParams.pSwapChain = config->D3D_NS.pSwapChain; + RParams.RTSize = config->D3D_NS.Header.RTSize; + RParams.Multisample = config->D3D_NS.Header.Multisample; + + DistortionCaps = distortionCaps; + + //DistortionWarper.SetVsync((hmdCaps & ovrHmdCap_NoVSync) ? false : true); + + pEyeTextures[0] = *new Texture(&RParams, Texture_RGBA, Sizei(0), + getSamplerState(Sample_Linear|Sample_ClampBorder)); + pEyeTextures[1] = *new Texture(&RParams, Texture_RGBA, Sizei(0), + getSamplerState(Sample_Linear|Sample_ClampBorder)); + + initBuffersAndShaders(); + + // Rasterizer state + D3D1X_(RASTERIZER_DESC) rs; + memset(&rs, 0, sizeof(rs)); + rs.AntialiasedLineEnable = true; + rs.CullMode = D3D1X_(CULL_BACK); + rs.DepthClipEnable = true; + rs.FillMode = D3D1X_(FILL_SOLID); + RParams.pDevice->CreateRasterizerState(&rs, &Rasterizer.GetRawRef()); + + // TBD: Blend state.. not used? + // We'll want to turn off blending + +#if (OVR_D3D_VERSION == 11) + GpuProfiler.Init(RParams.pDevice, RParams.pContext); +#endif + + return true; +} + + +void DistortionRenderer::SubmitEye(int eyeId, ovrTexture* eyeTexture) +{ + const ovrD3D1X(Texture)* tex = (const ovrD3D1X(Texture)*)eyeTexture; + + if (eyeTexture) + { + // Use tex->D3D_NS.Header.RenderViewport to update UVs for rendering in case they changed. + // TBD: This may be optimized through some caching. + ovrEyeDesc ed = RState.EyeRenderDesc[eyeId].Desc; + ed.TextureSize = tex->D3D_NS.Header.TextureSize; + ed.RenderViewport = tex->D3D_NS.Header.RenderViewport; + + ovrHmd_GetRenderScaleAndOffset(HMD, ed, DistortionCaps, UVScaleOffset[eyeId]); + + pEyeTextures[eyeId]->UpdatePlaceholderTexture(tex->D3D_NS.pTexture, tex->D3D_NS.pSRView, + tex->D3D_NS.Header.TextureSize); + } +} + +void DistortionRenderer::EndFrame(bool swapBuffers, unsigned char* latencyTesterDrawColor, + unsigned char* latencyTester2DrawColor) +{ + +#if 0 + + // MA: This causes orientation and positional stutter!! NOT USABLE. + if (!TimeManager.NeedDistortionTimeMeasurement() && + (RState.DistortionCaps & ovrDistortion_TimeWarp)) + { + // Wait for timewarp distortion if it is time + FlushGpuAndWaitTillTime(TimeManager.GetFrameTiming().TimewarpPointTime); + } + + // Always measure distortion time so that TimeManager can better + // estimate latency-reducing time-warp wait timing. + { + GpuProfiler.BeginQuery(); + + renderDistortion(pEyeTextures[0], pEyeTextures[1]); + + GpuProfiler.EndQuery(); + TimeManager.AddDistortionTimeMeasurement(GpuProfiler.GetTiming(false)); + } +#else + + if (!TimeManager.NeedDistortionTimeMeasurement()) + { + if (RState.DistortionCaps & ovrDistortion_TimeWarp) + { + // Wait for timewarp distortion if it is time and Gpu idle + FlushGpuAndWaitTillTime(TimeManager.GetFrameTiming().TimewarpPointTime); + } + + renderDistortion(pEyeTextures[0], pEyeTextures[1]); + } + else + { + // If needed, measure distortion time so that TimeManager can better estimate + // latency-reducing time-warp wait timing. + WaitUntilGpuIdle(); + double distortionStartTime = ovr_GetTimeInSeconds(); + + renderDistortion(pEyeTextures[0], pEyeTextures[1]); + + WaitUntilGpuIdle(); + TimeManager.AddDistortionTimeMeasurement(ovr_GetTimeInSeconds() - distortionStartTime); + } +#endif + + if(latencyTesterDrawColor) + { + renderLatencyQuad(latencyTesterDrawColor); + } + else if(latencyTester2DrawColor) + { + renderLatencyPixel(latencyTester2DrawColor); + } + + if (swapBuffers) + { + if (RParams.pSwapChain) + { + UINT swapInterval = (RState.HMDCaps & ovrHmdCap_NoVSync) ? 0 : 1; + RParams.pSwapChain->Present(swapInterval, 0); + + // Force GPU to flush the scene, resulting in the lowest possible latency. + // It's critical that this flush is *after* present. + WaitUntilGpuIdle(); + } + else + { + // TBD: Generate error - swapbuffer option used with null swapchain. + } + } +} + + +void DistortionRenderer::WaitUntilGpuIdle() +{ + // Flush and Stall CPU while waiting for GPU to complete rendering all of the queued draw calls + D3D1x_QUERY_DESC queryDesc = { D3D1X_(QUERY_EVENT), 0 }; + Ptr<ID3D1xQuery> query; + BOOL done = FALSE; + + if (RParams.pDevice->CreateQuery(&queryDesc, &query.GetRawRef()) == S_OK) + { + D3DSELECT_10_11(query->End(), + RParams.pContext->End(query)); + + // GetData will returns S_OK for both done == TRUE or FALSE. + // Exit on failure to avoid infinite loop. + do { } + while(!done && + !FAILED(D3DSELECT_10_11(query->GetData(&done, sizeof(BOOL), 0), + RParams.pContext->GetData(query, &done, sizeof(BOOL), 0))) + ); + } +} + +double DistortionRenderer::FlushGpuAndWaitTillTime(double absTime) +{ + double initialTime = ovr_GetTimeInSeconds(); + if (initialTime >= absTime) + return 0.0; + + // Flush and Stall CPU while waiting for GPU to complete rendering all of the queued draw calls + D3D1x_QUERY_DESC queryDesc = { D3D1X_(QUERY_EVENT), 0 }; + Ptr<ID3D1xQuery> query; + BOOL done = FALSE; + bool callGetData = false; + + if (RParams.pDevice->CreateQuery(&queryDesc, &query.GetRawRef()) == S_OK) + { + D3DSELECT_10_11(query->End(), + RParams.pContext->End(query)); + callGetData = true; + } + + double newTime = initialTime; + volatile int i; + + while (newTime < absTime) + { + if (callGetData) + { + // GetData will returns S_OK for both done == TRUE or FALSE. + // Stop calling GetData on failure. + callGetData = !FAILED(D3DSELECT_10_11(query->GetData(&done, sizeof(BOOL), 0), + RParams.pContext->GetData(query, &done, sizeof(BOOL), 0))) && !done; + } + else + { + for (int j = 0; j < 50; j++) + i = 0; + } + newTime = ovr_GetTimeInSeconds(); + } + + // How long we waited + return newTime - initialTime; +} + +void DistortionRenderer::initBuffersAndShaders() +{ + for ( int eyeNum = 0; eyeNum < 2; eyeNum++ ) + { + // Allocate & generate distortion mesh vertices. + ovrDistortionMesh meshData; + +// double startT = ovr_GetTimeInSeconds(); + + if (!ovrHmd_CreateDistortionMesh( HMD, RState.EyeRenderDesc[eyeNum].Desc, + RState.DistortionCaps, + UVScaleOffset[eyeNum], &meshData) ) + { + OVR_ASSERT(false); + continue; + } + +// double deltaT = ovr_GetTimeInSeconds() - startT; +// LogText("GenerateDistortion time = %f\n", deltaT); + + // Now parse the vertex data and create a render ready vertex buffer from it + DistortionVertex * pVBVerts = (DistortionVertex*)OVR_ALLOC ( sizeof(DistortionVertex) * meshData.VertexCount ); + DistortionVertex * pCurVBVert = pVBVerts; + ovrDistortionVertex* pCurOvrVert = meshData.pVertexData; + + for ( unsigned vertNum = 0; vertNum < meshData.VertexCount; vertNum++ ) + { + pCurVBVert->Pos.x = pCurOvrVert->Pos.x; + pCurVBVert->Pos.y = pCurOvrVert->Pos.y; + pCurVBVert->TexR = (*(Vector2f*)&pCurOvrVert->TexR); + pCurVBVert->TexG = (*(Vector2f*)&pCurOvrVert->TexG); + pCurVBVert->TexB = (*(Vector2f*)&pCurOvrVert->TexB); + // Convert [0.0f,1.0f] to [0,255] + pCurVBVert->Col.R = (OVR::UByte)( pCurOvrVert->VignetteFactor * 255.99f ); + pCurVBVert->Col.G = pCurVBVert->Col.R; + pCurVBVert->Col.B = pCurVBVert->Col.R; + pCurVBVert->Col.A = (OVR::UByte)( pCurOvrVert->TimeWarpFactor * 255.99f );; + pCurOvrVert++; + pCurVBVert++; + } + + DistortionMeshVBs[eyeNum] = *new Buffer(&RParams); + DistortionMeshVBs[eyeNum]->Data ( Buffer_Vertex, pVBVerts, sizeof(DistortionVertex) * meshData.VertexCount ); + DistortionMeshIBs[eyeNum] = *new Buffer(&RParams); + DistortionMeshIBs[eyeNum]->Data ( Buffer_Index, meshData.pIndexData, ( sizeof(INT16) * meshData.IndexCount ) ); + + OVR_FREE ( pVBVerts ); + ovrHmd_DestroyDistortionMesh( &meshData ); + } + + // Uniform buffers + for(int i = 0; i < Shader_Count; i++) + { + UniformBuffers[i] = *new Buffer(&RParams); + //MaxTextureSet[i] = 0; + } + + initShaders(); +} + +void DistortionRenderer::renderDistortion(Texture* leftEyeTexture, Texture* rightEyeTexture) +{ + RParams.pContext->RSSetState(Rasterizer); + + RParams.pContext->OMSetRenderTargets(1, &RParams.pBackBufferRT, 0); + + setViewport(Recti(0,0, RParams.RTSize.w, RParams.RTSize.h)); + + // Not affected by viewport. + RParams.pContext->ClearRenderTargetView(RParams.pBackBufferRT, RState.ClearColor); + + for(int eyeNum = 0; eyeNum < 2; eyeNum++) + { + ShaderFill distortionShaderFill(DistortionShader); + distortionShaderFill.SetTexture(0, eyeNum == 0 ? leftEyeTexture : rightEyeTexture); + distortionShaderFill.SetInputLayout(DistortionVertexIL); + + DistortionShader->SetUniform2f("EyeToSourceUVScale", UVScaleOffset[eyeNum][0].x, UVScaleOffset[eyeNum][0].y); + DistortionShader->SetUniform2f("EyeToSourceUVOffset", UVScaleOffset[eyeNum][1].x, UVScaleOffset[eyeNum][1].y); + + if (DistortionCaps & ovrDistortion_TimeWarp) + { + ovrMatrix4f timeWarpMatrices[2]; + ovrHmd_GetEyeTimewarpMatrices(HMD, (ovrEyeType)eyeNum, + RState.EyeRenderPoses[eyeNum], timeWarpMatrices); + + // Feed identity like matrices in until we get proper timewarp calculation going on + DistortionShader->SetUniform4x4f("EyeRotationStart", Matrix4f(timeWarpMatrices[0])); + DistortionShader->SetUniform4x4f("EyeRotationEnd", Matrix4f(timeWarpMatrices[1])); + + renderPrimitives(&distortionShaderFill, DistortionMeshVBs[eyeNum], DistortionMeshIBs[eyeNum], + NULL, 0, (int)DistortionMeshVBs[eyeNum]->GetSize(), Prim_Triangles); + } + else + { + renderPrimitives(&distortionShaderFill, DistortionMeshVBs[eyeNum], DistortionMeshIBs[eyeNum], + NULL, 0, (int)DistortionMeshVBs[eyeNum]->GetSize(), Prim_Triangles); + } + } +} + +void DistortionRenderer::createDrawQuad() +{ + const int numQuadVerts = 4; + LatencyTesterQuadVB = *new Buffer(&RParams); + if(!LatencyTesterQuadVB) + { + return; + } + + LatencyTesterQuadVB->Data(Buffer_Vertex, NULL, numQuadVerts * sizeof(Vertex)); + Vertex* vertices = (Vertex*)LatencyTesterQuadVB->Map(0, numQuadVerts * sizeof(Vertex), Map_Discard); + if(!vertices) + { + OVR_ASSERT(false); // failed to lock vertex buffer + return; + } + + const float left = -1.0f; + const float top = -1.0f; + const float right = 1.0f; + const float bottom = 1.0f; + + vertices[0] = Vertex(Vector3f(left, top, 0.0f), Color(255, 255, 255, 255)); + vertices[1] = Vertex(Vector3f(left, bottom, 0.0f), Color(255, 255, 255, 255)); + vertices[2] = Vertex(Vector3f(right, top, 0.0f), Color(255, 255, 255, 255)); + vertices[3] = Vertex(Vector3f(right, bottom, 0.0f), Color(255, 255, 255, 255)); + + LatencyTesterQuadVB->Unmap(vertices); +} + +void DistortionRenderer::renderLatencyQuad(unsigned char* latencyTesterDrawColor) +{ + const int numQuadVerts = 4; + + if(!LatencyTesterQuadVB) + { + createDrawQuad(); + } + + ShaderFill quadFill(SimpleQuadShader); + quadFill.SetInputLayout(SimpleQuadVertexIL); + + setViewport(Recti(0,0, RParams.RTSize.w, RParams.RTSize.h)); + + SimpleQuadShader->SetUniform2f("Scale", 0.2f, 0.2f); + SimpleQuadShader->SetUniform4f("Color", (float)latencyTesterDrawColor[0] / 255.99f, + (float)latencyTesterDrawColor[0] / 255.99f, + (float)latencyTesterDrawColor[0] / 255.99f, + 1.0f); + + for(int eyeNum = 0; eyeNum < 2; eyeNum++) + { + SimpleQuadShader->SetUniform2f("PositionOffset", eyeNum == 0 ? -0.4f : 0.4f, 0.0f); + renderPrimitives(&quadFill, LatencyTesterQuadVB, NULL, NULL, 0, numQuadVerts, Prim_TriangleStrip); + } +} + +void DistortionRenderer::renderLatencyPixel(unsigned char* latencyTesterPixelColor) +{ + const int numQuadVerts = 4; + + if(!LatencyTesterQuadVB) + { + createDrawQuad(); + } + + ShaderFill quadFill(SimpleQuadShader); + quadFill.SetInputLayout(SimpleQuadVertexIL); + + setViewport(Recti(0,0, RParams.RTSize.w, RParams.RTSize.h)); + + SimpleQuadShader->SetUniform4f("Color", (float)latencyTesterPixelColor[0] / 255.99f, + (float)latencyTesterPixelColor[0] / 255.99f, + (float)latencyTesterPixelColor[0] / 255.99f, + 1.0f); + + Vector2f scale(2.0f / RParams.RTSize.w, 2.0f / RParams.RTSize.h); + SimpleQuadShader->SetUniform2f("Scale", scale.x, scale.y); + SimpleQuadShader->SetUniform2f("PositionOffset", 1.0f, 1.0f); + renderPrimitives(&quadFill, LatencyTesterQuadVB, NULL, NULL, 0, numQuadVerts, Prim_TriangleStrip); +} + +void DistortionRenderer::renderPrimitives( + const ShaderFill* fill, + Buffer* vertices, Buffer* indices, + Matrix4f* viewMatrix, int offset, int count, + PrimitiveType rprim) +{ + OVR_ASSERT(fill->GetInputLayout() != 0); + RParams.pContext->IASetInputLayout((ID3D1xInputLayout*)fill->GetInputLayout()); + + if (indices) + { + RParams.pContext->IASetIndexBuffer(indices->GetBuffer(), DXGI_FORMAT_R16_UINT, 0); + } + + ID3D1xBuffer* vertexBuffer = vertices->GetBuffer(); + UINT vertexStride = sizeof(Vertex); + UINT vertexOffset = offset; + RParams.pContext->IASetVertexBuffers(0, 1, &vertexBuffer, &vertexStride, &vertexOffset); + + ShaderSet* shaders = ((ShaderFill*)fill)->GetShaders(); + + ShaderBase* vshader = ((ShaderBase*)shaders->GetShader(Shader_Vertex)); + unsigned char* vertexData = vshader->UniformData; + if (vertexData) + { + // TODO: some VSes don't start with StandardUniformData! + if ( viewMatrix ) + { + StandardUniformData* stdUniforms = (StandardUniformData*) vertexData; + stdUniforms->View = viewMatrix->Transposed(); + stdUniforms->Proj = StdUniforms.Proj; + } + UniformBuffers[Shader_Vertex]->Data(Buffer_Uniform, vertexData, vshader->UniformsSize); + vshader->SetUniformBuffer(UniformBuffers[Shader_Vertex]); + } + + for(int i = Shader_Vertex + 1; i < Shader_Count; i++) + { + if (shaders->GetShader(i)) + { + ((ShaderBase*)shaders->GetShader(i))->UpdateBuffer(UniformBuffers[i]); + ((ShaderBase*)shaders->GetShader(i))->SetUniformBuffer(UniformBuffers[i]); + } + } + + D3D1X_(PRIMITIVE_TOPOLOGY) prim; + switch(rprim) + { + case Prim_Triangles: + prim = D3D1X_(PRIMITIVE_TOPOLOGY_TRIANGLELIST); + break; + case Prim_Lines: + prim = D3D1X_(PRIMITIVE_TOPOLOGY_LINELIST); + break; + case Prim_TriangleStrip: + prim = D3D1X_(PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + break; + default: + OVR_ASSERT(0); + return; + } + RParams.pContext->IASetPrimitiveTopology(prim); + + fill->Set(rprim); + + if (indices) + { + RParams.pContext->DrawIndexed(count, 0, 0); + } + else + { + RParams.pContext->Draw(count, 0); + } +} + +void DistortionRenderer::setViewport(const Recti& vp) +{ + D3D1x_VIEWPORT d3dvp; + + d3dvp.Width = D3DSELECT_10_11(vp.w, (float)vp.w); + d3dvp.Height = D3DSELECT_10_11(vp.h, (float)vp.h); + d3dvp.TopLeftX = D3DSELECT_10_11(vp.x, (float)vp.x); + d3dvp.TopLeftY = D3DSELECT_10_11(vp.y, (float)vp.y); + d3dvp.MinDepth = 0; + d3dvp.MaxDepth = 1; + RParams.pContext->RSSetViewports(1, &d3dvp); +} + + + + +static D3D1X_(INPUT_ELEMENT_DESC) DistortionMeshVertexDesc[] = +{ + {"Position", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D1X_(INPUT_PER_VERTEX_DATA), 0}, + {"TexCoord", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D1X_(INPUT_PER_VERTEX_DATA), 0}, + {"TexCoord", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D1X_(INPUT_PER_VERTEX_DATA), 0}, + {"TexCoord", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D1X_(INPUT_PER_VERTEX_DATA), 0}, + {"Color", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 32, D3D1X_(INPUT_PER_VERTEX_DATA), 0}, +}; + +static D3D1X_(INPUT_ELEMENT_DESC) SimpleQuadMeshVertexDesc[] = +{ + {"Position", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D1X_(INPUT_PER_VERTEX_DATA), 0}, +}; + +// TODO: this is D3D specific +void DistortionRenderer::initShaders() +{ + { + PrecompiledShader vsShaderByteCode = DistortionVertexShaderLookup[DistortionVertexShaderBitMask & DistortionCaps]; + Ptr<D3D_NS::VertexShader> vtxShader = *new D3D_NS::VertexShader( + &RParams, + (void*)vsShaderByteCode.ShaderData, vsShaderByteCode.ShaderSize, + vsShaderByteCode.ReflectionData, vsShaderByteCode.ReflectionSize); + + ID3D1xInputLayout** objRef = &DistortionVertexIL.GetRawRef(); + + HRESULT validate = RParams.pDevice->CreateInputLayout( + DistortionMeshVertexDesc, sizeof(DistortionMeshVertexDesc) / sizeof(DistortionMeshVertexDesc[0]), + vsShaderByteCode.ShaderData, vsShaderByteCode.ShaderSize, objRef); + OVR_UNUSED(validate); + + DistortionShader = *new ShaderSet; + DistortionShader->SetShader(vtxShader); + + PrecompiledShader psShaderByteCode = DistortionPixelShaderLookup[DistortionPixelShaderBitMask & DistortionCaps]; + + Ptr<D3D_NS::PixelShader> ps = *new D3D_NS::PixelShader( + &RParams, + (void*)psShaderByteCode.ShaderData, psShaderByteCode.ShaderSize, + psShaderByteCode.ReflectionData, psShaderByteCode.ReflectionSize); + + DistortionShader->SetShader(ps); + } + + { + Ptr<D3D_NS::VertexShader> vtxShader = *new D3D_NS::VertexShader( + &RParams, + (void*)SimpleQuad_vs, sizeof(SimpleQuad_vs), + SimpleQuad_vs_refl, sizeof(SimpleQuad_vs_refl) / sizeof(SimpleQuad_vs_refl[0])); + //NULL, 0); + + ID3D1xInputLayout** objRef = &SimpleQuadVertexIL.GetRawRef(); + + HRESULT validate = RParams.pDevice->CreateInputLayout( + SimpleQuadMeshVertexDesc, sizeof(SimpleQuadMeshVertexDesc) / sizeof(SimpleQuadMeshVertexDesc[0]), + (void*)SimpleQuad_vs, sizeof(SimpleQuad_vs), objRef); + OVR_UNUSED(validate); + + SimpleQuadShader = *new ShaderSet; + SimpleQuadShader->SetShader(vtxShader); + + Ptr<D3D_NS::PixelShader> ps = *new D3D_NS::PixelShader( + &RParams, + (void*)SimpleQuad_ps, sizeof(SimpleQuad_ps), + SimpleQuad_ps_refl, sizeof(SimpleQuad_ps_refl) / sizeof(SimpleQuad_ps_refl[0])); + + SimpleQuadShader->SetShader(ps); + } +} + + + +ID3D1xSamplerState* DistortionRenderer::getSamplerState(int sm) +{ + if (SamplerStates[sm]) + return SamplerStates[sm]; + + D3D1X_(SAMPLER_DESC) ss; + memset(&ss, 0, sizeof(ss)); + if (sm & Sample_Clamp) + ss.AddressU = ss.AddressV = ss.AddressW = D3D1X_(TEXTURE_ADDRESS_CLAMP); + else if (sm & Sample_ClampBorder) + ss.AddressU = ss.AddressV = ss.AddressW = D3D1X_(TEXTURE_ADDRESS_BORDER); + else + ss.AddressU = ss.AddressV = ss.AddressW = D3D1X_(TEXTURE_ADDRESS_WRAP); + + if (sm & Sample_Nearest) + { + ss.Filter = D3D1X_(FILTER_MIN_MAG_MIP_POINT); + } + else if (sm & Sample_Anisotropic) + { + ss.Filter = D3D1X_(FILTER_ANISOTROPIC); + ss.MaxAnisotropy = 8; + } + else + { + ss.Filter = D3D1X_(FILTER_MIN_MAG_MIP_LINEAR); + } + ss.MaxLOD = 15; + RParams.pDevice->CreateSamplerState(&ss, &SamplerStates[sm].GetRawRef()); + return SamplerStates[sm]; +} + + +void DistortionRenderer::destroy() +{ + for(int eyeNum = 0; eyeNum < 2; eyeNum++) + { + DistortionMeshVBs[eyeNum].Clear(); + DistortionMeshIBs[eyeNum].Clear(); + } + + DistortionVertexIL.Clear(); + + if (DistortionShader) + { + DistortionShader->UnsetShader(Shader_Vertex); + DistortionShader->UnsetShader(Shader_Pixel); + DistortionShader.Clear(); + } + + LatencyTesterQuadVB.Clear(); +} + +}}} // OVR::CAPI::D3D1X diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.h b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.h new file mode 100644 index 0000000..f151d73 --- /dev/null +++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.h @@ -0,0 +1,131 @@ +/************************************************************************************ + +Filename : CAPI_D3D1X_DistortionRenderer.h +Content : Experimental distortion renderer +Created : November 11, 2013 +Authors : Volga Aksoy + +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. + +************************************************************************************/ + +// No include guard, since this fill will be multiply-included. +//#ifndef OVR_CAPI_D3D1X_DistortionRenderer_h + +#include "CAPI_D3D1X_Util.h" +#include "../CAPI_DistortionRenderer.h" + +#include "../../Kernel/OVR_Log.h" + +namespace OVR { namespace CAPI { namespace D3D_NS { + + +// ***** D3D1X::DistortionRenderer + +// Implementation of DistortionRenderer for D3D10/11. + +class DistortionRenderer : public CAPI::DistortionRenderer +{ +public: + DistortionRenderer(ovrHmd hmd, + FrameTimeManager& timeManager, + const HMDRenderState& renderState); + ~DistortionRenderer(); + + + // Creation function for the device. + static CAPI::DistortionRenderer* Create(ovrHmd hmd, + FrameTimeManager& timeManager, + const HMDRenderState& renderState); + + + // ***** Public DistortionRenderer interface + + virtual bool Initialize(const ovrRenderAPIConfig* apiConfig, + unsigned hmdCaps, unsigned distortionCaps); + + virtual void SubmitEye(int eyeId, ovrTexture* eyeTexture); + + virtual void EndFrame(bool swapBuffers, unsigned char* latencyTesterDrawColor, unsigned char* latencyTester2DrawColor); + + // TBD: Make public? + void WaitUntilGpuIdle(); + + // Similar to ovr_WaitTillTime but it also flushes GPU. + // Note, it exits when time expires, even if GPU is not in idle state yet. + double FlushGpuAndWaitTillTime(double absTime); + +private: + // Helpers + void initBuffersAndShaders(); + void initShaders(); + void initFullscreenQuad(); + void destroy(); + + void setViewport(const Recti& vp); + + void renderDistortion(Texture* leftEyeTexture, Texture* rightEyeTexture); + + void renderPrimitives(const ShaderFill* fill, Buffer* vertices, Buffer* indices, + Matrix4f* viewMatrix, int offset, int count, + PrimitiveType rprim); + + void createDrawQuad(); + void renderLatencyQuad(unsigned char* latencyTesterDrawColor); + void renderLatencyPixel(unsigned char* latencyTesterPixelColor); + + // Create or get cached D3D sampler based on flags. + ID3D1xSamplerState* getSamplerState(int sm); + + + // TBD: Should we be using oe from RState instead? + unsigned DistortionCaps; + + // D3DX device and utility variables. + RenderParams RParams; + Ptr<Texture> pEyeTextures[2]; + + // U,V scale and offset needed for timewarp. + ovrVector2f UVScaleOffset[2][2]; + + //Ptr<Buffer> mpFullScreenVertexBuffer; + + Ptr<Buffer> DistortionMeshVBs[2]; // one per-eye + Ptr<Buffer> DistortionMeshIBs[2]; // one per-eye + + Ptr<ShaderSet> DistortionShader; + Ptr<ID3D1xInputLayout> DistortionVertexIL; + + struct StandardUniformData + { + Matrix4f Proj; + Matrix4f View; + } StdUniforms; + Ptr<Buffer> UniformBuffers[Shader_Count]; + + Ptr<ID3D1xSamplerState> SamplerStates[Sample_Count]; + Ptr<ID3D1xRasterizerState> Rasterizer; + + Ptr<Buffer> LatencyTesterQuadVB; + Ptr<ShaderSet> SimpleQuadShader; + Ptr<ID3D1xInputLayout> SimpleQuadVertexIL; + + GpuTimer GpuProfiler; +}; + +}}} // OVR::CAPI::D3D1X 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 diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.h b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.h new file mode 100644 index 0000000..f8d7bd3 --- /dev/null +++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.h @@ -0,0 +1,505 @@ +/************************************************************************************ + +Filename : CAPI_D3D1X_Util.h +Content : D3DX 10/11 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. + +************************************************************************************/ + +// ***** IMPORTANT: +// This file can be included twice, once with OVR_D3D_VERSION=10 and +// once with OVR_D3D_VERSION=11. + + +#ifndef OVR_D3D_VERSION +#error define OVR_D3D_VERSION to 10 or 11 +#endif + +// Custom include guard, allowing one of each D3D10/11. +#if (OVR_D3D_VERSION == 10 && !defined(INC_OVR_CAPI_D3D10_Util_h)) || \ + (OVR_D3D_VERSION == 11 && !defined(INC_OVR_CAPI_D3D11_Util_h)) + +#include "../../Kernel/OVR_String.h" +#include "../../Kernel/OVR_Array.h" +#include "../../Kernel/OVR_Math.h" + +#include <Windows.h> +#include <comdef.h> // for _COM_SMARTPTR_TYPEDEF() + +#undef D3D_NS // namespace +#undef D3D1X_ +#undef ID3D1X // interface prefix +#undef ovrD3D1X // ovrD3D10Config, etc. +#undef D3D11_COMMA_0 // Injects on ", 0" for D3D11 only +#undef D3DSELECT_10_11 +#undef IID_ID3D1xShaderReflection + +#if (OVR_D3D_VERSION == 10) + + #define INC_OVR_CAPI_D3D10_Util_h + #define D3D_NS D3D10 + #define D3D1X_(x) D3D10_##x + #define ID3D1X(x) ID3D10##x + #define ovrD3D1X(x) ovrD3D10##x + #define D3DSELECT_10_11(a10, a11) a10 + #define D3D11_COMMA_0 + #define IID_ID3D1xShaderReflection IID_ID3D10ShaderReflection + #include <d3d10_1.h> // avoids warning? + #include <d3d10.h> + +#else // (OVR_D3D_VERSION == 11) + + #define INC_OVR_CAPI_D3D11_Util_h + #define D3D_NS D3D11 + #define D3D1X_(x) D3D11_##x + #define ID3D1X(x) ID3D11##x + #define ovrD3D1X(x) ovrD3D11##x + #define D3DSELECT_10_11(a10, a11) a11 + #define D3D11_COMMA_0 , 0 + #define IID_ID3D1xShaderReflection IID_ID3D11ShaderReflection + #include <d3d11.h> + #include <D3D11Shader.h> +#endif + + +namespace OVR { namespace CAPI { namespace D3D_NS { + +// D3D Namespace-local types. +typedef ID3D1X(Device) ID3D1xDevice; +typedef ID3D1X(RenderTargetView) ID3D1xRenderTargetView; +typedef ID3D1X(Texture2D) ID3D1xTexture2D; +typedef ID3D1X(ShaderResourceView) ID3D1xShaderResourceView; +typedef ID3D1X(DepthStencilView) ID3D1xDepthStencilView; +typedef ID3D1X(DepthStencilState) ID3D1xDepthStencilState; +typedef ID3D1X(InputLayout) ID3D1xInputLayout; +typedef ID3D1X(Buffer) ID3D1xBuffer; +typedef ID3D1X(VertexShader) ID3D1xVertexShader; +typedef ID3D1X(PixelShader) ID3D1xPixelShader; +typedef ID3D1X(GeometryShader) ID3D1xGeometryShader; +typedef ID3D1X(BlendState) ID3D1xBlendState; +typedef ID3D1X(RasterizerState) ID3D1xRasterizerState; +typedef ID3D1X(SamplerState) ID3D1xSamplerState; +typedef ID3D1X(Query) ID3D1xQuery; +typedef ID3D1X(ShaderReflection) ID3D1xShaderReflection; +typedef ID3D1X(ShaderReflectionVariable) ID3D1xShaderReflectionVariable; +typedef ID3D1X(ShaderReflectionConstantBuffer) ID3D1xShaderReflectionConstantBuffer; +typedef D3D1X_(VIEWPORT) D3D1x_VIEWPORT; +typedef D3D1X_(QUERY_DESC) D3D1x_QUERY_DESC; +typedef D3D1X_(SHADER_BUFFER_DESC) D3D1x_SHADER_BUFFER_DESC; +typedef D3D1X_(SHADER_VARIABLE_DESC) D3D1x_SHADER_VARIABLE_DESC; +// Blob is the same +typedef ID3D10Blob ID3D1xBlob; + +#if (OVR_D3D_VERSION == 10) + typedef ID3D10Device ID3D1xDeviceContext; +#else + typedef ID3D11DeviceContext ID3D1xDeviceContext; +#endif + + +// Assert on HRESULT failure +inline void VERIFY_HRESULT(HRESULT hr) +{ + if (FAILED(hr)) + OVR_ASSERT(false); +} + +class Buffer; + +// Rendering parameters/pointers describing D3DX rendering setup. +struct RenderParams +{ + ID3D1xDevice* pDevice; + ID3D1xDeviceContext* pContext; + ID3D1xRenderTargetView* pBackBufferRT; + IDXGISwapChain* pSwapChain; + Sizei RTSize; + int Multisample; +}; + + +// Rendering primitive type used to render Model. +enum PrimitiveType +{ + Prim_Triangles, + Prim_Lines, + Prim_TriangleStrip, + Prim_Unknown, + Prim_Count +}; + +// Types of shaders that can be stored together in a ShaderSet. +enum ShaderStage +{ + Shader_Vertex = 0, + Shader_Fragment = 2, + Shader_Pixel = 2, + Shader_Count = 3, +}; + +enum MapFlags +{ + Map_Discard = 1, + Map_Read = 2, // do not use + Map_Unsynchronized = 4, // like D3D11_MAP_NO_OVERWRITE +}; + + +// Buffer types used for uploading geometry & constants. +enum BufferUsage +{ + Buffer_Unknown = 0, + Buffer_Vertex = 1, + Buffer_Index = 2, + Buffer_Uniform = 4, + Buffer_TypeMask = 0xff, + Buffer_ReadOnly = 0x100, // Buffer must be created with Data(). +}; + +enum TextureFormat +{ + Texture_RGBA = 0x0100, + Texture_Depth = 0x8000, + Texture_TypeMask = 0xff00, + Texture_SamplesMask = 0x00ff, + Texture_RenderTarget = 0x10000, + Texture_GenMipmaps = 0x20000, +}; + +// Texture sampling modes. +enum SampleMode +{ + Sample_Linear = 0, + Sample_Nearest = 1, + Sample_Anisotropic = 2, + Sample_FilterMask = 3, + + Sample_Repeat = 0, + Sample_Clamp = 4, + Sample_ClampBorder = 8, // If unsupported Clamp is used instead. + Sample_AddressMask =12, + + Sample_Count =13, +}; + +// Base class for vertex and pixel shaders. Stored in ShaderSet. +class Shader : public RefCountBase<Shader> +{ + friend class ShaderSet; + +protected: + ShaderStage Stage; + +public: + Shader(ShaderStage s) : Stage(s) {} + virtual ~Shader() {} + + ShaderStage GetStage() const { return Stage; } + + virtual void Set(PrimitiveType) const { } + virtual void SetUniformBuffer(class Buffer* buffers, int i = 0) { OVR_UNUSED2(buffers, i); } + +protected: + virtual bool SetUniform(const char* name, int n, const float* v) { OVR_UNUSED3(name, n, v); return false; } + virtual bool SetUniformBool(const char* name, int n, const bool* v) { OVR_UNUSED3(name, n, v); return false; } +}; + + + +// A group of shaders, one per stage. +// A ShaderSet is applied to a RenderDevice for rendering with a given fill. +class ShaderSet : public RefCountBase<ShaderSet> +{ +protected: + Ptr<Shader> Shaders[Shader_Count]; + +public: + ShaderSet() { } + ~ShaderSet() { } + + virtual void SetShader(Shader *s) + { + Shaders[s->GetStage()] = s; + } + virtual void UnsetShader(int stage) + { + Shaders[stage] = NULL; + } + Shader* GetShader(int stage) { return Shaders[stage]; } + + virtual void Set(PrimitiveType prim) const + { + for (int i = 0; i < Shader_Count; i++) + if (Shaders[i]) + Shaders[i]->Set(prim); + } + + // Set a uniform (other than the standard matrices). It is undefined whether the + // uniforms from one shader occupy the same space as those in other shaders + // (unless a buffer is used, then each buffer is independent). + virtual bool SetUniform(const char* name, int n, const float* v) + { + bool result = 0; + for (int i = 0; i < Shader_Count; i++) + if (Shaders[i]) + result |= Shaders[i]->SetUniform(name, n, v); + + return result; + } + bool SetUniform1f(const char* name, float x) + { + const float v[] = {x}; + return SetUniform(name, 1, v); + } + bool SetUniform2f(const char* name, float x, float y) + { + const float v[] = {x,y}; + return SetUniform(name, 2, v); + } + bool SetUniform3f(const char* name, float x, float y, float z) + { + const float v[] = {x,y,z}; + return SetUniform(name, 3, v); + } + bool SetUniform4f(const char* name, float x, float y, float z, float w = 1) + { + const float v[] = {x,y,z,w}; + return SetUniform(name, 4, v); + } + + bool SetUniformv(const char* name, const Vector3f& v) + { + const float a[] = {v.x,v.y,v.z,1}; + return SetUniform(name, 4, a); + } + + virtual bool SetUniform4x4f(const char* name, const Matrix4f& m) + { + Matrix4f mt = m.Transposed(); + return SetUniform(name, 16, &mt.M[0][0]); + } +}; + + +// Fill combines a ShaderSet (vertex, pixel) with textures, if any. +// Every model has a fill. +class ShaderFill : public RefCountBase<ShaderFill> +{ + Ptr<ShaderSet> Shaders; + Ptr<class Texture> Textures[8]; + void* InputLayout; // HACK this should be abstracted + +public: + ShaderFill(ShaderSet* sh) : Shaders(sh) { InputLayout = NULL; } + ShaderFill(ShaderSet& sh) : Shaders(sh) { InputLayout = NULL; } + + ShaderSet* GetShaders() const { return Shaders; } + void* GetInputLayout() const { return InputLayout; } + + virtual void Set(PrimitiveType prim = Prim_Unknown) const; + virtual void SetTexture(int i, class Texture* tex) { if (i < 8) Textures[i] = tex; } + void SetInputLayout(void* newIL) { InputLayout = (void*)newIL; } +}; + + +class ShaderBase : public Shader +{ +public: + RenderParams* pParams; + unsigned char* UniformData; + int UniformsSize; + + enum VarType + { + VARTYPE_FLOAT, + VARTYPE_INT, + VARTYPE_BOOL, + }; + + struct Uniform + { + const char* Name; + VarType Type; + int Offset, Size; + }; + const Uniform* UniformRefl; + size_t UniformReflSize; + + ShaderBase(RenderParams* rp, ShaderStage stage); + ~ShaderBase(); + + ShaderStage GetStage() const { return Stage; } + + void InitUniforms(const Uniform* refl, size_t reflSize); + bool SetUniform(const char* name, int n, const float* v); + bool SetUniformBool(const char* name, int n, const bool* v); + + void UpdateBuffer(Buffer* b); +}; + + +template<ShaderStage SStage, class D3DShaderType> +class ShaderImpl : public ShaderBase +{ +public: + D3DShaderType* D3DShader; + + ShaderImpl(RenderParams* rp, void* s, size_t size, const Uniform* refl, size_t reflSize) : ShaderBase(rp, SStage) + { + Load(s, size); + InitUniforms(refl, reflSize); + } + ~ShaderImpl() + { + if (D3DShader) + D3DShader->Release(); + } + + // These functions have specializations. + bool Load(void* shader, size_t size); + void Set(PrimitiveType prim) const; + void SetUniformBuffer(Buffer* buffers, int i = 0); +}; + +typedef ShaderImpl<Shader_Vertex, ID3D1xVertexShader> VertexShader; +typedef ShaderImpl<Shader_Fragment, ID3D1xPixelShader> PixelShader; + + +class Buffer : public RefCountBase<Buffer> +{ +public: + RenderParams* pParams; + Ptr<ID3D1xBuffer> D3DBuffer; + size_t Size; + int Use; + bool Dynamic; + +public: + Buffer(RenderParams* rp) : pParams(rp), Size(0), Use(0) {} + ~Buffer(); + + ID3D1xBuffer* GetBuffer() const { return D3DBuffer; } + + virtual size_t GetSize() { return Size; } + virtual void* Map(size_t start, size_t size, int flags = 0); + virtual bool Unmap(void *m); + virtual bool Data(int use, const void* buffer, size_t size); +}; + + +class Texture : public RefCountBase<Texture> +{ +public: + RenderParams* pParams; + Ptr<ID3D1xTexture2D> Tex; + Ptr<ID3D1xShaderResourceView> TexSv; + Ptr<ID3D1xRenderTargetView> TexRtv; + Ptr<ID3D1xDepthStencilView> TexDsv; + mutable Ptr<ID3D1xSamplerState> Sampler; + Sizei TextureSize; + int Samples; + + Texture(RenderParams* rp, int fmt, const Sizei texSize, + ID3D1xSamplerState* sampler, int samples = 1); + ~Texture(); + + virtual Sizei GetSize() const { return TextureSize; } + virtual int GetSamples() const { return Samples; } + + // virtual void SetSampleMode(int sm); + + // Updates texture to point to specified resources + // - used for slave rendering. + void UpdatePlaceholderTexture(ID3D1xTexture2D* texture, + ID3D1xShaderResourceView* psrv, + const Sizei& textureSize) + { + Tex = texture; + TexSv = psrv; + TexRtv.Clear(); + TexDsv.Clear(); + + TextureSize = textureSize; + +#ifdef OVR_BUILD_DEBUG + D3D1X_(TEXTURE2D_DESC) desc; + texture->GetDesc(&desc); + OVR_ASSERT(TextureSize == Sizei(desc.Width, desc.Height)); +#endif + } + + + virtual void Set(int slot, ShaderStage stage = Shader_Fragment) const; + +}; + + +class GpuTimer : public RefCountBase<GpuTimer> +{ +public: + GpuTimer() + : QuerySets(MaxNumQueryFrames) + , D3dDevice(NULL) + , Context(NULL) + , LastQueuedFrame(-1) + , LastTimedFrame(-1) + { } + + void Init(ID3D1xDevice* device, ID3D1xDeviceContext* content); + + void BeginQuery(); + void EndQuery(); + + // Returns -1 if timing is invalid + float GetTiming(bool blockUntilValid); + +protected: + static const unsigned MaxNumQueryFrames = 10; + + int GotoNextFrame(int frame) + { + return (frame + 1) % MaxNumQueryFrames; + } + + _COM_SMARTPTR_TYPEDEF(ID3D1xQuery, __uuidof(ID3D1xQuery)); + + struct GpuQuerySets + { + ID3D1xQueryPtr DisjointQuery; + ID3D1xQueryPtr TimeStartQuery; + ID3D1xQueryPtr TimeEndQuery; + bool QueryStarted; + bool QueryAwaitingTiming; + + GpuQuerySets() : QueryStarted(false), QueryAwaitingTiming(false) {} + }; + Array<GpuQuerySets> QuerySets; + + int LastQueuedFrame; + int LastTimedFrame; + + Ptr<ID3D1xDevice> D3dDevice; + Ptr<ID3D1xDeviceContext> Context; +}; + +}}} // OVR::CAPI::D3D1X + +#endif // INC_OVR_CAPI_D3D10/11_Util_h diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.cpp b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.cpp new file mode 100644 index 0000000..21b885e --- /dev/null +++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.cpp @@ -0,0 +1,251 @@ +/************************************************************************************ + +Filename : CAPI_D3D1X_DistortionRenderer.cpp +Content : Experimental distortion renderer +Created : March 7th, 2014 +Authors : Tom Heath + +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_D3D9_DistortionRenderer.h" +#define OVR_D3D_VERSION 9 +#include "../../OVR_CAPI_D3D.h" + +namespace OVR { namespace CAPI { namespace D3D9 { + + +///QUESTION : Why not just a normal constructor? +CAPI::DistortionRenderer* DistortionRenderer::Create(ovrHmd hmd, + FrameTimeManager& timeManager, + const HMDRenderState& renderState) +{ + return new DistortionRenderer(hmd, timeManager, renderState); +} + +DistortionRenderer::DistortionRenderer(ovrHmd hmd, FrameTimeManager& timeManager, + const HMDRenderState& renderState) + : CAPI::DistortionRenderer(ovrRenderAPI_D3D9, hmd, timeManager, renderState) +{ +} +/**********************************************/ +DistortionRenderer::~DistortionRenderer() +{ + //Release any memory + eachEye[0].dxIndices->Release(); + eachEye[0].dxVerts->Release(); + eachEye[1].dxIndices->Release(); + eachEye[1].dxVerts->Release(); +} + + +/******************************************************************************/ +bool DistortionRenderer::Initialize(const ovrRenderAPIConfig* apiConfig, + unsigned hmdCaps, unsigned arg_distortionCaps) +{ + // TBD: Decide if hmdCaps are needed here or are a part of RenderState + OVR_UNUSED(hmdCaps); + + ///QUESTION - what is returned bool for??? Are we happy with this true, if not config. + const ovrD3D9Config * config = (const ovrD3D9Config*)apiConfig; + if (!config) return true; + if (!config->D3D9.pDevice) return false; + + //Glean all the required variables from the input structures + device = config->D3D9.pDevice; + screenSize = config->D3D9.Header.RTSize; + distortionCaps = arg_distortionCaps; + + CreateVertexDeclaration(); + CreateDistortionShaders(); + Create_Distortion_Models(); + + return (true); +} + + +/**************************************************************/ +void DistortionRenderer::SubmitEye(int eyeId, ovrTexture* eyeTexture) +{ + //Doesn't do a lot in here?? + const ovrD3D9Texture* tex = (const ovrD3D9Texture*)eyeTexture; + + //Write in values + eachEye[eyeId].texture = tex->D3D9.pTexture; + + //Its only at this point we discover what the viewport of the texture is. + //because presumably we allow users to realtime adjust the resolution. + //Which begs the question - why did we ask them what viewport they were + //using before, which gave them a set of UV offsets. In fact, our + //asking for eye mesh must be entirely independed of these viewports, + //presumably only to get the parameters. + + ovrEyeDesc ed = RState.EyeRenderDesc[eyeId].Desc; + ed.TextureSize = tex->D3D9.Header.TextureSize; + ed.RenderViewport = tex->D3D9.Header.RenderViewport; + + ovrHmd_GetRenderScaleAndOffset(HMD, ed, distortionCaps, eachEye[eyeId].UVScaleOffset); +} + + +/******************************************************************/ +void DistortionRenderer::EndFrame(bool swapBuffers, unsigned char* latencyTesterDrawColor, unsigned char* latencyTester2DrawColor) +{ + OVR_UNUSED(swapBuffers); + OVR_UNUSED(latencyTesterDrawColor); + + ///QUESTION : Should I be clearing the screen? + ///QUESTION : Should I be ensuring the screen is the render target + + if (!TimeManager.NeedDistortionTimeMeasurement()) + { + if (RState.DistortionCaps & ovrDistortion_TimeWarp) + { + // Wait for timewarp distortion if it is time and Gpu idle + WaitTillTimeAndFlushGpu(TimeManager.GetFrameTiming().TimewarpPointTime); + } + + RenderBothDistortionMeshes(); + } + else + { + // If needed, measure distortion time so that TimeManager can better estimate + // latency-reducing time-warp wait timing. + WaitUntilGpuIdle(); + double distortionStartTime = ovr_GetTimeInSeconds(); + + RenderBothDistortionMeshes(); + WaitUntilGpuIdle(); + + TimeManager.AddDistortionTimeMeasurement(ovr_GetTimeInSeconds() - distortionStartTime); + } + + if(latencyTesterDrawColor) + { + ///QUESTION : Is this still to be supported? + ///renderLatencyQuad(latencyTesterDrawColor); + } + + if(latencyTester2DrawColor) + { + // TODO: + } + + if (swapBuffers) + { + device->Present( NULL, NULL, NULL, NULL ); + + /// if (RParams.pSwapChain) + { + /// UINT swapInterval = (RState.HMDCaps & ovrHmdCap_NoVSync) ? 0 : 1; + /// RParams.pSwapChain->Present(swapInterval, 0); + + // Force GPU to flush the scene, resulting in the lowest possible latency. + // It's critical that this flush is *after* present. + /// WaitUntilGpuIdle(); + } + /// else + { + // TBD: Generate error - swapbuffer option used with null swapchain. + } + } +} + + +void DistortionRenderer::WaitUntilGpuIdle() +{ +#if 0 + // Flush and Stall CPU while waiting for GPU to complete rendering all of the queued draw calls + D3D1x_QUERY_DESC queryDesc = { D3D1X_(QUERY_EVENT), 0 }; + Ptr<ID3D1xQuery> query; + BOOL done = FALSE; + + if (RParams.pDevice->CreateQuery(&queryDesc, &query.GetRawRef()) == S_OK) + { + D3DSELECT_10_11(query->End(), + RParams.pContext->End(query)); + + // GetData will returns S_OK for both done == TRUE or FALSE. + // Exit on failure to avoid infinite loop. + do { } + while(!done && + !FAILED(D3DSELECT_10_11(query->GetData(&done, sizeof(BOOL), 0), + RParams.pContext->GetData(query, &done, sizeof(BOOL), 0))) + ); + } +#endif +} + +double DistortionRenderer::WaitTillTimeAndFlushGpu(double absTime) +{ + +OVR_UNUSED(absTime); +#if 0 + double initialTime = ovr_GetTimeInSeconds(); + if (initialTime >= absTime) + return 0.0; + + // Flush and Stall CPU while waiting for GPU to complete rendering all of the queued draw calls + D3D1x_QUERY_DESC queryDesc = { D3D1X_(QUERY_EVENT), 0 }; + Ptr<ID3D1xQuery> query; + BOOL done = FALSE; + bool callGetData = false; + + if (RParams.pDevice->CreateQuery(&queryDesc, &query.GetRawRef()) == S_OK) + { + D3DSELECT_10_11(query->End(), + RParams.pContext->End(query)); + callGetData = true; + } + + double newTime = initialTime; + volatile int i; + + while (newTime < absTime) + { + if (callGetData) + { + // GetData will returns S_OK for both done == TRUE or FALSE. + // Stop calling GetData on failure. + callGetData = !FAILED(D3DSELECT_10_11(query->GetData(&done, sizeof(BOOL), 0), + RParams.pContext->GetData(query, &done, sizeof(BOOL), 0))) && !done; + } + else + { + for (int j = 0; j < 50; j++) + i = 0; + } + newTime = ovr_GetTimeInSeconds(); + } + + // How long we waited + return newTime - initialTime; +#endif + return 0; //dummy +} + + + + + + + +}}} // OVR::CAPI::D3D1X + + diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.h b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.h new file mode 100644 index 0000000..9332b83 --- /dev/null +++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.h @@ -0,0 +1,120 @@ +/************************************************************************************ + +Filename : CAPI_D3D1X_DistortionRenderer.h +Content : Experimental distortion renderer +Created : March 7, 2014 +Authors : Tom Heath + +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. + +************************************************************************************/ + +#undef new + +#if _MSC_VER < 1700 +#include <d3dx9.h> +#else +#include <d3d9.h> +#endif + +#if defined(OVR_DEFINE_NEW) +#define new OVR_DEFINE_NEW +#endif + +#include "../CAPI_DistortionRenderer.h" + + +namespace OVR { namespace CAPI { namespace D3D9 { + + +//Implementation of DistortionRenderer for D3D9. +/***************************************************/ +class DistortionRenderer : public CAPI::DistortionRenderer +{ +public: + DistortionRenderer(ovrHmd hmd, FrameTimeManager& timeManager, const HMDRenderState& renderState); + ~DistortionRenderer(); + + // Creation function for the device. + static CAPI::DistortionRenderer* Create(ovrHmd hmd, + FrameTimeManager& timeManager, + const HMDRenderState& renderState); + + // ***** Public DistortionRenderer interface + virtual bool Initialize(const ovrRenderAPIConfig* apiConfig, + unsigned hmdCaps, unsigned distortionCaps); + + virtual void SubmitEye(int eyeId, ovrTexture* eyeTexture); + + virtual void EndFrame(bool swapBuffers, unsigned char* latencyTesterDrawColor, unsigned char* latencyTester2DrawColor); + + // TBD: Make public? + void WaitUntilGpuIdle(); + + // Similar to ovr_WaitTillTime but it also flushes GPU. + // Note, it exits when time expires, even if GPU is not in idle state yet. + double WaitTillTimeAndFlushGpu(double absTime); + +private: + + //Functions + void CreateDistortionShaders(void); + void Create_Distortion_Models(void); + void CreateVertexDeclaration(void); + void RenderBothDistortionMeshes(); + void RecordAndSetState(int which, int type, DWORD newValue); + void RevertAllStates(void); + + + //Data, structures and pointers + IDirect3DDevice9 * device; + IDirect3DVertexDeclaration9 * vertexDecl; + IDirect3DPixelShader9 * pixelShader; + IDirect3DVertexShader9 * vertexShader; + IDirect3DVertexShader9 * vertexShaderTimewarp; + ovrSizei screenSize; + unsigned distortionCaps; + + struct FOR_EACH_EYE + { + IDirect3DVertexBuffer9 * dxVerts; + IDirect3DIndexBuffer9 * dxIndices; + int numVerts; + int numIndices; + IDirect3DTexture9 * texture; + ovrVector2f UVScaleOffset[2]; + } eachEye[2]; + + + //Structure to store our state changes + #define MAX_SAVED_STATES 100 + struct SavedStateType + { + int which; //0 for samplerstate, 1 for renderstate + int type; + DWORD valueToRevertTo; + } savedState[MAX_SAVED_STATES]; + + //Keep track of how many we've done, for reverting + int numSavedStates; + + + +}; + +}}} // OVR::CAPI::D3D9 diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_Util.cpp b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_Util.cpp new file mode 100644 index 0000000..ea36100 --- /dev/null +++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_Util.cpp @@ -0,0 +1,317 @@ +/************************************************************************************ + +Filename : CAPI_D3D1X_Util.cpp +Content : D3D9 utility functions for rendering +Created : March 7 , 2014 +Authors : Tom Heath + +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_D3D9_DistortionRenderer.h" +#define OVR_D3D_VERSION 9 +#include "../../OVR_CAPI_D3D.h" + + +namespace OVR { namespace CAPI { namespace D3D9 { + + + +#define PRECOMPILE_FLAG 0 +#if !PRECOMPILE_FLAG +//To make these, you need to run it with PRECOMPILE_FLAG, which also uses them, so good for debugging. +//Then cut and paste these from the output window. +//Then turn off the flag. +DWORD precompiledVertexShaderSrc[95] = {4294836736,3014654,1111577667,28,127,4294836736,2,28,33024,120,68,131074,655361,88,0,104,2,131073,88,0,1415936325,1668436847,1716475477,1952805734,2880154368,196609,131073,1,0,1415936325,1668436847,1666405973,6646881,845116278,1291858015,1869767529,1952870259,693250080,1397508128,1750278220,1919247457,1836008224,1701603696,775495794,959330610,858665525,3223857,83886161,2685337601,1065353216,0,1056964608,0,33554463,2147483648,2416902144,33554463,2147614720,2416902145,33554463,2147483653,2416902146,33554463,2147549189,2416902147,33554463,2147614725,2416902148,33554433,2147680256,2699296768,67108868,3758292992,2162425856,2430861314,2699296770,67108868,3758292993,2162425856,2430861315,2699296770,67108868,3758292994,2162425856,2430861316,2699296770,67108868,3222208512,2416181248,2689597441,2686779393,33554433,3758161923,2415919105,65535,}; +DWORD precompiledVertexShaderTimewarpSrc[293] = {4294836736,4456446,1111577667,28,215,4294836736,4,28,33024,208,108,1310722,5373956,124,0,140,262146,1179652,124,0,157,131074,655361,176,0,192,2,131073,176,0,1382381893,1952543855,1164865385,2868929646,196611,262148,1,0,1382381893,1952543855,1399746409,1953653108,1702446336,1918070612,1331058019,1702061670,2880110708,196609,131073,1,0,1415936325,1668436847,1666405973,6646881,845116278,1291858015,1869767529,1952870259,693250080,1397508128,1750278220,1919247457,1836008224,1701603696,775495794,959330610,858665525,3223857,83886161,2685337601,1065353216,0,1056964608,0,33554463,2147483648,2416902144,33554463,2147549184,2416902145,33554463,2147614720,2416902146,33554463,2147483653,2416902147,33554463,2147549189,2416902148,33554463,2147614725,2416902149,33554433,2147549184,2695495684,50331650,2147549185,2164260864,2695495700,33554433,2147614720,2695495685,50331650,2147614721,2169831424,2695495701,33554433,2147745792,2695495686,50331650,2147745793,2175401984,2695495702,33554433,2148007936,2695495687,50331650,2148007937,2180972544,2695495703,67108868,2148466688,2415919105,2162425857,2162425856,67108868,2148466689,2416181251,2689597441,2684682241,50331657,2147549186,2162425856,2162425857,33554438,2147549186,2147483650,33554433,2147680259,2699296772,50331650,2147876866,2177892355,2697986068,67108868,2147549187,2415919105,2158624770,2689925124,67108868,2147549188,2415919105,2153054210,2684354564,33554433,2147680261,2699296773,50331650,2147876866,2177105925,2697199637,67108868,2147614723,2415919105,2153054210,2689925125,67108868,2147614724,2415919105,2158624770,2684354565,33554433,2147680261,2699296774,50331650,2147811333,2177171461,2697265174,67108868,2147745795,2415919105,2147483653,2689925126,67108868,2147745796,2415919105,2158624773,2684354566,33554433,2147680261,2699296775,50331650,2148073477,2166685701,2686779415,67108868,2148007939,2415919105,2147483653,2689925127,67108868,2148007940,2415919105,2164195333,2684354567,50331657,2147549189,2162425860,2162425857,50331657,2147614725,2162425859,2162425857,50331653,2147680257,2147483650,2162425861,33554433,2147680258,2699296768,67108868,3758292992,2162425858,2162425857,2699296770,67108868,2148466689,2416181252,2689597441,2684682241,50331657,2147549189,2162425860,2162425857,50331657,2147614725,2162425859,2162425857,50331657,2147549185,2162425856,2162425857,33554438,2147549185,2147483649,50331653,2147680257,2147483649,2162425861,67108868,3758292993,2162425858,2162425857,2699296770,67108868,2148466689,2416181253,2689597441,2684682241,50331657,2147549188,2162425860,2162425857,50331657,2147614724,2162425859,2162425857,50331657,2147549184,2162425856,2162425857,33554438,2147549184,2147483648,50331653,2147680256,2147483648,2162425860,67108868,3758292994,2162425858,2162425856,2699296770,67108868,3222208512,2416181248,2689597441,2686779393,33554433,3758161923,2415919106,65535,}; +DWORD precompiledPixelShaderSrc[84] = {4294902528,2228222,1111577667,28,79,4294902528,1,28,33024,72,48,3,131073,56,0,1954047316,6648437,786436,65537,1,0,861893488,1291858015,1869767529,1952870259,693250080,1397508128,1750278220,1919247457,1836008224,1701603696,775495794,959330610,858665525,3223857,83886161,2685337600,1065353216,0,0,0,33554463,2147483653,2416115712,33554463,2147549189,2416115713,33554463,2147614725,2416115714,33554463,2147680261,2415984643,33554463,2415919104,2685339648,50331714,2148466688,2430861312,2699298816,67108868,2148073472,2147483648,2690908160,2686779392,50331714,2148466689,2430861313,2699298816,33554433,2147614720,2153054209,50331714,2148466689,2430861314,2699298816,33554433,2147745792,2158624769,50331653,2148468736,2162425856,2415919107,65535,}; + +#else +#include "d3dcompiler.h" +/***************************************************************************/ +const char* VertexShaderSrc = + + "float2 EyeToSourceUVScale : register(c0); \n" + "float2 EyeToSourceUVOffset : register(c2); \n" + + "void main(in float2 Position : POSITION, in float TimeWarp : POSITION1, \n" + " in float Vignette : POSITION2, in float2 TexCoord0 : TEXCOORD0, \n" + " in float2 TexCoord1 : TEXCOORD1, in float2 TexCoord2 : TEXCOORD2, \n" + " out float4 oPosition : SV_Position, out float2 oTexCoord0 : TEXCOORD0, \n" + " out float2 oTexCoord1 : TEXCOORD1, out float2 oTexCoord2 : TEXCOORD2, \n" + " out float oVignette : TEXCOORD3) \n" + "{ \n" + " oTexCoord0 = EyeToSourceUVScale * TexCoord0 + EyeToSourceUVOffset; \n" + " oTexCoord1 = EyeToSourceUVScale * TexCoord1 + EyeToSourceUVOffset; \n" + " oTexCoord2 = EyeToSourceUVScale * TexCoord2 + EyeToSourceUVOffset; \n" + " oVignette = Vignette; \n" + " oPosition = float4(Position.xy, 0.5, 1.0); \n" + "}"; + +/***************************************************************************/ +const char* VertexShaderTimewarpSrc = + + "float2 EyeToSourceUVScale : register(c0); \n" + "float2 EyeToSourceUVOffset : register(c2); \n" + "float4x4 EyeRotationStart : register(c4); \n" + "float4x4 EyeRotationEnd : register(c20); \n" + + "float2 TimewarpTexCoord(float2 TexCoord, float4x4 rotMat) \n" + "{ \n" + " float3 transformed = float3( mul ( rotMat, float4(TexCoord.xy, 1, 1) ).xyz); \n" + " float2 flattened = (transformed.xy / transformed.z); \n" + " return(EyeToSourceUVScale * flattened + EyeToSourceUVOffset); \n" + "} \n" + "void main(in float2 Position : POSITION, in float TimeWarp : POSITION1, \n" + " in float Vignette : POSITION2, in float2 TexCoord0 : TEXCOORD0, \n" + " in float2 TexCoord1 : TEXCOORD1, in float2 TexCoord2 : TEXCOORD2, \n" + " out float4 oPosition : SV_Position, out float2 oTexCoord0 : TEXCOORD0, \n" + " out float2 oTexCoord1 : TEXCOORD1, out float2 oTexCoord2 : TEXCOORD2, \n" + " out float oVignette : TEXCOORD3) \n" + "{ \n" + " float4x4 lerpedEyeRot = lerp(EyeRotationStart, EyeRotationEnd, TimeWarp); \n" + " oTexCoord0 = TimewarpTexCoord(TexCoord0,lerpedEyeRot); \n" + " oTexCoord1 = TimewarpTexCoord(TexCoord1,lerpedEyeRot); \n" + " oTexCoord2 = TimewarpTexCoord(TexCoord2,lerpedEyeRot); \n" + " oVignette = Vignette; \n" + " oPosition = float4(Position.xy, 0.5, 1.0); \n" + "}"; + +/***************************************************************************/ +const char* PixelShaderSrc = + + " sampler2D Texture : register(s0); \n" + + "float4 main(in float4 oPosition : SV_Position, in float2 oTexCoord0 : TEXCOORD0, \n" + " in float2 oTexCoord1 : TEXCOORD1, in float2 oTexCoord2 : TEXCOORD2, \n" + " in float oVignette : TEXCOORD3) \n" + " : SV_Target \n" + "{ \n" + " float R = tex2D(Texture,oTexCoord0).r; \n" + " float G = tex2D(Texture,oTexCoord1).g; \n" + " float B = tex2D(Texture,oTexCoord2).b; \n" + " return (oVignette*float4(R,G,B,1)); \n" + "}"; + +/*************************************************************/ +ID3DBlob* ShaderCompile(char * shaderName, const char * shaderSrcString, const char * profile) +{ + ID3DBlob* pShaderCode = NULL; + ID3DBlob* pErrorMsg = NULL; + + if (FAILED(D3DCompile(shaderSrcString, strlen(shaderSrcString),NULL,NULL,NULL, + "main",profile,D3DCOMPILE_OPTIMIZATION_LEVEL3,0, + &pShaderCode,&pErrorMsg))) + MessageBoxA(NULL,(char *) pErrorMsg->GetBufferPointer(),"", MB_OK); + if (pErrorMsg) pErrorMsg->Release(); + + //Now write out blob + char tempString[1000]; + int numDWORDs = ((int)pShaderCode->GetBufferSize())/4; + DWORD * ptr = (DWORD *)pShaderCode->GetBufferPointer(); + sprintf_s(tempString,"DWORD %s[%d] = {",shaderName,numDWORDs); + OutputDebugStringA(tempString); + for (int i = 0;i < numDWORDs; i++) + { + sprintf_s(tempString,"%lu,",ptr[i]); + OutputDebugStringA(tempString); + } + OutputDebugStringA("};\n"); + + return(pShaderCode); +} +#endif + +/***********************************************************/ +void DistortionRenderer::CreateDistortionShaders(void) +{ +#if PRECOMPILE_FLAG + ID3DBlob * pShaderCode; + pShaderCode = ShaderCompile("precompiledVertexShaderSrc",VertexShaderSrc,"vs_2_0"); + device->CreateVertexShader( ( DWORD* )pShaderCode->GetBufferPointer(), &vertexShader ); + pShaderCode->Release(); + + pShaderCode = ShaderCompile("precompiledVertexShaderTimewarpSrc",VertexShaderTimewarpSrc,"vs_2_0"); + device->CreateVertexShader( ( DWORD* )pShaderCode->GetBufferPointer(), &vertexShaderTimewarp ); + pShaderCode->Release(); + + pShaderCode = ShaderCompile("precompiledPixelShaderSrc",PixelShaderSrc,"ps_3_0"); + device->CreatePixelShader( ( DWORD* )pShaderCode->GetBufferPointer(), &pixelShader ); + pShaderCode->Release(); +#else + device->CreateVertexShader( precompiledVertexShaderSrc, &vertexShader ); + device->CreateVertexShader( precompiledVertexShaderTimewarpSrc, &vertexShaderTimewarp ); + device->CreatePixelShader( precompiledPixelShaderSrc, &pixelShader ); +#endif +} + + +/***************************************************/ +void DistortionRenderer::CreateVertexDeclaration(void) +{ + static const D3DVERTEXELEMENT9 VertexElements[7] = { + { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, + { 0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 1 }, + { 0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 2 }, + { 0, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, + { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 }, + { 0, 32, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2 }, + D3DDECL_END() }; + device->CreateVertexDeclaration( VertexElements, &vertexDecl ); +} + + +/******************************************************/ +void DistortionRenderer::Create_Distortion_Models(void) +{ + //Make the distortion models + for (int eye=0;eye<2;eye++) + { + ovrVector2f dummy_UVScaleOffset[2]; //because it needs to be updated by a later call + FOR_EACH_EYE * e = &eachEye[eye]; + ovrDistortionMesh meshData; + ovrHmd_CreateDistortionMesh(HMD, RState.EyeRenderDesc[eye].Desc, distortionCaps, + dummy_UVScaleOffset, &meshData); + + e->numVerts = meshData.VertexCount; + e->numIndices = meshData.IndexCount; + + device->CreateVertexBuffer( (e->numVerts)*sizeof(ovrDistortionVertex),0, 0,D3DPOOL_MANAGED, &e->dxVerts, NULL ); + ovrDistortionVertex * dxv; e->dxVerts->Lock( 0, 0, (void**)&dxv, 0 ); + for (int v=0;v<e->numVerts;v++) dxv[v] = meshData.pVertexData[v]; + + device->CreateIndexBuffer( (e->numIndices)*sizeof(u_short),0, D3DFMT_INDEX16,D3DPOOL_MANAGED, &e->dxIndices, NULL ); + unsigned short* dxi; e->dxIndices->Lock( 0, 0, (void**)&dxi, 0 ); + for (int i=0;i<e->numIndices;i++) dxi[i] = meshData.pIndexData[i]; + + ovrHmd_DestroyDistortionMesh( &meshData ); + } +} + +/**********************************************************/ +void DistortionRenderer::RenderBothDistortionMeshes(void) +{ + //Record and set render state + numSavedStates=0; + RecordAndSetState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); + RecordAndSetState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); + RecordAndSetState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR ); + RecordAndSetState(0, D3DSAMP_BORDERCOLOR, 0x000000 ); + RecordAndSetState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER ); + RecordAndSetState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER ); + RecordAndSetState(1, D3DRS_MULTISAMPLEANTIALIAS, FALSE ); + RecordAndSetState(1, D3DRS_DITHERENABLE, FALSE ); + RecordAndSetState(1, D3DRS_ZENABLE, FALSE ); + RecordAndSetState(1, D3DRS_ZWRITEENABLE, TRUE ); + RecordAndSetState(1, D3DRS_ZFUNC, D3DCMP_LESSEQUAL ); + RecordAndSetState(1, D3DRS_CULLMODE , D3DCULL_CCW ); + RecordAndSetState(1, D3DRS_ALPHABLENDENABLE , FALSE ); + RecordAndSetState(1, D3DRS_DEPTHBIAS , 0 ); + RecordAndSetState(1, D3DRS_SRCBLEND , D3DBLEND_SRCALPHA ); + RecordAndSetState(1, D3DRS_DESTBLEND , D3DBLEND_INVSRCALPHA ); + RecordAndSetState(1, D3DRS_FILLMODE, D3DFILL_SOLID ); + RecordAndSetState(1, D3DRS_ALPHATESTENABLE, FALSE); + RecordAndSetState(1, D3DRS_DEPTHBIAS , 0 ); + RecordAndSetState(1, D3DRS_LIGHTING, FALSE ); + RecordAndSetState(1, D3DRS_FOGENABLE, FALSE ); + + for (int eye=0; eye<2; eye++) + { + FOR_EACH_EYE * e = &eachEye[eye]; + D3DVIEWPORT9 vp; vp.X=0; vp.Y=0; vp.Width=screenSize.w; vp.Height=screenSize.h; vp.MinZ=0; vp.MaxZ = 1; + device->SetViewport(&vp); + device->SetStreamSource( 0, e->dxVerts,0, sizeof(ovrDistortionVertex) ); + device->SetVertexDeclaration( vertexDecl ); + device->SetIndices( e->dxIndices ); + device->SetPixelShader( pixelShader ); + device->SetTexture( 0, e->texture); + + //Choose which vertex shader, with associated additional inputs + if (distortionCaps & ovrDistortion_TimeWarp) + { + device->SetVertexShader( vertexShaderTimewarp ); + + ovrMatrix4f timeWarpMatrices[2]; + ovrHmd_GetEyeTimewarpMatrices(HMD, (ovrEyeType)eye, + RState.EyeRenderPoses[eye], timeWarpMatrices); + + // Feed identity like matrices in until we get proper timewarp calculation going on + device->SetVertexShaderConstantF(4, (float *) &timeWarpMatrices[0],4); + device->SetVertexShaderConstantF(20,(float *) &timeWarpMatrices[1],4); + } + else + { + device->SetVertexShader( vertexShader ); + } + + + //Set up vertex shader constants + device->SetVertexShaderConstantF( 0, ( FLOAT* )&(e->UVScaleOffset[0]), 1 ); + device->SetVertexShaderConstantF( 2, ( FLOAT* )&(e->UVScaleOffset[1]), 1 ); + + device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,0,0,e->numVerts,0,e->numIndices/3); + } + + //Revert render state + RevertAllStates(); + +} + +/*********************************************************************************/ +void DistortionRenderer::RecordAndSetState(int which, int type, DWORD newValue) +{ + SavedStateType * sst = &savedState[numSavedStates++]; + sst->which = which; + sst->type = type; + if (which==0) + { + device->GetSamplerState( 0, (D3DSAMPLERSTATETYPE)type, &sst->valueToRevertTo); + device->SetSamplerState( 0, (D3DSAMPLERSTATETYPE)type, newValue); + } + else + { + device->GetRenderState( (D3DRENDERSTATETYPE)type, &sst->valueToRevertTo); + device->SetRenderState( (D3DRENDERSTATETYPE)type, newValue); + } +} +/*********************************************************************************/ +void DistortionRenderer::RevertAllStates(void) +{ + for (int i=0;i<numSavedStates;i++) + { + SavedStateType * sst = &savedState[i]; + if (sst->which==0) + { + device->SetSamplerState( 0, (D3DSAMPLERSTATETYPE)sst->type, sst->valueToRevertTo); + } + else + { + device->SetRenderState( (D3DRENDERSTATETYPE)sst->type, sst->valueToRevertTo); + } + } +} + + + + + + + + +}}}
\ No newline at end of file |