I'm using the following code to lock an IDirect3DTexture9 for update. This piece of code works fine on my NVidia graphic card (NVidia GeForce GTX 970M) but causes memory violation on Intel integrated graphic card (Intel HD Graphics 530), even the texture is immediately unlocked and no data is written on locked region. x, y, w and h parameters are far from boundary conditions so the locked rect is totally inside the texture.
void InnerLock(int x, int y, int w, int h, D3DLOCKED_RECT *lr)
{
int left, right, top, bottom;
left = clamp(x, 0, Width() - 1);
top = clamp(y, 0, Height() - 1);
right = clamp(x + w, left + 1, Width());
bottom = clamp(y + h, top + 1, Height());
RECT rc = { left, top, right, bottom };
texture->LockRect(0, lr, &rc, D3DLOCK_NO_DIRTY_UPDATE);
// this line returns zero but causes an exception on igdumdim32.dll later
texture->AddDirtyRect(&rc)
// everything become all right when I set the whole texture as dirty region
//RECT fc = { 0, 0, Width(), Height() };
//texture->AddDirtyRect(&fc);
}
The AddDirtyRect operator returns correct value, but the error occurs later in igdumdim32.dll (I'm not sure where the error exactly occurs, maybe in the draw call).
I first found the error when using LockRect with zero flag. The program crashed on some rect parameter (in my case the error occurred when y value of the rect is large enough, but still smaller than texture height). Then I used D3DLOCK_NO_DIRTY_UPDATE and manually added dirty rect. The error only occurs when AddDirtyRect is called.
This error is reproduced on another user with intel graphics card. My operating system is Windows 10. All drivers are updated to the latest version. If you need any information please tell me. Thank you!
Related
I'm trying to create a randomly generated "planet" (circle), and I want the areas of water, land and foliage to be decided by perlin noise, or something similar. Currently I have this (psudo)code:
for (int radius = 0; radius < circleRadius; radius++) {
for (float theta = 0; theta < TWO_PI; theta += 0.1) {
float x = radius * cosine(theta);
float y = radius * sine(theta);
int colour = whateverFunctionIMake(x, y);
setPixel(x, y, colour);
}
}
Not only does this not work (there are "gaps" in the circle because of precision issues), it's incredibly slow. Even if I increase the resolution by changing the increment to 0.01, it still has missing pixels and is even slower (I get 10fps on my mediocre computer using Java (I know not the best) and an increment of 0.01. This is certainly not acceptable for a game).
How might I achieve a similar result whilst being much less computationally expensive?
Thanks in advance.
Why not use:
(x-x0)^2 + (y-y0)^2 <= r^2
so simply:
int x0=?,y0=?,r=?; // your planet position and size
int x,y,xx,rr,col;
for (rr=r*r,x=-r;x<=r;x++)
for (xx=x*x,y=-r;y<=r;y++)
if (xx+(y*y)<=rr)
{
col = whateverFunctionIMake(x, y);
setPixel(x0+x, y0+y, col);
}
all on integers, no floating or slow operations, no gaps ... Do not forget to use randseed for the coloring function ...
[Edit1] some more stuff
Now if you want speed than you need direct pixel access (in most platforms Pixels, SetPixel, PutPixels etc are slooow. because they perform a lot of stuff like range checking, color conversions etc ... ) In case you got direct pixel access or render into your own array/image whatever you need to add clipping with screen (so you do not need to check if pixel is inside screen on each pixel) to avoid access violations if your circle is overlapping screen.
As mentioned in the comments you can get rid of the x*x and y*y inside loop using previous value (as both x,y are only incrementing). For more info about it see:
32bit SQRT in 16T without multiplication
the math is like this:
(x+1)^2 = (x+1)*(x+1) = x^2 + 2x + 1
so instead of xx = x*x we just do xx+=x+x+1 for not incremented yet x or xx+=x+x-1 if x is already incremented.
When put all together I got this:
void circle(int x,int y,int r,DWORD c)
{
// my Pixel access
int **Pixels=Main->pyx; // Pixels[y][x]
int xs=Main->xs; // resolution
int ys=Main->ys;
// circle
int sx,sy,sx0,sx1,sy0,sy1; // [screen]
int cx,cy,cx0, cy0 ; // [circle]
int rr=r*r,cxx,cyy,cxx0,cyy0; // [circle^2]
// BBOX + screen clip
sx0=x-r; if (sx0>=xs) return; if (sx0< 0) sx0=0;
sy0=y-r; if (sy0>=ys) return; if (sy0< 0) sy0=0;
sx1=x+r; if (sx1< 0) return; if (sx1>=xs) sx1=xs-1;
sy1=y+r; if (sy1< 0) return; if (sy1>=ys) sy1=ys-1;
cx0=sx0-x; cxx0=cx0*cx0;
cy0=sy0-y; cyy0=cy0*cy0;
// render
for (cxx=cxx0,cx=cx0,sx=sx0;sx<=sx1;sx++,cxx+=cx,cx++,cxx+=cx)
for (cyy=cyy0,cy=cy0,sy=sy0;sy<=sy1;sy++,cyy+=cy,cy++,cyy+=cy)
if (cxx+cyy<=rr)
Pixels[sy][sx]=c;
}
This renders a circle with radius 512 px in ~35ms so 23.5 Mpx/s filling on mine setup (AMD A8-5500 3.2GHz Win7 64bit single thread VCL/GDI 32bit app coded by BDS2006 C++). Just change the direct pixel access to style/api you use ...
[Edit2]
to measure speed on x86/x64 you can use RDTSC asm instruction here some ancient C++ code I used ages ago (on 32bit environment without native 64bit stuff):
double _rdtsc()
{
LARGE_INTEGER x; // unsigned 64bit integer variable from windows.h I think
DWORD l,h; // standard unsigned 32 bit variables
asm {
rdtsc
mov l,eax
mov h,edx
}
x.LowPart=l;
x.HighPart=h;
return double(x.QuadPart);
}
It returns clocks your CPU has elapsed since power up. Beware you should account for overflows as on fast machines the 32bit counter is overflowing in seconds. Also each core has separate counter so set affinity to single CPU. On variable speed clock before measurement heat upi CPU by some computation and to convert to time just divide by CPU clock frequency. To obtain it just do this:
t0=_rdtsc()
sleep(250);
t1=_rdtsc();
fcpu = (t1-t0)*4;
and measurement:
t0=_rdtsc()
mesured stuff
t1=_rdtsc();
time = (t1-t0)/fcpu
if t1<t0 you overflowed and you need to add the a constant to result or measure again. Also the measured process must take less than overflow period. To enhance precision ignore OS granularity. for more info see:
Measuring Cache Latencies
Cache size estimation on your system? setting affinity example
Negative clock cycle measurements with back-to-back rdtsc?
I've read window(3NCURSES) man page, but I can't fully understand what mvwin() function actually does and what happens to its subwindows.
The code below creates a window with a title "Window" and a border, it also creates a subwindow that is used for printing y,x position without corrupting parent window border. It then moves the parent window to a new location, but the result is not what I expected:
After the window is moved, the outline of the windows border + text is not automatically erased at the old location.
After the move, writing text to a subwindow, outputs it at the old and new location.
After the move, parent window has new y,x coordinates, but subwindow still shows old coordinates.
I don't have a lot of experience with ncurses, and maybe I'm missing something, but this behaviour is completely illogical. If I have to manually erase windows at old location and manually move all subwindows, then this negates the benefit of using ncurses in the first place. I was expecting ncurses to automatically handle these low-level details.
My understanding of subwindows was that they are used to partition one large window into smaller non-overlapping areas. So when the parent window is moved or refreshed, all its subwindows should be moved or refreshed automatically. Is this correct?
#include <assert.h>
#include <ncurses.h>
#include <unistd.h>
int main()
{
WINDOW *win, *swin;
int lines, cols, y, x;
initscr();
keypad(stdscr, TRUE);
noecho();
// Create window
lines = 10; cols = 40;
y = 5; x = 5;
win = newwin(lines, cols, y, x);
assert(win != NULL);
// Create window border
box(win, 0, 0);
mvwprintw(win, 0, 2, " Window ");
// Create subwindow
swin = subwin(win, lines-2, cols-2, y+1, x+1);
assert(swin != NULL);
// Print window and subwindow y,x
mvwprintw(swin, 0, 0, "win y,x=%d,%d swin y,x=%d,%d\n",
getbegy(win), getbegx(win), getbegy(swin), getbegx(swin));
// Refresh
wnoutrefresh(stdscr);
wnoutrefresh(win);
wnoutrefresh(swin);
doupdate();
sleep(2);
// Move window
y = 20; x = 40;
mvwin(win, y, x);
mvwprintw(swin, 0, 0, "win y,x=%d,%d swin y,x=%d,%d\n",
getbegy(win), getbegx(win), getbegy(swin), getbegx(swin));
// Refresh
wnoutrefresh(stdscr);
wnoutrefresh(win);
wnoutrefresh(swin);
doupdate();
wgetch(swin);
endwin();
return 0;
}
Apparently not: a quick check with Solaris 10 gives the same behavior. You might find some scenario where ncurses differs unintentionally, but this is not one of those. The FAQ makes this point about compatibility:
extensions (deviations from SVr4 curses) are allowed only if they do not modify the documented/observed behavior of the API.
The Solaris manual page does not make this clear, since the only mention of subwindows is in regard to moving them:
The mvwin() routine moves the window so that the upper left-hand corner is at position (x, y). If the move would cause the window to be off the screen, it is an error and the window is not moved. Moving subwindows is allowed, but should be avoided.
The Solaris source code tells the story for that: it does nothing with subwindows. Some retesting a while back (early 2006) in response to a user's comment about differences pointed out that ncurses was incorrectly attempting to copy subwindows. That part is ifdef'd out (since it's too interesting to just delete). Since there's not much left for mvwin to do, the actual code is fairly similar.
X/Open's description of mvwin is too brief and vague to be of any use.
In my ContentPage (which takes up the whole screen), I'm setting the SizeChanged event as follows:
private void init()
{
EventHandler orientation_update_handler = (object sender, System.EventArgs e) =>
{
var binding_context = BindingContext as MyViewModel;
binding_context?.OnOrientationChanged(Width, Height, Scale);
};
SizeChanged += orientation_update_handler;
orientation_update_handler.Invoke(null, null);
// other event handler setup...
Trying to set a breakpoint within orientation_update_handler but that's not getting hit...
Anyways; set a breakpoint in OnOrientationChanged. The width and height it's receiving are both half of what they actually are, and the scale always seems to be 1.
However, in my App delegate's FinishedLaunching function, while UIScreen.MainScreen.Bounds.Width always seems to be the same as ContentPage.Width, UIScreen.MainScreen.Scale on the other hand is different to ContentPage.Scale and multiplying UIScreen.MainScreen.Bounds.Width by UIScreen.MainScreen.Scale gives me the correct screen resolution of the device.
Why is ContentPage.Scale always 1? If it were the correct value, I could multiply by the width and get the correct screen resolution.
Why is ContentPage.Scale always 1? If it were the correct value, I could multiply by the width and get the correct screen resolution.
This is a misconception. Width and height are not given in physical pixels, see here
Apple iPhone and iPad devices continue to work in units of points
and
Android is similar. Programmers work in units of density-independent pixels (dps)
in both systems 160 units equate to one inch (or 64 units translate to 1 cm).
I noticed a strange behaviour with Direct3D while doing this tutorial.
The dimensions I am getting from the Window Object differ from the configured resolution of windows. There I set 1920*1080, the width and height from the Winows Object is 1371*771.
CoreWindow^ Window = CoreWindow::GetForCurrentThread();
// set the viewport
D3D11_VIEWPORT viewport = { 0 };
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = Window->Bounds.Width; //should be 1920, actually is 1371
viewport.Height = Window->Bounds.Height; //should be 1080, actually is 771
I am developing on an Alienware 14, maybe this causes this problem, but I could not find any answers, yet.
CoreWindow sizes, pointer locations, etc. are not expressed in pixels. They are expressed in Device Independent Pixels (DIPS). To convert to/from pixels you need to use the Dots Per Inch (DPI) value.
inline int ConvertDipsToPixels(float dips) const
{
return int(dips * m_DPI / 96.f + 0.5f);
}
inline float ConvertPixelsToDips(int pixels) const
{
return (float(pixels) * 96.f / m_DPI);
}
m_DPI comes from DisplayInformation::GetForCurrentView()->LogicalDpi and you get the DpiChanged event when and if it changes.
See DPI and Device-Independent Pixels for more details.
You should take a look at the Direct3D UWP Game templates on GitHub, and check out how this is handled in Main.cpp.
I want to have a fullscreen mode that keeps the aspect ratio by adding black bars on either side. I tried just creating a display mode, but I can't make it fullscreen unless it's a pre-approved resolution, and when I use a bigger diaplay than the native resolution the pixels become messed up, and lines appeared between all of the tiles in the game for some reason.
I think I need to use FBOs to render the scenario to a texture instead of the window, and then just use a fullscreen approved resolution and render the texture properly stretched out in the center of the screen, but I just don't understand how to render to a texture in order to do that, or how to stretch an image. Could someone please help me?
EDIT
I got fullscreen working, but it makes everything all broken looking There are random lines on the edges of anything that's written to the window. There are no glitchy lines when it's in native resolution though. Here's my code:
Display.setTitle("Mega Man");
try{
Display.setDisplayMode(Display.getDesktopDisplayMode());
Display.create();
}catch(LWJGLException e){
e.printStackTrace();
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,WIDTH,HEIGHT,0,1,-1);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
try{Display.setFullscreen(true);}catch(Exception e){}
int sh=Display.getHeight();
int sw=WIDTH*sh/HEIGHT;
GL11.glViewport(Display.getWidth()/2-sw/2, 0, sw, sh);
Screenshot of the glitchy fullscreen here: http://sta.sh/021fohgnmxwa
EDIT
Here is the texture rendering code that I use to draw everything:
public static void DrawQuadTex(Texture tex, int x, int y, float width, float height, float texWidth, float texHeight, float subx, float suby, float subd, String mirror){
if (tex==null){return;}
if (mirror==null){mirror = "";}
//subx, suby, and subd are to grab sprites from a sprite sheet. subd is the measure of both the width and length of the sprite, as only images with dimensions that are the same and are powers of 2 are properly displayed.
int xinner = 0;
int xouter = (int) width;
int yinner = 0;
int youter = (int) height;
if (mirror.indexOf("h")>-1){
xinner = xouter;
xouter = 0;
}
if (mirror.indexOf("v")>-1){
yinner = youter;
youter = 0;
}
tex.bind();
glTranslatef(x,y,0);
glBegin(GL_QUADS);
glTexCoord2f(subx/texWidth,suby/texHeight);
glVertex2f(xinner,yinner);
glTexCoord2f((subx+subd)/texWidth,suby/texHeight);
glVertex2f(xouter,yinner);
glTexCoord2f((subx+subd)/texWidth,(suby+subd)/texHeight);
glVertex2f(xouter,youter);
glTexCoord2f(subx/texWidth,(suby+subd)/texHeight);
glVertex2f(xinner,youter);
glEnd();
glLoadIdentity();
}
Just to keep it clean I give you a real answer and not just a comment.
The aspect ratio problem can be solved with help of glViewport. Using this method you can decide which area of the surface that will be rendered to. The default viewport will cover the whole surface.
Since the second problem with the corrupt rendering (also described here https://stackoverflow.com/questions/28846531/sprite-game-in-full-screen-aliasing-issue) appeared after changing viewport I will give my thought about it in this answer as well.
Without knowing exactly how the rendering code for the tile background looks. I would guess that the problem is due to any differences in the resolution between the glViewport and glOrtho calls.
Example: If the glOrtho resolution is half the viewport resolution then each openGL unit is actually 2 pixels. If you then renders a tile between x=0 and x=9 and then the next one between x=10 and x=19 you will get an empty space between them.
To solve this you can change the resolution so that they are the same. Or you can render the tile to overlap, first one x=0 to x=10 second one x=10 to x=20 and so on.
Without seeing the tile rendering code I can't verify it this is the problem though.