我试图使用缓冲区在我的程序中的几个'图层'(线程)之间进行通信,现在我有内部发生了什么的视觉输出,我意识到有一个毁灭性的时间量被吃掉在使用这些缓冲区的过程中。缓冲区通信速度噩梦
下面是关于我的代码中发生了什么的一些说明。
- 当再现模式在此线程被触发时,它开始与发送尽可能多的点,它可以给它下面
- 从下侧线的点层(线程)然后被处理并返回到该线程通过下侧线的输出缓冲器
点接收回被映射(现在)如在D3D表面的白色像素
如果我绕过缓冲器并直接把点到表面的像素,只大约需要3秒钟完成整个工作
- 如果我的手点下来,然后有下层传递右后卫,跳过任何实际的数字处理,整个作业大约需要30分钟(这使得整个程序没用)
改变我的缓冲区的大小对速度没有明显的影响
我本来是用在我的缓冲区互斥体,但在尝试了解决问题
已经消除了他们有什么我可以做不同的解决这是我遇到的速度问题? ...与我处理这些消息的方式有关吗?
这是我的代码 我很抱歉,它是如此混乱。我不得不在这个项目上移动得太快,并且在我一直在尝试的评论中留下了很多片段。
DWORD WINAPI CONTROLSUBSYSTEM::InternalExProcedure(__in LPVOID lpSelf)
{
XMSG xmsg;
LPCONTROLSUBSYSTEM lpThis = ((LPCONTROLSUBSYSTEM)lpSelf);
BOOL bStall;
BOOL bRendering = FALSE;
UINT64 iOutstandingPoints = 0; // points that are out being tested
UINT64 iPointsDone = 0;
UINT64 iPointsTotal = 0;
BOOL bAssigning;
DOUBLE dNextX;
DOUBLE dNextY;
while(1)
{
if(lpThis->hwTargetWindow!=NULL && lpThis->d3ddev!=NULL)
{
lpThis->d3ddev->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0);
if(lpThis->d3ddev->BeginScene())
{
lpThis->d3ddev->StretchRect(lpThis->sfRenderingCanvas,NULL,lpThis->sfBackBuffer,NULL,D3DTEXF_NONE);
lpThis->d3ddev->EndScene();
}
lpThis->d3ddev->Present(NULL,NULL,NULL,NULL);
}
//bStall = TRUE;
// read input buffer
if(lpThis->bfInBuffer.PeekMessage(&xmsg))
{
bStall = FALSE;
if(HIBYTE(xmsg.wType)==HIBYTE(CONT_MSG))
{
// take message off
lpThis->bfInBuffer.GetMessage(&xmsg);
// double check consistency
if(HIBYTE(xmsg.wType)==HIBYTE(CONT_MSG))
{
switch(LOBYTE(xmsg.wType))
{
case SETRESOLUTION_MSG:
lpThis->iAreaWidth = (UINT)xmsg.dptPoint.X;
lpThis->iAreaHeight = (UINT)xmsg.dptPoint.Y;
lpThis->sfRenderingCanvas->Release();
if(lpThis->d3ddev->CreateOffscreenPlainSurface(
(UINT)xmsg.dptPoint.X,(UINT)xmsg.dptPoint.Y,
D3DFMT_X8R8G8B8,
D3DPOOL_DEFAULT,
&(lpThis->sfRenderingCanvas),
NULL)!=D3D_OK)
{
MessageBox(NULL,"Error resizing surface.","ERROR",MB_ICONERROR);
}
else
{
D3DLOCKED_RECT lrt;
if(D3D_OK == lpThis->sfRenderingCanvas->LockRect(&lrt,NULL,0))
{
lpThis->iPitch = lrt.Pitch;
VOID *data;
data = lrt.pBits;
ZeroMemory(data,lpThis->iPitch*lpThis->iAreaHeight);
lpThis->sfRenderingCanvas->UnlockRect();
MessageBox(NULL,"Surface Resized","yay",0);
}
else
{
MessageBox(NULL,"Error resizing surface.","ERROR",MB_ICONERROR);
}
}
break;
case SETCOLORMETHOD_MSG:
break;
case SAVESNAPSHOT_MSG:
lpThis->SaveSnapshot();
break;
case FORCERENDER_MSG:
bRendering = TRUE;
iPointsTotal = lpThis->iAreaHeight*lpThis->iPitch;
iPointsDone = 0;
MessageBox(NULL,"yay, render something!",":o",0);
break;
default:
break;
}
}// else, lost this message
}
else
{
if(HIBYTE(xmsg.wType)==HIBYTE(MATH_MSG))
{
XMSG xmsg2;
switch(LOBYTE(xmsg.wType))
{
case RESETFRAME_MSG:
case ZOOMIN_MSG:
case ZOOMOUT_MSG:
case PANUP_MSG:
case PANDOWN_MSG:
case PANLEFT_MSG:
case PANRIGHT_MSG:
// tell self to start a render
xmsg2.wType = CONT_MSG|FORCERENDER_MSG;
if(lpThis->bfInBuffer.PutMessage(&xmsg2))
{
// pass it down
while(!lpThis->lplrSubordinate->PutMessage(&xmsg));
// message passed so pull it from buffer
lpThis->bfInBuffer.GetMessage(&xmsg);
}
break;
default:
// pass it down
if(lpThis->lplrSubordinate->PutMessage(&xmsg))
{
// message passed so pull it from buffer
lpThis->bfInBuffer.GetMessage(&xmsg);
}
break;
}
}
else if(lpThis->lplrSubordinate!=NULL)
// pass message down
{
if(lpThis->lplrSubordinate->PutMessage(&xmsg))
{
// message passed so pull it from buffer
lpThis->bfInBuffer.GetMessage(&xmsg);
}
}
}
}
// read output buffer from subordinate
if(lpThis->lplrSubordinate!=NULL && lpThis->lplrSubordinate->PeekMessage(&xmsg))
{
bStall = FALSE;
if(xmsg.wType==(REPLY_MSG|TESTPOINT_MSG))
{
// got point test back
D3DLOCKED_RECT lrt;
if(D3D_OK == lpThis->sfRenderingCanvas->LockRect(&lrt,NULL,0))
{
INT pitch = lrt.Pitch;
VOID *data;
data = lrt.pBits;
INT Y=dRound((xmsg.dptPoint.Y/(DOUBLE)100)*((DOUBLE)lpThis->iAreaHeight));
INT X=dRound((xmsg.dptPoint.X/(DOUBLE)100)*((DOUBLE)pitch));
// decide color
if(xmsg.iNum==0)
((WORD *)data)[X+Y*pitch] = 0xFFFFFFFF;
else
((WORD *)data)[X+Y*pitch] = 0xFFFFFFFF;
// message handled so remove from buffer
lpThis->lplrSubordinate->GetMessage(&xmsg);
lpThis->sfRenderingCanvas->UnlockRect();
}
}
else if(lpThis->bfOutBuffer.PutMessage(&xmsg))
{
// message sent so pull the real one off the buffer
lpThis->lplrSubordinate->GetMessage(&xmsg);
}
}
if(bRendering && lpThis->lplrSubordinate!=NULL)
{
bAssigning = TRUE;
while(bAssigning)
{
dNextX = 100*((DOUBLE)(iPointsDone%lpThis->iPitch))/((DOUBLE)lpThis->iPitch);
dNextY = 100*(DOUBLE)((INT)(iPointsDone/lpThis->iPitch))/(DOUBLE)(lpThis->iAreaHeight);
xmsg.dptPoint.X = dNextX;
xmsg.dptPoint.Y = dNextY;
//
//xmsg.iNum = 0;
//xmsg.wType = REPLY_MSG|TESTPOINT_MSG;
//
xmsg.wType = MATH_MSG|TESTPOINT_MSG;
/*D3DLOCKED_RECT lrt;
if(D3D_OK == lpThis->sfRenderingCanvas->LockRect(&lrt,NULL,0))
{
INT pitch = lrt.Pitch;
VOID *data;
data = lrt.pBits;
INT Y=dRound((dNextY/(DOUBLE)100)*((DOUBLE)lpThis->iAreaHeight));
INT X=dRound((dNextX/(DOUBLE)100)*((DOUBLE)pitch));
((WORD *)data)[X+Y*pitch] = 0xFFFFFFFF;
lpThis->sfRenderingCanvas->UnlockRect();
}
iPointsDone++;
if(iPointsDone>=iPointsTotal)
{
MessageBox(NULL,"done rendering","",0);
bRendering = FALSE;
bAssigning = FALSE;
}
*/
if(lpThis->lplrSubordinate->PutMessage(&xmsg))
{
bStall = FALSE;
iPointsDone++;
if(iPointsDone>=iPointsTotal)
{
MessageBox(NULL,"done rendering","",0);
bRendering = FALSE;
bAssigning = FALSE;
}
}
else
{
bAssigning = FALSE;
}
}
}
//if(bStall)
//Sleep(10);
}
return 0;
}
}
(仍然习惯这个论坛的代码块的东西)
编辑:
下面是我认为是在概念上类似于一个例子,虽然这个例子消耗它在生产中的消息同一个线程。
#include <Windows.h>
#include "BUFFER.h"
int main()
{
BUFFER myBuffer;
INT jobsTotal = 1024*768;
INT currentJob = 0;
INT jobsOut = 0;
XMSG xmsg;
while(1)
{
if(myBuffer.PeekMessage(&xmsg))
{
// do something with message
// ...
// if successful, remove message
myBuffer.GetMessage(&xmsg);
jobsOut--;
}
while(currentJob<jobsTotal)
{
if(myBuffer.PutMessage(&xmsg))
{
currentJob++;
jobsOut++;
}
else
{
// buffer is full at the moment
// stop for now and put more on later
break;
}
}
if(currentJob==jobsTotal && jobsOut==0)
{
MessageBox(NULL,"done","",0);
break;
}
}
return 0;
}
该示例还运行约3秒钟,而不是30分钟。
顺便说一句,如果有人知道为什么Visual Studio一直试图让我说PeekMessageA和GetMessageA而不是我定义的实际名称,那也很好。
你知道,我真的很想帮助,但是你已经有了大量的代码,这有点复杂和无关紧要,不完整。如果可以将它提取到显示问题的最小应用程序,您会得到更好的回应。 – Arelius 2011-04-21 06:42:44
PeekMessageA等的原因是你已经包含了'windows.h'头文件,这个头文件将'PeekMessage'定义为'PeekMessageA'或'PeekMessageW'的宏,这取决于你的unicode设置。你可以(1)和它一起生活,(2)使用不与Win32 API重叠的不同名称,(3)分隔你的Win32代码,它必须包含你的缓冲区代码中的windows.h,而不包括windows。h在使用缓冲区的同一个文件中,或者(4)'#undef'这些宏,并且在你想要Win32函数的任何时候使用完整的名称':: PeekMessageA'。 – 2011-04-21 13:20:39