fix github issues 4/6/8 & move sample to use new nuget build

* fix: Component: Microsoft.Wpf.Interop.DirectX.dll should have
TargetFrameworkVersionAttribute=4.5
(https://github.com/Microsoft/WPFDXInterop/issues/8 )
* fix: Sample improvement: D3DVisualization.cpp - RenderTarget should
not be recreated each Render() call
(https://github.com/Microsoft/WPFDXInterop/issues/4 )
Have SurfaceQueueInteropHelper notify d3d renderer when a surface was
recreated (due to a resize) to make it easier for them to understand
when to recreate rendertarget, etc...  That mostly involves plumbing
through a bool in the Render event handler signature.

Removed SetRenderSize in the d3d rendering component of sample...as that
turned out to be unnecessary. Explained it in mainwindow.xaml.cs change.

Believe that this fix also solves this issue:
Sample/Component Bug: After several resizes, rendering sometimes stops
(https://github.com/Microsoft/WPFDXInterop/issues/6 )
This commit is contained in:
Rob Relyea 2015-11-04 15:25:08 -08:00
Родитель 5e32e60cca
Коммит ceae359eda
9 изменённых файлов: 71 добавлений и 74 удалений

Просмотреть файл

@ -64,14 +64,14 @@ extern void __cdecl Cleanup()
/// <summary>
/// Render for global class instance
/// </summary>
extern HRESULT __cdecl Render(void * pResource)
extern HRESULT __cdecl Render(void * pResource, bool isNewSurface)
{
if ( NULL == pApplication )
{
return E_FAIL;
}
return pApplication->Render(pResource);
return pApplication->Render(pResource, isNewSurface);
}
/// <summary>
@ -120,20 +120,6 @@ extern HRESULT _cdecl SetCameraPhi(float phi)
return 0;
}
/// <summary>
/// Sets the size of the this visualization
/// </summary>
extern HRESULT _cdecl SetRenderSize(int pixelWidth, int pixelHeight)
{
if (NULL == pApplication)
{
return E_FAIL;
}
pApplication->SetRenderSize(pixelWidth, pixelHeight);
return 0;
}
/// <summary>
/// Constructor
/// </summary>
@ -391,19 +377,11 @@ void CCube::SetUpViewport()
m_Projection = XMMatrixPerspectiveFovLH(XM_PIDIV4, m_Width / (FLOAT)m_Height, 0.01f, 100.0f);
}
HRESULT CCube::SetRenderSize(int pixelWidth, int pixelHeight)
{
m_Width = pixelWidth;
m_Height = pixelHeight;
return S_OK;
}
/// <summary>
/// Renders a frame
/// Initializes RenderTarget
/// </summary>
/// <returns>S_OK for success, or failure code</returns>
HRESULT CCube::Render(void * pResource)
HRESULT CCube::InitRenderTarget(void * pResource)
{
HRESULT hr = S_OK;
@ -426,19 +404,19 @@ HRESULT CCube::Render(void * pResource)
pDXGIResource->Release();
IUnknown * tempResource11;
hr = m_pd3dDevice->OpenSharedResource(sharedHandle, __uuidof(ID3D11Resource), (void**)(&tempResource11));
hr = m_pd3dDevice->OpenSharedResource(sharedHandle, __uuidof(ID3D11Resource), (void**)(&tempResource11));
if (FAILED(hr))
{
return hr;
}
ID3D11Texture2D * pOutputResource;
hr = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)(&pOutputResource));
hr = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)(&pOutputResource));
if (FAILED(hr))
{
return hr;
}
tempResource11->Release();
tempResource11->Release();
D3D11_RENDER_TARGET_VIEW_DESC rtDesc;
rtDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
@ -458,11 +436,39 @@ HRESULT CCube::Render(void * pResource)
m_Width = outputResourceDesc.Width;
m_Height = outputResourceDesc.Height;
SetUpViewport();
SetUpViewport();
}
m_pImmediateContext->OMSetRenderTargets(1, &m_pRenderTargetView, NULL);
if ( NULL != pOutputResource )
{
pOutputResource->Release();
}
return hr;
}
/// <summary>
/// Renders a frame
/// </summary>
/// <returns>S_OK for success, or failure code</returns>
HRESULT CCube::Render(void * pResource, bool isNewSurface)
{
HRESULT hr = S_OK;
// If we've gotten a new Surface, need to initialize the renderTarget.
// One of the times that this happens is on a resize.
if ( isNewSurface )
{
m_pImmediateContext->OMSetRenderTargets(0, NULL, NULL);
hr = InitRenderTarget(pResource);
if (FAILED(hr))
{
return hr;
}
}
// Update our time
static float t = 0.0f;
if (m_driverType == D3D_DRIVER_TYPE_REFERENCE)
@ -487,7 +493,6 @@ HRESULT CCube::Render(void * pResource)
static float ClearColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
m_pImmediateContext->ClearRenderTargetView(m_pRenderTargetView, ClearColor);
// Update the view matrix
m_camera.Update();
@ -499,19 +504,12 @@ HRESULT CCube::Render(void * pResource)
cb.mProjection = XMMatrixTranspose(viewProjection);
m_pImmediateContext->UpdateSubresource(m_pConstantBuffer, 0, NULL, &cb, 0, 0);
//
// Renders a triangle
//
m_pImmediateContext->VSSetShader(m_pVertexShader, NULL, 0);
m_pImmediateContext->VSSetConstantBuffers(0, 1, &m_pConstantBuffer);
m_pImmediateContext->PSSetShader(m_pPixelShader, NULL, 0);
m_pImmediateContext->DrawIndexed(36, 0, 0); // 36 vertices needed for 12 triangles in a triangle list
if ( NULL != pOutputResource )
{
pOutputResource->Release();
}
if ( NULL != m_pImmediateContext )
{
m_pImmediateContext->Flush();

Просмотреть файл

@ -32,7 +32,7 @@ extern "C" {
}
extern "C" {
__declspec(dllexport) HRESULT __cdecl Render(void * pResource);
__declspec(dllexport) HRESULT __cdecl Render(void * pResource, bool isNewSurface);
}
extern "C" {
@ -47,10 +47,6 @@ extern "C" {
__declspec(dllexport) HRESULT __cdecl SetCameraPhi(float phi);
}
extern "C" {
__declspec(dllexport) HRESULT __cdecl SetRenderSize(int pixelWidth, int pixelHeight);
}
class CCube
{
@ -75,7 +71,7 @@ public:
/// Renders a frame
/// </summary>
/// <returns>S_OK for success, or failure code</returns>
HRESULT Render(void * pResource);
HRESULT Render(void * pResource, bool isNewSurface);
/// <summary>
@ -84,9 +80,6 @@ public:
/// <returns>Pointer to the camera</returns>
CCamera* GetCamera();
// Method for host to communicate size for rendering this D3D visualization.
HRESULT SetRenderSize(int pixelWidth, int pixelHeight);
// Special function definitions to ensure alignment between c# and c++
void* operator new(size_t size)
{
@ -100,7 +93,9 @@ public:
private:
HRESULT InitRenderTarget(void * pResource);
void SetUpViewport();
// 3d camera
CCamera m_camera;

Просмотреть файл

@ -58,9 +58,9 @@
NativeMethods.InvokeWithDllProtection(NativeMethods.Cleanup);
}
private static int Render(IntPtr resourcePointer)
private static int Render(IntPtr resourcePointer, bool isNewSurface)
{
return NativeMethods.InvokeWithDllProtection(() => NativeMethods.Render(resourcePointer));
return NativeMethods.InvokeWithDllProtection(() => NativeMethods.Render(resourcePointer, isNewSurface));
}
private static int SetCameraRadius(float radius)
@ -119,10 +119,10 @@
int surfWidth = (int)(host.ActualWidth < 0 ? 0 : Math.Ceiling(host.ActualWidth * dpiScale));
int surfHeight = (int)(host.ActualHeight < 0 ? 0 : Math.Ceiling(host.ActualHeight * dpiScale));
// notify the D3D11Image and the DxRendering component of the pixel size desired for the DirectX rendering.
// Notify the D3D11Image of the pixel size desired for the DirectX rendering.
// The D3DRendering component will determine the size of the new surface it is given, at that point.
InteropImage.SetPixelSize(surfWidth, surfHeight);
NativeMethods.SetRenderSize(surfWidth, surfHeight);
// Stop rendering if the D3DImage isn't visible - currently just if width or height is 0
// TODO: more optimizations possible (scrolled off screen, etc...)
bool isVisible = (surfWidth != 0 && surfHeight != 0);
@ -261,9 +261,9 @@
}
#endregion Helpers
private void DoRender(IntPtr surface)
private void DoRender(IntPtr surface, bool isNewSurface)
{
Render(surface);
Render(surface, isNewSurface);
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
@ -299,7 +299,7 @@
public static extern void Cleanup();
[DllImport("D3DVisualization.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int Render(IntPtr resourcePointer);
public static extern int Render(IntPtr resourcePointer, bool isNewSurface);
[DllImport("D3DVisualization.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int SetCameraRadius(float radius);
@ -310,9 +310,6 @@
[DllImport("D3DVisualization.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int SetCameraPhi(float phi);
[DllImport("D3DVisualization.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int SetRenderSize(int pixelWidth, int pixelHeight);
/// <summary>
/// Method used to invoke an Action that will catch DllNotFoundExceptions and display a warning dialog.
/// </summary>

Просмотреть файл

@ -52,7 +52,7 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Wpf.Interop.DirectX">
<HintPath>..\packages\Microsoft.Wpf.Interop.DirectX-x64.0.9.0-beta-22855\lib\net45\Microsoft.Wpf.Interop.DirectX.dll</HintPath>
<HintPath>..\packages\Microsoft.Wpf.Interop.DirectX-x64.0.9.0-beta-22856\lib\net45\Microsoft.Wpf.Interop.DirectX.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Xml" />

Просмотреть файл

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Wpf.Interop.DirectX-x64" version="0.9.0-beta-22855" targetFramework="net45" />
<package id="Microsoft.Wpf.Interop.DirectX-x64" version="0.9.0-beta-22856" targetFramework="net45" />
</packages>

Просмотреть файл

@ -8,7 +8,7 @@ namespace Microsoft {
static D3D11Image::D3D11Image()
{
OnRenderProperty = DependencyProperty::Register("OnRender",
Action<IntPtr>::typeid,
Action<IntPtr, bool>::typeid,
D3D11Image::typeid,
gcnew UIPropertyMetadata(nullptr, gcnew PropertyChangedCallback(&RenderChanged)));
@ -57,7 +57,7 @@ namespace Microsoft {
{
if (image->Helper != nullptr)
{
image->Helper->RenderD2D = static_cast<Action<IntPtr>^>(args.NewValue);
image->Helper->RenderD2D = static_cast<Action<IntPtr, bool>^>(args.NewValue);
}
}
}

Просмотреть файл

@ -40,14 +40,14 @@ namespace Microsoft {
/// The OnRender action delegate will fire and pass the surface to the application that the DirectX rendering component should
/// render into.
property Action<IntPtr>^ OnRender
property Action<IntPtr, bool>^ OnRender
{
Action<IntPtr>^ get()
Action<IntPtr, bool>^ get()
{
return static_cast<Action<IntPtr>^>(GetValue(OnRenderProperty));
return static_cast<Action<IntPtr, bool>^>(GetValue(OnRenderProperty));
}
void set(Action<IntPtr>^ value)
void set(Action<IntPtr, bool>^ value)
{
SetValue(OnRenderProperty, value);
}

Просмотреть файл

@ -51,11 +51,11 @@ namespace Microsoft {
return S_OK;
}
void SurfaceQueueInteropHelper::RenderToDXGI(IntPtr pdxgiSurface)
void SurfaceQueueInteropHelper::RenderToDXGI(IntPtr pdxgiSurface, bool isNewSurface)
{
if (nullptr != m_renderD2D)
{
m_renderD2D(pdxgiSurface);
m_renderD2D(pdxgiSurface, isNewSurface);
}
}
@ -297,6 +297,8 @@ namespace Microsoft {
UINT size = sizeof(int);
bool fNeedUnlock = false;
bool isNewSurface = !m_areSurfacesInitialized;
if (m_shouldSkipRender || (nullptr == m_d3dImage) || !Initialize())
{
@ -321,7 +323,7 @@ namespace Microsoft {
// Render D3D10 content
try
{
RenderToDXGI((IntPtr)(void*)pDXGISurface);
RenderToDXGI((IntPtr)(void*)pDXGISurface, isNewSurface);
}
catch (Exception^)
{
@ -342,7 +344,12 @@ namespace Microsoft {
// Get the top level surface from the texture
IFC(pTexture9->GetSurfaceLevel(0, &pSurface9));
m_d3dImage->SetBackBuffer(System::Windows::Interop::D3DResourceType::IDirect3DSurface9, (IntPtr)(void*)pSurface9, true /* enableSoftwareFallback */);
m_d3dImage->SetBackBuffer(System::Windows::Interop::D3DResourceType::IDirect3DSurface9,
(IntPtr)(void*)pSurface9,
true // enableSoftwareFallback
// Supports fallback to software rendering for Remote Desktop, etc...
// Was added in WPF 4.5
);
// Produce Surface
m_ABProducer->Enqueue(pTexture9, &count, sizeof(int), SURFACE_QUEUE_FLAG_DO_NOT_WAIT);

Просмотреть файл

@ -16,7 +16,7 @@ namespace Microsoft {
public ref class SurfaceQueueInteropHelper : IDisposable
{
private:
Action<IntPtr>^ m_renderD2D;
Action<IntPtr, bool>^ m_renderD2D;
D3DImage^ m_d3dImage;
DependencyPropertyChangedEventHandler^ m_frontBufferAvailableChanged;
UINT m_pixelWidth, m_pixelHeight;
@ -48,7 +48,7 @@ namespace Microsoft {
HRESULT InitD3D10();
void RenderToDXGI(IntPtr pdxgiSurface);
void RenderToDXGI(IntPtr pdxgiSurface, bool isNewSurface);
void CleanupD3D10();
@ -73,9 +73,9 @@ namespace Microsoft {
public:
/// The action delegate called when a render is required.
property Action<IntPtr>^ SurfaceQueueInteropHelper::RenderD2D
property Action<IntPtr, bool>^ SurfaceQueueInteropHelper::RenderD2D
{
void set(Action<IntPtr>^ value) { m_renderD2D = value; }
void set(Action<IntPtr, bool>^ value) { m_renderD2D = value; }
}
/// Gets or sets the associated D3DImage object that is working in conjunction with this helper.