Улучшение быстродействия растяжения картинки в памяти в Direct3D 10

Я пишу directshow фильтр с использованием Direct3D 10.

Мне надо поднять производительность кода, расположеного ниже, в 2 - 2.5 раза.

Вся работа происходит при загрузке в память с переворачиванием изображения (строка 49), при масштабировании изображения в памяти (строка 546),

при копировании изображения для сохранения соотношения сторон экрана (строка 442).

При последнем копировании выполняется перестановка красной и синей компонент цвета, потому что у меня не создаётся CComPtr m_pSwapChain; для формата бэк буфера DXGI_FORMAT_B8G8R8A8_UNORM = 87,(даёт суммарное ухудшение быстродействия на 20%)

Кто знает, как можно поднять быстродействие программы?

struct THREAD_MEMORY_DATA{ DWORD* local_destination;

DWORD* local_source;

int limit_value;

int step_x;

int size_x;

int size_y;

BOOL finished;

};

void _cdecl load_media_sample_to_surface_thread(void *local_data){

THREAD_MEMORY_DATA *local_memory_data = (THREAD_MEMORY_DATA *)local_data;

const int limit_value = local_memory_data->limit_value;

const int step_x = local_memory_data->step_x;

const int size_x = local_memory_data->size_x;

const int size_y = local_memory_data->size_y;

DWORD* local_source_memory = local_memory_data->local_source;

DWORD* local_destination_memory = local_memory_data->local_destination;

DWORD* local_source_memory_tempramental = NULL;

DWORD* local_destination_memory_tempramental = NULL;

DWORD* local_source_limit_memory = NULL;

for(int local_counter_height_surface=0;local_counter_height_surface<size_y; local_counter_height_surface++) { local_source_limit_memory = local_source_memory + limit_value; local_source_memory_tempramental = local_source_memory;

local_destination_memory_tempramental = local_destination_memory;

while (local_source_memory_tempramental != local_source_limit_memory) *(local_destination_memory_tempramental++) = *(local_source_memory_tempramental++); local_source_memory -= size_x; local_destination_memory += step_x;

}

local_memory_data->finished = TRUE;

}

void load_media_sample_to_surface(DWORD* local_destination,DWORD* local_source,int local_step,int local_size_x,int local_size_y){ THREAD_MEMORY_DATA local_memory_data_1;

THREAD_MEMORY_DATA local_memory_data_2;

local_memory_data_1.local_source = local_source;

local_memory_data_1.local_destination = local_destination;

local_memory_data_1.step_x = local_step/sizeof(DWORD);

local_memory_data_1.limit_value = local_size_x;

local_memory_data_1.size_x = local_size_x;

local_memory_data_1.size_y = local_size_y/2;

local_memory_data_1.finished = FALSE;

local_memory_data_2.local_source = local_source - local_size_x*local_size_y/2;

local_memory_data_2.local_destination = local_destination + local_step/sizeof(DWORD)*local_size_y/2;

local_memory_data_2.step_x = local_step/sizeof(DWORD);

local_memory_data_2.limit_value = local_size_x;

local_memory_data_2.size_x = local_size_x;

local_memory_data_2.size_y = local_size_y/2;

local_memory_data_2.finished = FALSE;

_beginthread(load_media_sample_to_surface_thread,0,(void*)&local_memory_data_1);

_beginthread(load_media_sample_to_surface_thread,0,(void*)&local_memory_data_2);

while(!local_memory_data_1.finished)

Sleep(1);

while(!local_memory_data_2.finished) Sleep(1);

}

void stretch_memory_R8G8B8A8(int source_height,int source_width,void *source_memory,int destination_height,int destination_width,void *destination_memory);

HRESULT CTransform::Transform( IMediaSample *pMediaSample, AM_MEDIA_TYPE* media_type, ID3D10Device* direct_3D_device, IDXGISwapChain* swap_chain, CVideoText *parameter_VideoText, CMyD3DApplication *parameter_MyD3DApplication, int parameter_ratio_x, int parameter_ratio_y){ if ( pMediaSample==NULL || media_type==NULL || direct_3D_device == NULL || parameter_VideoText == NULL || swap_chain == NULL ) { return E_POINTER;

}

  1. ifdef USE_LOG
{ REFERENCE_TIME local_start_time,local_end_time; pMediaSample->GetTime(&local_start_time,&local_end_time); HANDLE local_file_handle = CreateFileW(L"StereoRendererLR.log.txt",GENERIC_WRITE,0,NULL,OPEN_ALWAYS,0,0); wchar_t local_string_input[] = L"start time (%d) end time (%d)\r\n"; wchar_t local_string_output[500]; wsprintfW(local_string_output,local_string_input,local_start_time,local_end_time); ULONG local_byte_written = 0; SetFilePointer(local_file_handle,0,0,FILE_END); WriteFile(local_file_handle,local_string_output,wcslen(local_string_output)*sizeof(wchar_t),&local_byte_written,NULL); CloseHandle(local_file_handle); }
  1. endif
AM_MEDIA_TYPE* pType = media_type;

VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pType->pbFormat;

BYTE *pData; // Pointer to the actual image buffer long lDataLen; // Holds length of any given sample

RGBQUAD *prgb; // Holds a pointer to the current pixel

if(pMediaSample->GetPointer(&pData)!=S_OK) { return E_FAIL; }

lDataLen = pMediaSample->GetSize();

// Get the image properties from the BITMAPINFOHEADER WORD iPixelSize = pvi->bmiHeader.biBitCount / 8; LONG cxImage = pvi->bmiHeader.biWidth; LONG cyImage = pvi->bmiHeader.biHeight; INT cbImage = cyImage * cxImage * iPixelSize; INT numPixels = cxImage * cyImage;

prgb = (RGBQUAD*) pData;

int pixels_shift = 2*cxImage/100;

REFERENCE_TIME rtStart, rtEnd;

pMediaSample->GetTime(&rtStart, &rtEnd);

HRESULT local_handle_result = S_OK;

DXGI_SWAP_CHAIN_DESC local_desc; local_handle_result = swap_chain->GetDesc( &local_desc

);

if(local_handle_result!=S_OK) { return local_handle_result;

}

UINT local_CONST_BackBufferWidth = local_desc.BufferDesc.Width;

UINT local_CONST_BackBufferHeight = local_desc.BufferDesc.Height;

RECT local_source_texture_surface_rectangle = {0,0,0,0}; local_source_texture_surface_rectangle.right = cxImage;

local_source_texture_surface_rectangle.bottom = cyImage+1;

RGBQUAD *local_source_texture_memory = new RGBQUAD[cxImage*(cyImage+1)];

const int local_value_1 = cyImage-1;

DWORD* local_source_memory = (DWORD*)prgb+local_value_1*cxImage;

DWORD* local_destination_memory = (DWORD*)local_source_texture_memory;

load_media_sample_to_surface(local_destination_memory,local_source_memory,cxImage*sizeof(DWORD),cxImage,cyImage);

// Stereo Blitdefines
  1. define NVSTEREO_IMAGE_SIGNATURE 0x4433564e //NV3D
typedef struct _Nv_Stereo_Image_Header { unsigned int dwSignature; unsigned int dwWidth; unsigned int dwHeight; unsigned int dwBPP; unsigned int dwFlags; } NVSTEREOIMAGEHEADER, *LPNVSTEREOIMAGEHEADER; // ORedflags in the dwFlagsfielsof the _Nv_Stereo_Image_Headerstructure above
  1. define SIH_SWAP_EYES 0x00000001
  2. define SIH_SCALE_TO_FIT 0x00000002
// write stereo signature in the last raw of the stereo image LPNVSTEREOIMAGEHEADER pSIH =

(LPNVSTEREOIMAGEHEADER)(((unsigned char *) local_source_texture_memory) + cxImage*cyImage*sizeof(RGBQUAD));

// Update the signature header values pSIH->dwSignature = NVSTEREO_IMAGE_SIGNATURE; pSIH->dwBPP = 32; pSIH->dwFlags = SIH_SWAP_EYES; // Src image has left on left and right on right pSIH->dwWidth = cxImage; pSIH->dwHeight = cyImage;

// Unlock surface

// Тестовые значения/*//*/// parameter_ratio_x = 1;// parameter_ratio_y = 20;

/*//*/

RECT local_target_rect_final_bufer;

RECT local_source_rectangle_final;

double local_ratio_x = parameter_ratio_x*2;

double local_ratio_y = parameter_ratio_y;

int local_scale_value = 100;

if(cyImage>10) { local_scale_value = 10;

}

if(cyImage>100) { local_scale_value = 100;

}

if(cyImage>1000) { local_scale_value = 1000;

}

if(cyImage>10000) { local_scale_value = 10000;

}

if(parameter_ratio_x==0) { local_ratio_x = cxImage/local_scale_value;

}

if(parameter_ratio_y==0) { local_ratio_y = cyImage/local_scale_value;

}

int local_size_x = local_scale_value*local_ratio_x; int local_size_y = local_scale_value*local_ratio_y;

// Требуемое соотношение local_ratio_x к local_ratio_y

RECT local_ration_destination = {0,0,local_size_x,local_size_y};

if(parameter_MyD3DApplication->get_FullScreenMode()==true) { int gImageWidth = local_size_x; // Source image width int gImageHeight = local_size_y;// Source image height

RECT dstRect = { 0, 0, gImageWidth, gImageHeight};

RECT srcRect_stretch = { 0, 0, gImageWidth, gImageHeight}; // D3DVIEWPORT9 local_view_port;

// direct_3D_device->GetViewport(&local_view_port);

RECT local_view_port_rect = {0,0,local_CONST_BackBufferWidth,local_CONST_BackBufferHeight}; SIZE local_view_port_size = {local_CONST_BackBufferWidth,local_CONST_BackBufferHeight}; // RECT local_view_port_rect = {local_view_port.X,local_view_port.Y,local_view_port.Width,local_view_port.Height};// SIZE local_view_port_size = {local_view_port.Width,local_view_port.Height}; RECT local_target_rect; local_target_rect.left = 0; local_target_rect.right = local_size_x; local_target_rect.top = 0; local_target_rect.bottom = local_size_y; RECT local_target_rect_final_window; RECT local_window_rect; SIZE local_window_size; HWND local_owner_window = parameter_VideoText->GetOwnerWindow(); if(local_owner_window==0) { local_owner_window = parameter_VideoText->m_D3DApp.GetWindow(); if(local_owner_window==0) { return S_OK; } }

GetClientRect(local_owner_window,&local_window_rect);

local_window_size.cx = local_window_rect.right - local_window_rect.left; local_window_size.cy = local_window_rect.bottom - local_window_rect.top; double local_multiplication_target = 1.0*local_view_port_size.cx/local_view_port_size.cy; double local_multiplication_video = 1.0*(local_target_rect.right-local_target_rect.left)/(local_target_rect.bottom-local_target_rect.top);

double local_multiplication_window = 1.0*local_window_size.cx/local_window_size.cy;

double ratio_x = 1.0; double ratio_y = 1.0; if (local_multiplication_window<local_multiplication_video) { local_target_rect_final_window.left = 0; local_target_rect_final_window.right = local_window_size.cx; local_target_rect_final_window.top = local_window_size.cy/2 - 1.0*(local_target_rect.bottom-local_target_rect.top)/(local_target_rect.right-local_target_rect.left)*local_window_size.cx/2; local_target_rect_final_window.bottom = local_window_size.cy/2 + 1.0*(local_target_rect.bottom-local_target_rect.top)/(local_target_rect.right-local_target_rect.left)*local_window_size.cx/2; } else { local_target_rect_final_window.left = local_window_size.cx/2 - 1.0*(local_target_rect.right-local_target_rect.left)/(local_target_rect.bottom-local_target_rect.top)*local_window_size.cy/2; local_target_rect_final_window.right = local_window_size.cx/2 + 1.0*(local_target_rect.right-local_target_rect.left)/(local_target_rect.bottom-local_target_rect.top)*local_window_size.cy/2; local_target_rect_final_window.top = 0; local_target_rect_final_window.bottom = local_window_size.cy;

}

//const int CONST_BackBufferWidth = 1920;

//const int CONST_BackBufferHeight = 1080;

if(1.0*(local_size_x/2)/local_size_y*parameter_MyD3DApplication->CONST_BackBufferHeight/parameter_MyD3DApplication->CONST_BackBufferWidth < 1.0) { ratio_x = 1.0*(local_size_x/2)/local_size_y*parameter_MyD3DApplication->CONST_BackBufferHeight/parameter_MyD3DApplication->CONST_BackBufferWidth; // Ширина 2 кадров приводится к ширине одного кадра (разрешение экрана CONST_BackBufferWidth на CONST_BackBufferHeight) ratio_y = 1.0; } else { ratio_x = 1.0; ratio_y = 1.0/(local_size_x/2)*local_size_y/parameter_MyD3DApplication->CONST_BackBufferHeight*parameter_MyD3DApplication->CONST_BackBufferWidth; // Ширина 2 кадров приводится к ширине одного кадра (разрешение экрана CONST_BackBufferWidth на CONST_BackBufferHeight) } local_target_rect_final_bufer.left = 1.0*local_view_port_size.cx/local_window_size.cx*local_target_rect_final_window.left; local_target_rect_final_bufer.right = 1.0*local_view_port_size.cx/local_window_size.cx*local_target_rect_final_window.right; local_target_rect_final_bufer.top = 1.0*local_view_port_size.cy/local_window_size.cy*local_target_rect_final_window.top; local_target_rect_final_bufer.bottom = 1.0*local_view_port_size.cy/local_window_size.cy*local_target_rect_final_window.bottom; local_source_rectangle_final.left = 0; local_source_rectangle_final.right = local_view_port_size.cx*2*ratio_x; local_source_rectangle_final.top = 0; local_source_rectangle_final.bottom = local_view_port_size.cy*ratio_y; } else

{

int gImageWidth = local_size_x; // Source image width int gImageHeight = local_size_y;// Source image height

RECT dstRect = { 0, 0, gImageWidth, gImageHeight};

RECT srcRect_stretch = { 0, 0, gImageWidth, gImageHeight};

// D3DVIEWPORT9 local_view_port;

// direct_3D_device->GetViewport(&local_view_port);

RECT local_view_port_rect = {0,0,local_CONST_BackBufferWidth,local_CONST_BackBufferHeight};

SIZE local_view_port_size = {local_CONST_BackBufferWidth,local_CONST_BackBufferHeight};

// RECT local_view_port_rect = {local_view_port.X,local_view_port.Y,local_view_port.Width,local_view_port.Height};

// SIZE local_view_port_size = {local_view_port.Width,local_view_port.Height};

RECT local_target_rect; local_target_rect.left = 0; local_target_rect.right = local_size_x; local_target_rect.top = 0; local_target_rect.bottom = local_size_y;

RECT local_target_rect_final_window;

RECT local_window_rect; SIZE local_window_size; HWND local_owner_window = parameter_VideoText->GetOwnerWindow(); if(local_owner_window==0) { local_owner_window = parameter_VideoText->m_D3DApp.GetWindow(); if(local_owner_window==0) { return S_OK; } } GetClientRect(local_owner_window,&local_window_rect); local_window_size.cx = local_window_rect.right - local_window_rect.left;

local_window_size.cy = local_window_rect.bottom - local_window_rect.top;

double local_multiplication_target = 1.0*local_view_port_size.cx/local_view_port_size.cy; double local_multiplication_video = 1.0*(local_target_rect.right-local_target_rect.left)/(local_target_rect.bottom-local_target_rect.top); double local_multiplication_window = 1.0*local_window_size.cx/local_window_size.cy; if (local_multiplication_window<local_multiplication_video) { local_target_rect_final_window.left = 0; local_target_rect_final_window.right = local_window_size.cx; local_target_rect_final_window.top = local_window_size.cy/2 - 1.0*(local_target_rect.bottom-local_target_rect.top)/(local_target_rect.right-local_target_rect.left)*local_window_size.cx/2; local_target_rect_final_window.bottom = local_window_size.cy/2 + 1.0*(local_target_rect.bottom-local_target_rect.top)/(local_target_rect.right-local_target_rect.left)*local_window_size.cx/2; } else { local_target_rect_final_window.left = local_window_size.cx/2 - 1.0*(local_target_rect.right-local_target_rect.left)/(local_target_rect.bottom-local_target_rect.top)*local_window_size.cy/2; local_target_rect_final_window.right = local_window_size.cx/2 + 1.0*(local_target_rect.right-local_target_rect.left)/(local_target_rect.bottom-local_target_rect.top)*local_window_size.cy/2; local_target_rect_final_window.top = 0; local_target_rect_final_window.bottom = local_window_size.cy;

}

local_target_rect_final_bufer.left = 1.0*local_view_port_size.cx/local_window_size.cx*local_target_rect_final_window.left; local_target_rect_final_bufer.right = 1.0*local_view_port_size.cx/local_window_size.cx*local_target_rect_final_window.right; local_target_rect_final_bufer.top = 1.0*local_view_port_size.cy/local_window_size.cy*local_target_rect_final_window.top;

local_target_rect_final_bufer.bottom = 1.0*local_view_port_size.cy/local_window_size.cy*local_target_rect_final_window.bottom;

local_source_rectangle_final.left = 0; local_source_rectangle_final.right = local_view_port_size.cx; local_source_rectangle_final.top = 0; local_source_rectangle_final.bottom = local_view_port_size.cy;

}

direct_3D_device->ClearRenderTargetView( parameter_VideoText->m_D3DApp.GetRenderTargetView(), D3DXVECTOR4(0, 0, 0, 1) );

// Get the back buffer of the swap chain CComPtr pDestSurface; local_handle_result = swap_chain->GetBuffer( 0, __uuidof( ID3D10Texture2D ), (LPVOID*)&pDestSurface ); if( FAILED(local_handle_result) ) { delete []local_source_texture_memory; return local_handle_result;

}

if(pDestSurface) {

RGBQUAD *local_final_texture_memory_back_buffer = new RGBQUAD[local_CONST_BackBufferWidth*local_CONST_BackBufferHeight];

ZeroMemory(local_final_texture_memory_back_buffer,local_CONST_BackBufferWidth*local_CONST_BackBufferHeight*sizeof(RGBQUAD));

RGBQUAD *local_final_texture_memory_DATA_1 = new RGBQUAD[(local_target_rect_final_bufer.bottom-local_target_rect_final_bufer.top)*(local_target_rect_final_bufer.right-local_target_rect_final_bufer.left)];

stretch_memory_R8G8B8A8 ( cyImage,cxImage,local_source_texture_memory, (local_target_rect_final_bufer.bottom-local_target_rect_final_bufer.top), (local_target_rect_final_bufer.right-local_target_rect_final_bufer.left), local_final_texture_memory_DATA_1

);

for(int local_counter_y=local_target_rect_final_bufer.top;local_counter_y<local_target_rect_final_bufer.bottom;local_counter_y++) { for(int local_counter_x=local_target_rect_final_bufer.left;local_counter_x<local_target_rect_final_bufer.right;local_counter_x++) {/*/ *(DWORD*)(&local_final_texture_memory_back_buffer[local_counter_x+local_counter_y*local_CONST_BackBufferWidth]) = *(DWORD*)(&local_final_texture_memory_DATA_1 [ (local_counter_x-local_target_rect_final_bufer.left)+ (local_counter_y-local_target_rect_final_bufer.top)*(local_target_rect_final_bufer.right-local_target_rect_final_bufer.left) ]);/*/ local_final_texture_memory_back_buffer[local_counter_x+local_counter_y*local_CONST_BackBufferWidth].rgbBlue = local_final_texture_memory_DATA_1 [ (local_counter_x-local_target_rect_final_bufer.left)+ (local_counter_y-local_target_rect_final_bufer.top)*(local_target_rect_final_bufer.right-local_target_rect_final_bufer.left) ].rgbRed; local_final_texture_memory_back_buffer[local_counter_x+local_counter_y*local_CONST_BackBufferWidth].rgbGreen = local_final_texture_memory_DATA_1 [ (local_counter_x-local_target_rect_final_bufer.left)+ (local_counter_y-local_target_rect_final_bufer.top)*(local_target_rect_final_bufer.right-local_target_rect_final_bufer.left) ].rgbGreen; local_final_texture_memory_back_buffer[local_counter_x+local_counter_y*local_CONST_BackBufferWidth].rgbRed = local_final_texture_memory_DATA_1 [ (local_counter_x-local_target_rect_final_bufer.left)+ (local_counter_y-local_target_rect_final_bufer.top)*(local_target_rect_final_bufer.right-local_target_rect_final_bufer.left) ].rgbBlue; local_final_texture_memory_back_buffer[local_counter_x+local_counter_y*local_CONST_BackBufferWidth].rgbReserved = local_final_texture_memory_DATA_1 [ (local_counter_x-local_target_rect_final_bufer.left)+ (local_counter_y-local_target_rect_final_bufer.top)*(local_target_rect_final_bufer.right-local_target_rect_final_bufer.left) ].rgbReserved;//*/ }

}

delete []local_final_texture_memory_DATA_1;

memcpy( (BYTE*)local_final_texture_memory_back_buffer+local_CONST_BackBufferWidth*(local_CONST_BackBufferHeight-1)*sizeof(RGBQUAD), (BYTE*)local_source_texture_memory+cyImage*cxImage*sizeof(RGBQUAD),

sizeof(NVSTEREOIMAGEHEADER));

delete []local_source_texture_memory;

CComPtr local_final_texture;

D3D10_TEXTURE2D_DESC local_final_texture_desc;

D3D10_SUBRESOURCE_DATA local_final_texture_data;

local_final_texture_desc.Width = local_source_rectangle_final.right-local_source_rectangle_final.left; local_final_texture_desc.Height = local_source_rectangle_final.bottom-local_source_rectangle_final.top; local_final_texture_desc.MipLevels = 1; local_final_texture_desc.ArraySize = 1; local_final_texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; local_final_texture_desc.SampleDesc.Count = 1; local_final_texture_desc.SampleDesc.Quality = 0; local_final_texture_desc.Usage = D3D10_USAGE_DEFAULT; local_final_texture_desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; local_final_texture_desc.CPUAccessFlags = 0;

local_final_texture_desc.MiscFlags = 0;

local_final_texture_data.pSysMem = (const void *)local_final_texture_memory_back_buffer; local_final_texture_data.SysMemPitch = (local_target_rect_final_bufer.right-local_target_rect_final_bufer.left)*sizeof(RGBQUAD);

local_final_texture_data.SysMemSlicePitch = 0;

local_handle_result = direct_3D_device->CreateTexture2D( &local_final_texture_desc, &local_final_texture_data, &local_final_texture

);

if(local_handle_result!=S_OK) { delete []local_final_texture_memory_back_buffer; return local_handle_result; } if(local_final_texture==NULL) { delete []local_final_texture_memory_back_buffer; return local_handle_result;

}

delete []local_final_texture_memory_back_buffer;

direct_3D_device->CopyResource( pDestSurface, local_final_texture );

}

return S_OK;

}

void stretch_memory_R8G8B8A8(int source_height,int source_width,void *source_memory,int destination_height,int destination_width,void *destination_memory){ BYTE *destination_memory_BYTE = (BYTE *)destination_memory;

BYTE *source_memory_BYTE = (BYTE *)source_memory;

const double local_initial_value_width_0 = double(destination_width)/double(source_width);

for(int local_height_counter_source=0;local_height_counter_source<source_height;local_height_counter_source++) { int local_check_value_height = local_height_counter_source*destination_height/source_height+1+destination_height/source_height; if(local_check_value_height>destination_height) { local_check_value_height = destination_height; } for(int local_height_counter_destination=local_height_counter_source*destination_height/source_height; local_height_counter_destination<local_check_value_height; local_height_counter_destination++) { for(int local_width_counter_source=0;local_width_counter_source<source_width;local_width_counter_source++) { int local_initial_value_width = local_width_counter_source*local_initial_value_width_0; int local_check_value_width = local_initial_value_width+1+local_initial_value_width_0; if(local_check_value_width>destination_width) { local_check_value_width = destination_width; } for(int local_width_counter_destination=local_initial_value_width; local_width_counter_destination<local_check_value_width; local_width_counter_destination++) { *(DWORD*)(&destination_memory_BYTE[(local_width_counter_destination+local_height_counter_destination*destination_width)<<2]) = *(DWORD*)(&source_memory_BYTE[(local_width_counter_source+local_height_counter_source*source_width)<<2]); } } } }

}

Последняя правка: пн, 29/08/2011 - 22:06
Submitted by Kozlov_Sergey on

Комментарии

Профилировщик AMD показывает то, что написано в первом сообщении.Профилировщик Intel показывает, что 30% времени выполняетсяLine Source CPU Time706 hr = m_pSwapChain->Present(0,0); 21.419s

В вашем случае необходимо использовать аппаратные возможности GPU.
Тут могут быть варианты через какой интерфейс это делать:
Проверять нужно следующие направления ATI Stream, NVidia CUDA, Direct Compute - эти API ускоряют вычисления для общих массивов данных большой размерности.
Если же данные могут быть получены на вход и оформлены как текстура то все операции над ней выполняются с помощью шейдеров (в Вашем случае пиксельных).
На процессоре обрабатывать изображения можно только с использованием SIMD инструкций в несколько потоков иначе колосальная потеря в производительности.
У Вашего кода вышеперечисленных техник не наблюдается т. е. быстро он работать не будет или будет грузить процессор.
Submitted by Necro on
Quote:
Necro писал(а):
В вашем случае необходимо использовать аппаратные возможности GPU.
Тут могут быть варианты через какой интерфейс это делать:
Проверять нужно следующие направления ATI Stream, NVidia CUDA, Direct Compute - эти API ускоряют вычисления для общих массивов данных большой размерности.
Если же данные могут быть получены на вход и оформлены как текстура то все операции над ней выполняются с помощью шейдеров (в Вашем случае пиксельных).
На процессоре обрабатывать изображения можно только с использованием SIMD инструкций в несколько потоков иначе колосальная потеря в производительности.
У Вашего кода вышеперечисленных техник не наблюдается т. е. быстро он работать не будет или будет грузить процессор.
А почему на процессоре нельзя? Потому что GPU - дополнительный процессор?Про эти технологии (NVidia CUDA, шейдеры) я ещё ничего не знаю.

В GPU такая же программа как у меня. Почему она должна быстрее работать, чем моя?

Для решения задач существуют устоявшиеся подходы или техники. В случае с изображениями работать приходится с большими массивами данных, а операции над ними повторяются.
Использование GPU это один из подходов. Скорость выполнения на GPU действительно быстрее чем на процессоре (как минимум в 2 раза для встроенного и до 1000+ при внешнем адаптере).
Т. е. если вы еще не использовали GPU и SIMD, то тогда это нужно делать обязательно для Вашего случая.

Submitted by Necro on
Quote:
Necro писал(а):
Для решения задач существуют устоявшиеся подходы или техники. В случае с изображениями работать приходится с большими массивами данных, а операции над ними повторяются.
Использование GPU это один из подходов. Скорость выполнения на GPU действительно быстрее чем на процессоре (как минимум в 2 раза для встроенного и до 1000+ при внешнем адаптере).
Т. е. если вы еще не использовали GPU и SIMD, то тогда это нужно делать обязательно для Вашего случая.
Можно ли растянуть текстуру в пиксельном шейдере?Нужно 2 текстуры: исходная и та, которая будет с растянутой картинкой.Как передать вторую?Первую я посмотрел, как передавать.Код растяжения у меня есть с использованием двух типов данных int и double.app.getDevice()->SetTexture(0, sourceTexture);app.getDevice()->SetTexture(1, destinationTexture);

Так?

Доступные шейдеры для DX10 компании NVidia можете взять здесь (Библиотека шейдеров).

В вашем примере надо использовать максимально GPU т. е. нужно масштабировать не одну а например сразу 16/32/64 текстур за один вызов. Шейдера пиксельного/вершинного (я думаю через вершины Ваша задача решается) у меня нет для этого готового как и примера. Я думаю посмотрев на примеры из библиотеки Вы сможете для себя его написать без труда.

Submitted by Necro on

Если останавливаться на техниках GPGPU, то я бы юзал OpenCL он меньше зависит от вендоров и платформ.

Submitted by Victor on
Quote:
Necro писал(а):
Доступные шейдеры для DX10 компании NVidia можете взять здесь (Библиотека шейдеров).
В вашем примере надо использовать максимально GPU т. е. нужно масштабировать не одну а например сразу 16/32/64 текстур за один вызов. Шейдера пиксельного/вершинного (я думаю через вершины Ваша задача решается) у меня нет для этого готового как и примера. Я думаю посмотрев на примеры из библиотеки Вы сможете для себя его написать без труда.
У меня в каждом цикле рисования 2 текстуры:с исходным видео изображением (даже не текстура, а память - набор RGBQUAD),

результирующая текстура (сначала просто памать - набор RGBQUAD), помещаемая в Back Buffer.

Как переписать эту функцию в пиксельный шейдер?void stretch_memory_R8G8B8A8(int source_height,int source_width,void *source_memory,int destination_height,int destination_width,void *destination_memory){ BYTE *destination_memory_BYTE = (BYTE *)destination_memory;

BYTE *source_memory_BYTE = (BYTE *)source_memory;

const double local_initial_value_width_0 = double(destination_width)/double(source_width);

for(int local_height_counter_source=0;local_height_counter_source<source_height;local_height_counter_source++) { int local_check_value_height = local_height_counter_source*destination_height/source_height+1+destination_height/source_height; if(local_check_value_height>destination_height) { local_check_value_height = destination_height; } for(int local_height_counter_destination=local_height_counter_source*destination_height/source_height; local_height_counter_destination<local_check_value_height; local_height_counter_destination++) { for(int local_width_counter_source=0;local_width_counter_source<source_width;local_width_counter_source++) { int local_initial_value_width = local_width_counter_source*local_initial_value_width_0; int local_check_value_width = local_initial_value_width+1+local_initial_value_width_0; if(local_check_value_width>destination_width) { local_check_value_width = destination_width; } for(int local_width_counter_destination=local_initial_value_width; local_width_counter_destination<local_check_value_width; local_width_counter_destination++) { *(DWORD*)(&destination_memory_BYTE[(local_width_counter_destination+local_height_counter_destination*destination_width)<<2]) = *(DWORD*)(&source_memory_BYTE[(local_width_counter_source+local_height_counter_source*source_width)<<2]); } } } }

}

source_height, source_width - размеры исходной текстуры

source_memory - память исходной текстуры

destination_height, destination_width - размеры результирующей текстурыdestination_memory - память результирующей текстуры

Где почитать про синтаксис пиксельных шейдеров версии 4.0?

В примерах без знания синтаксиса, ключевых слов ничего не понятно.

Я думаю, что должно быть как-то так:

struct PS_INPUT{// типы объявлять не знаю какint source_height;int source_width;void *source_memory;int destination_height;int destination_width;void *destination_memory;//

};

struct PS_OUTPUT{int destination_height;int destination_width;void *destination_memory;

}

PS_OUTPUT stretch_memory_R8G8B8A8(PS_INPUT local_input){

PS_OUTPUT local_output;

int destination_height = local_input.destination_height;int destination_width = local_input.destination_width;

void *destination_memory = local_input.destination_memory;

int source_height = local_input.source_height;int source_width = local_input.source_width;

void *source_memory = local_input.source_memory;

BYTE *destination_memory_BYTE = (BYTE *)destination_memory;

BYTE *source_memory_BYTE = (BYTE *)source_memory;

const double local_initial_value_width_0 = double(destination_width)/double(source_width);

for(int local_height_counter_source=0;local_height_counter_source<source_height;local_height_counter_source++) { int local_check_value_height = local_height_counter_source*destination_height/source_height+1+destination_height/source_height; if(local_check_value_height>destination_height) { local_check_value_height = destination_height; } for(int local_height_counter_destination=local_height_counter_source*destination_height/source_height; local_height_counter_destination<local_check_value_height; local_height_counter_destination++) { for(int local_width_counter_source=0;local_width_counter_source<source_width;local_width_counter_source++) { int local_initial_value_width = local_width_counter_source*local_initial_value_width_0; int local_check_value_width = local_initial_value_width+1+local_initial_value_width_0; if(local_check_value_width>destination_width) { local_check_value_width = destination_width; } for(int local_width_counter_destination=local_initial_value_width; local_width_counter_destination<local_check_value_width; local_width_counter_destination++) { *(DWORD*)(&destination_memory_BYTE[(local_width_counter_destination+local_height_counter_destination*destination_width)<<2]) = *(DWORD*)(&source_memory_BYTE[(local_width_counter_source+local_height_counter_source*source_width)<<2]); } } }

}

local_output.destination_height = destination_height;local_output.destination_width = destination_width;

local_output.destination_memory = destination_memory;

return local_output;}

Начинать нужно с примеров Microsoft DirectX SDK.
Дополнительно можно скачать SDK от ATI и NVidia.
Шейдеры описываются в отдельном файле со своим синтаксисом.
Есть специальные пакеты для написания и профайлинга шейдеров FX Composer.

По ним можно разобрать насколько качественно сделана игра или движок. PerfHUD

Submitted by Necro on

Ничего не понятно.

Как описать в входных пераметрах текстуру?

FX Composer - на 30 дней.

Неужели никто не может переделать?

Или хотя бы напишите, как объявить две текстуры в параметрах.

Quote:
Necro писал(а):
Начинать нужно с примеров Microsoft DirectX SDK.
Дополнительно можно скачать SDK от ATI и NVidia.
Шейдеры описываются в отдельном файле со своим синтаксисом.
Есть специальные пакеты для написания и профайлинга шейдеров FX Composer.
По ним можно разобрать насколько качественно сделана игра или движок. PerfHUD
Скачал библиотеру nvidia-texture-tools.Собрал, переделал свой проект.

Имеем 2 fps, а у меня было 20.

Библиотека использует технологию CUDA.

Может то, что я использовал, из библиотеки и не использует CUDA, но разница в 10 раз не в пользу nvidia.

Кто-нибудь работал с этой библиотекой?

Вот моё использование этой библиотеки.

nv::AutoPtr<nv::Filter> filter(new nv::BoxFilter());

nv::Image image; image.setFormat(nv::Image::Format_ARGB);

image.wrap((void*)local_source_texture_memory, cxImage, cyImage);

nv::FloatImage fimage(&image); nv::AutoPtr<nv::FloatImage> fresult ( fimage.resize ( *filter, (local_target_rect_final_bufer.right-local_target_rect_final_bufer.left), (local_target_rect_final_bufer.bottom-local_target_rect_final_bufer.top), nv::FloatImage::WrapMode_Clamp )

);

image.unwrap();

for(int local_counter_line=0;local_counter_line<(local_target_rect_final_bufer.bottom-local_target_rect_final_bufer.top);local_counter_line++) { float *local_line_data = fresult->scanline(local_counter_line,0); { for(int local_counter_row=0;local_counter_row<(local_target_rect_final_bufer.right-local_target_rect_final_bufer.left);local_counter_row++) { local_final_texture_memory_DATA_1 [ local_counter_row+local_counter_line*(local_target_rect_final_bufer.right-local_target_rect_final_bufer.left) ].rgbBlue = 255*local_line_data[local_counter_row]; } } local_line_data = fresult->scanline(local_counter_line,1); { for(int local_counter_row=0;local_counter_row<(local_target_rect_final_bufer.right-local_target_rect_final_bufer.left);local_counter_row++) { local_final_texture_memory_DATA_1 [ local_counter_row+local_counter_line*(local_target_rect_final_bufer.right-local_target_rect_final_bufer.left) ].rgbGreen = 255*local_line_data[local_counter_row]; } } local_line_data = fresult->scanline(local_counter_line,2); { for(int local_counter_row=0;local_counter_row<(local_target_rect_final_bufer.right-local_target_rect_final_bufer.left);local_counter_row++) { local_final_texture_memory_DATA_1 [ local_counter_row+local_counter_line*(local_target_rect_final_bufer.right-local_target_rect_final_bufer.left) ].rgbRed = 255*local_line_data[local_counter_row]; } } local_line_data = fresult->scanline(local_counter_line,3); { for(int local_counter_row=0;local_counter_row<(local_target_rect_final_bufer.right-local_target_rect_final_bufer.left);local_counter_row++) { local_final_texture_memory_DATA_1 [ local_counter_row+local_counter_line*(local_target_rect_final_bufer.right-local_target_rect_final_bufer.left) ].rgbReserved = 255*local_line_data[local_counter_row]; } }

}

Я нашёл библиотеки NVidia использующие CUDA.

http://developer.nvidia.com/technologies/libraries

Но там только общие описания.Кто-нибудь уже использовал эти библиотеки?Кто-нибудь уже использовал эти библиотеки для растяжения текстуры?

В какой библиотеке есть функция растяжения изображения, выполняющаяся на GPU?

Написал кажется, но скомпилировать не знаю как.global void stretch(int source_height,int source_width,void *source_memory,int destination_height,int destination_width,void *destination_memory){

int tid = blockIdx.x; // handle the data at this index

DWORD *destination_memory_DWORD = (DWORD *)destination_memory; DWORD *source_memory_DWORD = (DWORD *)source_memory; const double local_initial_value_width_0 = double(destination_width)/double(source_width);

const int local_initial_value_width_0_int = local_initial_value_width_0;

int local_height_counter_source = tid; if(local_height_counter_source>=source_height)

return;

// for(int local_height_counter_source=0;local_height_counter_source<source_height;local_height_counter_source++) { int local_check_value_height = local_height_counter_source*destination_height/source_height+1+destination_height/source_height; if(local_check_value_height>destination_height) { local_check_value_height = destination_height; } for(int local_height_counter_destination=local_height_counter_source*destination_height/source_height; local_height_counter_destination<local_check_value_height; local_height_counter_destination++) { for(int local_width_counter_source=0;local_width_counter_source<source_width;local_width_counter_source++) { int local_initial_value_width = local_width_counter_source*local_initial_value_width_0; int local_check_value_width = local_initial_value_width+1+local_initial_value_width_0_int; if(local_check_value_width>destination_width) { local_check_value_width = destination_width; } for(int local_width_counter_destination=local_initial_value_width; local_width_counter_destination<local_check_value_width; local_width_counter_destination++) { destination_memory_DWORD[(local_width_counter_destination+local_height_counter_destination*destination_width)]) = source_memory_DWORD[(local_width_counter_source+local_height_counter_source*source_width)]); } } } }

}

void stretch_memory_R8G8B8A8_CUDA(int source_height,int source_width,void *source_memory,int destination_height,int destination_width,void *destination_memory){ BYTE *destination_memory_BYTE = (BYTE *)destination_memory;

BYTE *source_memory_BYTE = (BYTE *)source_memory;

DWORD *destination_memory_BYTE_CUDA; DWORD *source_memory_BYTE_CUDA; // allocate the memory on the GPU HANDLE_ERROR( cudaMalloc( (void**)&destination_memory_BYTE_CUDA, destination_height * destination_width * sizeof(RGBQUAD) ) );

HANDLE_ERROR( cudaMalloc( (void**)&source_memory_BYTE_CUDA, source_height * source_width * sizeof(RGBQUAD) ) );

// copy the array 'source_memory_BYTE' to the GPU HANDLE_ERROR( cudaMemcpy( source_memory_BYTE_CUDA, source_memory_BYTE, source_height * source_width * sizeof(RGBQUAD),

cudaMemcpyHostToDevice ) );

stretch<<<source_height,1>>>( source_height, source_width, source_memory_BYTE_CUDA, destination_height, destination_width, destination_memory_BYTE_CUDA );

// copy the array 'destination_memory_BYTE' back from the GPU to the CPU HANDLE_ERROR( cudaMemcpy( destination_memory_BYTE, destination_memory_BYTE_CUDA, destination_height * destination_width * sizeof(RGBQUAD),

cudaMemcpyDeviceToHost ) );

// free the memory allocated on the GPU cudaFree( source_memory_BYTE_CUDA ); cudaFree( destination_memory_BYTE_CUDA );}

Скомпилировал.

Теперь вызов cudaSetDevice(0) возвращает cudaErrorInsufficientDriver.

Вам при работе с технологией CUDA надо иметь и драйвер предоставляющий ускорение и установленный у пользователя. Отсюда перед использованием техники ВСЕГДА проверяйте наличие CUDA ускорения и версию Вам необходимую.

Submitted by Necro on
Как проверять?Мне сначала нужно сделать, чтобы у меня работало.

Может из-за этого и программа из библиотеки не запустилась?

Я запускаю для начала 1 блок и 1 нить на графическом процессоре.

Для тестирования закрашиваю память в какой-то цвет.

Что здесь не правильно?

  1. include "stretch.h"
  1. include <cuda_runtime_api.h>
global void stretch(int source_height,int source_width,void *source_memory,int destination_height,int destination_width,void *destination_memory){

int tid = threadIdx.x; // handle the data at this index

long *destination_memory_DWORD = (long *)destination_memory; long *source_memory_DWORD = (long *)source_memory; const double local_initial_value_width_0 = double(destination_width)/double(source_width);

const int local_initial_value_width_0_int = local_initial_value_width_0;

// int local_height_counter_source = tid;// if(local_height_counter_source>=source_height)

// return;

{ for(int local_height_destination=0;local_height_destination<destination_height;local_height_destination++) { for(int local_width_destination=0;local_width_destination<destination_width;local_width_destination++) { destination_memory_DWORD[(local_width_destination+local_height_destination*destination_width)] = 0xFF0FFF0F; } } return;

}

for(int local_height_counter_source=0;local_height_counter_source<source_height;local_height_counter_source++) { int local_check_value_height = local_height_counter_source*destination_height/source_height+1+destination_height/source_height; if(local_check_value_height>destination_height) { local_check_value_height = destination_height; } for(int local_height_counter_destination=local_height_counter_source*destination_height/source_height; local_height_counter_destination<local_check_value_height; local_height_counter_destination++) { for(int local_width_counter_source=0;local_width_counter_source<source_width;local_width_counter_source++) { int local_initial_value_width = local_width_counter_source*local_initial_value_width_0; int local_check_value_width = local_initial_value_width+1+local_initial_value_width_0_int; if(local_check_value_width>destination_width) { local_check_value_width = destination_width; } for(int local_width_counter_destination=local_initial_value_width; local_width_counter_destination<local_check_value_width; local_width_counter_destination++) { destination_memory_DWORD[(local_width_counter_destination+local_height_counter_destination*destination_width)] = source_memory_DWORD[(local_width_counter_source+local_height_counter_source*source_width)]; } } } }

}

void stretch_memory_R8G8B8A8_CUDA(int source_height,int source_width,void *source_memory,int destination_height,int destination_width,void *destination_memory){ char *destination_memory_BYTE = (char *)destination_memory;

char *source_memory_BYTE = (char *)source_memory;

long *destination_memory_BYTE_CUDA; long *source_memory_BYTE_CUDA; // allocate the memory on the GPU if(cudaSuccess == cudaMalloc( (void**)&destination_memory_BYTE_CUDA, destination_height * destination_width * sizeof(long) ) ) { if(cudaSuccess == cudaMalloc( (void**)&source_memory_BYTE_CUDA, source_height * source_width * sizeof(long) ) )

{

// copy the array 'source_memory_BYTE' to the GPU if(cudaSuccess == cudaMemcpy( source_memory_BYTE_CUDA, source_memory_BYTE, source_height * source_width * sizeof(long), cudaMemcpyHostToDevice ) )

{

// stretch<<<1,source_height>>>( source_height, source_width, source_memory_BYTE_CUDA, destination_height, destination_width, destination_memory_BYTE_CUDA );

stretch<<<1,1>>>( source_height, source_width, source_memory_BYTE_CUDA, destination_height, destination_width, destination_memory_BYTE_CUDA );

// copy the array 'destination_memory_BYTE' back from the GPU to the CPU if(cudaSuccess == cudaMemcpy( destination_memory_BYTE, destination_memory_BYTE_CUDA, destination_height * destination_width * sizeof(long), cudaMemcpyDeviceToHost ) ) { }

}

// free the memory allocated on the GPU cudaFree( source_memory_BYTE_CUDA ); } cudaFree( destination_memory_BYTE_CUDA ); }

}

Потом destination_memory выводится на экран. Экран чёрный.

Ты в дебагере проверил, все ли оно проходит нормально и без ошибок? Не вижу сам рендер.

Submitted by MaxImuS on

В ядро (kernel) отладчик не заходит. Остальное проверил. Везде успешные коды завершения. Рендер работает (отличается от провереного (который выводит изображение) вызовом функции растяжения картинки в памяти).

ОС х64 или х32? Проверь, что возвращает sizeof(long)

Submitted by MaxImuS on
Quote:
MaxImuS писал(а):
ОС х64 или х32? Проверь, что возвращает sizeof(long)
У меня Windows 7 32.sizeof(long)==4Я DWORD заменил на long, потому что всё, что касается CUDA, вынес в отдельный файл.

В памяти после выполнения kernel функции только нули (и в памяти, выделеной CUDA, и в памяти, выделеной мной).

Render в первом сообщении строка 536:536. direct_3D_device->CopyResource(537. pDestSurface,538. local_final_texture539. );

И потом, при выходе из функции:// Show the frame on the primary surface.20. hr = m_pSwapChain->Present(0,0);HRESULT CMyD3DApplication::Render(){ while(true) { DWORD local_wait_result_1; if((local_wait_result_1 = WaitForSingleObject(member_VideoText->stop_transform_event,1)) == WAIT_OBJECT_0) { continue; } else { break; }

}

SetEvent(member_VideoText->transform_event);

ID3D10Device* local_direct_3d_device = GetDirect3DDevice(); CComPtr local_direct_3d_device_com(local_direct_3d_device); CComPtr local_media_sample_com(member_pMediaSample); CComPtr local_swap_chain(GetSwapChain());

Filter_Transform.Transform(local_media_sample_com,member_media_type,local_direct_3d_device_com,local_swap_chain,member_VideoText,this,member_ratio_x,member_ratio_y);

member_pMediaSample = NULL;

member_media_type = NULL;

ResetEvent(member_VideoText->transform_event);

return S_OK;} // Render the scene as normal if( FAILED( hr = Render() ) ) {
  1. ifdef USE_LOG
{ HANDLE local_file_handle = CreateFileW(L"StereoRendererLR.log.txt",GENERIC_WRITE,0,NULL,OPEN_ALWAYS,0,0); wchar_t local_string_input[] = L"Render Fail\r\n"; wchar_t local_string_output[500]; wsprintfW(local_string_output,local_string_input); ULONG local_byte_written = 0; SetFilePointer(local_file_handle,0,0,FILE_END); WriteFile(local_file_handle,local_string_output,wcslen(local_string_output)*sizeof(wchar_t),&local_byte_written,NULL); CloseHandle(local_file_handle); }
  1. endif
return hr;

}

// Show the frame on the primary surface. hr = m_pSwapChain->Present(0,0); if( FAILED(hr) ) {
  1. ifdef USE_LOG
{ HANDLE local_file_handle = CreateFileW(L"StereoRendererLR.log.txt",GENERIC_WRITE,0,NULL,OPEN_ALWAYS,0,0); wchar_t local_string_input[] = L"Present Fail\r\n"; wchar_t local_string_output[500]; wsprintfW(local_string_output,local_string_input); ULONG local_byte_written = 0; SetFilePointer(local_file_handle,0,0,FILE_END); WriteFile(local_file_handle,local_string_output,wcslen(local_string_output)*sizeof(wchar_t),&local_byte_written,NULL); CloseHandle(local_file_handle); }
  1. endif
return hr; }

Проверить какие у вас стоят аппаратные ускорения с высокой точностью можно через утилиту GPU-Z.
Когда она покажет что у Вас есть ускорение CUDA можно двигаться дальше, запускать примеры, делать тестовые замеры.

Вставьте скрин интересно посмотреть что у Вас за GPU.
Дополнительно CUDA имеет версии т. е. если Ваш GPU не тянет нужную то меняем GPU или берем библиотеки для него расчитанные (там может быть урезан функционал).

Submitted by Necro on

Как вставить снимок экрана?

Quote:
Kozlov_Sergey писал(а):
Как вставить снимок экрана?
Там есть отдельная кнопка внизу при вставке комментария.
Submitted by Necro on

[img_assist|nid=1212|title=GPU|desc=|link=popup|align=left|width=100|height=96]

Quote:
Kozlov_Sergey писал(а):
[img_assist|nid=1212|title=GPU|desc=|link=popup|align=left|width=100|height=96]
Вы ошиблись не CPU-Z а GPU-Z. Схожие названия у программ. Скачайте нужную.

Можно посмотреть в сторону и более информативных утилит. Например GPU Caps Viewer или GPU Shark

Submitted by Necro on

[img_assist|nid=1213|title=GPU 1|desc=|link=popup|align=left|width=80|height=100]

Судя по тому что я вижу Ваш GPU может только 1.1 API использовать смотрите в списке CUDA GPUs.

Для запуска всех примеров SDK (те что требуют больше 1.1) Вам надо поменять видео карту.

Submitted by Necro on

GameDev.by