I'm trying reflect all constant buffers with variables from shader, but the reflector gives the wrong names.
shader:
struct ModelViewProjection
{
matrix MVP;
float a;
};
struct SomeConstBuffer1
{
matrix MVP;
float a;
};
struct SomeConstBuffer2
{
matrix MVP;
float a;
};
ConstantBuffer<ModelViewProjection> cb3 : register(b3);
ConstantBuffer<SomeConstBuffer1> cb4 : register(b4);
ConstantBuffer<SomeConstBuffer2> cb6 : register(b6);
c++ code:
void Dx12CoreShader::reflectShader(SubShader& shader)
{
ID3D12ShaderReflection* reflection;
ThrowIfFailed(D3DReflect(shader.blob->GetBufferPointer(), shader.blob->GetBufferSize(), IID_ID3D12ShaderReflection, (void**)& reflection));
D3D12_SHADER_DESC desc;
reflection->GetDesc(&desc);
// here ok. desc.ConstantBuffers == 3
for (unsigned int i = 0; i < desc.ConstantBuffers; ++i)
{
ID3D12ShaderReflectionConstantBuffer* buffer = reflection->GetConstantBufferByIndex(i);
D3D12_SHADER_BUFFER_DESC bufferDesc;
buffer->GetDesc(&bufferDesc);
// here ok. bufferDesc.Name == "cb3"
// here wrong! bufferDesc.Variables==1, I expected 2
for (UINT j = 0; j < bufferDesc.Variables; j++)
{
ID3D12ShaderReflectionVariable* var = buffer->GetVariableByIndex(j);
D3D12_SHADER_VARIABLE_DESC varDesc;
var->GetDesc(&varDesc);
// here also wrong.
// I expect "MVP" first but it returns also "cb3"
}
}
}
My configuration: AMD Ryzen 3 2200U with radeon Vega Mobile Gfx.
what am I doing wrong? could this be a bug?
Similar situation works correctly on DirectX 11.
UPD: I use all variables for preventing compiler to optimize.
I fixed.
cbuffer ModelViewProjection : register(b3)
{
matrix MVP;
float a;
};
cbuffer SomeConstBuffer1 : register(b4)
{
matrix MVP1;
float a1;
};
cbuffer SomeConstBuffer2 : register(b6)
{
matrix MVP2;
float a2;
};
As soon as you need a cbuffer array, you will need to switch to the original notation you used. The second notation you posted is the one used before SM5.1, with SM5.1 the ConstantBuffer template is considered the default.
Still, there is a way to obtain all data you need, by going through the reflection data and checking whether a cbuffer variable of the D3D12_SHADER_TYPE_DESC class is a D3D_SVC_STRUCT, then you can loop over the members.
Related
i am new in this and i am working on App of media player and recording app. in which i have shown song list of device in the listview and recording start / stop / play. Now i want to convert that .mp3 recorded file into .mp4 and one image will show on behalf of a video in that file. Help me to achive this i have no idea and i refer many links and i didnt find anything.
Please check this link for your first question:
Why can't we initialize class members at their declaration?
Usually constructor is use to initialize value to data variables of class.
For 2nd Question:
If data member is not initialize after creation of object, It will contain garbage value. So initialize or assign suitable value to as per your need.
Check below code:
#include<iostream>
using namespace std;
class swap_values
{
int a, b, temp;
public:
swap_values(){
a=0;b=0;temp=0;
}
swap_values(int x, int y){
a = x;
b = y;
temp = 0;
}
void swapped()
{
temp = b;
b=a;
a=temp;
}
void print(){
cout<<"a: "<<a<<" b: "<<b<<endl;
}
};
int main()
{
int x =10; int y = 20;
swap_values obj(x, y);
obj.print();
obj.swapped();
obj.print();
return 0;
}
Everything can be done in better ways but just using your code this will work for you -
#include <iostream>
using namespace std;
class Swap {
private:
int a,b,temp;
public:
Swap()
{
a=10;
b=20;
temp=0;
}
void swapNums()
{
temp=a; a=b; b=temp;
cout<<a<<" " <<b<<endl;
}
};
int main() {
Swap s;
s.swapNums();
return 0;
}
You can avoid using class name as some function name. You can instead use constructor without a return type where you can initialise the member variables. swap method looks fine.
i am not able to initialize my variable in class.
class swap
{
int a=10; \\cannot declare here
int b=20; \\ cannot declare here
}
Since C++11, this is fine, you can have default member initialization.
The error is due to missing semicolon after }.
why it has garbage value with b ??
a=b;
b=temp;
temp=a;
Since temp was never initialized before assigning it to b, temp has an indeterminate value.
Any usage will lead to undefined behavior.
Here's a simple Swap struct:
struct Swap
{
int a = 10; // default member initialization
int b = 20; // default member initialization
Swap(int a = 20, int b = 10): a(b), b(a) {}; // swap on initialization
// using member initializer list
};
Swap s;
std::cout << s.a // 20
<< s.b // 10
<< std::endl;
In this example, default member initialization is "obsolete" / "redundant" due to member initializer list.
I have a struct containing the parameters of a linear function, as well as the function itself. What I want to do is copy this struct to the device and then evaluate the linear function. The following example doesn't make sense but it is sufficient to describe the difficulties I have:
struct model
{
double* params;
double (*func)(double*, double);
};
I don't know how to copy this struct to the device.
Here are my functions:
Init function
// init function for struct model
__host__ void model_init(model* m, double* params, double(*func)(double*,double))
{
if(m)
{
m->params = params;
m->func = func;
}
}
Evaluation function
__device__ double model_evaluate(model* m, double x)
{
if(m)
{
return m->func(m->params, x);
}
return 0.0;
}
The actual function
__host__ __device__ double linear_function(double* params, double x)
{
return params[0] + params[1] * x;
}
Function called inside kernel
__device__ double compute(model *d_linear_model)
{
return model_evaluate(d_linear_model,1.0);
}
The kernel itself
__global__ void kernel(double *array, model *d_linear_model, int N)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < N)
{
array[idx] = compute(d_linear_model);
}
}
I know how to copy an array from host to device but I don't know how to do this for this concrete struct which contains a function.
The kernel call in main then looks like this:
int block_size = 4;
int n_blocks = N_array/block_size + (N_array % block_size == 0 ? 0:1);
kernel<<<n_blocks, block_size>>>(device_array, d_linear_model, N_array);
You've outlined two items that I consider to be somewhat more difficult than beginner-level CUDA programming:
use of device function pointers
a "deep copy" operation (on the embedded params pointer in your model structure)
Both of these topics have been covered in other questions. For example this question/answer discusses deep copy operations - when a data structure has embedded pointers to other data. And this question/answer links to a variety of resources on device function pointer usage.
But I'll go ahead and offer a possible solution for your posted case. Most of your code is usable as-is (at least for demonstration purposes). As mentioned already, your model structure will present two challenges:
struct model
{
double* params; // requires a "deep copy" operation
double (*func)(double*, double); // requires special handling for device function pointers
};
As a result, although most of your code is usable as-is, your "init" function is not. That might work for a host realization, but not for a device realization.
The deep copy operation requires us to copy the overall structure, plus separately copy the data pointed to by the embedded pointer, plus separately copy or "fixup" the embedded pointer itself.
The usage of a device function pointer is restricted by the fact that we cannot grab the actual device function pointer in host code - that is illegal in CUDA. So one possible solution is to use a __device__ construct to "capture" the device function pointer, then do a cudaMemcpyFromSymbol operation in host code, to retrieve the numerical value of the device function pointer, which can then be moved about in ordinary fashion.
Here's a worked example building on what you have shown, demonstrating the two concepts above. I have not created a "device init" function - but all the code necessary to do that is in the main function. Once you've grasped the concepts, you can take whatever code you wish out of the main function below and craft it into your "device init" function, if you wish to create one.
Here's a worked example:
$ cat t968.cu
#include <iostream>
#define NUM_PARAMS 2
#define ARR_SIZE 1
#define nTPB 256
struct model
{
double* params;
double (*func)(double*, double);
};
// init function for struct model -- not using this for device operations
__host__ void model_init(model* m, double* params, double(*func)(double*,double))
{
if(m)
{
m->params = params;
m->func = func;
}
}
__device__ double model_evaluate(model* m, double x)
{
if(m)
{
return m->func(m->params, x);
}
return 0.0;
}
__host__ __device__ double linear_function(double* params, double x)
{
return params[0] + params[1] * x;
}
__device__ double compute(model *d_linear_model)
{
return model_evaluate(d_linear_model,1.0);
}
__global__ void kernel(double *array, model *d_linear_model, int N)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < N)
{
array[idx] = compute(d_linear_model);
}
}
__device__ double (*linear_function_ptr)(double*, double) = linear_function;
int main(){
// grab function pointer from device code
double (*my_fp)(double*, double);
cudaMemcpyFromSymbol(&my_fp, linear_function_ptr, sizeof(void *));
// setup model
model my_model;
my_model.params = new double[NUM_PARAMS];
my_model.params[0] = 1.0;
my_model.params[1] = 2.0;
my_model.func = my_fp;
// setup for device copy of model
model *d_model;
cudaMalloc(&d_model, sizeof(model));
// setup "deep copy" for params
double *d_params;
cudaMalloc(&d_params, NUM_PARAMS*sizeof(double));
cudaMemcpy(d_params, my_model.params, NUM_PARAMS*sizeof(double), cudaMemcpyHostToDevice);
// copy model to device
cudaMemcpy(d_model, &my_model, sizeof(model), cudaMemcpyHostToDevice);
// fixup device params pointer in device model
cudaMemcpy(&(d_model->params), &d_params, sizeof(double *), cudaMemcpyHostToDevice);
// run test
double *d_array, *h_array;
cudaMalloc(&d_array, ARR_SIZE*sizeof(double));
h_array = new double[ARR_SIZE];
for (int i = 0; i < ARR_SIZE; i++) h_array[i] = i;
cudaMemcpy(d_array, h_array, ARR_SIZE*sizeof(double), cudaMemcpyHostToDevice);
kernel<<<(ARR_SIZE+nTPB-1)/nTPB,nTPB>>>(d_array, d_model, ARR_SIZE);
cudaMemcpy(h_array, d_array, ARR_SIZE*sizeof(double), cudaMemcpyDeviceToHost);
std::cout << "Results: " << std::endl;
for (int i = 0; i < ARR_SIZE; i++) std::cout << h_array[i] << " ";
std::cout << std::endl;
return 0;
}
$ nvcc -o t968 t968.cu
$ cuda-memcheck ./t968
========= CUDA-MEMCHECK
Results:
3
========= ERROR SUMMARY: 0 errors
$
For brevity of presentation, I've dispensed with proper cuda error checking (instead I have run the code with cuda-memcheck to demonstrate that it is without runtime error) but I would recommend proper error checking if you're having any trouble with a code.
I wrote a code to calculate area and circumference of a circle using references.I am getting error message as
" unresolved external symbol "void c_decl circle" " AND
" unresolved externals"AND
"more than one instance of overloaded function"
I have given the code below
#include<stdafx.h>
#include<iostream>
void circle(int,float,float);
using namespace std;
int main()
{
int r;
float a=0.0,c=0.0;
cout<<"Enter the radius:"<<endl;
cin>>r;
circle(r,a,c);
cout<<a<<"\t"<<c<<endl;
return 0;
}
void circle(const int &i,float &j,float &k)
{
j=3.14*i*i;
k=2*3.14*i;
}
Please help.Thanks
This might be what you wanted.
The Circle function needs to be above the main method so the compiler knows it exists when you're calling it.
The j and k parameters of the Circle function are points. Pointers are declared with the '' . The '' is also used to get the value from the pointer.
circle(r,&a,&c), This methods takes in the memory locations of both a and c. The memory locations are then given to the pointers. The & gets the memory location while the * gets the actual value.
Anyway it seems to work this way.
#include<iostream>
void circle(int,float,float);
using namespace std;
void circle( int i,float *j,float *k)
{
float s;
*j=3.14*i*i;
*k=2*3.14*i;
}
int main()
{
int r;
float a=0.0,c=0.0;
cout<<"Enter the radius:"<<endl;
cin>>r;
circle(r,&a,&c);
cout<<a<<"\t"<<c<<endl;
return 0;
}
My struct is as follows:
typedef struct KeypointSt {
float row, col;
float scale, ori;
unsigned char *descrip; /* Vector of descriptor values */
struct KeypointSt *next;
} *Keypoint;
The following is a part of a code in C. How can I translate it to C++, considering allocation and de-allocation of heap.
Keypoint k, keys = NULL;
for (i = 0; i < num; i++) {
/* Allocate memory for the keypoint. */
k = (Keypoint) malloc(sizeof(struct KeypointSt));
k->next = keys;
keys = k;
k->descrip = malloc(len);
for (j = 0; j < len; j++) {
k->descrip[j] = (unsigned char) val;
}
}
One possible way of converting to C++ is:
#include <cstring> // memset()
typedef struct KeypointSt
{
float row, col;
float scale, ori;
size_t len;
unsigned char *descrip; /* Vector of descriptor values */
KeypointSt *next;
KeypointSt(int p_len, int p_val) : row(0.0), col(0.0), scale(0.0),
ori(0.0), len(p_len),
descrip(new unsigned char[len]), next(0)
{ memset(descrip, len, p_val); }
~KeypointSt() { delete descrip; }
} *Keypoint;
extern KeypointSt *init_keypoints(size_t num, size_t len, unsigned char val);
extern void free_keypoints(KeypointSt *list);
KeypointSt *init_keypoints(size_t num, size_t len, unsigned char val)
{
KeypointSt *keys = NULL;
for (size_t i = 0; i < num; i++)
{
/* Allocate memory for the keypoint. */
KeypointSt *k = new KeypointSt(len, val);
k->next = keys;
keys = k;
}
return keys;
}
void free_keypoints(KeypointSt *list)
{
while (list != 0)
{
KeypointSt *next = list->next;
delete list;
list = next;
}
}
int main(void)
{
KeypointSt *keys = init_keypoints(4, 5, 6);
free_keypoints(keys);
return 0;
}
The only reason I've kept the typedef in place is because you have existing code; the C++ code would be better using KeypointSt * everywhere — or renaming the structure tag to Keypoint and using Keypoint * in place of your original Keypoint. I don't like non-opaque types where the typedef conceals a pointer. If I see a declaration XYZ xyz;, and it is a structure or class type, I expect to use xyz.pqr and not xyz->pqr.
We can debate code layout of the constructor code, the absence of a default constructor (no arrays), and the absence of a copy constructor and an assignment operator (both needed because of the allocation for descrip). The code of init_keypoints() is not exception safe; a memory allocation failure will leak memory. Fixing that is left as an exercise (it isn't very hard, I think, but I don't claim exception-handling expertise). I've not attempted to consider any extra requirements imposed by C++11. Simply translating from C to C++ is 'easy' until you look at the extra demands that C++ makes — demands that make your life easier in the long run, but at a short-term cost in pain.
In this code snippet, the Init() function acts as a on-demand initializer that fills in all member variables of the structure. This is done to avoid calling default constructors all members of a large array on the stack:
struct Foo {
int m_Member;
void Init(int i);
};
void Foo::Init(int i) {
m_Member = i;
// Many other members initialized here.
}
void SomeFunction(int n) {
Foo buffer[64];
assert(n <= 64);
// Explicitly initialize what is needed.
for (int i = 0; i < n; ++i) {
buffer[i].Init(i * 3);
}
// Use buffer[0] - buffer[n-1] somehow.
}
This triggers a static analysis error in VS2012 with /analyze:
warning C6001: Using uninitialized memory 'buffer'.: Lines: 17, 19, 20
I'm looking for a way to annotate Foo::Init() so that this warning doesn't occur. There are plenty of other ways to make the warning go away, including:
Adding an empty constructor
Moving Init() to the constructor and calling placement new in the loop
But I'd like to avoid changing the structure of the code.
I've tried the following annotation without success:
void _At_(this, _Out_) Init();
This syntax is accepted, but only changes the warning to be:
warning C6001: Using uninitialized memory 'buffer'.: Lines: 18, 20, 21
warning C6001: Using uninitialized memory 'buffer[BYTE:0]'.: Lines: 18, 20, 21
Does anyone know how I can declare the intent of this Init() function to the static analysis engine?
Your question is somewhat elusive. You have shown SomeFunction taking int, but want annotation for method Init or constructor.
The warning shown is absolutely correct, assert won't hide the warning. You need to put if to check if n is greateer than 64 and reset n (or do something else, but not to loop when n>=64).
For annotation you need to use __in_bcount or similar alternative. An example:
bool SetBuffer(__in_bcount(8) const char* sBuffer);
Whichs says sBuffer is of 8 bytes (not elements).
You can read this this article for more information.
Too ugly to add an extra helper?
struct Foo {
int m_Member;
void Init(int i);
};
void Foo::Init(int i) {
m_Member = i;
// Many other members initialized here.
}
void Initialize(__in_bcount(sizeof(Foo) * n) Foo* buffer, int n) {
// Explicitly initialize what is needed.
for (int i = 0; i < n; ++i) {
buffer[i].Init(i * 3);
}
}
void SomeFunction(int n) {
Foo buffer[64];
assert(n <= 64);
Initialize(buffer, n);
// Use buffer[0] - buffer[n-1] somehow.
}
I found a work around by implementing a function to index the array. I flagged the return value as invalid so that this new function only escapes the uninitialized value check in the specific case where the return value is only used to initialize. I've only tested this in VS2017.
#define _Ret_invalid_ _SAL2_Source_(_Ret_invalid_, (), _Ret1_impl_(__notvalid_impl))
template <typename T>
_Ret_invalid_ T& UninitialzedIndex(T* pt, int index)
{
return pt[index];
}
Then, where the value is indexed, I call UninitialzedIndex instead of operator[]
void SomeFunction(int n) {
Foo buffer[64];
if (n <= 64)
return;
// Explicitly initialize what is needed.
for (int i = 0; i < n; ++i) {
UninitialzedIndex(buffer, i).Init(i * 3);
}
// Use buffer[0] - buffer[n-1] somehow.
}
Just add a default constructor (that calls Init()). What is wrong with that?
[Edit] The root problem is not how to lie to the static analyzer or your compiler. It is how to enforce that you don't leave foo in an uninitialized state. There is nothing wrong with adding a default constructor. I'd say the desire to NOT do it imposes risk.
Perhaps some client will use that poorly constructed foo class (Long after you wrote it and long after you are gone) and perhaps they will forget to call .Init() ?? What then? They will be left with data that is uninitialized.
If you are looking to enforce that rule, no amount of static analysis will help you there.
Take care of the foundation before you put on the roof.