400 likes | 611 Views
From Android or iOS: Bringing your OpenGL ES game to the Windows Store. Phil Napieralski, Doug Erickson, Richard McKinney Program Manager, Senior Content Developer, CTO Halfbrick 3-189. Agenda slide. Getting started Bringing OpenGL ES 2.0 to DirectX Case Study by Halfbrick.
E N D
From Android or iOS: Bringing your OpenGL ES game to the Windows Store Phil Napieralski, Doug Erickson, Richard McKinney Program Manager, Senior Content Developer, CTO Halfbrick 3-189
Agenda slide • Getting started • Bringing OpenGL ES 2.0 to DirectX • Case Study by Halfbrick
Choosing your language • Windows Store games • C++ and DirectX support • Use C# with DirectX through third-party libraries • Optionally combine with XAML for UI • Similar to AXML on Android or UIKit on iOS • Can have separate view frameworks • XAML + DirectX for menu screen • Pure DirectX for in-game graphics screen
Bringing OpenGL ES 2.0 to DirectX • Doug Erickson
Same scene, different perspectives • OpenGL ES 2.0 • Retains a few fixed-function artifacts • Vendor-specific, can be extended • Language-specific API implementations (C, Objective-C, Java) • Targets mobile platforms only • Direct3D • Vendor agnostic, no extensions • Targets all current Windows platforms • MS-only • Most of your effort is spent understanding the Windows Runtime and Windows platform programming conventions. • Overall: Not so different!
What do I have to worry about? • More detailed hardware resource APIs • DXGI and Direct3D allow for more low-level configuration and resource tweaking • API abstraction level • APIs are expressed as “interfaces” and “resources” • Graphics device is represented as an abstracted interface • Code and programming model changes • Review and use the VS 2013 DirectX templates • Use IAsyncOperation::Completed event or PPL “task” • GLSL->HLSL
EGL to DXGI Read the docs here: Compare EGL to DXGI and Direct3D • OpenGL ES 2.0: • - Get an EGLDisplay • - Select an EGLConfig • - Get an EGLSurface • - Get an EGLContext; associate it with EGLSurface for rendering • Direct3D call flow: • - Acquire the CoreWindow from the app object • - Call D3D11CreateDevice to create a D3D device and device context • - Get a DXGI factory from D3D device to create a swap chain for the CoreWindow • - Get back buffer from swap chain and provide to D3D device as render target • Short form: Use the Visual Studio 2013 Preview templates!
Porting to a Direct3D 11 framework • Get things from ID3D11Device to use when configuring ID3D11DeviceContext • ID3D11Device2 • Obtains and manages GPU resources • see: glCreateShader, glBufferData, glGenBuffers, glTexImage2D, etc • No concept of shader programs! (see ID3D11DeviceContext2) • ID3D11DeviceContext2 • Configures and manages your rendering pipeline • Performs the rendering commands • Configures shaders directly with resources from ID3D11Device APIs • see: glAttachShader, glGetUniform*, glDrawElements
Resources • Resource: an object used by the GPU, such as a texture, vertex buffer, index buffer, or constant buffer. • Subresource: a part of a larger structured resource, for instance a single mipmap out of a 2D texture, or a single face of a cubemap. • View: a way for the GPU to interpret the resource.
UniformsConstant buffers • cbuffers: • Must be 16-byte (4 float) aligned, so use DxMath types • Use for your transformation matrices! • Should only be updated when the data changes • C++ codestruct TRANSFORMS • {XMFLOAT4x4 modelView; • XMFLOAT4x4 modelViewProj; • XMFLOAT4x4 inverseModelView; • } • HLSL code • cbuffer Transforms : register(b0) • { • matrix ModelView; • matrix ModelViewProj; • matrix InverseModelView; • } • OpenGL ES 2.0: • glGetUniformLocation • glUniform* (e.g. glUniformMatrix4fv, glUniform4fv…)Shader: declare with uniform keyword • Direct3D 11: • CD3D11_BUFFER_DESC with • D3D11_BIND_CONSTANT_BUFFER • ID3D11Device::CreateBuffer() • 1 struct for CPU code; 1 cbuffer for shader code (see left)Shader: declare with cbuffer keyword (and register) Update on context with: • ID3D11DeviceContext->UpdateSubresource() • supply buffer and buffer data
Attributes->Vertex Buffers w/ Input Layout • - OpenGL – RH coords • - D3D – ambidextrous • - Use DirectXMath matrix functions! • C++ code • struct VERTEXDATA{ • XMFLOAT4: pos; XMFLOAT4: normal; XMFLOAT2: uv;} • HLSL code • structVertexShaderInput • { float4 pos: POSITION0; float4 normal: NORMAL0; • float2 uv: TEXCOORD0;} • OpenGL ES 2.0: • Map loc to GLSL attrib name with glGetAttribLocation • Last: glVertexAttribPointer/glEnableVertexAttribArray • Index: pass list (or buffer) to glDrawElements() • DirectX 11: • Create a struct for your vertex data (use DirectXMath types!) • Create two arrays: 1 for vertices; 1 for indices • Create an input layout with ID3D11Device::CreateInputLayout() • + specify your non-SV semantics! (more later) • Call ID3D11Device->CreateBuffer() • HLSL: create shader input structs (with semantics!) that match • MAKE SURE ORDER AND SEMANTICS IN LAYOUT MATCH HLSL STRUCT
Textures Texture compression formats: OpenGL ES 2.0: ETC (PVRTC for iOS) DirectX 11: DDS w/ BC* (see feature level) Need to convert from original assets! --HLSL declaration:Texture2D SimpleTexture : register(t0); SamplerStateSimpleSampler : register(s0); Texture2D NormalTexture : register(t1); SamplerStateNormalSampler : register(s1); • Texture APIs: • OpenGL ES 2.0: • glGenTextures, glBindTexture, glTexImage2D, glCompressedTexImage2D, glTexParameter*, • DirectX 11: • D3D11_TEXTURE2D_DESC ID3D11Device::CreateTexture2D ->ID3D11Texture2D • * do the same for ID3D11SamplerState * D3D11_SHADER_RESOURCE_VIEW_DESC • ID3D11Device::CreateShaderResourceView • ->ID3D11ShaderResourceView • GLSL: sampler2d type, texture2d to readHLSL: Texture2D type, Texture2D + SamplerState to read • - use t and s registers!
Shaders • Input Assembly: • ID3D11DeviceContext::IASetVertexBuffers • ID3D11DeviceContext::IASetIndexBuffers • Vertex Shader: • ID3D11DeviceContext::VSSetShader() • ID3D11DeviceContext::VSSetConstantBuffers() • Pixel Shader/Fragment Shader: • ID3D11DeviceContext::PSSetShader() • ID3D11DeviceContext::PSSetConstantBuffers() • ID3D11DeviceContext::PSSetShaderResources() • NOTE: • Make sure you specify the register slot when setting buffers and resources! • OpenGL ES 2.0: Compiled at runtime • Uses “shader program” • DirectX 11: • Compiled as .CSO files at compile time • New for 8.1! Link shader at run-time • No concept of high-level “shader program”
GLSLHLSL • All input/output between stages must have a semantic • Map value passed from one stage to another, interpolated, etc. • No specific meaning to GPU (unless SV_) • Example • normal: MYCOOLNORMAL0; • uv: MYAMAZINGTEXCOORD0; • “SV” semantics are like GL intrinsics • Behavior depends on shader stage • Modified by GPU (rasterization) • Examples: • position : SV_POSITION; • Use shader analysis tools / count instructions • GL Intrinsic->SV Semantic examples: • gl_Position = SV_Position • gl_FragColor = SV_Target • gl_FragData[n] = SV_Target[n]Registers! • - b[0-n] for buffers • - t[0-n] for textures • - s[0-n] for samplers
Further guidance • MSDN: Port your OpenGL ES 2.0 game to DirectX 11 • MSDN: DirectX graphics and gaming portal • MSDN: Developing games portal
Porting to Windows 8Build 2013 • Richard McKinney • CTO – Halfbrick Studios
Agenda • Windows Store ecosystem • General tips and tricks • Performance hints
Windows Store app ecosystem • Much like Android, there’s a wide range of devices you should try to support for Windows Store apps (anything that runs Windows 8). Luckily there’s only one marketplace. • You can have a 1 GHz netbook with 1 gig of RAM running your game and your users still expect it to run well. Try to hit as many targets as you can. • Target a wide range of devices when testing, from the more power efficient netbooks and Surface RT tablets to higher spec x86 tablets and a beefy desktop PC.
Windows Store app ecosystem • You should have profiling code that runs at startup to fine tune performance to the system it’s run on (if needed). • You don’t generally see complex graphics options menus in iOS and Android games. Determine what works best by profiling and maybe allow for some overrides for graphically intensive titles. • When we ported our games, there was no support for consumable In-app purchases on the Windows Store. You can get around this by designing your IAP system around 24 hour expiring durables, or having multiples of the same item.
Store certification tips (or why you’ll fail cert) • The certification processes for Windows Store apps are pretty intense. They do a huge amount of checks that other stores don’t do. • Run the Windows App Certification Kit (WACK) tool on your game periodically. Fix up any failures it reports as soon as you can. This is step 1 when you submit, so you’ll find lots of potential problems early. • The WACK tool doesn’t scale correctly across devices. Run it regularly on your lowest spec device. • You must have a privacy policy in your game or you’ll fail certification.
Store certification tips • Create your game on the Windows Store dashboard early on. You’ll see that there’s a huge number of fields to fill out, so go through each section and make sure you are prepared to answer those questions. • Be prepared to translate everything on the Description page for every language your app manifest declares you support. We’ve failed cert before due to non-localized screenshots. • Judiciously use the notes to testers fields. I never delete old notes and put the new notes up top. Heck, I even put my phone number in there (sadly they’ve never called).
Windows Phone 8 • If you’re looking to support Windows Phone 8 alongside Windows 8, you need to look at the differences between them early on. They’re not as similar as the documentation suggests. • If you’re just starting out now, you may want to start with Windows Phone 8 because lots of things that work on the phone work on Windows 8, but not vice-versa. • For Windows Phone 8, test on a low spec Lumia 520/620 early. They’re quite popular, but have much lower memory. You don’t want to have to opt out of these devices at the last minute.
Live tiles for user retention • Live tiles are the best time investment in terms of platform specific features. Make sure you create an engaging live tile to draw users back into your game. • Our tiles in Fruit Ninja and Jetpack Joyride are drawn in game with render to texture for dynamic content custom to your progress. We save those textures out and reference them in the tile notifications, trying to entice players back into the game for just one more run.
Tips, tricks and advice • You MUST supply shaders that are built for Shader Model 4 Level 9_1 at minimum. Failure to do this causes your game not to run on low- end devices. Go as high as you want, but start there! • Make sure your game supports multiple aspect ratios. If you’re porting from Android/iOS+iPad, you likely already do. You’ll definitely need to expect 4:3 and 16:9 at least. Optimize your layouts for them. • Prefer using IAsyncOperation::Completed over PPL tasks. The samples all make it look easy, but you’ll actually want proper error checking! We rewrote several things that used PPL tasks over time.
Tips, tricks and advice • Develop a set of conversion routines from Platform::String to your more convenient string types early on.You should only be using them inside the Windows 8 platform code. • Windows Store apps are highly multithreaded just by the nature of the asynchronous models. You’ll likely run into something that must be done on the main thread though. Store off your UI thread dispatcher at the very start of your IFrameworkView derivative’s Run() method, and then anything you supply to RunAsync() on it will be on your main thread.
Where’s my UI thread? • // Save off the thread dispatcher in your IFrameWorkView's Run method: • m_uiThreadDispatcher = CoreWindow::GetForCurrentThread()->Dispatcher; • // Use that dispatcher to run code asynchronously on the main thread: • m_uiThreadDispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, refnew Windows::UI::Core::DispatchedHandler([=]() • { • // I'm on the UI thread! • }));
Performance tips • Be careful about how often you query for device orientation if not using OrientationChanged events. It’s expensive and should only be done at intervals. • Prefer using DXGI_FORMAT_B8G8R8A8 over RGBA. The low spec devices won’t support RGBA and convert it at load time. For us, this was at least 500ms for nothing. For you it could be much more. • You need a splash screen animating while your game is initializing. You have almost no time to respond before the WACK tool fails you for being unresponsive. Either thread or chunk up initialization steps.
Performance hints • Some devices are extremely fill rate limited. You may need to scale your frame buffers dynamically based on your profiling results. • Test on multiple GPUs from the beginning! We made the mistake of reusing vertex buffers several times in a frame, calling DiscardResource on them. This worked perfectly until we found just before submitting that there were a few GPUs that still stalled the pipeline and knocked our performance down to < 1fps.
Always turn off touch visualizations! • // This prevents a CPU spike every time the screen's touched • Windows::UI::Input::PointerVisualizationSettings::GetForCurrentView()->IsContactFeedbackEnabled = false;
Resources • dev.windows.com • Porting OpenGL ES 2.0 to DirectX11.1/Windows Store • Windows Phone 8 differences • XAML DirectX 3D Shooting Game Sample
Give us your feedback!! • What? • Are you interested in having an impact on the future user experiences in Visual Studio? Come help us shape the future. • When & Where? • Schedule a time with us vsdr@microsoft.com • Room 254 South Moscone, West Mezzanine Level • Why? • Your input and feedback will influence future Microsoft Visual Studio tools
Required Slide *delete this box when your slide is finalized Your MS Tag will be inserted here during the final scrub. Evaluate this session • Scan this QR codeto evaluate this session and be automatically entered in a drawing to win a prize!