DirectX OMSetRenderTargets 中的访问冲突
Posted
技术标签:
【中文标题】DirectX OMSetRenderTargets 中的访问冲突【英文标题】:Access violation in DirectX OMSetRenderTargets 【发布时间】:2011-10-01 19:29:25 【问题描述】:在 D3D_FEATURE_LEVEL_9_1
中运行 DirectX 11 的 Triangle 示例应用程序时,我收到以下错误(Lesson2.Triangles.exe 中 0x527DAE81 (d3d11_1sdklayers.dll) 处的未处理异常:0xC0000005:访问冲突读取位置 0x00000000)。此错误发生在 OMSetRenderTargets 函数中,如下所示,如果我从程序中删除该函数,则不会发生此错误(但是,屏幕是蓝色的,并且不呈现三角形)
//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//// PARTICULAR PURPOSE.
////
//// Copyright (c) Microsoft Corporation. All rights reserved
#include
#include
#include "DirectXSample.h"
#include "BasicMath.h"
#include "BasicReaderWriter.h"
using namespace Microsoft::WRL;
using namespace Windows::UI::Core;
using namespace Windows::Foundation;
using namespace Windows::ApplicationModel::Core;
using namespace Windows::ApplicationModel::Infrastructure;
// This class defines the application as a whole.
ref class Direct3DTutorialViewProvider : public IViewProvider
private:
CoreWindow^ m_window;
ComPtr m_swapChain;
ComPtr m_d3dDevice;
ComPtr m_d3dDeviceContext;
ComPtr m_renderTargetView;
public:
// This method is called on application launch.
void Initialize(
_In_ CoreWindow^ window,
_In_ CoreApplicationView^ applicationView
)
m_window = window;
// This method is called after Initialize.
void Load(_In_ Platform::String^ entryPoint)
// This method is called after Load.
void Run()
// First, create the Direct3D device.
// This flag is required in order to enable compatibility with Direct2D.
UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#if defined(_DEBUG)
// If the project is in a debug build, enable debugging via SDK Layers with this flag.
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
// This array defines the ordering of feature levels that D3D should attempt to create.
D3D_FEATURE_LEVEL featureLevels[] =
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_1
;
ComPtr d3dDevice;
ComPtr d3dDeviceContext;
DX::ThrowIfFailed(
D3D11CreateDevice(
nullptr, // specify nullptr to use the default adapter
D3D_DRIVER_TYPE_HARDWARE,
nullptr, // leave as nullptr if hardware is used
creationFlags, // optionally set debug and Direct2D compatibility flags
featureLevels,
ARRAYSIZE(featureLevels),
D3D11_SDK_VERSION, // always set this to D3D11_SDK_VERSION
&d3dDevice,
nullptr,
&d3dDeviceContext
)
);
// Retrieve the Direct3D 11.1 interfaces.
DX::ThrowIfFailed(
d3dDevice.As(&m_d3dDevice)
);
DX::ThrowIfFailed(
d3dDeviceContext.As(&m_d3dDeviceContext)
);
// After the D3D device is created, create additional application resources.
CreateWindowSizeDependentResources();
// Create a Basic Reader-Writer class to load data from disk. This class is examined
// in the Resource Loading sample.
BasicReaderWriter^ reader = ref new BasicReaderWriter();
// Load the raw vertex shader bytecode from disk and create a vertex shader with it.
auto vertexShaderBytecode = reader->ReadData("SimpleVertexShader.cso");
ComPtr vertexShader;
DX::ThrowIfFailed(
m_d3dDevice->CreateVertexShader(
vertexShaderBytecode->Data,
vertexShaderBytecode->Length,
nullptr,
&vertexShader
)
);
// Create an input layout that matches the layout defined in the vertex shader code.
// For this lesson, this is simply a float2 vector defining the vertex position.
const D3D11_INPUT_ELEMENT_DESC basicVertexLayoutDesc[] =
"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 ,
;
ComPtr inputLayout;
DX::ThrowIfFailed(
m_d3dDevice->CreateInputLayout(
basicVertexLayoutDesc,
ARRAYSIZE(basicVertexLayoutDesc),
vertexShaderBytecode->Data,
vertexShaderBytecode->Length,
&inputLayout
)
);
// Load the raw pixel shader bytecode from disk and create a pixel shader with it.
auto pixelShaderBytecode = reader->ReadData("SimplePixelShader.cso");
ComPtr pixelShader;
DX::ThrowIfFailed(
m_d3dDevice->CreatePixelShader(
pixelShaderBytecode->Data,
pixelShaderBytecode->Length,
nullptr,
&pixelShader
)
);
// Create vertex and index buffers that define a simple triangle.
float3 triangleVertices[] =
float3(-0.5f, -0.5f,13.5f),
float3( 0.0f, 0.5f,0),
float3( 0.5f, -0.5f,0),
;
D3D11_BUFFER_DESC vertexBufferDesc = 0;
vertexBufferDesc.ByteWidth = sizeof(float3) * ARRAYSIZE(triangleVertices);
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.MiscFlags = 0;
vertexBufferDesc.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA vertexBufferData;
vertexBufferData.pSysMem = triangleVertices;
vertexBufferData.SysMemPitch = 0;
vertexBufferData.SysMemSlicePitch = 0;
ComPtr vertexBuffer;
DX::ThrowIfFailed(
m_d3dDevice->CreateBuffer(
&vertexBufferDesc,
&vertexBufferData,
&vertexBuffer
)
);
// Once all D3D resources are created, configure the application window.
// Allow the application to respond when the window size changes.
m_window->SizeChanged +=
ref new TypedEventHandler(
this,
&Direct3DTutorialViewProvider::OnWindowSizeChanged
);
// Specify the cursor type as the standard arrow cursor.
m_window->PointerCursor = ref new CoreCursor(CoreCursorType::Arrow, 0);
// Activate the application window, making it visible and enabling it to receive events.
m_window->Activate();
// Enter the render loop. Note that tailored applications should never exit.
while (true)
// Process events incoming to the window.
m_window->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
// Specify the render target we created as the output target.
ID3D11RenderTargetView* targets[1] = m_renderTargetView.Get();
m_d3dDeviceContext->OMSetRenderTargets(
1,
targets,
NULL // use no depth stencil
);
// Clear the render target to a solid color.
const float clearColor[4] = 0.071f, 0.04f, 0.561f, 1.0f ;
//Code fails here
m_d3dDeviceContext->ClearRenderTargetView(
m_renderTargetView.Get(),
clearColor
);
m_d3dDeviceContext->IASetInputLayout(inputLayout.Get());
// Set the vertex and index buffers, and specify the way they define geometry.
UINT stride = sizeof(float3);
UINT offset = 0;
m_d3dDeviceContext->IASetVertexBuffers(
0,
1,
vertexBuffer.GetAddressOf(),
&stride,
&offset
);
m_d3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// Set the vertex and pixel shader stage state.
m_d3dDeviceContext->VSSetShader(
vertexShader.Get(),
nullptr,
0
);
m_d3dDeviceContext->PSSetShader(
pixelShader.Get(),
nullptr,
0
);
// Draw the cube.
m_d3dDeviceContext->Draw(3,0);
// Present the rendered image to the window. Because the maximum frame latency is set to 1,
// the render loop will generally be throttled to the screen refresh rate, typically around
// 60Hz, by sleeping the application on Present until the screen is refreshed.
DX::ThrowIfFailed(
m_swapChain->Present(1, 0)
);
// This method is called before the application exits.
void Uninitialize()
private:
// This method is called whenever the application window size changes.
void OnWindowSizeChanged(
_In_ CoreWindow^ sender,
_In_ WindowSizeChangedEventArgs^ args
)
m_renderTargetView = nullptr;
CreateWindowSizeDependentResources();
// This method creates all application resources that depend on
// the application window size. It is called at app initialization,
// and whenever the application window size changes.
void CreateWindowSizeDependentResources()
if (m_swapChain != nullptr)
// If the swap chain already exists, resize it.
DX::ThrowIfFailed(
m_swapChain->ResizeBuffers(
2,
0,
0,
DXGI_FORMAT_R8G8B8A8_UNORM,
0
)
);
else
// If the swap chain does not exist, create it.
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = 0;
swapChainDesc.Stereo = false;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.Scaling = DXGI_SCALING_NONE;
swapChainDesc.Flags = 0;
// Use automatic sizing.
swapChainDesc.Width = 0;
swapChainDesc.Height = 0;
// This is the most common swap chain format.
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
// Don't use multi-sampling.
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
// Use two buffers to enable flip effect.
swapChainDesc.BufferCount = 2;
// We recommend using this swap effect for all applications.
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
// Once the swap chain description is configured, it must be
// created on the same adapter as the existing D3D Device.
// First, retrieve the underlying DXGI Device from the D3D Device.
ComPtr dxgiDevice;
DX::ThrowIfFailed(
m_d3dDevice.As(&dxgiDevice)
);
// Ensure that DXGI does not queue more than one frame at a time. This both reduces
// latency and ensures that the application will only render after each VSync, minimizing
// power consumption.
DX::ThrowIfFailed(
dxgiDevice->SetMaximumFrameLatency(1)
);
// Next, get the parent factory from the DXGI Device.
ComPtr dxgiAdapter;
DX::ThrowIfFailed(
dxgiDevice->GetAdapter(&dxgiAdapter)
);
ComPtr dxgiFactory;
DX::ThrowIfFailed(
dxgiAdapter->GetParent(
__uuidof(IDXGIFactory2),
&dxgiFactory
)
);
// Finally, create the swap chain.
DX::ThrowIfFailed(
dxgiFactory->CreateSwapChainForImmersiveWindow(
m_d3dDevice.Get(),
DX::GetIUnknown(m_window),
&swapChainDesc,
nullptr, // allow on all displays
&m_swapChain
)
);
// Once the swap chain is created, create a render target view. This will
// allow Direct3D to render graphics to the window.
ComPtr backBuffer;
DX::ThrowIfFailed(
m_swapChain->GetBuffer(
0,
__uuidof(ID3D11Texture2D),
&backBuffer
)
);
DX::ThrowIfFailed(
m_d3dDevice->CreateRenderTargetView(
backBuffer.Get(),
nullptr,
&m_renderTargetView
)
);
// After the render target view is created, specify that the viewport,
// which describes what portion of the window to draw to, should cover
// the entire window.
D3D11_TEXTURE2D_DESC backBufferDesc = 0;
backBuffer->GetDesc(&backBufferDesc);
D3D11_VIEWPORT viewport;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
viewport.Width = static_cast(backBufferDesc.Width);
viewport.Height = static_cast(backBufferDesc.Height);
viewport.MinDepth = D3D11_MIN_DEPTH;
viewport.MaxDepth = D3D11_MAX_DEPTH;
m_d3dDeviceContext->RSSetViewports(1, &viewport);
;
// This class defines how to create the custom View Provider defined above.
ref class Direct3DTutorialViewProviderFactory : IViewProviderFactory
public:
IViewProvider^ CreateViewProvider()
return ref new Direct3DTutorialViewProvider();
;
[Platform::MTAThread]
int main(array^)
auto viewProviderFactory = ref new Direct3DTutorialViewProviderFactory();
Windows::ApplicationModel::Core::CoreApplication::Run(viewProviderFactory);
return 0;
【问题讨论】:
此时m_renderTargetView
是否为空?
没有。与该函数调用相关的任何内容都不是 NULL,除了深度模板(根据文档,它可以是 NULL,而且它似乎没有任何区别)
尝试将您的设备创建为调试设备,看看 D3D 是否有任何内部错误
@Necrolis 它被创建为调试:creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
【参考方案1】:
我暂时将此标记为答案。随意发布不同的答案,我将对其进行调查,然后选择该答案。有时最好的答案是“Microsoft Magic”。微软似乎在内部做一些不向第三方开发者公开的事情。在这个开发阶段不能说太多,所以目前最好在旧设备上简单地使用 WARP 光栅器.....
【讨论】:
【参考方案2】:在我看来,您好像在尝试使用一些已发布的资源。也许您应该调试来自Release()
的输出结果,因为它会告诉您现有引用的数量。
【讨论】:
Release() 永远不会被调用,所以不应该是这种情况。 @IDWMaster:当您将nullptr
分配给智能指针时,您会在智能指针中调用它。以上是关于DirectX OMSetRenderTargets 中的访问冲突的主要内容,如果未能解决你的问题,请参考以下文章