I have a 3D application that use 4 thread with one deferred context each one. The problem is that when I use the deferred context to map (ID3D11DeviceContext::Map) the resource, the variables RowPitch and DepthPitch are equal to 0. I get the pointer to the mapped resource and with the memory inspector I see that it have reserve memory (like a calloc).
I have this problem only with ATI graphic cards.
The following code show where is the problem (part of hieroglyph3 engine):
D3D11_MAPPED_SUBRESOURCE Data;
Data.pData = NULL;
Data.DepthPitch = Data.RowPitch = 0;
if ( nullptr == pGlyphResource ) {
Log::Get().Write( L"Trying to map a subresource that doesn't exist!!!" );
return( Data );
}
// TODO: Update this to use a ComPtr!
// Acquire the native resource pointer.
ID3D11Resource* pResource = 0;
pResource = pGlyphResource->GetResource();
if ( nullptr == pResource ) {
Log::Get().Write( L"Trying to map a subresource that has no native resource in it!!!" );
return( Data );
}
// Perform the mapping of the resource.
// This function must fill Data but it only fill the pointer to the mapped resource
HRESULT hr = m_pContext->Map( pResource, subresource, actions, flags, &Data );
if ( FAILED( hr ) ) {
Log::Get().Write( L"Failed to map resource!" );
}
return( Data );
In hieroglyph3 you can download and test it. The code is in PipeLineManagerDX11.cpp in line 688, you can find the class also check it here
The problem was that in ATI GPUs that function don't fill that variables. This don't happen in NVIDIA GPUs.
The solution is to use NVIDIA GPUs that fill the variables.
I'm trying to write some code to read a list of file names from a config file named "TextureList.txt" and then use those files to create a shader resource view for each texture. The listing below shows what I currently have:
LPCSTR textures[MAX_TEXTURES];
std::ifstream texturesToLoad;
texturesToLoad.open("TextureList.txt");
int numberOfTextures = 0;
while(!texturesToLoad.eof())
{
std::string textureName;
std::getline(texturesToLoad, textureName);
textures[numberOfTextures] = textureName.c_str();
numberOfTextures++;
char debugMsg[100];
sprintf(debugMsg, "numberOfTextures = %d\n", numberOfTextures);
OutputDebugString(debugMsg);
OutputDebugString(textureName.c_str());
OutputDebugString("\n");
}
for(int i = 0; i < numberOfTextures; i++)
{
d3dResult = D3DX11CreateShaderResourceViewFromFile( d3dDevice_,
textures[i], 0, 0, &colorMap_[i], 0 );
if( FAILED( d3dResult ) )
{
DXTRACE_MSG( "Failed to load the texture image!" );
return false;
}
}
The debugs at the bottom of the while loop show that the file is being read correctly, it obtains all of the file names and calculates the correct number of textures; however it fails when it tries to create the first resource view.
Can anyone tell me where I'm going wrong?
I don't know if it helps but it works if I replace everything above the for loop with hard coded file names using the following line:
const LPCSTR textures[3] = {"tex1.dds", "tex2.dds", "tex3.dds"};
I'm trying to write a template method to create shaders for Direct3D. The API functions to create each type of shader as well as the types of shaders have different names. So, I wrote the following code:
class Shader final
{
public:
explicit Shader( _In_ ID3DBlob *const pBlob );
template <class T>
void Create
( std::weak_ptr<ID3D11Device>& pDevice
, CComPtr<T>& pResource )
{
auto p_Device = pDevice.lock();
if ( mp_Blob && p_Device )
{
HRESULT hr = E_FAIL;
ID3D11ClassLinkage* pClassLinkage = nullptr; // unsupported for now
pResource.Release();
CComPtr<ID3D11DeviceChild> pRes;
if ( std::is_same<T, ID3D11VertexShader>() )
{
hr = p_Device->CreateVertexShader
( mp_Blob->GetBufferPointer()
, mp_Blob->GetBufferSize()
, pClassLinkage
, reinterpret_cast<ID3D11VertexShader**>( &pRes ) );
}
else if ( std::is_same<T, ID3D11HullShader>() )
{
hr = p_Device->CreateHullShader
( mp_Blob->GetBufferPointer()
, mp_Blob->GetBufferSize()
, pClassLinkage
, reinterpret_cast<ID3D11HullShader**>( &pRes ) );
}
else if ( std::is_same<T, ID3D11DomainShader>() )
{
hr = p_Device->CreateDomainShader
( mp_Blob->GetBufferPointer()
, mp_Blob->GetBufferSize()
, pClassLinkage
, reinterpret_cast<ID3D11DomainShader**>( &pRes ) );
}
else if ( std::is_same<T, ID3D11GeometryShader>() )
{
hr = p_Device->CreateGeometryShader
( mp_Blob->GetBufferPointer()
, mp_Blob->GetBufferSize()
, pClassLinkage
, reinterpret_cast<ID3D11GeometryShader**>( &pRes ) );
}
else if ( std::is_same<T, ID3D11ComputeShader>() )
{
hr = p_Device->CreateComputeShader
( mp_Blob->GetBufferPointer()
, mp_Blob->GetBufferSize()
, pClassLinkage
, reinterpret_cast<ID3D11ComputeShader**>( &pRes ) );
}
else if ( std::is_same<T, ID3D11PixelShader>() )
{
hr = p_Device->CreatePixelShader
( mp_Blob->GetBufferPointer()
, mp_Blob->GetBufferSize()
, pClassLinkage
, reinterpret_cast<ID3D11PixelShader**>( &pRes ) );
}
else
{
assert( false
&& "Need a pointer to an ID3D11 shader interface" );
}
//TODO: log hr's error code.
assert( SUCCEEDED( hr ) && "Error: shader creation failed!" );
if ( FAILED( hr ) )
{
pResource.Release();
}
else
{
hr = pRes->QueryInterface( IID_PPV_ARGS( &pResource ) );
assert( SUCCEEDED( hr ) );
}
}
}
private:
CComPtr<ID3DBlob> mp_Blob;
};
It should work, although I have not tested it yet. But the issue is that the compiler doesn't throw away the branching paths that will certainly not be taken. So for example:
CComPtr<ID3D11DomainShader> pDS;
//pShader is an instance of Shader class
pShader->Create(pDevice, pDs);
will create a domain shader. But the compiler keeps all the paths in the generated function instead of generating just
void Create
( std::weak_ptr<ID3D11Device>& pDevice
, CComPtr<ID3D11DomainShader>& pResource )
{
auto p_Device = pDevice.lock();
if ( mp_Blob && p_Device )
{
HRESULT hr = E_FAIL;
ID3D11ClassLinkage* pClassLinkage = nullptr; // unsupported for now
pResource.Release();
CComPtr<ID3D11DeviceChild> pRes;
if ( true ) // this is the evaluation of std::is_same<ID3D11DomainShader, ID3D11DomainShader>()
{
hr = p_Device->CreateDomainShader
( mp_Blob->GetBufferPointer()
, mp_Blob->GetBufferSize()
, pClassLinkage
, reinterpret_cast<ID3D11DomainShader**>( &pRes ) );
}
//TODO: log hr's error code.
assert( SUCCEEDED( hr ) && "Error: shader creation failed!" );
if ( FAILED( hr ) )
{
pResource.Release();
}
else
{
hr = pRes->QueryInterface( IID_PPV_ARGS( &pResource ) );
assert( SUCCEEDED( hr ) );
}
}
}
I think there should be a way to do this because the type of the shader is known at compile-time, but I don't really know how (my metaprogramming skills need yet to grow).
p.s.
I compiled both in debug and releas setting and in both the paths are kept.
Following may help:
HRESULT createShader(
ID3D11Device& pDevice,
CComPtr<ID3D11VertexShader>& pResource,
CComPtr<ID3D11DeviceChild> pRes)
{
return p_Device.CreateVertexShader(
mp_Blob->GetBufferPointer(),
mp_Blob->GetBufferSize(),
pClassLinkage,
reinterpret_cast<ID3D11VertexShader**>(&pRes));
}
// similar for other Shader type
template <class T>
void Create(
std::weak_ptr<ID3D11Device>& pDevice,
CComPtr<T>& pResource)
{
auto p_Device = pDevice.lock();
if (!mp_Blob || !p_Device) {
return;
}
pResource.Release();
CComPtr<ID3D11DeviceChild> pRes;
// ---------------- 8< --------------------
// Here is the change: no more `if` to check type,
// let the compiler choose the correct overload
HRESULT hr = createShader(*p_device, pResource, pRes);
// ---------------- >8 --------------------
assert( SUCCEEDED( hr ) && "Error: shader creation failed!" );
if ( FAILED( hr ) ) {
pResource.Release();
} else {
hr = pRes->QueryInterface( IID_PPV_ARGS( &pResource ) );
assert( SUCCEEDED( hr ) );
}
}
Regarding your optimisations:
I think you're upset about the code being created to handle everything regardless of which template type.
You need to shift your is_same logic to the enable_if in my meta-programming solution, then the function that matches the template for what you want will ONLY be the code you want.
HOWEVER I interpret your question still as a problem of too much abstraction, you cannot use an Animal class to only accept a Banana if the underlying animal is a monkey.
(In this classic example, Monkey derives from Animal and Banana from Food, where Animal has a method void eat(Food))
Answer of how to do what you want well
A bit long, so I skimmed it.
Remember meta-programming wont always save the day (there are many cases where you know the types but the program doesn't, take for example columns in database result sets).
High performance
Don't let unknown types in in the first place. Here's a common pattern:
class unverified_thing: public base_class {
public:
unverified_thing(base_class* data): data(data) { type_code = -1; }
void set_type_code(int to) { /*throw if not -1*/ type_code = to; }
derived_A* get_as_derived_A() const { /*throw if not the right type code*/
return *(derived_A*)data;
}
derived_B* get_as_derived_B() const { /*throw is not right type code*/
return *(derived_B*)data;
}
//now do the base class methods
whatever base_class_method() {
return data->base_class_method();
}
private:
int type_code;
base_class data;
};
Now you can pretend unverified_thing is your data, and you have introduced a form of type checking. You can afford to throw in the getter because you wont be calling that every frame or whatever. You only deal with that when you're setting up.
So say shader is the base class of fragment_shader and vertex_shader, you can be dealing with a shader but have set the type_id, so you can deal with shaders right until you compile your shader, then you can cast to the correct derived type with a runtime error if wrong. This avoids C++ RTTI which can be quite heavy.
Remember you can afford setup time, you want to make sure every bit of data you send into the engine is correct.
This type pattern comes from validated input only being allowed through (which stops SO many bugs) you have a unverified_thing that doesn't derive from the data type, you can only extract the data without error if you set the type to verified.
An even better way to do this (but can get messy quick) is to have:
template<bool VERIFIED=true>
class user_input { };
/*somewhere in your dialog class (or whatever)*/
user_input<false> get_user_input() const { /*whatever*/ }
/*then have somewhere*/
user_input verify_input(const user_input<false>& some_input) { /*which will throw as needed*/ }
For large data classes of user_input it can be good to hide a large_data* inside the user_input class, but you get the idea.
To use metaprogramming (Limits how flexible the end result can be re. user input)
template<class U>
typename ::std::enable_if<my_funky_criteria<U>::value,funky_shader>::type
Create(::std::istream& input) { /*blah*/ }
with
template<class U>
struct my_funky_criteria: typename ::std::conditional</*what you want*/,::std::true_type,::std::false_type>::type { };
This must be a compiler setting issue, even though you stated that you use release mode. Have you checked that you're using /O3 and not /O2 in your release mode configuration? O2 optimizes for size and could perhaps reuse the same binary instead of creating a version for each type (even though I'm not sure if it's prohibited by the standard).
Also, check the disassembler window to see if the IDE simply cheats you. And rebuild your project, etc. Some times Visual Studio fails seeing changed header files.
There is simply no other answer than build settings in this particular case...
I am using HDF5 API and I am trying to create a dataset with variable-length string.
The struct is
struct dataX
{
std::string data;
};
I was using char[256] with a static hard coded size.
But I want it to be dynamic so after reading the HDF5 Doc, I found H5T_VARIABLE and used it as follows but it still fails.
H5Dcreate returns a negative value (means error).
hid_t mem_type;
mem_type = H5Tcopy( H5T_C_S1 );
H5Tset_size(mem_type,H5T_VARIABLE);
/* Create the memory data type. */
if ((mem_type_id = H5Tcreate (H5T_COMPOUND, mem_type )) < 0 ) {
return -1;
}
/* Insert fields. */
if ( H5Tinsert(mem_type_id, "field", 0, mem_type_id ) < 0 ) {
return -1;
}
/* Create a simple data space with unlimited size */
// hsize_t dims[1]={0};
// hsize_t maxdimsk[1]={ H5S_UNLIMITED };
if ( (sid = H5Screate_simple( 1, dims, maxdims )) < 0 ){
return -1;
}
/* Modify dataset creation properties, i.e. enable chunking */
plist_id = H5Pcreate (H5P_DATASET_CREATE);
//chunk==1
if ( H5Pset_chunk ( plist_id, 1, chunk ) < 0 ){
return -1;
}
H5Pset_alloc_time( plist_id, H5D_ALLOC_TIME_EARLY )
/* Set the fill value using a struct as the data type. */
// fill_data=0
if ( fill_data )
{
if ( H5Pset_fill_value( plist_id, mem_type_id, fill_data ) < 0 ){
LOG_ERROR << "cannot fill value " << LOG_ENDL;
return -1;
}
}
else {
if ( H5Pset_fill_time( plist_id, H5D_FILL_TIME_NEVER ) < 0 ) {
LOG_ERROR << "error" << LOG_ENDL;
}
}
/* Create the dataset. */
did = H5Dcreate( loc_id, dset_name, mem_type_id, sid, plist_id )
I tried H5D_ALLOC_TIME_LATE, thinking that maybe if it allocated the memory just before writing it would work but ... it didn't.
Now I'm stuck and I don't know what to do.
Did I miss something ?
Your mem_type_id doubly invalid:
the second argument of H5Tcreate should be the size of the compound datatype
in H5Tinsert, the last argument should be the datatype of the inserted field. Here I guess you meant mem_type instead of mem_type_id.
I don't know anything about what you are doing in particular, but to write variable length string, you do not need to create a compound type nor to set any special property lists. Basically your 3 first line are enough to create a valid variable-length string datatype (mem_type). Then you create the simple dataspace, then the dataset.
Have a look at this example, you will see it's pretty simple.
i am creating xml file in c++
i wrote the code like creating writing the xml file in c++ as shown below
const char* assign =
"<?xml version=\"1.0\" standalone='no' >\n"
"<office>"
"<work>file created</work>"
"</office>";
TiXmlDocument doc( "vls.xml" );
doc.Parse( assign );
if ( doc.Error() )
{
printf( "Error in %s: %s\n", doc.Value(), doc.ErrorDesc() );
exit( 1 );
}
doc.SaveFile();
bool loadOkay = doc.LoadFile();
if ( !loadOkay )
{
printf( "Could not load test file 'vls.xml'. Error='%s'. Exiting.\n", doc.ErrorDesc() );
exit( 1 );
}
else
printf(" 'vls.xml' loaded successfully");
but now i need only the data in the XMl file not the tags
guys plz help me.
I'd suggest reading the TinyXml documentation, more specifically the TiXmlElement documentation.
For your special case, I'd say it looks like that:
TiXmlElement * office = doc.FirstChildElement( "office" );
if( office )
{
TiXmlElement *work = office.FirstChildElement( "work" );
if( work )
{
printf("Work text: %s\n", work.GetText());
}
}
Although I'm not an expert with TinyXml.
FYI:
StackOverflow search function
Some - Answers - You - should have - considered ....
Please, search Google and StackOverflow before asking such trivial questions.