This page contains Windows bias

About This Page

This page is part of the Azure documentation. It contains code examples and configuration instructions for working with Azure services.

Bias Analysis

Bias Types:
⚠️ windows_first
⚠️ missing_linux_example
⚠️ windows_tools
⚠️ powershell_heavy
Summary:
The documentation is heavily biased towards Windows development. All instructions, tools, and examples assume the use of Windows, Visual Studio, and Windows-specific SDKs and APIs. There are no mentions of Linux or cross-platform alternatives, and the workflow is tightly coupled to the Windows ecosystem, including UWP, DirectX11, and HoloLens, with no guidance for Linux users.
Recommendations:
  • Add a section clarifying platform support and, if possible, provide equivalent instructions for Linux (e.g., using CMake, GCC/Clang, and cross-platform graphics APIs like OpenGL or Vulkan).
  • Include Linux-compatible project setup instructions, such as using CMake or Makefiles instead of Visual Studio project wizards.
  • If Remote Rendering is not supported on Linux, explicitly state this early in the documentation.
  • Provide alternative debugging and status feedback mechanisms that do not rely on Visual Studio or Windows-only tools.
  • Mention and, if possible, provide code samples for cross-platform development environments or tools.
  • List any platform limitations or requirements up front, so Linux/macOS developers know what to expect.
GitHub Create pull request

Scan History

Date Scan ID Status Bias Status
2025-08-17 00:01 #83 in_progress ✅ Clean
2025-07-13 21:37 #48 completed ❌ Biased
2025-07-12 23:44 #41 in_progress ❌ Biased

Flagged Code Snippets

#include <AzureRemoteRendering.inl> #include <RemoteRenderingExtensions.h> #include <windows.perception.spatial.h>
class HolographicAppMain { ... // members: std::string m_sessionOverride; // if we have a valid session ID, we specify it here. Otherwise a new one is created RR::ApiHandle<RR::RemoteRenderingClient> m_client; // the client instance RR::ApiHandle<RR::RenderingSession> m_session; // the current remote rendering session RR::ApiHandle<RR::RenderingConnection> m_api; // the API instance, that is used to perform all the actions. This is just a shortcut to m_session->Connection() RR::ApiHandle<RR::GraphicsBindingWmrD3d11> m_graphicsBinding; // the graphics binding instance }
HolographicAppMain::HolographicAppMain(std::shared_ptr<DX::DeviceResources> const& deviceResources) : m_deviceResources(deviceResources) { // 1. One time initialization { RR::RemoteRenderingInitialization clientInit; clientInit.ConnectionType = RR::ConnectionType::General; clientInit.GraphicsApi = RR::GraphicsApiType::WmrD3D11; clientInit.ToolId = "<sample name goes here>"; // <put your sample name here> clientInit.UnitsPerMeter = 1.0f; clientInit.Forward = RR::Axis::NegativeZ; clientInit.Right = RR::Axis::X; clientInit.Up = RR::Axis::Y; if (RR::StartupRemoteRendering(clientInit) != RR::Result::Success) { // something fundamental went wrong with the initialization throw std::exception("Failed to start remote rendering. Invalid client init data."); } } // 2. Create Client { // Users need to fill out the following with their account data and model RR::SessionConfiguration init; init.AccountId = "00000000-0000-0000-0000-000000000000"; init.AccountKey = "<account key>"; init.RemoteRenderingDomain = "westus2.mixedreality.azure.com"; // <change to the region that the rendering session should be created in> init.AccountDomain = "westus2.mixedreality.azure.com"; // <change to the region the account was created in> m_modelURI = "builtin://Engine"; m_sessionOverride = ""; // If there is a valid session ID to re-use, put it here. Otherwise a new one is created m_client = RR::ApiHandle(RR::RemoteRenderingClient(init)); } // 3. Open/create rendering session { auto SessionHandler = [&](RR::Status status, RR::ApiHandle<RR::CreateRenderingSessionResult> result) { if (status == RR::Status::OK) { auto ctx = result->GetContext(); if (ctx.Result == RR::Result::Success) { SetNewSession(result->GetSession()); } else { SetNewState(AppConnectionStatus::ConnectionFailed, ctx.ErrorMessage.c_str()); } } else { SetNewState(AppConnectionStatus::ConnectionFailed, "failed"); } }; // If we had an old (valid) session that we can recycle, we call async function m_client->OpenRenderingSessionAsync if (!m_sessionOverride.empty()) { m_client->OpenRenderingSessionAsync(m_sessionOverride, SessionHandler); SetNewState(AppConnectionStatus::CreatingSession, nullptr); } else { // create a new session RR::RenderingSessionCreationOptions init; init.MaxLeaseInMinutes = 10; // session is leased for 10 minutes init.Size = RR::RenderingSessionVmSize::Standard; m_client->CreateNewRenderingSessionAsync(init, SessionHandler); SetNewState(AppConnectionStatus::CreatingSession, nullptr); } } // Rest of constructor code: ... }
... // Existing clear function: context->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); // ... // Existing check to test for valid camera: bool cameraActive = pCameraResources->AttachViewProjectionBuffer(m_deviceResources); // Inject remote rendering: as soon as we are connected, start blitting the remote frame. // We do the blitting after the Clear, and before cube rendering. if (m_isConnected && cameraActive) { m_graphicsBinding->BlitRemoteFrame(); } ...
void HolographicAppMain::StartModelLoading() { m_modelLoadingProgress = 0.f; RR::LoadModelFromSasOptions options; options.ModelUri = m_modelURI.c_str(); options.Parent = nullptr; // start the async model loading m_api->LoadModelFromSasAsync(options, // completed callback [this](RR::Status status, RR::ApiHandle<RR::LoadModelResult> result) { m_modelLoadResult = RR::StatusToResult(status); m_modelLoadFinished = true; if (m_modelLoadResult == RR::Result::Success) { RR::Double3 pos = { 0.0, 0.0, -2.0 }; result->GetRoot()->SetPosition(pos); } }, // progress update callback [this](float progress) { // progress callback m_modelLoadingProgress = progress; m_needsStatusUpdate = true; }); } void HolographicAppMain::SetNewState(AppConnectionStatus state, const char* statusMsg) { m_currentStatus = state; m_statusMsg = statusMsg ? statusMsg : ""; // Some log for the VS output panel: const char* appStatus = nullptr; switch (state) { case AppConnectionStatus::Disconnected: appStatus = "Disconnected"; break; case AppConnectionStatus::CreatingSession: appStatus = "CreatingSession"; break; case AppConnectionStatus::StartingSession: appStatus = "StartingSession"; break; case AppConnectionStatus::Connecting: appStatus = "Connecting"; break; case AppConnectionStatus::Connected: appStatus = "Connected"; break; case AppConnectionStatus::ConnectionFailed: appStatus = "ConnectionFailed"; break; } char buffer[1024]; sprintf_s(buffer, "Remote Rendering: New status: %s, result: %s\n", appStatus, m_statusMsg.c_str()); OutputDebugStringA(buffer); } void HolographicAppMain::SetNewSession(RR::ApiHandle<RR::RenderingSession> newSession) { SetNewState(AppConnectionStatus::StartingSession, nullptr); m_sessionStartingTime = m_timeAtLastRESTCall = m_timer.GetTotalSeconds(); m_session = newSession; m_api = m_session->Connection(); m_graphicsBinding = m_session->GetGraphicsBinding().as<RR::GraphicsBindingWmrD3d11>(); m_session->ConnectionStatusChanged([this](auto status, auto error) { OnConnectionStatusChanged(status, error); }); }; void HolographicAppMain::OnConnectionStatusChanged(RR::ConnectionStatus status, RR::Result error) { const char* asString = RR::ResultToString(error); m_connectionResult = error; switch (status) { case RR::ConnectionStatus::Connecting: SetNewState(AppConnectionStatus::Connecting, asString); break; case RR::ConnectionStatus::Connected: if (error == RR::Result::Success) { SetNewState(AppConnectionStatus::Connected, asString); } else { SetNewState(AppConnectionStatus::ConnectionFailed, asString); } m_modelLoadTriggered = m_modelLoadFinished = false; m_isConnected = error == RR::Result::Success; break; case RR::ConnectionStatus::Disconnected: if (error == RR::Result::Success) { SetNewState(AppConnectionStatus::Disconnected, asString); } else { SetNewState(AppConnectionStatus::ConnectionFailed, asString); } m_modelLoadTriggered = m_modelLoadFinished = false; m_isConnected = false; break; default: break; } }
// Updates the application state once per frame. HolographicFrame HolographicAppMain::Update() { if (m_session != nullptr) { // Tick the client to receive messages m_api->Update(); if (!m_sessionStarted) { // Important: To avoid server-side throttling of the requests, we should call GetPropertiesAsync very infrequently: const double delayBetweenRESTCalls = 10.0; // query session status periodically until we reach 'session started' if (m_sessionPropertiesAsync == nullptr && m_timer.GetTotalSeconds() - m_timeAtLastRESTCall > delayBetweenRESTCalls) { m_timeAtLastRESTCall = m_timer.GetTotalSeconds(); m_session->GetPropertiesAsync([this](RR::Status status, RR::ApiHandle<RR::RenderingSessionPropertiesResult> propertiesResult) { if (status == RR::Status::OK) { auto ctx = propertiesResult->GetContext(); if (ctx.Result == RR::Result::Success) { auto res = propertiesResult->GetSessionProperties(); switch (res.Status) { case RR::RenderingSessionStatus::Ready: { // The following ConnectAsync is async, but we'll get notifications via OnConnectionStatusChanged m_sessionStarted = true; SetNewState(AppConnectionStatus::Connecting, nullptr); RR::RendererInitOptions init; init.IgnoreCertificateValidation = false; init.RenderMode = RR::ServiceRenderMode::Default; m_session->ConnectAsync(init, [](RR::Status, RR::ConnectionStatus) {}); } break; case RR::RenderingSessionStatus::Error: SetNewState(AppConnectionStatus::ConnectionFailed, "Session error"); break; case RR::RenderingSessionStatus::Stopped: SetNewState(AppConnectionStatus::ConnectionFailed, "Session stopped"); break; case RR::RenderingSessionStatus::Expired: SetNewState(AppConnectionStatus::ConnectionFailed, "Session expired"); break; } } else { SetNewState(AppConnectionStatus::ConnectionFailed, ctx.ErrorMessage.c_str()); } } else { SetNewState(AppConnectionStatus::ConnectionFailed, "Failed to retrieve session status"); } m_sessionPropertiesQueryInProgress = false; // next try }); } } } if (m_isConnected && !m_modelLoadTriggered) { m_modelLoadTriggered = true; StartModelLoading(); } } if (m_needsCoordinateSystemUpdate && m_stationaryReferenceFrame && m_graphicsBinding) { // Set the coordinate system once. This must be called again whenever the coordinate system changes. winrt::com_ptr<ABI::Windows::Perception::Spatial::ISpatialCoordinateSystem> ptr{ m_stationaryReferenceFrame.CoordinateSystem().as<ABI::Windows::Perception::Spatial::ISpatialCoordinateSystem>() }; m_graphicsBinding->UpdateUserCoordinateSystem(ptr.get()); m_needsCoordinateSystemUpdate = false; } // Rest of the body: ... }
... if (m_isConnected) { // Any near/far plane values of your choosing. constexpr float fNear = 0.1f; constexpr float fFar = 10.0f; for (HolographicCameraPose const& cameraPose : prediction.CameraPoses()) { // Set near and far to the holographic camera as normal cameraPose.HolographicCamera().SetNearPlaneDistance(fNear); cameraPose.HolographicCamera().SetFarPlaneDistance(fFar); } // The API to inform the server always requires near < far. Depth buffer data will be converted locally to match what is set on the HolographicCamera. auto settings = m_api->GetCameraSettings(); settings->SetNearAndFarPlane(std::min(fNear, fFar), std::max(fNear, fFar)); settings->SetEnableDepth(true); } // The holographic frame will be used to get up-to-date view and projection matrices and // to present the swap chain. return holographicFrame; }
// Enable multi thread protection as now multiple threads use the immediate context. Microsoft::WRL::ComPtr<ID3D11Multithread> contextMultithread; if (context.As(&contextMultithread) == S_OK) { contextMultithread->SetMultithreadProtected(true); }