RenderTiny_D3D1X_Device.cpp
Go to the documentation of this file.
00001 /************************************************************************************
00002 
00003 Filename    :   RenderTiny_D3D1x.cpp
00004 Content     :   RenderDevice implementation  for D3DX10/11.
00005 Created     :   September 10, 2012
00006 Authors     :   Andrew Reisse
00007 
00008 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
00009 
00010 Licensed under the Apache License, Version 2.0 (the "License");
00011 you may not use this file except in compliance with the License.
00012 You may obtain a copy of the License at
00013 
00014 http://www.apache.org/licenses/LICENSE-2.0
00015 
00016 Unless required by applicable law or agreed to in writing, software
00017 distributed under the License is distributed on an "AS IS" BASIS,
00018 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00019 See the License for the specific language governing permissions and
00020 limitations under the License.
00021 
00022 ************************************************************************************/
00023 
00024 #include "Kernel/OVR_Log.h"
00025 #include "Kernel/OVR_Std.h"
00026 
00027 #include "RenderTiny_D3D1X_Device.h"
00028 
00029 #include <d3dcompiler.h>
00030 
00031 namespace OVR { namespace RenderTiny { namespace D3D10 {
00032 
00033 
00034 //-------------------------------------------------------------------------------------
00035 // Vertex format
00036 static D3D1x_(INPUT_ELEMENT_DESC) ModelVertexDesc[] =
00037 {
00038     {"Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(Vertex, Pos),   D3D1x_(INPUT_PER_VERTEX_DATA), 0},
00039     {"Color",    0, DXGI_FORMAT_R8G8B8A8_UNORM,  0, offsetof(Vertex, C),     D3D1x_(INPUT_PER_VERTEX_DATA), 0},
00040     {"TexCoord", 0, DXGI_FORMAT_R32G32_FLOAT,    0, offsetof(Vertex, U),     D3D1x_(INPUT_PER_VERTEX_DATA), 0},    
00041     {"Normal",   0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(Vertex, Norm),  D3D1x_(INPUT_PER_VERTEX_DATA), 0},
00042 };
00043 
00044 // These shaders are used to render the world, including lit vertex-colored and textured geometry.
00045 
00046 // Used for world geometry; has projection matrix.
00047 static const char* StdVertexShaderSrc =
00048     "float4x4 Proj;\n"
00049     "float4x4 View;\n"
00050     "struct Varyings\n"
00051     "{\n"
00052     "   float4 Position : SV_Position;\n"
00053     "   float4 Color    : COLOR0;\n"
00054     "   float2 TexCoord : TEXCOORD0;\n"    
00055     "   float3 Normal   : NORMAL;\n"
00056     "   float3 VPos     : TEXCOORD4;\n"
00057     "};\n"
00058     "void main(in float4 Position : POSITION, in float4 Color : COLOR0, in float2 TexCoord : TEXCOORD0,"
00059     "          in float3 Normal : NORMAL,\n"
00060     "          out Varyings ov)\n"
00061     "{\n"
00062     "   ov.Position = mul(Proj, mul(View, Position));\n"
00063     "   ov.Normal = mul(View, Normal);\n"
00064     "   ov.VPos = mul(View, Position);\n"
00065     "   ov.TexCoord = TexCoord;\n"    
00066     "   ov.Color = Color;\n"
00067     "}\n";
00068 
00069 // Used for text/clearing; no projection.
00070 static const char* DirectVertexShaderSrc =
00071     "float4x4 View : register(c4);\n"
00072     "void main(in float4 Position : POSITION, in float4 Color : COLOR0,\n"
00073     "          in float2 TexCoord : TEXCOORD0, in float3 Normal : NORMAL,\n"
00074     "          out float4 oPosition : SV_Position, out float4 oColor : COLOR,\n"
00075     "          out float2 oTexCoord : TEXCOORD0,"
00076     "          out float3 oNormal : NORMAL)\n"
00077     "{\n"
00078     "   oPosition = mul(View, Position);\n"
00079     "   oTexCoord = TexCoord;\n"    
00080     "   oColor = Color;\n"
00081     "   oNormal = mul(View, Normal);\n"
00082     "}\n";
00083 
00084 static const char* SolidPixelShaderSrc =
00085     "float4 Color;\n"
00086     "struct Varyings\n"
00087     "{\n"
00088     "   float4 Position : SV_Position;\n"
00089     "   float4 Color    : COLOR0;\n"
00090     "   float2 TexCoord : TEXCOORD0;\n"
00091     "};\n"
00092     "float4 main(in Varyings ov) : SV_Target\n"
00093     "{\n"
00094     "   return Color;\n"
00095     "}\n";
00096 
00097 static const char* GouraudPixelShaderSrc =
00098     "struct Varyings\n"
00099     "{\n"
00100     "   float4 Position : SV_Position;\n"
00101     "   float4 Color    : COLOR0;\n"
00102     "   float2 TexCoord : TEXCOORD0;\n"
00103     "};\n"
00104     "float4 main(in Varyings ov) : SV_Target\n"
00105     "{\n"
00106     "   return ov.Color;\n"
00107     "}\n";
00108 
00109 static const char* TexturePixelShaderSrc =
00110     "Texture2D Texture : register(t0);\n"
00111     "SamplerState Linear : register(s0);\n"
00112     "struct Varyings\n"
00113     "{\n"
00114     "   float4 Position : SV_Position;\n"
00115     "   float4 Color    : COLOR0;\n"
00116     "   float2 TexCoord : TEXCOORD0;\n"
00117     "};\n"
00118     "float4 main(in Varyings ov) : SV_Target\n"
00119     "{\n"
00120     "   float4 color2 = ov.Color * Texture.Sample(Linear, ov.TexCoord);\n"
00121     "   if (color2.a <= 0.4)\n"
00122     "           discard;\n"
00123     "   return color2;\n"
00124     "}\n";
00125 
00126 
00127 #define LIGHTING_COMMON                 \
00128     "cbuffer Lighting : register(b1)\n" \
00129     "{\n"                               \
00130     "    float3 Ambient;\n"             \
00131     "    float3 LightPos[8];\n"         \
00132     "    float4 LightColor[8];\n"       \
00133     "    float  LightCount;\n"          \
00134     "};\n"                              \
00135     "struct Varyings\n"                 \
00136     "{\n"                                       \
00137     "   float4 Position : SV_Position;\n"       \
00138     "   float4 Color    : COLOR0;\n"            \
00139     "   float2 TexCoord : TEXCOORD0;\n"         \
00140     "   float3 Normal   : NORMAL;\n"            \
00141     "   float3 VPos     : TEXCOORD4;\n"         \
00142     "};\n"                                      \
00143     "float4 DoLight(Varyings v)\n"              \
00144     "{\n"                                       \
00145     "   float3 norm = normalize(v.Normal);\n"   \
00146     "   float3 light = Ambient;\n"              \
00147     "   for (uint i = 0; i < LightCount; i++)\n"\
00148     "   {\n"                                        \
00149     "       float3 ltp = (LightPos[i] - v.VPos);\n" \
00150     "       float  ldist = dot(ltp,ltp);\n"         \
00151     "       ltp = normalize(ltp);\n"                \
00152     "       light += saturate(LightColor[i] * v.Color.rgb * dot(norm, ltp) / sqrt(ldist));\n"\
00153     "   }\n"                                        \
00154     "   return float4(light, v.Color.a);\n"         \
00155     "}\n"
00156 
00157 static const char* LitSolidPixelShaderSrc =
00158     LIGHTING_COMMON
00159     "float4 main(in Varyings ov) : SV_Target\n"
00160     "{\n"
00161     "   return DoLight(ov) * ov.Color;\n"
00162     "}\n";
00163 
00164 static const char* LitTexturePixelShaderSrc =
00165     "Texture2D Texture : register(t0);\n"
00166     "SamplerState Linear : register(s0);\n"
00167     LIGHTING_COMMON
00168     "float4 main(in Varyings ov) : SV_Target\n"
00169     "{\n"
00170     "   return DoLight(ov) * Texture.Sample(Linear, ov.TexCoord);\n"
00171     "}\n";
00172 
00173 
00174 //-------------------------------------------------------------------------------------
00175 // ***** Distortion Post-process Shaders
00176 
00177 static const char* PostProcessVertexShaderSrc =
00178     "float4x4 View : register(c4);\n"
00179     "float4x4 Texm : register(c8);\n"
00180     "void main(in float4 Position : POSITION, in float4 Color : COLOR0, in float2 TexCoord : TEXCOORD0,\n" 
00181     "          out float4 oPosition : SV_Position, out float4 oColor : COLOR, out float2 oTexCoord : TEXCOORD0)\n"
00182     "{\n"
00183     "   oPosition = mul(View, Position);\n"
00184     "   oTexCoord = mul(Texm, float4(TexCoord,0,1));\n"
00185     "   oColor = Color;\n"
00186     "}\n";
00187 
00188 // Shader with just lens distortion correction.
00189 static const char* PostProcessPixelShaderSrc =
00190     "Texture2D Texture : register(t0);\n"
00191     "SamplerState Linear : register(s0);\n"
00192     "float2 LensCenter;\n"
00193     "float2 ScreenCenter;\n"
00194     "float2 Scale;\n"
00195     "float2 ScaleIn;\n"
00196     "float4 HmdWarpParam;\n"
00197     "\n"
00198 
00199     // Scales input texture coordinates for distortion.
00200     // ScaleIn maps texture coordinates to Scales to ([-1, 1]), although top/bottom will be
00201     // larger due to aspect ratio.
00202     "float2 HmdWarp(float2 in01)\n"
00203     "{\n"
00204     "   float2 theta = (in01 - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
00205     "   float  rSq = theta.x * theta.x + theta.y * theta.y;\n"
00206     "   float2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
00207     "                   HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
00208     "   return LensCenter + Scale * theta1;\n"
00209     "}\n"
00210 
00211     "float4 main(in float4 oPosition : SV_Position, in float4 oColor : COLOR,\n"
00212     " in float2 oTexCoord : TEXCOORD0) : SV_Target\n"
00213     "{\n"
00214     "   float2 tc = HmdWarp(oTexCoord);\n"
00215     "   if (any(clamp(tc, ScreenCenter-float2(0.25,0.5), ScreenCenter+float2(0.25, 0.5)) - tc))\n"
00216     "       return 0;\n"
00217     "   return Texture.Sample(Linear, tc);\n"
00218     "}\n";
00219 
00220 // Shader with lens distortion and chromatic aberration correction.
00221 static const char* PostProcessPixelShaderWithChromAbSrc =
00222     "Texture2D Texture : register(t0);\n"
00223     "SamplerState Linear : register(s0);\n"
00224     "float2 LensCenter;\n"
00225     "float2 ScreenCenter;\n"
00226     "float2 Scale;\n"
00227     "float2 ScaleIn;\n"
00228     "float4 HmdWarpParam;\n"
00229     "float4 ChromAbParam;\n"
00230     "\n"
00231 
00232     // Scales input texture coordinates for distortion.
00233     // ScaleIn maps texture coordinates to Scales to ([-1, 1]), although top/bottom will be
00234     // larger due to aspect ratio.
00235     "float4 main(in float4 oPosition : SV_Position, in float4 oColor : COLOR,\n"
00236     "            in float2 oTexCoord : TEXCOORD0) : SV_Target\n"
00237     "{\n"
00238     "   float2 theta = (oTexCoord - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
00239     "   float  rSq= theta.x * theta.x + theta.y * theta.y;\n"
00240     "   float2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
00241     "                   HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
00242     "   \n"
00243     "   // Detect whether blue texture coordinates are out of range since these will scaled out the furthest.\n"
00244     "   float2 thetaBlue = theta1 * (ChromAbParam.z + ChromAbParam.w * rSq);\n"
00245     "   float2 tcBlue = LensCenter + Scale * thetaBlue;\n"
00246     "   if (any(clamp(tcBlue, ScreenCenter-float2(0.25,0.5), ScreenCenter+float2(0.25, 0.5)) - tcBlue))\n"
00247     "       return 0;\n"
00248     "   \n"
00249     "   // Now do blue texture lookup.\n"
00250     "   float  blue = Texture.Sample(Linear, tcBlue).b;\n"
00251     "   \n"
00252     "   // Do green lookup (no scaling).\n"
00253     "   float2 tcGreen = LensCenter + Scale * theta1;\n"
00254     "   float  green = Texture.Sample(Linear, tcGreen).g;\n"
00255     "   \n"
00256     "   // Do red scale and lookup.\n"
00257     "   float2 thetaRed = theta1 * (ChromAbParam.x + ChromAbParam.y * rSq);\n"
00258     "   float2 tcRed = LensCenter + Scale * thetaRed;\n"
00259     "   float  red = Texture.Sample(Linear, tcRed).r;\n"
00260     "   \n"
00261     "   return float4(red, green, blue, 1);\n"
00262     "}\n";
00263 
00264 
00265 static const char* VShaderSrcs[VShader_Count] =
00266 {
00267     DirectVertexShaderSrc,
00268     StdVertexShaderSrc,
00269     PostProcessVertexShaderSrc
00270 };
00271 static const char* FShaderSrcs[FShader_Count] =
00272 {
00273     SolidPixelShaderSrc,
00274     GouraudPixelShaderSrc,
00275     TexturePixelShaderSrc,    
00276     PostProcessPixelShaderSrc,
00277     PostProcessPixelShaderWithChromAbSrc,
00278     LitSolidPixelShaderSrc,
00279     LitTexturePixelShaderSrc    
00280 };
00281 
00282 
00283 //-------------------------------------------------------------------------------------
00284 // ***** Buffer
00285 
00286 Buffer::~Buffer()
00287 {
00288 }
00289 
00290 bool Buffer::Data(int use, const void *buffer, size_t size)
00291 {
00292     if (D3DBuffer && Size >= size)
00293     {
00294         if (Dynamic)
00295         {
00296             if (!buffer)
00297                 return true;
00298 
00299             void* v = Map(0, size, Map_Discard);
00300             if (v)
00301             {
00302                 memcpy(v, buffer, size);
00303                 Unmap(v);
00304                 return true;
00305             }
00306         }
00307         else
00308         {
00309             Ren->Context->UpdateSubresource(D3DBuffer, 0, NULL, buffer, 0, 0);
00310             return true;
00311         }
00312     }
00313     if (D3DBuffer)
00314     {
00315         D3DBuffer = NULL;
00316         Size = 0;
00317         Use = 0;
00318         Dynamic = 0;
00319     }
00320 
00321     D3D1x_(BUFFER_DESC) desc;
00322     memset(&desc, 0, sizeof(desc));
00323     if (use & Buffer_ReadOnly)
00324     {
00325         desc.Usage = D3D1x_(USAGE_IMMUTABLE);
00326         desc.CPUAccessFlags = 0;
00327     }
00328     else
00329     {
00330         desc.Usage = D3D1x_(USAGE_DYNAMIC);
00331         desc.CPUAccessFlags = D3D1x_(CPU_ACCESS_WRITE);
00332         Dynamic = 1;
00333     }
00334 
00335     switch(use & Buffer_TypeMask)
00336     {
00337     case Buffer_Vertex:  desc.BindFlags = D3D1x_(BIND_VERTEX_BUFFER); break;
00338     case Buffer_Index:   desc.BindFlags = D3D1x_(BIND_INDEX_BUFFER);  break;
00339     case Buffer_Uniform:
00340         desc.BindFlags = D3D1x_(BIND_CONSTANT_BUFFER);
00341         size += ((size + 15) & ~15) - size;
00342         break;
00343     }
00344 
00345     desc.ByteWidth = (unsigned)size;
00346 
00347     D3D1x_(SUBRESOURCE_DATA) sr;
00348     sr.pSysMem = buffer;
00349     sr.SysMemPitch = 0;
00350     sr.SysMemSlicePitch = 0;
00351 
00352     HRESULT hr = Ren->Device->CreateBuffer(&desc, buffer ? &sr : NULL, &D3DBuffer.GetRawRef());
00353     if (SUCCEEDED(hr))
00354     {
00355         Use = use;
00356         Size = desc.ByteWidth;
00357         return 1;
00358     }
00359     return 0;
00360 }
00361 
00362 void*  Buffer::Map(size_t start, size_t size, int flags)
00363 {
00364     OVR_UNUSED(size);
00365 
00366     D3D1x_(MAP) mapFlags = D3D1x_(MAP_WRITE);
00367     if (flags & Map_Discard)    
00368         mapFlags = D3D1x_(MAP_WRITE_DISCARD);    
00369     if (flags & Map_Unsynchronized)    
00370         mapFlags = D3D1x_(MAP_WRITE_NO_OVERWRITE);    
00371 
00372     void* map = 0;
00373     if (SUCCEEDED(D3DBuffer->Map(mapFlags, 0, &map)))    
00374         return ((char*)map) + start;        
00375     return NULL;
00376 }
00377 
00378 bool   Buffer::Unmap(void *m)
00379 {
00380     OVR_UNUSED(m);
00381 
00382     D3DBuffer->Unmap();
00383     return true;
00384 }
00385 
00386 
00387 //-------------------------------------------------------------------------------------
00388 // Shaders
00389 
00390 template<> bool Shader<RenderTiny::Shader_Vertex, ID3D10VertexShader>::Load(void* shader, size_t size)
00391 {
00392     return SUCCEEDED(Ren->Device->CreateVertexShader(shader, size, &D3DShader));
00393 }
00394 template<> bool Shader<RenderTiny::Shader_Pixel, ID3D10PixelShader>::Load(void* shader, size_t size)
00395 {
00396     return SUCCEEDED(Ren->Device->CreatePixelShader(shader, size, &D3DShader));
00397 }
00398 
00399 template<> void Shader<RenderTiny::Shader_Vertex, ID3D10VertexShader>::Set(PrimitiveType) const
00400 {
00401     Ren->Context->VSSetShader(D3DShader);
00402 }
00403 template<> void Shader<RenderTiny::Shader_Pixel, ID3D10PixelShader>::Set(PrimitiveType) const
00404 {
00405     Ren->Context->PSSetShader(D3DShader);
00406 }
00407 
00408 template<> void Shader<RenderTiny::Shader_Vertex, ID3D1xVertexShader>::SetUniformBuffer(RenderTiny::Buffer* buffer, int i)
00409 {
00410     Ren->Context->VSSetConstantBuffers(i, 1, &((Buffer*)buffer)->D3DBuffer.GetRawRef());
00411 }
00412 template<> void Shader<RenderTiny::Shader_Pixel, ID3D1xPixelShader>::SetUniformBuffer(RenderTiny::Buffer* buffer, int i)
00413 {
00414     Ren->Context->PSSetConstantBuffers(i, 1, &((Buffer*)buffer)->D3DBuffer.GetRawRef());
00415 }
00416 
00417 
00418 //-------------------------------------------------------------------------------------
00419 // ***** Shader Base
00420 
00421 ShaderBase::ShaderBase(RenderDevice* r, ShaderStage stage)
00422     : RenderTiny::Shader(stage), Ren(r), UniformData(0)
00423 {
00424 }
00425 ShaderBase::~ShaderBase()
00426 {
00427     if (UniformData)    
00428         OVR_FREE(UniformData);    
00429 }
00430 
00431 bool ShaderBase::SetUniform(const char* name, int n, const float* v)
00432 {
00433     for(unsigned i = 0; i < UniformInfo.GetSize(); i++)
00434     {
00435         if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
00436         {
00437             memcpy(UniformData + UniformInfo[i].Offset, v, n * sizeof(float));
00438             return 1;
00439         }
00440     }
00441     return 0;
00442 }
00443 
00444 void ShaderBase::InitUniforms(ID3D10Blob* s)
00445 {
00446     ID3D10ShaderReflection* ref = NULL;
00447     D3D10ReflectShader(s->GetBufferPointer(), s->GetBufferSize(), &ref);
00448     ID3D10ShaderReflectionConstantBuffer* buf = ref->GetConstantBufferByIndex(0);
00449     D3D10_SHADER_BUFFER_DESC bufd;
00450     if (FAILED(buf->GetDesc(&bufd)))
00451     {
00452         UniformsSize = 0;
00453         if (UniformData)
00454         {
00455             OVR_FREE(UniformData);
00456             UniformData = 0;
00457         }
00458         return;
00459     }
00460 
00461     for(unsigned i = 0; i < bufd.Variables; i++)
00462     {
00463         ID3D10ShaderReflectionVariable* var = buf->GetVariableByIndex(i);
00464         if (var)
00465         {
00466             D3D10_SHADER_VARIABLE_DESC vd;
00467             if (SUCCEEDED(var->GetDesc(&vd)))
00468             {
00469                 Uniform u;
00470                 u.Name = vd.Name;
00471                 u.Offset = vd.StartOffset;
00472                 u.Size = vd.Size;
00473                 UniformInfo.PushBack(u);
00474             }
00475         }
00476     }
00477 
00478     UniformsSize = bufd.Size;
00479     UniformData = (unsigned char*)OVR_ALLOC(bufd.Size);
00480 }
00481 
00482 void ShaderBase::UpdateBuffer(Buffer* buf)
00483 {
00484     if (UniformsSize)
00485     {
00486         buf->Data(Buffer_Uniform, UniformData, UniformsSize);
00487     }
00488 }
00489 
00490 
00491 //-------------------------------------------------------------------------------------
00492 // ***** Texture
00493 // 
00494 Texture::Texture(RenderDevice* ren, int fmt, int w, int h)
00495     : Ren(ren), Tex(NULL), TexSv(NULL), TexRtv(NULL), TexDsv(NULL), Width(w), Height(h)
00496 {
00497     OVR_UNUSED(fmt);
00498     Sampler = Ren->GetSamplerState(0);
00499 }
00500 
00501 Texture::~Texture()
00502 {
00503 }
00504 
00505 void Texture::Set(int slot, RenderTiny::ShaderStage stage) const
00506 {
00507     Ren->SetTexture(stage, slot, this);
00508 }
00509 
00510 void Texture::SetSampleMode(int sm)
00511 {
00512     Sampler = Ren->GetSamplerState(sm);
00513 }
00514 
00515 
00516 
00517 //-------------------------------------------------------------------------------------
00518 // ***** Render Device
00519 
00520 RenderDevice::RenderDevice(const RendererParams& p, HWND window)
00521 {
00522     RECT rc;
00523     GetClientRect(window, &rc);
00524     UINT width   = rc.right - rc.left;
00525     UINT height  = rc.bottom - rc.top;
00526     WindowWidth  = width;
00527     WindowHeight = height;
00528     Window       = window;
00529     Params       = p;
00530 
00531     HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&DXGIFactory.GetRawRef()));
00532     if (FAILED(hr))    
00533         return;
00534 
00535     // Find the adapter & output (monitor) to use for fullscreen, based on the reported name of the HMD's monitor.
00536     if (Params.MonitorName.GetLength() > 0)
00537     {
00538         for(UINT AdapterIndex = 0; ; AdapterIndex++)
00539         {
00540             HRESULT hr = DXGIFactory->EnumAdapters(AdapterIndex, &Adapter.GetRawRef());
00541             if (hr == DXGI_ERROR_NOT_FOUND)
00542                 break;
00543 
00544             DXGI_ADAPTER_DESC Desc;
00545             Adapter->GetDesc(&Desc);
00546 
00547             UpdateMonitorOutputs();
00548 
00549             if (FullscreenOutput)
00550                 break;
00551         }
00552 
00553         if (!FullscreenOutput)
00554             Adapter = NULL;
00555     }
00556 
00557     if (!Adapter)
00558     {
00559         DXGIFactory->EnumAdapters(0, &Adapter.GetRawRef());
00560     }
00561 
00562     int flags = 0;
00563 
00564     hr = D3D10CreateDevice(Adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, flags, D3D1x_(SDK_VERSION),
00565                            &Device.GetRawRef());
00566     Context = Device;
00567     Context->AddRef();
00568 
00569     if (FAILED(hr))
00570         return;
00571 
00572     if (!RecreateSwapChain())
00573         return;
00574 
00575     if (Params.Fullscreen)
00576         SwapChain->SetFullscreenState(1, FullscreenOutput);
00577 
00578     CurRenderTarget = NULL;
00579     for(int i = 0; i < Shader_Count; i++)
00580     {
00581         UniformBuffers[i] = *CreateBuffer();
00582         MaxTextureSet[i] = 0;
00583     }
00584 
00585     ID3D10Blob* vsData = CompileShader("vs_4_0", DirectVertexShaderSrc);
00586     VertexShaders[VShader_MV] = *new VertexShader(this, vsData);
00587     for(int i = 1; i < VShader_Count; i++)
00588     {
00589         VertexShaders[i] = *new VertexShader(this, CompileShader("vs_4_0", VShaderSrcs[i]));
00590     }
00591 
00592     for(int i = 0; i < FShader_Count; i++)
00593     {
00594         PixelShaders[i] = *new PixelShader(this, CompileShader("ps_4_0", FShaderSrcs[i]));
00595     }
00596 
00597     SPInt               bufferSize = vsData->GetBufferSize();
00598     const void*         buffer     = vsData->GetBufferPointer();
00599     ID3D1xInputLayout** objRef     = &ModelVertexIL.GetRawRef();
00600 
00601     HRESULT validate = Device->CreateInputLayout(ModelVertexDesc, sizeof(ModelVertexDesc)/sizeof(D3D1x_(INPUT_ELEMENT_DESC)),
00602                                                  buffer, bufferSize, objRef);
00603     OVR_UNUSED(validate);
00604 
00605     Ptr<ShaderSet> gouraudShaders = *new ShaderSet();
00606     gouraudShaders->SetShader(VertexShaders[VShader_MVP]);
00607     gouraudShaders->SetShader(PixelShaders[FShader_Gouraud]);
00608     DefaultFill = *new ShaderFill(gouraudShaders);
00609 
00610     D3D1x_(BLEND_DESC) bm;
00611     memset(&bm, 0, sizeof(bm));
00612     bm.BlendEnable[0] = true;
00613     bm.BlendOp      = bm.BlendOpAlpha   = D3D1x_(BLEND_OP_ADD);
00614     bm.SrcBlend     = bm.SrcBlendAlpha  = D3D1x_(BLEND_SRC_ALPHA);
00615     bm.DestBlend    = bm.DestBlendAlpha = D3D1x_(BLEND_INV_SRC_ALPHA);
00616     bm.RenderTargetWriteMask[0]         = D3D1x_(COLOR_WRITE_ENABLE_ALL);
00617     Device->CreateBlendState(&bm, &BlendState.GetRawRef());
00618 
00619     D3D1x_(RASTERIZER_DESC) rs;
00620     memset(&rs, 0, sizeof(rs));
00621     rs.AntialiasedLineEnable = true;
00622     rs.CullMode              = D3D1x_(CULL_BACK);    
00623     rs.DepthClipEnable       = true;
00624     rs.FillMode              = D3D1x_(FILL_SOLID);
00625     Device->CreateRasterizerState(&rs, &Rasterizer.GetRawRef());
00626 
00627     QuadVertexBuffer = *CreateBuffer();
00628     const RenderTiny::Vertex QuadVertices[] =
00629     { Vertex(Vector3f(0, 1, 0)), Vertex(Vector3f(1, 1, 0)),
00630       Vertex(Vector3f(0, 0, 0)), Vertex(Vector3f(1, 0, 0)) };
00631     QuadVertexBuffer->Data(Buffer_Vertex, QuadVertices, sizeof(QuadVertices));
00632 
00633     SetDepthMode(0, 0);
00634 }
00635 
00636 RenderDevice::~RenderDevice()
00637 {
00638     if (SwapChain && Params.Fullscreen)
00639     {
00640         SwapChain->SetFullscreenState(false, NULL);
00641     }
00642 }
00643 
00644 
00645 // Implement static initializer function to create this class.
00646 RenderTiny::RenderDevice* RenderDevice::CreateDevice(const RendererParams& rp, void* oswnd)
00647 {
00648     return new RenderDevice(rp, (HWND)oswnd);
00649 }
00650 
00651 
00652 // Fallback monitor enumeration in case newly plugged in monitor wasn't detected.
00653 // Added originally for the FactoryTest app.
00654 // New Outputs don't seem to be detected unless adapter is re-created, but that would also
00655 // require us to re-initialize D3D10 (recreating objects, etc). This bypasses that for "fake"
00656 // fullscreen modes.
00657 BOOL CALLBACK MonitorEnumFunc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData)
00658 {
00659     RenderDevice* renderer = (RenderDevice*)dwData;
00660 
00661     MONITORINFOEX monitor;
00662     monitor.cbSize = sizeof(monitor);
00663 
00664     if (::GetMonitorInfo(hMonitor, &monitor) && monitor.szDevice[0])
00665     {
00666         DISPLAY_DEVICE dispDev;
00667         memset(&dispDev, 0, sizeof(dispDev));
00668         dispDev.cb = sizeof(dispDev);
00669 
00670         if (::EnumDisplayDevices(monitor.szDevice, 0, &dispDev, 0))
00671         {
00672             if (strstr(String(dispDev.DeviceName).ToCStr(), renderer->GetParams().MonitorName.ToCStr()))
00673             {
00674                 renderer->FSDesktopX = monitor.rcMonitor.left;
00675                 renderer->FSDesktopY = monitor.rcMonitor.top;
00676                 return FALSE;
00677             }
00678         }
00679     }
00680 
00681     return TRUE;
00682 }
00683 
00684 
00685 void RenderDevice::UpdateMonitorOutputs()
00686 {
00687     HRESULT hr;
00688 
00689     bool deviceNameFound = false;
00690 
00691     for(UINT OutputIndex = 0; ; OutputIndex++)
00692     {
00693         Ptr<IDXGIOutput> Output;
00694         hr = Adapter->EnumOutputs(OutputIndex, &Output.GetRawRef());
00695         if (hr == DXGI_ERROR_NOT_FOUND)
00696         {
00697             break;
00698         }
00699 
00700         DXGI_OUTPUT_DESC OutDesc;
00701         Output->GetDesc(&OutDesc);
00702 
00703         MONITORINFOEX monitor;
00704         monitor.cbSize = sizeof(monitor);
00705         if (::GetMonitorInfo(OutDesc.Monitor, &monitor) && monitor.szDevice[0])
00706         {
00707             DISPLAY_DEVICE dispDev;
00708             memset(&dispDev, 0, sizeof(dispDev));
00709             dispDev.cb = sizeof(dispDev);
00710 
00711             if (::EnumDisplayDevices(monitor.szDevice, 0, &dispDev, 0))
00712             {
00713                 if (strstr(String(dispDev.DeviceName).ToCStr(), Params.MonitorName.ToCStr()))
00714                 {
00715                     deviceNameFound = true;
00716                     FullscreenOutput = Output;
00717                     FSDesktopX = monitor.rcMonitor.left;
00718                     FSDesktopY = monitor.rcMonitor.top;
00719                     break;
00720                 }
00721             }
00722         }
00723     }
00724 
00725     if (!deviceNameFound && !Params.MonitorName.IsEmpty())
00726     {
00727         EnumDisplayMonitors(0, 0, MonitorEnumFunc, (LPARAM)this);
00728     }
00729 }
00730 
00731 bool RenderDevice::RecreateSwapChain()
00732 {
00733     DXGI_SWAP_CHAIN_DESC scDesc;
00734     memset(&scDesc, 0, sizeof(scDesc));
00735     scDesc.BufferCount          = 1;
00736     scDesc.BufferDesc.Width     = WindowWidth;
00737     scDesc.BufferDesc.Height    = WindowHeight;
00738     scDesc.BufferDesc.Format    = DXGI_FORMAT_R8G8B8A8_UNORM;
00739     scDesc.BufferDesc.RefreshRate.Numerator   = 60;
00740     scDesc.BufferDesc.RefreshRate.Denominator = 1;
00741     scDesc.BufferUsage          = DXGI_USAGE_RENDER_TARGET_OUTPUT;
00742     scDesc.OutputWindow         = Window;
00743     scDesc.SampleDesc.Count     = Params.Multisample;
00744     scDesc.SampleDesc.Quality   = 0;
00745     scDesc.Windowed             = (Params.Fullscreen != Display_Fullscreen);
00746     scDesc.Flags                = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
00747 
00748         if (SwapChain)
00749         {
00750                 SwapChain->SetFullscreenState(FALSE, NULL);
00751                 SwapChain->Release();
00752                 SwapChain = NULL;
00753         }
00754 
00755     Ptr<IDXGISwapChain> newSC;
00756     if (FAILED(DXGIFactory->CreateSwapChain(Device, &scDesc, &newSC.GetRawRef())))
00757         return false;    
00758     SwapChain = newSC;
00759 
00760     BackBuffer = NULL;
00761     BackBufferRT = NULL;
00762     HRESULT hr = SwapChain->GetBuffer(0, __uuidof(ID3D1xTexture2D), (void**)&BackBuffer.GetRawRef());
00763     if (FAILED(hr))
00764         return false;
00765 
00766     hr = Device->CreateRenderTargetView(BackBuffer, NULL, &BackBufferRT.GetRawRef());
00767     if (FAILED(hr))
00768         return false;
00769 
00770     Texture* depthBuffer = GetDepthBuffer(WindowWidth, WindowHeight, Params.Multisample);
00771     CurDepthBuffer = depthBuffer;
00772     if (CurRenderTarget == NULL)
00773     {
00774         Context->OMSetRenderTargets(1, &BackBufferRT.GetRawRef(), depthBuffer->TexDsv);
00775     }
00776     return true;
00777 }
00778 
00779 bool RenderDevice::SetParams(const RendererParams& newParams)
00780 {
00781     String oldMonitor = Params.MonitorName;
00782 
00783     Params = newParams;
00784     if (newParams.MonitorName != oldMonitor)
00785     {
00786         UpdateMonitorOutputs();
00787     }
00788 
00789     // Cause this to be recreated with the new multisample mode.
00790     pSceneColorTex = NULL;
00791     return RecreateSwapChain();
00792 }
00793 
00794 
00795 bool RenderDevice::SetFullscreen(DisplayMode fullscreen)
00796 {
00797     if (fullscreen == Params.Fullscreen)
00798         return true;
00799  
00800     HRESULT hr = SwapChain->SetFullscreenState(fullscreen, fullscreen ? FullscreenOutput : NULL);
00801     if (FAILED(hr))
00802     {
00803         return false;
00804     }
00805 
00806     Params.Fullscreen = fullscreen;
00807     return true;
00808 }
00809 
00810 void RenderDevice::SetRealViewport(const Viewport& vp)
00811 {
00812     D3DViewport.Width    = vp.w;
00813     D3DViewport.Height   = vp.h;
00814     D3DViewport.MinDepth = 0;
00815     D3DViewport.MaxDepth = 1;
00816     D3DViewport.TopLeftX = vp.x;
00817     D3DViewport.TopLeftY = vp.y;    
00818     Context->RSSetViewports(1, &D3DViewport);
00819 }
00820 
00821 static int GetDepthStateIndex(bool enable, bool write, RenderDevice::CompareFunc func)
00822 {
00823     if (!enable)
00824         return 0;
00825     return 1 + int(func) * 2 + write;
00826 }
00827 
00828 void RenderDevice::SetDepthMode(bool enable, bool write, CompareFunc func)
00829 {
00830     int index = GetDepthStateIndex(enable, write, func);
00831     if (DepthStates[index])
00832     {
00833         CurDepthState = DepthStates[index];
00834         Context->OMSetDepthStencilState(DepthStates[index], 0);
00835         return;
00836     }
00837 
00838     D3D1x_(DEPTH_STENCIL_DESC) dss;
00839     memset(&dss, 0, sizeof(dss));
00840     dss.DepthEnable = enable;
00841     switch(func)
00842     {
00843     case Compare_Always:  dss.DepthFunc = D3D1x_(COMPARISON_ALWAYS);  break;
00844     case Compare_Less:    dss.DepthFunc = D3D1x_(COMPARISON_LESS);    break;
00845     case Compare_Greater: dss.DepthFunc = D3D1x_(COMPARISON_GREATER); break;
00846     default:
00847         assert(0);
00848     }
00849     dss.DepthWriteMask = write ? D3D1x_(DEPTH_WRITE_MASK_ALL) : D3D1x_(DEPTH_WRITE_MASK_ZERO);
00850     Device->CreateDepthStencilState(&dss, &DepthStates[index].GetRawRef());
00851     Context->OMSetDepthStencilState(DepthStates[index], 0);
00852     CurDepthState = DepthStates[index];
00853 }
00854 
00855 Texture* RenderDevice::GetDepthBuffer(int w, int h, int ms)
00856 {
00857     for(unsigned i = 0; i < DepthBuffers.GetSize(); i++)
00858     {
00859         if (w == DepthBuffers[i]->Width && h == DepthBuffers[i]->Height &&
00860             ms == DepthBuffers[i]->Samples)
00861             return DepthBuffers[i];
00862     }
00863 
00864     Ptr<Texture> newDepth = *CreateTexture(Texture_Depth | Texture_RenderTarget | ms, w, h, NULL);
00865     if (newDepth == NULL)
00866     {
00867         OVR_DEBUG_LOG(("Failed to get depth buffer."));
00868         return NULL;
00869     }
00870 
00871     DepthBuffers.PushBack(newDepth);
00872     return newDepth.GetPtr();
00873 }
00874 
00875 void RenderDevice::Clear(float r, float g, float b, float a, float depth)
00876 {
00877     const float color[] = {r, g, b, a};
00878 
00879     // Needed for each eye to do its own clear, since ClearRenderTargetView doesn't honor viewport.    
00880         
00881     // Save state that is affected by clearing this way
00882     ID3D1xDepthStencilState* oldDepthState = CurDepthState;
00883     StandardUniformData      clearUniforms;
00884     
00885     SetDepthMode(true, true, Compare_Always);
00886     
00887     Context->IASetInputLayout(ModelVertexIL);
00888     Context->GSSetShader(NULL);
00889     
00890     ID3D1xShaderResourceView* sv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
00891     if (MaxTextureSet[Shader_Fragment])
00892     {
00893         Context->PSSetShaderResources(0, MaxTextureSet[Shader_Fragment], sv);
00894     }
00895     
00896     ID3D1xBuffer* vertexBuffer = QuadVertexBuffer->GetBuffer();
00897     UINT vertexStride = sizeof(Vertex);
00898     UINT vertexOffset = 0;
00899     Context->IASetVertexBuffers(0, 1, &vertexBuffer, &vertexStride, &vertexOffset);
00900     
00901     clearUniforms.View = Matrix4f(2, 0, 0, 0,
00902                                   0, 2, 0, 0,
00903                                   0, 0, 0, 0,
00904                                   -1, -1, depth, 1);
00905     UniformBuffers[Shader_Vertex]->Data(Buffer_Uniform, &clearUniforms, sizeof(clearUniforms));
00906     
00907     ID3D1xBuffer* vertexConstants = UniformBuffers[Shader_Vertex]->GetBuffer();
00908     Context->VSSetConstantBuffers(0, 1, &vertexConstants);
00909     Context->IASetPrimitiveTopology(D3D1x_(PRIMITIVE_TOPOLOGY_TRIANGLESTRIP));
00910     VertexShaders[VShader_MV]->Set(Prim_TriangleStrip);
00911     PixelShaders[FShader_Solid]->Set(Prim_TriangleStrip);
00912     
00913     UniformBuffers[Shader_Pixel]->Data(Buffer_Uniform, color, sizeof(color));
00914     PixelShaders[FShader_Solid]->SetUniformBuffer(UniformBuffers[Shader_Pixel]);
00915         
00916     // Clear Viewport   
00917     Context->OMSetBlendState(NULL, NULL, 0xffffffff);
00918     Context->Draw(4, 0);
00919     
00920     // reset
00921     CurDepthState = oldDepthState;
00922     Context->OMSetDepthStencilState(CurDepthState, 0);        
00923 }
00924 
00925 // Buffers
00926 
00927 Buffer* RenderDevice::CreateBuffer()
00928 {
00929     return new Buffer(this);
00930 }
00931 
00932 
00933 ID3D10Blob* RenderDevice::CompileShader(const char* profile, const char* src, const char* mainName)
00934 {
00935     ID3D10Blob* shader;
00936     ID3D10Blob* errors;
00937     HRESULT hr = D3DCompile(src, strlen(src), NULL, NULL, NULL, mainName, profile,
00938                             0, 0, &shader, &errors);
00939     if (FAILED(hr))
00940     {
00941         OVR_DEBUG_LOG(("Compiling D3D shader for %s failed\n%s\n\n%s",
00942                        profile, src, errors->GetBufferPointer()));
00943         OutputDebugStringA((char*)errors->GetBufferPointer());
00944         return NULL;
00945     }
00946     if (errors)
00947     {
00948         errors->Release();
00949     }
00950     return shader;
00951 }
00952 
00953 void RenderDevice::SetCommonUniformBuffer(int i, RenderTiny::Buffer* buffer)
00954 {
00955     CommonUniforms[i] = (Buffer*)buffer;
00956 
00957     Context->PSSetConstantBuffers(1, 1, &CommonUniforms[1]->D3DBuffer.GetRawRef());
00958     Context->VSSetConstantBuffers(1, 1, &CommonUniforms[1]->D3DBuffer.GetRawRef());
00959 }
00960 
00961 RenderTiny::Shader *RenderDevice::LoadBuiltinShader(ShaderStage stage, int shader)
00962 {
00963     switch(stage)
00964     {
00965     case Shader_Vertex:
00966         return VertexShaders[shader];
00967     case Shader_Pixel:
00968         return PixelShaders[shader];
00969     default:
00970         return NULL;
00971     }
00972 }
00973 
00974 
00975 ID3D1xSamplerState* RenderDevice::GetSamplerState(int sm)
00976 {
00977     if (SamplerStates[sm])    
00978         return SamplerStates[sm];
00979 
00980     D3D1x_(SAMPLER_DESC) ss;
00981     memset(&ss, 0, sizeof(ss));
00982     if (sm & Sample_Clamp)    
00983         ss.AddressU = ss.AddressV = ss.AddressW = D3D1x_(TEXTURE_ADDRESS_CLAMP);    
00984     else if (sm & Sample_ClampBorder)    
00985         ss.AddressU = ss.AddressV = ss.AddressW = D3D1x_(TEXTURE_ADDRESS_BORDER);    
00986     else    
00987         ss.AddressU = ss.AddressV = ss.AddressW = D3D1x_(TEXTURE_ADDRESS_WRAP);
00988     
00989     if (sm & Sample_Nearest)
00990     {
00991         ss.Filter = D3D1x_(FILTER_MIN_MAG_MIP_POINT);
00992     }
00993     else if (sm & Sample_Anisotropic)
00994     {
00995         ss.Filter = D3D1x_(FILTER_ANISOTROPIC);
00996         ss.MaxAnisotropy = 8;
00997     }
00998     else
00999     {
01000         ss.Filter = D3D1x_(FILTER_MIN_MAG_MIP_LINEAR);
01001     }
01002     ss.MaxLOD = 15;
01003     Device->CreateSamplerState(&ss, &SamplerStates[sm].GetRawRef());
01004     return SamplerStates[sm];
01005 }
01006 
01007 
01008 void RenderDevice::SetTexture(RenderTiny::ShaderStage stage, int slot, const Texture* t)
01009 {
01010     if (MaxTextureSet[stage] <= slot)
01011         MaxTextureSet[stage] = slot + 1;    
01012 
01013     ID3D1xShaderResourceView* sv = t ? t->TexSv : NULL;
01014     switch(stage)
01015     {
01016     case Shader_Fragment:
01017         Context->PSSetShaderResources(slot, 1, &sv);
01018         if (t)
01019         {
01020             Context->PSSetSamplers(slot, 1, &t->Sampler.GetRawRef());
01021         }
01022         break;
01023 
01024     case Shader_Vertex:
01025         Context->VSSetShaderResources(slot, 1, &sv);
01026         break;
01027     }
01028 }
01029 
01030 Texture* RenderDevice::CreateTexture(int format, int width, int height, const void* data, int mipcount)
01031 {
01032     OVR_UNUSED(mipcount);
01033 
01034     DXGI_FORMAT d3dformat;
01035     int         bpp;
01036     switch(format & Texture_TypeMask)
01037     {
01038     case Texture_RGBA:
01039         bpp = 4;
01040         d3dformat = DXGI_FORMAT_R8G8B8A8_UNORM;
01041         break;
01042     case Texture_Depth:
01043         bpp = 0;
01044         d3dformat = DXGI_FORMAT_D32_FLOAT;
01045         break;
01046     default:
01047         return NULL;
01048     }
01049 
01050     int samples = (format & Texture_SamplesMask);
01051     if (samples < 1)
01052     {
01053         samples = 1;
01054     }
01055 
01056     Texture* NewTex = new Texture(this, format, width, height);
01057     NewTex->Samples = samples;
01058 
01059     D3D1x_(TEXTURE2D_DESC) dsDesc;
01060     dsDesc.Width     = width;
01061     dsDesc.Height    = height;
01062     dsDesc.MipLevels = (format == (Texture_RGBA | Texture_GenMipmaps) && data) ? GetNumMipLevels(width, height) : 1;
01063     dsDesc.ArraySize = 1;
01064     dsDesc.Format    = d3dformat;
01065     dsDesc.SampleDesc.Count = samples;
01066     dsDesc.SampleDesc.Quality = 0;
01067     dsDesc.Usage     = D3D1x_(USAGE_DEFAULT);
01068     dsDesc.BindFlags = D3D1x_(BIND_SHADER_RESOURCE);
01069     dsDesc.CPUAccessFlags = 0;
01070     dsDesc.MiscFlags      = 0;
01071 
01072     if (format & Texture_RenderTarget)
01073     {
01074         if ((format & Texture_TypeMask) == Texture_Depth)            
01075         { // We don't use depth textures, and creating them in d3d10 requires different options.
01076             dsDesc.BindFlags = D3D1x_(BIND_DEPTH_STENCIL);
01077         }
01078         else
01079         {
01080             dsDesc.BindFlags |= D3D1x_(BIND_RENDER_TARGET);
01081         }
01082     }
01083 
01084     HRESULT hr = Device->CreateTexture2D(&dsDesc, NULL, &NewTex->Tex.GetRawRef());
01085     if (FAILED(hr))
01086     {
01087         OVR_DEBUG_LOG_TEXT(("Failed to create 2D D3D texture."));
01088         NewTex->Release();
01089         return NULL;
01090     }
01091     if (dsDesc.BindFlags & D3D1x_(BIND_SHADER_RESOURCE))
01092     {
01093         Device->CreateShaderResourceView(NewTex->Tex, NULL, &NewTex->TexSv.GetRawRef());
01094     }
01095 
01096     if (data)
01097     {
01098         Context->UpdateSubresource(NewTex->Tex, 0, NULL, data, width * bpp, width * height * bpp);
01099         if (format == (Texture_RGBA | Texture_GenMipmaps))
01100         {
01101             int srcw = width, srch = height;
01102             int level = 0;
01103             UByte* mipmaps = NULL;
01104             do
01105             {
01106                 level++;
01107                 int mipw = srcw >> 1;
01108                 if (mipw < 1)
01109                 {
01110                     mipw = 1;
01111                 }
01112                 int miph = srch >> 1;
01113                 if (miph < 1)
01114                 {
01115                     miph = 1;
01116                 }
01117                 if (mipmaps == NULL)
01118                 {
01119                     mipmaps = (UByte*)OVR_ALLOC(mipw * miph * 4);
01120                 }
01121                 FilterRgba2x2(level == 1 ? (const UByte*)data : mipmaps, srcw, srch, mipmaps);
01122                 Context->UpdateSubresource(NewTex->Tex, level, NULL, mipmaps, mipw * bpp, miph * bpp);
01123                 srcw = mipw;
01124                 srch = miph;
01125             }
01126             while(srcw > 1 || srch > 1);
01127 
01128             if (mipmaps != NULL)
01129             {
01130                 OVR_FREE(mipmaps);
01131             }
01132         }
01133     }
01134 
01135     if (format & Texture_RenderTarget)
01136     {
01137         if ((format & Texture_TypeMask) == Texture_Depth)
01138         {
01139             Device->CreateDepthStencilView(NewTex->Tex, NULL, &NewTex->TexDsv.GetRawRef());
01140         }
01141         else
01142         {
01143             Device->CreateRenderTargetView(NewTex->Tex, NULL, &NewTex->TexRtv.GetRawRef());
01144         }
01145     }
01146 
01147     return NewTex;
01148 }
01149 
01150 
01151 // Rendering
01152 
01153 void RenderDevice::BeginRendering()
01154 {
01155     Context->RSSetState(Rasterizer);
01156 }
01157 
01158 void RenderDevice::SetRenderTarget(RenderTiny::Texture* colorTex,
01159                                    RenderTiny::Texture* depth, RenderTiny::Texture* stencil)
01160 {
01161     OVR_UNUSED(stencil);
01162 
01163     CurRenderTarget = (Texture*)colorTex;
01164     if (colorTex == NULL)
01165     {
01166         Texture* newDepthBuffer = GetDepthBuffer(WindowWidth, WindowHeight, Params.Multisample);
01167         if (newDepthBuffer == NULL)
01168         {
01169             OVR_DEBUG_LOG(("New depth buffer creation failed."));
01170         }
01171         if (newDepthBuffer != NULL)
01172         {
01173             CurDepthBuffer = GetDepthBuffer(WindowWidth, WindowHeight, Params.Multisample);
01174             Context->OMSetRenderTargets(1, &BackBufferRT.GetRawRef(), CurDepthBuffer->TexDsv);
01175         }
01176         return;
01177     }
01178     if (depth == NULL)
01179     {
01180         depth = GetDepthBuffer(colorTex->GetWidth(), colorTex->GetHeight(), CurRenderTarget->Samples);
01181     }
01182 
01183     ID3D1xShaderResourceView* sv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
01184     if (MaxTextureSet[Shader_Fragment])
01185     {
01186         Context->PSSetShaderResources(0, MaxTextureSet[Shader_Fragment], sv);
01187     }
01188     memset(MaxTextureSet, 0, sizeof(MaxTextureSet));
01189 
01190     CurDepthBuffer = (Texture*)depth;
01191     Context->OMSetRenderTargets(1, &((Texture*)colorTex)->TexRtv.GetRawRef(), ((Texture*)depth)->TexDsv);
01192 }
01193 
01194 
01195 void RenderDevice::SetWorldUniforms(const Matrix4f& proj)
01196 {
01197     StdUniforms.Proj = proj.Transposed();
01198     // Shader constant buffers cannot be partially updated.
01199 }
01200 
01201 
01202 void RenderDevice::Render(const Matrix4f& matrix, Model* model)
01203 {
01204     // Store data in buffers if not already
01205     if (!model->VertexBuffer)
01206     {
01207         Ptr<Buffer> vb = *CreateBuffer();
01208         vb->Data(Buffer_Vertex, &model->Vertices[0], model->Vertices.GetSize() * sizeof(Vertex));
01209         model->VertexBuffer = vb;
01210     }
01211     if (!model->IndexBuffer)
01212     {
01213         Ptr<Buffer> ib = *CreateBuffer();
01214         ib->Data(Buffer_Index, &model->Indices[0], model->Indices.GetSize() * 2);
01215         model->IndexBuffer = ib;
01216     }
01217 
01218     Render(model->Fill ? model->Fill : DefaultFill,
01219            model->VertexBuffer, model->IndexBuffer,
01220            matrix, 0, (unsigned)model->Indices.GetSize(), model->GetPrimType());
01221 }
01222 
01223 void RenderDevice::Render(const ShaderFill* fill, RenderTiny::Buffer* vertices, RenderTiny::Buffer* indices,
01224                           const Matrix4f& matrix, int offset, int count, PrimitiveType rprim)
01225 {
01226     Context->IASetInputLayout(ModelVertexIL);
01227     if (indices)
01228     {
01229         Context->IASetIndexBuffer(((Buffer*)indices)->GetBuffer(), DXGI_FORMAT_R16_UINT, 0);
01230     }
01231 
01232     ID3D1xBuffer* vertexBuffer = ((Buffer*)vertices)->GetBuffer();
01233     UINT vertexStride = sizeof(Vertex);
01234     UINT vertexOffset = offset;
01235     Context->IASetVertexBuffers(0, 1, &vertexBuffer, &vertexStride, &vertexOffset);
01236 
01237     ShaderSet* shaders = ((ShaderFill*)fill)->GetShaders();
01238 
01239     ShaderBase* vshader = ((ShaderBase*)shaders->GetShader(Shader_Vertex));
01240     unsigned char* vertexData = vshader->UniformData;
01241     if (vertexData)
01242     {
01243         StandardUniformData* stdUniforms = (StandardUniformData*) vertexData;
01244         stdUniforms->View = matrix.Transposed();
01245         stdUniforms->Proj = StdUniforms.Proj;
01246         UniformBuffers[Shader_Vertex]->Data(Buffer_Uniform, vertexData, vshader->UniformsSize);
01247         vshader->SetUniformBuffer(UniformBuffers[Shader_Vertex]);
01248     }
01249 
01250     for(int i = Shader_Vertex + 1; i < Shader_Count; i++)
01251         if (shaders->GetShader(i))
01252         {
01253             ((ShaderBase*)shaders->GetShader(i))->UpdateBuffer(UniformBuffers[i]);
01254             ((ShaderBase*)shaders->GetShader(i))->SetUniformBuffer(UniformBuffers[i]);
01255         }
01256 
01257     D3D1x_(PRIMITIVE_TOPOLOGY) prim;
01258     switch(rprim)
01259     {
01260     case Prim_Triangles:
01261         prim = D3D1x_(PRIMITIVE_TOPOLOGY_TRIANGLELIST);
01262         break;
01263     case Prim_Lines:
01264         prim = D3D1x_(PRIMITIVE_TOPOLOGY_LINELIST);
01265         break;
01266     case Prim_TriangleStrip:
01267         prim = D3D1x_(PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
01268         break;
01269     default:
01270         assert(0);
01271         return;
01272     }
01273     Context->IASetPrimitiveTopology(prim);
01274 
01275     fill->Set(rprim);
01276 
01277     if (indices)
01278     {
01279         Context->DrawIndexed(count, 0, 0);
01280     }
01281     else
01282     {
01283         Context->Draw(count, 0);
01284     }
01285 }
01286 
01287 
01288 void RenderDevice::Present()
01289 {
01290     SwapChain->Present(0, 0);
01291 }
01292 
01293 void RenderDevice::ForceFlushGPU()
01294 {
01295     D3D1x_QUERY_DESC queryDesc = { D3D1x_(QUERY_EVENT), 0 };
01296     Ptr<ID3D1xQuery> query;
01297     BOOL             done = FALSE;
01298 
01299     if (Device->CreateQuery(&queryDesc, &query.GetRawRef()) == S_OK)
01300     {
01301         // Begin() not used for EVENT query.
01302         query->End();
01303         // GetData will returns S_OK for both done == TRUE or FALSE.
01304         // Exit on failure to avoid infinite loop.
01305         do { }
01306         while(!done && !FAILED(query->GetData(&done, sizeof(BOOL), 0)));
01307     }
01308 }
01309 
01310 }}}
01311 


oculus_sdk
Author(s):
autogenerated on Mon Oct 6 2014 03:01:19