I have some code to get the current screens contents which works smoothly on at least one computer (code simplified, only the relevant parts are shown and error handling is removed):
hr = D3D11CreateDevice(nullptr,gDriverTypes[DriverTypeIndex],nullptr,0,gFeatureLevels,
NumFeatureLevels,D3D11_SDK_VERSION,&lDevice,&lFeatureLevel,
&lImmediateContext);
ComPtr<IDXGIDevice> lDxgiDevice;
hr = lDevice.As(&lDxgiDevice);
// Get DXGI adapter
ComPtr<IDXGIAdapter> lDxgiAdapter;
hr = lDxgiDevice->GetParent(__uuidof(IDXGIAdapter), &lDxgiAdapter);
lDxgiDevice.Reset();
// Get output
ComPtr<IDXGIOutput> lDxgiOutput;
hr = lDxgiAdapter->EnumOutputs(output, &lDxgiOutput);
lDxgiAdapter.Reset();
hr = lDxgiOutput->GetDesc(&lOutputDesc);
// QI for Output 1
ComPtr<IDXGIOutput1> lDxgiOutput1;
hr = lDxgiOutput.As(&lDxgiOutput1);
lDxgiOutput.Reset();
// Create desktop duplication
hr = lDxgiOutput1->DuplicateOutput(lDevice.Get(), &lDeskDupl);
On an other computer that last call to DuplicateOutput() fails, here "hr" returns E_UNEXPECTED.
DxDiag of this second, not working computer shows DirectX12, right as the first, working one.
Any idea how to get additional information about the reason for this error or any idea what could be wrong?
Thanks!
Related
I'm developing a library for reading CD-ROMs and the ISO9660 file system.
Long story short, pretty much everything is working except for one thing I'm having a hard time figuring out how it's done:
Where does XA standard defines differentiation among Mode 2 Form 1 from Mode 2 Form 2?
Currently, I am using the following pseudo-code to differentiate between both forms; albeit it's a naive heuristic, it does work but well, it's far from ideal:
var buffer = ... // this is a raw sector of 2352 bytes
var m2F1 = ISector.Cast<SectorMode2Form1>(buffer);
var edc1 = EdcHelper.ComputeBlock(0, buffer, 16, 2056);
var edc2 = BitConverter.ToUInt32(m2F1.Edc, 0);
var isM2F1 = edc1 == edc2;
if (isM2F1) return CdRomSectorMode.Mode2Form1;
// NOTE we cannot reliably check EDC of M2F2 since it's optional
var isForm2 =
m2F1.SubHeaderCopy1.SubMode.HasFlag(SectorMode2Form1SubHeaderSubMode.Form2) &&
m2F1.SubHeaderCopy2.SubMode.HasFlag(SectorMode2Form1SubHeaderSubMode.Form2);
if (isForm2) return CdRomSectorMode.Mode2Form2;
return CdRomSectorMode.Mode2Formless;
If you look at some software like IsoBuster, it appears to be a track-level property, however, I'm failing to understand where the value would be read from within the track.
I'm actually doing something similar in typescript for my ps1 mod tools. It seems like you actually probably have it correct here, since I'm going to assume your HasFlag check is checking position bit position 6 of the subheader. If that flag is set, you are in form 2.
So what you probably want something like:
const sectorBytes = new Uint8Arrray(buffer);
if (sectorBytes[0x012] & 0x20) === 0x20) {
return CdRomSectorMode.Mode2Form2;
} else {
return CdRomSectorMode.Mode2Form1;
}
You could of course use the flag code you already have, but that would require you to use one of the types first to get that. This just keeps it generic bytes and checks the flag, then returns the relevant mode.
I'm having a weird problem while developing my DirectShow application. I am using Delphi 6 with the DSPACK DirectShow component library. One of the IBaseFilter instances doesn't seem to recognize a pin that it owns when I try to find the pin in the filter using it's TPinInfo.achName property (_PinInfo). (Note, in this case it is the IBaseFilter created by the TSampleGrabber component that is exhibiting this weird behavior).
The sequence of events, encapsulated in the code sample below is this:
Find the first available input pin in the IBaseFilter instance. In the code below this is the pin passed to testPinInfo().
Execute QueryPinInfo() on the returned pin to get that information. The returned information shows the pin's achName as 'Input'.
Try to find a pin named 'Input' in the very same IBaseFilter instance using IBaseFilter.findPin().
Get NIL back indicating a pin could not be found with that name. This in my opinion is a really strange condition (error).
Does anyone know what kind of conditions could cause this scenario? I don't think it's a memory corruption problem because the data structures involved look fine when I inspect them in the debugger. Is it possible that some IBaseFilter implementations neglect to implement the FindPin() method properly?
Here's the code below:
procedure testPinInfo(intfInputPin: IPin);
var
intfTestPin: IPin;
pinInfo_input: TPinInfo;
begin
intfTestPin := nil;
// Get the pin information.
ZeroMemory(#pinInfo_input, SizeOf(pinInfo_input));
intfInputPin.QueryPinInfo(pinInfo_input);
// Now immediately turn around and try to find the pin in the filter that
// owns it, using the name found in pinInfo_input
pinInfo_input.pFilter.FindPin(pinInfo_input.achName, intfTestPin);
// >>> intfTestPin is NIL (unassigned). This is an error.
end;
Don't use FindPin, you always have better ways to do it. Look for unconnected pin of desired direction with the media type of interest. If you look for preview/capture pins specifically, you always have an option to use IKsPropertySet interface to unambiguously identify the pins you need.
I had a similar issue to this so I made my own version of FindPin :-
HRESULT GraphControl::FindPinByName(IBaseFilter* pFilter,LPCWSTR pName,IPin** ppPin)
{
HRESULT hr = E_FAIL;
IEnumPins* pEnum = NULL;
IPin* pPin = NULL;
DWORD pFetched = 0;
PIN_INFO pinInfo = {0};
// Create a pin enumerator
if(FAILED(pFilter->EnumPins(&pEnum)))
return E_FAIL;
// Get the first instance
hr = pEnum->Next(1,&pPin,&pFetched);
while( hr == S_OK )
{
pPin->QueryPinInfo(&pinInfo);
// Compare the names
if (wcscmp(pName,pinInfo.achName) == 0 )
{
// pin names match so use this one and exit
*ppPin = pPin;
break;
}
SAFE_RELEASE(pinInfo.pFilter);
SAFE_RELEASE(pPin);
hr = pEnum->Next(1,&pPin,&pFetched);
}
SAFE_RELEASE(pinInfo.pFilter);
SAFE_RELEASE(pEnum);
// if the pPin address is null we didnt find a pin with the wanted name
if(&*pPin == NULL)
hr = VFW_E_NOT_FOUND;
return hr;
}
For FindPin you need the corresponding Id, check QueryId(). For Input it's usually "In".
I've been having difficulty identifying the correct parameters for the PresentParameters and DirectX device, so that there can be both vertex-level gouraud shading and the use of a z buffer. Some triangle meshes work fine, others have background triangles appearing in front of triangles which are closer-to-camera.
An example of this is found here: http://gallery.me.com/robert.perkins/100045/zBufferGone. The input data is a simple list of vertices in facets. The winding order of the vertices in each facet is nondeterministic (comes from various CAD software export functions) and there is no normals data.
The PresentParameters are being set up right now as follows. I realize this is C# instead of C++ but I think it's descriptive enough, and the parameters pass through to C++ code. This produces the image in the picture; the behavior is the same on the Reference device:
pParams = new PresentParameters()
{
BackBufferWidth = this.ClientSize.Width,
BackBufferHeight = this.ClientSize.Height,
AutoDepthStencilFormat = Format.D16,
EnableAutoDepthStencil = true,
SwapEffect = SwapEffect.Discard,
Windowed = true
};
_engineDX9 = new EngineDX9(this, SlimDX.Direct3D9.DeviceType.Hardware, SlimDX.Direct3D9.CreateFlags.SoftwareVertexProcessing, pParams);
_engineDX9.DefaultCamera.NearPlane = 0;
_engineDX9.DefaultCamera.FarPlane = 10;
_engineDX9.D3DDevice.SetRenderState(RenderState.Ambient, false);
_engineDX9.D3DDevice.SetRenderState(RenderState.ZEnable, ZBufferType.UseZBuffer);
_engineDX9.D3DDevice.SetRenderState(RenderState.ZWriteEnable, true);
_engineDX9.D3DDevice.SetRenderState(RenderState.ZFunc, Compare.Always);
_engineDX9.BackColor = Color.White;
_engineDX9.FillMode = FillMode.Solid;
_engineDX9.CullMode = Cull.None;
_engineDX9.DefaultCamera.AspectRatio = (float)this.Width / this.Height;
All of my other setup attempts, even on the reference device, return a COM error code ({"D3DERR_INVALIDCALL: Invalid call (-2005530516)"}). What are the correct setup parameters?
EDIT: The C++ class which interfaces with DirectX9 sets defaults like this:
PresentParameters::PresentParameters()
{
BackBufferWidth = 640;
BackBufferHeight = 480;
BackBufferFormat = Format::X8R8G8B8;
BackBufferCount = 1;
Multisample = MultisampleType::None;
MultisampleQuality = 0;
SwapEffect = SlimDX::Direct3D9::SwapEffect::Discard;
DeviceWindowHandle = IntPtr::Zero;
Windowed = true;
EnableAutoDepthStencil = true;
AutoDepthStencilFormat = Format::D24X8;
PresentFlags = SlimDX::Direct3D9::PresentFlags::None;
FullScreenRefreshRateInHertz = 0;
PresentationInterval = PresentInterval::Immediate;
}
Where does it return an invalid call?
Edit: I'm assuming in the new EngineDX9 call? Have you tried setting a device window handle in the present parameters?
Edit 2: Have you turned on the debug spew in the DirectX control panel to see whether it tells you what the error is?
Edit3: You have tried setting backbufferWidth and Height to 0? What is backbuffercount set to? Might also be worth trying "Format.D24S8" on the backbuffer? Its "possible" your graphics card doesn't support 16-bit (unlikely though). Have you checked in the caps that the mode you are trying to create is valid? I asssume, btw, that the CLR language you are using automagically sets the parameters you don't set to 0? I,personally, always prefer to be explicit in such cases ....
PS I'm guessing here because im a native C++ DX9 coder not a CLR SlimDX coder ...
Edit4: I'm sure its the lack of window handle ... I'm probably wrong but thats the only thing i can see REALLY wrong with your setup. A windowed DX9 device requires a window. Btw set width and height to 0 to just use the window you are setting the device too's size ...
Edit 5: I've really been heading down the wrong route here. There is nothing wrong with the creation of the device that produced your "incorrect" device. Do not mess with the present parameters they are fine. The main reason you'll have problems with your Z-Buffering is that you set the compare function to always. This means that, regardless of what the z-buffer contains, pas the pixel and write its z into the z-buffer overwriting whatever is there already. I'd wager therein lies your Z-buffering problem.
I need to figure out how to get the data from D3D textures and surfaces back to system memory. What's the fastest way to do such things and how?
Also if I only need one subrect, how can one read back only that portion without having to read back the entire thing to system memory?
In short I'm looking for concise descriptions of how to copy the following to system memory:
a texture
a subset of a texture
a surface
a subset of a surface
a D3DUSAGE_RENDERTARGET texture
a subset of a D3DUSAGE_RENDERTARGET texture
This is Direct3D 9, but answers about newer versions of D3D would be appreciated too.
The most involved part is reading from some surface that is in video memory ("default pool"). This is most often render targets.
Let's get the easy parts first:
reading from a texture is the same as reading from 0-level surface of that texture. See below.
the same for subset of a texture.
reading from a surface that is in non-default memory pool ("system" or "managed") is just locking it and reading bytes.
the same for subset of surface. Just lock relevant portion and read it.
So now we have left surfaces that are in video memory ("default pool"). This would be any surface/texture marked as render target, or any regular surface/texture that you have created in default pool, or the backbuffer itself. The complex part here is that you can't lock it.
Short answer is: GetRenderTargetData method on D3D device.
Longer answer (a rough outline of the code that will be below):
rt = get render target surface (this can be surface of the texture, or backbuffer, etc.)
if rt is multisampled (GetDesc, check D3DSURFACE_DESC.MultiSampleType), then: a) create another render target surface of same size, same format but without multisampling; b) StretchRect from rt into this new surface; c) rt = this new surface (i.e. proceed on this new surface).
off = create offscreen plain surface (CreateOffscreenPlainSurface, D3DPOOL_SYSTEMMEM pool)
device->GetRenderTargetData( rt, off )
now off contains render target data. LockRect(), read data, UnlockRect() on it.
cleanup
Even longer answer (paste from the codebase I'm working on) follows. This will not compile out of the box, because it uses some classes, functions, macros and utilities from the rest of codebase; but it should get you started. I also ommitted most of error checking (e.g. whether given width/height is out of bounds). I also omitted the part that reads actual pixels and possibly converts them into suitable destination format (that is quite easy, but can get long, depending on number of format conversions you want to support).
bool GfxDeviceD3D9::ReadbackImage( /* params */ )
{
HRESULT hr;
IDirect3DDevice9* dev = GetD3DDevice();
SurfacePointer renderTarget;
hr = dev->GetRenderTarget( 0, &renderTarget );
if( !renderTarget || FAILED(hr) )
return false;
D3DSURFACE_DESC rtDesc;
renderTarget->GetDesc( &rtDesc );
SurfacePointer resolvedSurface;
if( rtDesc.MultiSampleType != D3DMULTISAMPLE_NONE )
{
hr = dev->CreateRenderTarget( rtDesc.Width, rtDesc.Height, rtDesc.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &resolvedSurface, NULL );
if( FAILED(hr) )
return false;
hr = dev->StretchRect( renderTarget, NULL, resolvedSurface, NULL, D3DTEXF_NONE );
if( FAILED(hr) )
return false;
renderTarget = resolvedSurface;
}
SurfacePointer offscreenSurface;
hr = dev->CreateOffscreenPlainSurface( rtDesc.Width, rtDesc.Height, rtDesc.Format, D3DPOOL_SYSTEMMEM, &offscreenSurface, NULL );
if( FAILED(hr) )
return false;
hr = dev->GetRenderTargetData( renderTarget, offscreenSurface );
bool ok = SUCCEEDED(hr);
if( ok )
{
// Here we have data in offscreenSurface.
D3DLOCKED_RECT lr;
RECT rect;
rect.left = 0;
rect.right = rtDesc.Width;
rect.top = 0;
rect.bottom = rtDesc.Height;
// Lock the surface to read pixels
hr = offscreenSurface->LockRect( &lr, &rect, D3DLOCK_READONLY );
if( SUCCEEDED(hr) )
{
// Pointer to data is lt.pBits, each row is
// lr.Pitch bytes apart (often it is the same as width*bpp, but
// can be larger if driver uses padding)
// Read the data here!
offscreenSurface->UnlockRect();
}
else
{
ok = false;
}
}
return ok;
}
SurfacePointer in the code above is a smart pointer to a COM object (it releases object on assignment or destructor). Simplifies error handling a lot. This is very similar to _comptr_t things in Visual C++.
The code above reads back whole surface. If you want to read just a part of it efficiently, then I believe fastest way is roughly:
create a default pool surface that is of the needed size.
StretchRect from part of original surface to that smaller one.
proceed as normal with the smaller one.
In fact this is quite similar to what code above does to handle multi-sampled surfaces. If you want to get just a part of a multi-sampled surface, you can do a multisample resolve and get part of it in one StretchRect, I think.
Edit: removed piece of code that does actual read of pixels and format conversions. Was not directly related to question, and the code was long.
Edit: updated to match edited question.
I need to figure out how to get the data from D3D textures and surfaces back to system memory. What's the fastest way to do such things and how?
Also if I only need one subrect, how can one read back only that portion without having to read back the entire thing to system memory?
In short I'm looking for concise descriptions of how to copy the following to system memory:
a texture
a subset of a texture
a surface
a subset of a surface
a D3DUSAGE_RENDERTARGET texture
a subset of a D3DUSAGE_RENDERTARGET texture
This is Direct3D 9, but answers about newer versions of D3D would be appreciated too.
The most involved part is reading from some surface that is in video memory ("default pool"). This is most often render targets.
Let's get the easy parts first:
reading from a texture is the same as reading from 0-level surface of that texture. See below.
the same for subset of a texture.
reading from a surface that is in non-default memory pool ("system" or "managed") is just locking it and reading bytes.
the same for subset of surface. Just lock relevant portion and read it.
So now we have left surfaces that are in video memory ("default pool"). This would be any surface/texture marked as render target, or any regular surface/texture that you have created in default pool, or the backbuffer itself. The complex part here is that you can't lock it.
Short answer is: GetRenderTargetData method on D3D device.
Longer answer (a rough outline of the code that will be below):
rt = get render target surface (this can be surface of the texture, or backbuffer, etc.)
if rt is multisampled (GetDesc, check D3DSURFACE_DESC.MultiSampleType), then: a) create another render target surface of same size, same format but without multisampling; b) StretchRect from rt into this new surface; c) rt = this new surface (i.e. proceed on this new surface).
off = create offscreen plain surface (CreateOffscreenPlainSurface, D3DPOOL_SYSTEMMEM pool)
device->GetRenderTargetData( rt, off )
now off contains render target data. LockRect(), read data, UnlockRect() on it.
cleanup
Even longer answer (paste from the codebase I'm working on) follows. This will not compile out of the box, because it uses some classes, functions, macros and utilities from the rest of codebase; but it should get you started. I also ommitted most of error checking (e.g. whether given width/height is out of bounds). I also omitted the part that reads actual pixels and possibly converts them into suitable destination format (that is quite easy, but can get long, depending on number of format conversions you want to support).
bool GfxDeviceD3D9::ReadbackImage( /* params */ )
{
HRESULT hr;
IDirect3DDevice9* dev = GetD3DDevice();
SurfacePointer renderTarget;
hr = dev->GetRenderTarget( 0, &renderTarget );
if( !renderTarget || FAILED(hr) )
return false;
D3DSURFACE_DESC rtDesc;
renderTarget->GetDesc( &rtDesc );
SurfacePointer resolvedSurface;
if( rtDesc.MultiSampleType != D3DMULTISAMPLE_NONE )
{
hr = dev->CreateRenderTarget( rtDesc.Width, rtDesc.Height, rtDesc.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &resolvedSurface, NULL );
if( FAILED(hr) )
return false;
hr = dev->StretchRect( renderTarget, NULL, resolvedSurface, NULL, D3DTEXF_NONE );
if( FAILED(hr) )
return false;
renderTarget = resolvedSurface;
}
SurfacePointer offscreenSurface;
hr = dev->CreateOffscreenPlainSurface( rtDesc.Width, rtDesc.Height, rtDesc.Format, D3DPOOL_SYSTEMMEM, &offscreenSurface, NULL );
if( FAILED(hr) )
return false;
hr = dev->GetRenderTargetData( renderTarget, offscreenSurface );
bool ok = SUCCEEDED(hr);
if( ok )
{
// Here we have data in offscreenSurface.
D3DLOCKED_RECT lr;
RECT rect;
rect.left = 0;
rect.right = rtDesc.Width;
rect.top = 0;
rect.bottom = rtDesc.Height;
// Lock the surface to read pixels
hr = offscreenSurface->LockRect( &lr, &rect, D3DLOCK_READONLY );
if( SUCCEEDED(hr) )
{
// Pointer to data is lt.pBits, each row is
// lr.Pitch bytes apart (often it is the same as width*bpp, but
// can be larger if driver uses padding)
// Read the data here!
offscreenSurface->UnlockRect();
}
else
{
ok = false;
}
}
return ok;
}
SurfacePointer in the code above is a smart pointer to a COM object (it releases object on assignment or destructor). Simplifies error handling a lot. This is very similar to _comptr_t things in Visual C++.
The code above reads back whole surface. If you want to read just a part of it efficiently, then I believe fastest way is roughly:
create a default pool surface that is of the needed size.
StretchRect from part of original surface to that smaller one.
proceed as normal with the smaller one.
In fact this is quite similar to what code above does to handle multi-sampled surfaces. If you want to get just a part of a multi-sampled surface, you can do a multisample resolve and get part of it in one StretchRect, I think.
Edit: removed piece of code that does actual read of pixels and format conversions. Was not directly related to question, and the code was long.
Edit: updated to match edited question.