The reference of the IDXGIFactory interface tells me, that in order to create a swap chain, I might use the same factory that was used to create the Direct3D device:
Because you can create a Direct3D device without creating a swap chain, you might need to retrieve the factory that is used to create the device in order to create a swap chain.
It also gives the following code exmaple:
IDXGIDevice * pDXGIDevice;
hr = g_pd3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&pDXGIDevice);
IDXGIAdapter * pDXGIAdapter;
hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&pDXGIAdapter);
IDXGIFactory * pIDXGIFactory;
pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&pIDXGIFactory);
The article is very spare and when trying to fully understand it, the following two questions arose, whereas the first question is the main question (concerning the title of this thread):
Why do I have to use the same factory that was used to create the Direct3D device in order to create the swap chain? Does the factory instance maintain an internal state which is important or is it just to avoid to create another instance of the factory which consumes resources?
Also, within the code sample I struggle with the following line of code:
hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&pDXGIAdapter);
To me, it is not logical, that the IDXGIAdapter is the the parent of the IDXGIDevice. Otherwise I would expect the IDXGIAdapter to have a method like CreateDevice which would make the adapter the parent of the device. But that is not the case. Why is the adapter the parent of the device?
The root of the problem goes back to DXGI 1.0 (Direct3D 10) and DXGI 1.1 (Direct3D 11). If you tried to use a IDXGIFactory created by both CreateDXGIFactory and CreateDXGIFactory1 in the same process, things would go pear-shaped pretty quick.
The other issue is that there's an implicit factory created when you use the 'default device' with Direct3D 10.x or 11.x device creation. The 'magic code sequence' above lets you get the factory created implicitly.
The second step in the docs should be dxgiDevice->GetAdapter not dxgiDevice->GetParent. I'll file a doc bug on that.
This is even easier to do if using Microsoft::WRL::ComPtr:
// First, retrieve the underlying DXGI Device from the D3D Device
ComPtr<IDXGIDevice1> dxgiDevice;
DX::ThrowIfFailed(m_d3dDevice.As(&dxgiDevice));
// Identify the physical adapter (GPU or card) this device is running on.
ComPtr<IDXGIAdapter> dxgiAdapter;
DX::ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf()));
// And obtain the factory object that created it.
ComPtr<IDXGIFactory1> dxgiFactory;
DX::ThrowIfFailed(dxgiAdapter->GetParent(__uuidof(IDXGIFactory1), &dxgiFactory));
Direct3D 12
Note that this whole area has been cleaned up with Direct3D 12, and you can't use QI to get an IDXGIDevice from a ID3D12Device.
References
DirectX Graphics Infrastructure (DXGI): Best Practices
Anatomy of Direct3D 11 Create Device
Related
I am currently trying to piece together a shader-based music visualizer. The plan is to read data from the current MMDevice, which I'm trying to follow the documentation for, but I must be doing something wrong because I had to jump through all sorts of hoops to get even just the MMDeviceEnumerator to compile.
In order for the uuids of MMDeviceEnumerator and IMMDeviceEnumerator to be defined, I had to set #define WINAPI_FAMILY WINAPI_FAMILY_GAMES. This was also required for EDataFlow and ERole enumerations to be defined. My first question is if I've missed some configuration somewhere, or if this is the intended method of enabling these things.
Currently, I have the following code in an AudioStream class:
class AudioStream {
public:
AudioStream() {
//SUCCEEDING(CoInitializeEx(nullptr, COINIT_MULTITHREADED));
SUCCEEDING(CoCreateInstance(
__uuidof(IMMDeviceEnumerator),
NULL,
CLSCTX_ALL,
__uuidof(MMDeviceEnumerator),
(void**)&this->mmDeviceEnumerator));
SUCCEEDING(this->mmDeviceEnumerator->GetDefaultAudioEndpoint(
eRender,
eConsole,
&this->mmDevice));
}
private:
IAudioClient* audioClient = NULL;
IAudioCaptureClient* captureClient = NULL;
IMMDeviceEnumerator* mmDeviceEnumerator = NULL;
IMMDevice* mmDevice = NULL;
};
If you're familiar with what the DirectX 12 project template looks like, this object is being instantiated in the Sample3DSceneRenderer constructor. The main issue I'm having right now is the following two errors which are immediately raised during startup:
onecore\com\combase\dcomrem\resolver.cxx(2299)\combase.dll!75AA0DFF: (caller: 75B1CF2C) ReturnHr(1) tid(42a8) 80040154 Class not registered
onecore\com\combase\dcomrem\resolver.cxx(2507)\combase.dll!75B1CF4D: (caller: 75AA29E4) ReturnHr(2) tid(42a8) 80040154 Class not registered
This causes the entire app to hang, and the project template visualization to never appear (the succeeding macro exits). Does anyone have any idea why this is failing? It must have to be something with the CoCreateInstance call :(
You are writing a Universal Windows Platform (UWP) app because that's what the "built-in" DirectX 12 App project template creates in Visual Studio. UWPs do not have access to all the same APIs and IMMDevice is not part of the UWP API surface area.
The fact that you defined WINAPI_FAMILY_GAMES means you hacked the API Family Partition macros which will define the API in a UWP context, but it doesn't mean that API actually works from the AppContainer process that all UWPs run in.
You really have two options:
(1) If you want to write a UWP, then you will need to enumerate audio devices via the proper Windows Runtime APIs which are in the Windows::Devices::Enumeration namespace.
Assuming you are using C++/CX language extensions (instead of the more modern C++/WinRT projections), then this code works:
auto operation = DeviceInformation::FindAllAsync(DeviceClass::AudioRender);
while (operation->Status == Windows::Foundation::AsyncStatus::Started)
{
Sleep(100);
}
if (operation->Status != Windows::Foundation::AsyncStatus::Completed)
{
throw std::runtime_error("FindAllAsync");
}
DeviceInformationCollection^ devices = operation->GetResults();
for (unsigned i = 0; i < devices->Size; ++i)
{
using Windows::Devices::Enumeration::DeviceInformation;
DeviceInformation^ d = devices->GetAt(i);
// d->Id->Data();
// d->Name->Data();
}
Also, if you want to get access to the audio capture device from a UWP, you must add a capability to your manifest to request it via <DeviceCapability Name="microphone"/>. See Microsoft Docs.
You should take the time to read the Microsoft Docs on UWPs so you have a better idea of what's supported and what's not.
(2) If you want to write a Win32 desktop app, use the directx-vs-templates instead which include DirectX 12 starting templates for Win32 desktop apps (plus alternative DirectX templates for UWP if that's your thing).
Whichever appmodel you use, you may want to take a look at DirectX Tool Kit for Audio.
BTW, WINAPI_FAMILY_GAMES is used by the Microsoft GDK for Xbox which is for writing titles for Xbox One and Xbox Series X|S. It uses Win32 APIs and doesn't use Windows Runtime APIs, so it has the IMMDevice interface in it's API surface. See Microsoft Docs.
Problem Description
In the following function, we have an IUnkown object which is querying another interface.
hr = pI->QueryInterface(IID_IActiveIMMApp, (void**)&pIApp);
I don't understand how can pI query IActiveIMMMessagePumpOwner. How can we know that there is a handle from the Com Object to IActiveIMMMessagePumpOwner. How can the IID_IActiveIMMApp used in here tell us that yes there is a handle to the IActiveIMMMessagePumpOwner and we would like to get the a pointer to the pointer pointing to the interface?
If CLSID_CActiveIMM is the reason for knowing that the COM objects handles the interface. then why can't add as much interfaces Ids as we want in CoCreateInstance.
Source Code
global_ime_init(ATOM atom, HWND hWnd)
{
IUnknown *pI;
HRESULT hr;
if (pIApp != NULL || pIMsg != NULL)
return;
OleInitialize(NULL);
/*
* Get interface IUnknown
*/
hr = CoCreateInstance(CLSID_CActiveIMM, NULL, CLSCTX_SERVER,
IID_IUnknown, (void**)&pI);
if (FAILED(hr) || !pI)
return;
/*
* Get interface IActiveIMMApp
*/
hr = pI->QueryInterface(IID_IActiveIMMApp, (void**)&pIApp);
if (FAILED(hr))
pIApp = NULL;
/*
* Get interface IActiveIMMMessagePumpOwner
*/
hr = pI->QueryInterface(IID_IActiveIMMMessagePumpOwner, (void**)&pIMsg);
if (FAILED(hr))
pIMsg = NULL;
if (pIApp != NULL)
{
pIApp->Activate(TRUE);
pIApp->FilterClientWindows(&atom, 1);
}
if (pIMsg != NULL)
pIMsg->Start();
pI->Release();
s_hWnd = hWnd;
}
P.S. I started learning the COM Model 1 hour ago, so please bear with me.
When the IUnknown::QueryInterface is executed, you pass the execution to the actual object and so if it recognizes the arguments and it understands the IID_IActiveIMMApp you passed, it supplies you with the pointer you ask for.
This is described in every COM tutorial in the QueryInterface explanation, for example, here:
QueryInterface is the mechanism that allows clients to dynamically discover (at run time) whether or not an interface is supported by a COM component; at the same time, it is the mechanism that a client uses to get an interface pointer from a COM component. When an application wants to use some function of a COM component, it calls that object's QueryInterface, requesting a pointer to the interface that implements the desired function. If the COM component supports that interface, it will return the appropriate interface pointer and a success code. If the COM component doesn't support the requested interface, it will return an error value. The application will then examine the return code; if successful, it will use the interface pointer to access the desired method. If the QueryInterface failed, the application will take some other action, letting the user know that the desired method is not available.
The following example shows a call to QueryInterface on the PhoneBook component. We are asking this component, "Do you support the ILookup interface?" If the call returns successfully, we know that the COM component supports the ILookup interface and we have a pointer to use to call methods contained in the ILookup interface (either LookupByName or LookupByNumber). If not, we know that the PhoneBook COM component does not implement the ILookup interface.
LPLOOKUP *pLookup;
TCHAR szNumber[64];
HRESULT hRes;
// Call QueryInterface on the COM Component PhoneBook, asking for a pointer
// to the Ilookup interface identified by a unique interface ID.
hRes = pPhoneBook->QueryInterface( IID_ILOOKUP, &pLookup);
if( SUCCEEDED( hRes ) )
{
pLookup->LookupByName("Daffy Duck", &szNumber); // Use Ilookup interface pointer.
pLookup->Release(); // Finished using the IPhoneBook interface pointer.
}
else
{
// Failed to acquire Ilookup interface pointer.
}
[...]
A COM component implements IUnknown to control its lifespan and to provide access to the interfaces it supports. A COM component does not provide direct access to its data. GUIDs provide a unique identifier for each class and interface, thereby preventing naming conflicts. And finally, the COM Library is implemented as part of the operating system, and provides the "legwork" associated with finding and launching COM components.
By holding any COM interface you are controlling its life time just by having a pointer, and the COM object you talk to is essentially a "black box". You "see" a "view" of its functionality by having methods of this particular COM interface available for calling. With QueryInterface you request another "view" with a different set of methods associated with the interface identifier. If you are given this new pointer and it's recognized by the COM object you talk to, those new methods are also available for calling.
I am trying to create a Vst3 plugin from a simple host app.
Here I have a simple code just to create an instance of a Vst3 plugin from a *.vst3 file.
auto proc = (GetFactoryProc)GetFunction(hmodule, "GetPluginFactory");
Steinberg::IPluginFactory* rawFactory = proc();
// Get factory info.
Steinberg::PFactoryInfo factoryInfo;
rawFactory->getFactoryInfo(&factoryInfo);
// Get classes.
for (size_t i = 0; i < rawFactory->countClasses(); i++)
{
Steinberg::PClassInfo info;
rawFactory->getClassInfo(i, &info);
// ------------------------------------
// ----------HOW TO USE THIS IDs-------
// ------------------------------------
Steinberg::FIDString cid = info.cid; // Is this correct?
Steinberg::FIDString iid = Steinberg::Vst::IComponent::iid; // I dont know what I am doing...
// ------------------------------------
// HOW TO USE THE createInstance FUNCTION?
// ------------------------------------
void* instance(nullptr);
Steinberg::tresult result = rawFactory->createInstance(cid, iid, &instance);
}
The questions is: What are this ids for? I can guess that cid stands for class-id. But what is the iid for and how can I get it to create an instance of a plugin class?
Every iid I take from any classes, IPluginFactory, IComponent and so on, I get unresolved external symbol.
The createInstance function return Steinberg::kNoInterface by the way so no classes is found when I try to insert an empty iid.
Anyone who know anything about Vst3 from Steinberg?
Any code example or documentation how to use the Vst3 for plugin hosting?
Thanks // Alex.
About module initialization.
A *.vst3 module may require additional initialization.
If a module exports some predefined functions, you should call it before getting the IPluginFactory.
The exported function names are "InitDll" and "ExitDll" for Windows platform.
// after the module is loaded.
auto initDll = (bool(*)())GetFunction(hmodule, "InitDll");
if(initDll) { initDll(); }
auto proc = (GetFactoryProc)GetFunction(hmodule, "GetPluginFactory");
Steinberg::IPluginFactory* rawFactory = proc();
// before the module is unloaded.
auto exitDll = (bool(*)())GetFunction(hmodule, "ExitDll");
if(exitDll) { exitDll(); }
You can also use VST3::Hosting::Module class defined in public.sdk/source/vst/hosting/module.h for this purpose.
About IDs.
The CID is the class-id (a.k.a. component-id) which is used for identifying the actual plugin component class in a vst3 module file.
A *.vst3 module file can contain multiple plugins however a host application can't identify a plugin by its actual C++ class name (because the host never knows it).
That's why the VST3 SDK provides the way to identify a actual plugin component class with CID.
The IID is the interface-id which is used for specifying a interface class.
In plugin loading context, IID represents which type of Interface class you want to get the created plugin as, normally it will be Vst::IComponent.
VST3 SDK is based on VST Module Architecture (VST-MA) which is very much like Component Object Model (COM) of Microsoft.
Learning COM will help you understand VST-MA.
Additionally, each plugins in a *.vst3 module file normally consist of two components: The Processor component and The EditController component.
The Processor component provides basic plugin APIs and DSP APIs.
The Processor component derives two interface classes: Vst::IComponent class and Vst::IAudioProcessor class.
The EditController component provides parameter management APIs and UI APIs.
Basic Conception
A VST 3 audio effect or instrument basically consists of two parts: a processing part and an edit controller part.
The corresponding interfaces are:
Processor : Steinberg::Vst::IAudioProcessor + Steinberg::Vst::IComponent
Controller : Steinberg::Vst::IEditController
The design of VST 3 suggests a complete separation of processor and edit controller by implementing two components. Splitting up an effect into these two parts requires some extra efforts for an implementation of course.
But this separation enables the host to run each component in a different context. It can even run them on different computers. Another benefit is that parameter changes can be separated when it comes to automation. While for processing these changes need to be transmitted in a sample accurate way, the GUI part can be updated with a much lower frequency and it can be shifted by the amount that results from any delay compensation or other processing offset.
A Plug-in that supports this separation has to set the Steinberg::Vst::kDistributable flag in the class info of the processor component (Steinberg::PClassInfo2::classFlags). Of course not every Plug-in can support this, for example if it depends deeply on resources that can not be easily moved to another computer. So when this flag is not set, the host must not try to separate the components in any way.
Although it is not recommended, it is possible to implement both, the processing part and the controller part in one component class. The host tries to query the Steinberg::Vst::IEditController interface after creating an Steinberg::Vst::IAudioProcessor and on success uses it as controller.
-- VST3 API Documentation (VST_SDK 3.6.13)
A plugins consists of two components, so you will call createInstance() twice.
This is the step to load a plugin from a *.vst3 module file:
Create the Processor component of the plugin from the module file, as Vst::IComponent class.
Initialize the Processor component.
Get the CID of the EditController component corresponding to the Processor component.
Create the EditController component from the module file with the CID.
Initialize the EditController component too.
Connect and setup them.
// Get classes.
for (size_t i = 0; i < rawFactory->countClasses(); i++)
{
Steinberg::PClassInfo info;
rawFactory->getClassInfo(i, &info);
// info.category will be kVstAudioEffectClass for Processor component.
// skip this component if not.
if(info.category != kVstAudioEffectClass) {
continue;
}
Vst::IComponent *comp(nullptr);
Steinberg::tresult result
= rawFactory->createInstance(info.cid, // tell factory which plugin to be created.
Vst::IComponent::iid, // tell factory which type of interface you want.
(void **)&comp // get the pointer to `comp`, and pass it as (void **)
);
if(result != kResultTrue) {
// TODO: error handling
return;
}
// now `comp` shall be valid pointer of Vst::IComponent.
// initialize comp
comp->setIoMode(Vst::IoModes::kAdvanced);
// you should define host context object before and pass it here as `FUnknown *`.
// the host context object is the class which normally derives Vst::IHostApplication,
// Vst::IComponentHandler, Vst::IPluginInterfaceSupport, etc.
comp->initialize(host_context);
TUID edit_cid;
comp->getControllerClassId(edit_cid);
// (in detail, IEditController interface may be obtained from IComponent directly if the plugin
// derives SingleComponentEffect.
// For such plugins, do not use this method and obtain IEditController with `comp->queryInstance()`
// )
Vst::IEditController *edit(nullptr);
result = rawFactory->createInstance(edit_cid,
Vst::IEditController::iid,
(void **)&edit);
if(result != kResultTrue) {
// TODO: error handling
return;
}
// initialize the EditController component too.
edit->initialize(host_context);
//...
// now the two components are created.
// connect and setup them.
// use the plugin.
// ...
// don't forget destruction after using it.
edit->terminate();
comp->terminate();
edit->release();
comp->release();
}
FYI, I develop an open-source VST3 Host Application called Terra.
https://github.com/hotwatermorning/Terra
It is still alpha version now. But it may be helpful for you.
Thank you.
I have a touchscreen controller (which is an I2C slave) that I need to enable via APCI. This should be done by calling the _PS0 ACPI method. I call this method by using AcpiEvaluateObject with no arguments and no return values.
AcpiEvaluateObject(nullptr, (ACPI_STRING)"\\_SB.I2C4._PS0", nullptr, nullptr); // returns AE_OK
AcpiEvaluateObject(nullptr, (ACPI_STRING)"\\_SB.I2C4.TCS2._PS0", nullptr, nullptr); // returns AE_AML_UNINITIALIZED_ARG
When calling this method on the parent object (I2C4), everything goes fine but calling it on the touch screen controller (TCS2), it fails. What also makes me wonder is that it returns AE_AML_UNINITIALIZED_ARG even though it doesn't take any args (according to the DSDT).
Calling the _CRS method on the same object also works without any problems. I also looked into the Linux kernel source how they change ACPI power states and they use the exact same mechanism. It boils down to the use of acpi_evaluate_object in acpi_dev_pm_explicit_set which also seems to work on the touchscreen device.
I'm not using Linux, but Genode and the Acpica library.
what am I missing to successfully enable the touchscreen device via ACPI? Is there something the Linux kernel is initializing implicitly (I couldn't find something like this)?
Goal
Broadly, I want to accomplish the following:
Generate a series of images in real-time from a program
Pass the images to a DirectShow source filter, which is registered as a capture source
Select the resulting "virtual webcam" in a program like Lync
The image generation is already written and must leverage an existing framework. I am currently working on the interface between the framework and DirectShow. My current implementation for passing the images is described below.
Interfacing
A COM interface is described in an .idl file, and the generated .c/.h files are included in the source filter and, by extension, the framework module.
Additional methods allow for specifying a media format to support and tuning parameters based on the rate of image generation.
The passImage method passes a pointer to a generated image buffer and the size of the buffer. This is called by a framework sink module when it receives new data to pass.
MyInterface.idl
[
object,
uuid("46B4BD3C-CD67-4158-BB83-89EA95306A4D"),
] interface IExtLiveSrc : IUnknown
{
...
HRESULT passImage
(
[in] unsigned long size,
[in, size_is(size)] BYTE **img
);
};
DirectShow Source Filter
The source filter is implemented as two classes and an associated CLSID that are exported as a DLL and registered using regsvr32. The DLLRegisterServer method is implemented appropriately to register the COM object under CLSID_VideoInputDeviceCategory.
MyFilter.h
class CVSource : public CSource {
static CUnknown *WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT *phr);
STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
// private constructor
}
class CVSourceStream : public CSourceStream
, public virtual IKsPropertySet
, public virtual IAMStreamConfig
, public virtual IExtLiveSrc
{
// constructor, IUnknown, IKsPropertySet, IAMStreamConfig methods
...
HRESULT FillBuffer(IMediaSample *pms);
STDMETHODIMP passImage(unsigned long size, BYTE **img);
}
Note: the pin (CSourceStream-derived class) implements the interface used to pass images. Assume that buffer size negotiation has already been established.
passImage()
STDMETHODIMP CVSourceStream::passImage(unsigned long size, BYTE **img) {
memcpy_s(this->bufferedImg, size, *img, size);
return S_OK;
}
FillBuffer()
HRESULT CVSourceStream::FillBuffer(IMediaSample *pms) {
// Set timestamp on IMediaSample instance
...
BYTE *pData;
pms->GetPointer(&pData);
long lDataLen = pms->GetSize();
memcpy_s(pData, lDataLen, this->bufferedImg, lDataLen);
return S_OK;
}
Question
Ignoring locking and synchronization for the moment (I know that FillBuffer() should block until data is available), I've made the following observations.
Adding a generated test sequence of buffers directly to FillBuffer() leads to Lync correctly displaying them.
When running my program, passImage() behaves correctly and the buffer instance variable receives the correct data. However, FillBuffer() never seems to be called when debugging.
Based on research I've done, it appears my issue is that the two different processes (my framework program and Lync) don't share the same data in the source filter DLL due to creating two separate instances of the filter graph.
What is the cleanest way for Lync's instance of the filter graph to share data with the images my program is despositing? I've seen "inter-process communication" tossed around. Though I'm not familiar with the concept, what would be a clear list of steps I would need to take towards my goal (pipes, sockets, shared memory, registry, etc.)?
Links
A similar discussion on the MSDN forums.
There's discussion of a similar problem to what I have but not enough concrete details, and I don't want to post on an old thread.
A similar question on stack overflow.
This is actually quite similar to what I already have. However, I need to run a new application that presumably creates its own filter graph.
You have to pass data between processes: Lync will always use the filter in its process, without asking where it takes data from. And since it is supposed to take data from external process, it has to deal with interprocess communication and "somehow connect" to remote process where the data comes from.
There are options how you can implement this "somehow" exactly. I would prefer using memory mapped files and events/mutexes for synchronization. Producer process generates data and stores them in MMF, then consumer filter inside Lync processes reads this and delivers as generated video.