diff options
Diffstat (limited to 'LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.h')
-rw-r--r-- | LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.h | 505 |
1 files changed, 505 insertions, 0 deletions
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 |