I'm trying to use OLE Variants to do XML validation in Embarcadero C++Builder 10.1 Berlin. My ultimate goal is to show all validation errors instead of just the first one (following this MSDN example). My class is below. When I run the following line, I get an exception of "Property name is invalid."
FXmlDomDoc.Exec( XmlFuncSetProperty );
If I comment this line out, everything runs fine.
This makes it seem that "MultipleErrorMessages" is not a valid argument to setProperty() on a MSXML2.DOMDocument.6.0. However, when I look at the list of Second-Level DOM Properties, it seems like this is a valid second-level property for a 6.0 XML DOM object.
What I have tried:
Defining XmlFuncSetProperty as a Procedure instead of a Function; same error.
Setting ValidateOnLoad / ValidateOnParse to false, just in case those somehow affected this; same error.
Re-writing the class using _di_IXMLDOMDocument3, _di_IXMLDOMSchemaCollection2, _di_IXMLDOMParseError. I couldn't find any support for multiple errors in those classes. I did find the functions I needed in a couple of other classes, but they were pure virtual.
Questions:
What am I missing here? Why is this error occurring?
Is there a better way to do this in C++ Builder?
.cpp file:
//------------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
//------------------------------------------------------------------------------
#include "XmlValidatorU.h"
#include <System.Win.ComObj.hpp>
//------------------------------------------------------------------------------
#pragma package(smart_init)
//------------------------------------------------------------------------------
// Validates XML against Schema
//------------------------------------------------------------------------------
// This class uses OLE objects from MSXML2 to validate XML from an XSD file.
// Generally, use the following steps to deal with OLE objects:
// 1. Define a Variant variable for your OLE Object; assign using CreateOleObject().
// 2. Define your TAutoCmd objects that will be used in Variant.Exec()
// 3. Set TAutoCmd args using << to add settings
// 4. Once everything is set up, call Exec() on your OLE Object variant
// More documentation on OLE objects / TAutoCmd at:
// http://docwiki.embarcadero.com/CodeExamples/Rio/en/AutoCmd_(C%2B%2B)
//------------------------------------------------------------------------------
// This macro clarifies that we're registering OLE Function names to our defined TAutoCmd variables.
//
#define RegisterAutoCmd( _AutoCmd, _OleFunc ) _AutoCmd( _OleFunc )
//------------------------------------------------------------------------------
// These macros clear AutoCmdArgs before setting them.
// I made these because setting an arg multiple times just stacks them up, changing the function signature.
// Then, OLE throws a "Member Not Found" error because it can't find a function with that signature.
//
#define AutoCmdArg( _AutoCmd, _Arg ) _AutoCmd.ClearArgs(); _AutoCmd << _Arg
#define AutoCmdArgs( _AutoCmd, _Arg1, _Arg2 ) AutoCmdArg( _AutoCmd, _Arg1 ); _AutoCmd << _Arg2
//------------------------------------------------------------------------------
__fastcall TXmlValidator::TXmlValidator( String _SchemaLocation )
:
RegisterAutoCmd( CacheProcAdd, "add" ),
RegisterAutoCmd( CacheSetValidateOnLoad, "validateOnLoad" ),
RegisterAutoCmd( XmlProcLoadXml, "loadXML" ),
RegisterAutoCmd( XmlFuncSetProperty, "setProperty" ),
RegisterAutoCmd( XmlSetValidateOnParse, "validateOnParse" ),
RegisterAutoCmd( XmlSetResolveExternals, "resolveExternals" ),
RegisterAutoCmd( XmlSetSchemas, "schemas" ),
RegisterAutoCmd( XmlGetParseError, "parseError" ),
RegisterAutoCmd( ParseErrorGetReason, "reason" )
{
if ( _SchemaLocation.IsEmpty() )
{
FInvalidMsg = "No Schema Location Specified";
}
else if ( ! FileExists( _SchemaLocation ) )
{
FInvalidMsg = "Schema File Does Not Exist: " + _SchemaLocation;
}
else
{
FInvalidMsg = "";
}
if ( FInvalidMsg.Length() > 0 )
{
return;
}
// Instantiate the OLE objects
FSchemaCache = CreateOleObject( "MSXML2.XMLSchemaCache.6.0" );
FXmlDomDoc = CreateOleObject( "MSXML2.DOMDocument.6.0" );
// Set static args that shouldn't change
AutoCmdArg( CacheSetValidateOnLoad, true );
AutoCmdArg( XmlSetValidateOnParse, true );
AutoCmdArg( XmlSetResolveExternals, true );
AutoCmdArgs( XmlFuncSetProperty, "MultipleErrorMessages", true );
const AnsiString NoNameSpace = "";
AutoCmdArgs( CacheProcAdd, NoNameSpace, AnsiString( _SchemaLocation ) );
// Load Cache
FSchemaCache.Exec( CacheSetValidateOnLoad ); // Validate on Load
FSchemaCache.Exec( CacheProcAdd ); // Add Schema file location to the cache
// Now that the cache is loaded, set cached schema as arg to XML
AutoCmdArg( XmlSetSchemas, FSchemaCache );
// Set up Xml Dom doc as much as we can...
FXmlDomDoc.Exec( XmlSetValidateOnParse );
FXmlDomDoc.Exec( XmlSetResolveExternals );
FXmlDomDoc.Exec( XmlSetSchemas );
FXmlDomDoc.Exec( XmlFuncSetProperty );
}
//------------------------------------------------------------------------------
String __fastcall TXmlValidator::ValidationError( String _Xml )
{
if ( FInvalidMsg.Length() > 0 )
{
return FInvalidMsg;
}
AutoCmdArg( XmlProcLoadXml, AnsiString( _Xml ) ); // update the XML for re-parsing
FXmlDomDoc.Exec( XmlProcLoadXml ); // Load the doc from the XML
Variant ParseErr = FXmlDomDoc.Exec( XmlGetParseError ); // Get the parseError object
return ParseErr.Exec( ParseErrorGetReason ); // Extract the reason
}
//------------------------------------------------------------------------------
.h file:
//------------------------------------------------------------------------------
#ifndef XmlValidatorUH
#define XmlValidatorUH
//------------------------------------------------------------------------------
class PACKAGE TXmlValidator
{
private:
String FInvalidMsg;
// OLE Variant Variables
Variant FSchemaCache;
Variant FXmlDomDoc;
// TAutoCmd Variables
Procedure CacheProcAdd;
PropertySet CacheSetValidateOnLoad;
Procedure XmlProcLoadXml;
Function XmlFuncSetProperty;
PropertySet XmlSetValidateOnParse;
PropertySet XmlSetResolveExternals;
PropertySet XmlSetSchemas;
PropertyGet XmlGetParseError;
PropertyGet ParseErrorGetReason;
public:
__fastcall TXmlValidator( String _SchemaLocation );
String __fastcall ValidationError( String _Xml );
};
//------------------------------------------------------------------------------
#endif
Thanks to Remy's excellent advice, I got this working in Debug mode. However, I found that AutoCmd caused an Access Violation in the Release build with this code. Therefore, for completeness, I've included my final answer below (that works in both Debug and Release). It abandons AutoCmd for OLEVariant methods.
.cpp file:
//------------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
//------------------------------------------------------------------------------
#include "XmlValidatorU.h"
#include <System.Win.ComObj.hpp>
//------------------------------------------------------------------------------
#pragma package(smart_init)
//------------------------------------------------------------------------------
// This class uses OLE objects from MSXML2 to validate XML from an XSD file.
// Generally, use the following steps to deal with OLE objects:
// 1. Define a Variant variable for your OLE Object; assign using CreateOleObject()
// 2. Use Variant.OlePropertySet(), OlePropertyGet(), OlePropertySet(), OleProcedure(),
// and OleFunction() to do actions on your OLE objects
// 3. Previously, I had this working with TAutoCmd arguments, which worked great
// in Debug, but then yielded a mysterious Access Violation in Release build.
//
// Even though it poops its pants in Release, here's documentation of Embarcadero's AutoCmd solution:
// http://docwiki.embarcadero.com/CodeExamples/Rio/en/AutoCmd_(C%2B%2B)
//
// See MSDN tutorial for allErrors here: https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms754649%28v%3dvs.85%29
//
//------------------------------------------------------------------------------
// This macro casts char* strings to WideString
#define wstr( _CharPtr ) WideString( L##_CharPtr )
//------------------------------------------------------------------------------
__fastcall TXmlValidator::TXmlValidator( String _SchemaLocation )
{
if ( _SchemaLocation.IsEmpty() )
{
FInvalidMsg = "No Schema Location Specified";
}
else if ( ! FileExists( _SchemaLocation ) )
{
FInvalidMsg = "Schema File Does Not Exist: " + _SchemaLocation;
}
else
{
FInvalidMsg = "";
}
if ( FInvalidMsg.Length() > 0 )
{
return;
}
// First, set up the MSXML2.XMLSchemaCache.6.0 OLE object
FSchemaCache = CreateOleObject( wstr( "MSXML2.XMLSchemaCache.6.0" ) );
FSchemaCache.OlePropertySet( _D( "validateOnLoad" ), true );
FSchemaCache.OleProcedure( _D( "add" ), wstr( "" ), WideString( _SchemaLocation ) );
// Now set up the MSXML2.DOMDocument.6.0 OLE object
FXmlDomDoc = CreateOleObject( wstr( "MSXML2.DOMDocument.6.0" ) );
FXmlDomDoc.OlePropertySet( _D( "validateOnParse" ), true );
FXmlDomDoc.OlePropertySet( _D( "resolveExternals" ), true );
FXmlDomDoc.OlePropertySet( _D( "schemas" ), FSchemaCache ); // set schemas to the cache we created above
FXmlDomDoc.OleProcedure( _D( "setProperty" ), wstr( "MultipleErrorMessages" ), true ); // secondary properties must call setProperty()
}
//------------------------------------------------------------------------------
// This function checks _ParseError for a non-zero error code.
// If found, add Reason and Location to _Result. If no Reason found, at least add Error Code.
void __fastcall TXmlValidator::AddErrorDesc( String& _Result, Variant _ParseError )
{
long TmpErrCode = _ParseError.OlePropertyGet( _D( "errorCode" ) );
if ( 0 == TmpErrCode )
{
return;
}
String TmpReason = _ParseError.OlePropertyGet( _D( "reason" ) );
String TmpXPath = _ParseError.OlePropertyGet( _D( "errorXPath" ) );
TmpReason = TmpReason.Trim();
TmpXPath = TmpXPath.Trim();
if ( TmpReason.IsEmpty() )
{
TmpReason = "Error Code: " + String( TmpErrCode );
}
else
{
TmpReason = "Reason: " + TmpReason;
}
if ( TmpXPath.Length() > 0 )
{
TmpXPath = StringReplace( TmpXPath, "[1]", "", TReplaceFlags() << rfReplaceAll );
TmpXPath = "Location: " + TmpXPath;
}
_Result += TmpReason + "\r\n\r\n";
_Result += TmpXPath + "\r\n";
}
//------------------------------------------------------------------------------
String __fastcall TXmlValidator::ValidationError( String _Xml )
{
String Result = FInvalidMsg;
if ( Result.Length() > 0 )
{
return Result;
}
FXmlDomDoc.OleProcedure( _D( "loadXML" ), WideString( _Xml ) );
// No need to call AddErrorDesc for TopParseErr; it duplicates the first item in allErrors
Variant TopParseErr = FXmlDomDoc.OlePropertyGet( _D( "parseError" ) );
Variant AllErrors = TopParseErr.OlePropertyGet( _D( "allErrors" ) );
int TmpAllErrLength = AllErrors.OlePropertyGet( _D( "length" ) );
for ( int ix = 0; ix < TmpAllErrLength; ix++ ) // Iterate through allErrors
{
Variant TmpErrItem = AllErrors.OlePropertyGet( _D( "item" ), ix );
AddErrorDesc( Result, TmpErrItem ); // Add error desc
}
return Result;
}
//------------------------------------------------------------------------------
.h file:
//------------------------------------------------------------------------------
#ifndef XmlValidatorUH
#define XmlValidatorUH
//------------------------------------------------------------------------------
class PACKAGE TXmlValidator
{
private:
String FInvalidMsg;
Variant FSchemaCache;
Variant FXmlDomDoc;
void __fastcall AddErrorDesc( String& _Result, Variant _ParseError );
public:
__fastcall TXmlValidator( String _SchemaLocation );
String __fastcall ValidationError( String _Xml );
};
//------------------------------------------------------------------------------
#endif
Related
In this code,
How many times would the generated string be copied for each case(case 1, case 2)?
Could anyone confirm my answers in the code body?
If so, can I tell case 2 is more efficient than case 1?
Or any other suggestions?
#include <optional>
#include <string>
std::optional<std::string> GenerateString() {
std::string s = "very long string";
return s;
}
class Message {
public:
Message(const std::string &s) : payload_{s} {}
Message(std::string &&s) : payload_{std::move(s)} {}
private:
std::string payload_;
};
int main() {
// case 1
const std::optional<std::string> &opt1 = GenerateString(); // no copy
const std::string &s1 = *opt1; // no copy
Message msg1{s1}; // copy: s1 -> payload_
// case 2
std::optional<std::string> &&opt2 = GenerateString(); // no copy
std::string &&s2 = std::move(*opt2); // no copy
Message msg2{std::move(s2)}; // no copy
return 0;
}
I’m working with FreeRTOS on a ZYNQ (Zedboard).
I have the problem that my InterruptHandler does not get called after the “enable ap_done interrupt” of my ipcore gets high…
Does anyone have an idea whats wrong?
here my setup:
code:
int main( void )
{
prvSetupHardware();
xil_printf( "Hello from Freertos+TCP++ example main\r\n" );
xTaskCreate( prvIPCoreTask,
"IPCORE",
configMINIMAL_STACK_SIZE,
NULL,
tskIDLE_PRIORITY + 2,
&xIPCoreTask );
/* Start the RTOS scheduler. */
vTaskStartScheduler();
}
static void prvIPCoreTask( void *pvParameters )
{
XCounter_Config *counter_config = XCounter_LookupConfig(XPAR_COUNTER_0_DEVICE_ID);;
xStatus = XCounter_CfgInitialize(&xCounter, counter_config);
configASSERT( xStatus == XST_SUCCESS );
( void ) xStatus;
xPortInstallInterruptHandler(XPAR_FABRIC_COUNTER_0_INTERRUPT_INTR, FreeRTOS_Counter_Handler,( void * ) &xCounter);
XScuGic_SetPriorityTriggerType( &xInterruptController, XPAR_FABRIC_COUNTER_0_INTERRUPT_INTR, configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT, ucRisingEdge );
vPortEnableInterrupt(XPAR_FABRIC_COUNTER_0_INTERRUPT_INTR);
XCounter_InterruptEnable(&xCounter, 0x1);
XCounter_InterruptGlobalEnable(&xCounter);
XCounter_Set_delay_time(&xCounter,1000);
xil_printf( "Before: %d\n", XCounter_InterruptGetStatus(&xCounter));
XCounter_Start(&xCounter);
for( ;; )
{
xil_printf( "after: %d\n", XCounter_InterruptGetStatus(&xCounter));
vTaskDelay( pdMS_TO_TICKS( DELAY_1_SECOND ) );;
}
}
void FreeRTOS_Counter_Handler( void *pvNotUsed )
{
xil_printf( "Counter Event\r\n" );
}
so I testet the ipcore in a simple standaloneproject and the interrupt ISR is also not called. whats wrong with my code?
void FreeRTOS_Counter_Handler( void *pvNotUsed )
{
int a = 1;
}
int main()
{
init_platform();
pxGICConfig = XScuGic_LookupConfig( XPAR_SCUGIC_SINGLE_DEVICE_ID );
XScuGic_CfgInitialize( &xInterruptController, pxGICConfig, pxGICConfig->CpuBaseAddress );
XCounter_Config *counter_config = XCounter_LookupConfig(XPAR_COUNTER_0_DEVICE_ID);;
XCounter_CfgInitialize(&xCounter, counter_config);
XCounter_InterruptEnable(&xCounter, 0x1);
XCounter_InterruptGlobalEnable(&xCounter);
XScuGic_Connect( &xInterruptController, XPAR_FABRIC_COUNTER_0_INTERRUPT_INTR, (Xil_ExceptionHandler) FreeRTOS_Counter_Handler, ( void * ) &xCounter );
XScuGic_SetPriorityTriggerType( &xInterruptController, XPAR_FABRIC_COUNTER_0_INTERRUPT_INTR, 4, 0x3 );
XScuGic_Enable( &xInterruptController, XPAR_FABRIC_COUNTER_0_INTERRUPT_INTR );
XCounter_Set_delay_time(&xCounter,1000);
XCounter_Start(&xCounter);
print("Hello World\n\r");
print("Successfully ran Hello World application");
while(1){
}
cleanup_platform();
return 0;
}
I've setup a simple FTPServer that only serves a specific purpose. Watching the code when a get is performed, I see GetFileDate and GetFileSize called twice, but I never see RetrieveFile being called. Instead, the client shows an exception of 'Connection reset by peer'.
All of the properties of IdFTPServer are default except for AllowAnonymousLogin. 100% of the FTP Server code is being shown:
I've tried changing the TerminateWaitTimeout value, but that didn't help.
__fastcall TFTPServer::TFTPServer(TComponent* Owner) : TDataModule(Owner)
{
root = IncludeTrailingPathDelimiter(GetCurrentDir()) + "files\\";
IdFTPServer1->Active = true;
}
// ---------------------------------------------------------------------------
void __fastcall TFTPServer::Close(void)
{
IdFTPServer1->Active = false;
}
// ---------------------------------------------------------------------------
void __fastcall TFTPServer::IdFTPServer1FileExistCheck(TIdFTPServerContext *ASender, const UnicodeString APathName, bool &VExist)
{
String file = StringReplace(APathName, "/", "", TReplaceFlags() << rfReplaceAll);
TSearchRec sr;
int done = FindFirst(root + file, 0, sr);
VExist = (done == 0);
FindClose(sr);
}
// ---------------------------------------------------------------------------
void __fastcall TFTPServer::IdFTPServer1GetFileDate(TIdFTPServerContext *ASender, const UnicodeString AFilename, TDateTime &VFileDate)
{
String file = StringReplace(AFilename, "/", "", TReplaceFlags() << rfReplaceAll);
TSearchRec sr;
int done = FindFirst(root + file, 0, sr);
if (done == 0)
{
VFileDate = sr.TimeStamp;
}
FindClose(sr);
}
// ---------------------------------------------------------------------------
void __fastcall TFTPServer::IdFTPServer1GetFileSize(TIdFTPServerContext *ASender, const UnicodeString AFilename, __int64 &VFileSize)
{
String file = StringReplace(AFilename, "/", "", TReplaceFlags() << rfReplaceAll);
TSearchRec sr;
int done = FindFirst(root + file, 0, sr);
if (done == 0)
{
VFileSize = sr.Size;
}
FindClose(sr);
}
// ---------------------------------------------------------------------------
void __fastcall TFTPServer::IdFTPServer1RetrieveFile(TIdFTPServerContext *ASender, const UnicodeString AFileName, TStream *&VStream)
{
String file = StringReplace(AFileName, "/", "", TReplaceFlags() << rfReplaceAll);
VStream = new TFileStream(root + file, fmOpenRead);
}
// ---------------------------------------------------------------------------
What am I missing?
I'm trying to load in meshes into DirectX 10. I've created a bunch of classes that handle it and allow me to call in a mesh with only a single line of code in my main game class.
How ever, when I run the program this is what renders:
In the debug output window the following errors keep appearing:
D3D10: ERROR: ID3D10Device::DrawIndexed: Input Assembler - Vertex Shader linkage error: Signatures between stages are incompatible. The reason is that Semantic 'TEXCOORD' is defined for mismatched hardware registers between the output stage and input stage. [ EXECUTION ERROR #343: DEVICE_SHADER_LINKAGE_REGISTERINDEX ]
D3D10: ERROR: ID3D10Device::DrawIndexed: Input Assembler - Vertex Shader linkage error: Signatures between stages are incompatible. The reason is that the input stage requires Semantic/Index (POSITION,0) as input, but it is not provided by the output stage. [ EXECUTION ERROR #342: DEVICE_SHADER_LINKAGE_SEMANTICNAME_NOT_FOUND ]
The thing is, I've no idea how to fix this. The code I'm using does work and I've simply brought all of that code into a new project of mine. There are no build errors and this only appears when the game is running
The .fx file is as follows:
float4x4 matWorld;
float4x4 matView;
float4x4 matProjection;
struct VS_INPUT
{
float4 Pos:POSITION;
float2 TexCoord:TEXCOORD;
};
struct PS_INPUT
{
float4 Pos:SV_POSITION;
float2 TexCoord:TEXCOORD;
};
Texture2D diffuseTexture;
SamplerState diffuseSampler
{
Filter = MIN_MAG_MIP_POINT;
AddressU = WRAP;
AddressV = WRAP;
};
//
// Vertex Shader
//
PS_INPUT VS( VS_INPUT input )
{
PS_INPUT output=(PS_INPUT)0;
float4x4 viewProjection=mul(matView,matProjection);
float4x4 worldViewProjection=mul(matWorld,viewProjection);
output.Pos=mul(input.Pos,worldViewProjection);
output.TexCoord=input.TexCoord;
return output;
}
//
// Pixel Shader
//
float4 PS(PS_INPUT input ) : SV_Target
{
return diffuseTexture.Sample(diffuseSampler,input.TexCoord);
//return float4(1.0f,1.0f,1.0f,1.0f);
}
RasterizerState NoCulling
{
FILLMODE=SOLID;
CULLMODE=NONE;
};
technique10 Render
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
SetRasterizerState(NoCulling);
}
}
In my game, the .fx file and model are called and set as follows:
Loading in shader file
//Set the shader flags - BMD
DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
dwShaderFlags |= D3D10_SHADER_DEBUG;
#endif
ID3D10Blob * pErrorBuffer=NULL;
if( FAILED( D3DX10CreateEffectFromFile( TEXT("TransformedTexture.fx" ), NULL, NULL, "fx_4_0", dwShaderFlags, 0, md3dDevice, NULL, NULL, &m_pEffect, &pErrorBuffer, NULL ) ) )
{
char * pErrorStr = ( char* )pErrorBuffer->GetBufferPointer();
//If the creation of the Effect fails then a message box will be shown
MessageBoxA( NULL, pErrorStr, "Error", MB_OK );
return false;
}
//Get the technique called Render from the effect, we need this for rendering later on
m_pTechnique=m_pEffect->GetTechniqueByName("Render");
//Number of elements in the layout
UINT numElements = TexturedLitVertex::layoutSize;
//Get the Pass description, we need this to bind the vertex to the pipeline
D3D10_PASS_DESC PassDesc;
m_pTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc );
//Create Input layout to describe the incoming buffer to the input assembler
if (FAILED(md3dDevice->CreateInputLayout( TexturedLitVertex::layout, numElements,PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &m_pVertexLayout ) ) )
{
return false;
}
model loading:
m_pTestRenderable=new CRenderable();
//m_pTestRenderable->create<TexturedVertex>(md3dDevice,8,6,vertices,indices);
m_pModelLoader = new CModelLoader();
m_pTestRenderable = m_pModelLoader->loadModelFromFile( md3dDevice,"armoredrecon.fbx" );
m_pGameObjectTest = new CGameObject();
m_pGameObjectTest->setRenderable( m_pTestRenderable );
// Set primitive topology, how are we going to interpet the vertices in the vertex buffer
md3dDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
if ( FAILED( D3DX10CreateShaderResourceViewFromFile( md3dDevice, TEXT( "armoredrecon_diff.png" ), NULL, NULL, &m_pTextureShaderResource, NULL ) ) )
{
MessageBox( NULL, TEXT( "Can't load Texture" ), TEXT( "Error" ), MB_OK );
return false;
}
m_pDiffuseTextureVariable = m_pEffect->GetVariableByName( "diffuseTexture" )->AsShaderResource();
m_pDiffuseTextureVariable->SetResource( m_pTextureShaderResource );
Finally, the draw function code:
//All drawing will occur between the clear and present
m_pViewMatrixVariable->SetMatrix( ( float* )m_matView );
m_pWorldMatrixVariable->SetMatrix( ( float* )m_pGameObjectTest->getWorld() );
//Get the stride(size) of the a vertex, we need this to tell the pipeline the size of one vertex
UINT stride = m_pTestRenderable->getStride();
//The offset from start of the buffer to where our vertices are located
UINT offset = m_pTestRenderable->getOffset();
ID3D10Buffer * pVB=m_pTestRenderable->getVB();
//Bind the vertex buffer to input assembler stage -
md3dDevice->IASetVertexBuffers( 0, 1, &pVB, &stride, &offset );
md3dDevice->IASetIndexBuffer( m_pTestRenderable->getIB(), DXGI_FORMAT_R32_UINT, 0 );
//Get the Description of the technique, we need this in order to loop through each pass in the technique
D3D10_TECHNIQUE_DESC techDesc;
m_pTechnique->GetDesc( &techDesc );
//Loop through the passes in the technique
for( UINT p = 0; p < techDesc.Passes; ++p )
{
//Get a pass at current index and apply it
m_pTechnique->GetPassByIndex( p )->Apply( 0 );
//Draw call
md3dDevice->DrawIndexed(m_pTestRenderable->getNumOfIndices(),0,0);
//m_pD3D10Device->Draw(m_pTestRenderable->getNumOfVerts(),0);
}
Is there anything I've clearly done wrong or are missing? Spent 2 weeks trying to workout what on earth I've done wrong to no avail.
Any insight a fresh pair eyes could give on this would be great.
Microsoft DxDiag can detect whether a system has "Direct3D Acceleration".
If the system has not the capability, DxDiag will write "Direct3D Acceleration not available" and will write in the console "Direct3D functionality not available. You should verify that the driver is a final version from the hardware manufacturer."
I would like the same with a C++ function.
I made some tests and the following function seems to do the job.
Any other better idea?
Thank you.
Alessandro
#include <ddraw.h>
#include <atlbase.h>
bool has3D()
{
CComPtr< IDirectDraw > dd;
HRESULT hr = ::DirectDrawCreate( 0, &dd, 0 );
if ( hr != DD_OK ) return false;
DDCAPS hel_caps, hw_caps;
::ZeroMemory( &hel_caps, sizeof( DDCAPS ) );
::ZeroMemory( &hw_caps, sizeof( DDCAPS ) );
hw_caps.dwSize = sizeof( DDCAPS );
hel_caps.dwSize = sizeof( DDCAPS );
hr = dd->GetCaps( &hw_caps, &hel_caps );
if ( hr != DD_OK ) return false;
return (hw_caps.dwCaps & DDCAPS_3D) && (hel_caps.dwCaps & DDCAPS_3D);
}
As DirectDraw is now deprecated, it's maybe preferable to use the Direct3D functions.
If the purpose is to detect if 3D acceleration is available for an application, I would initialize Direct3D and then check if the HAL Device Type is available.
LPDIRECT3D9 d3d = Direct3DCreate9( D3D_SDK_VERSION );
D3DCAPS9 caps;
if ( FAILED(d3d->GetDeviceCaps(D3DADAPTER_DEFAULT , D3DDEVTYPE_HAL, &caps)) )
{
return false;
}
You can check the validity of this code by forcing the software rendering in the DirectX Control Panel by checking the "Software only" checkbox in the Direct3D tab.
Test the code with and without the checkbox checked and see if it suits your needs.
You can access DX Diag via IDXDiagContainer and IDXDiagProvider