gpt4 book ai didi

java - 奇怪的 BufferStrategy 问题 - 游戏仅在 Intel GPU 上运行快速

转载 作者:IT老高 更新时间:2023-10-28 21:20:17 27 4
gpt4 key购买 nike

我遇到了一个非常奇怪的问题,我试图寻找答案几天和几天。我的游戏刚刚有了一个新的粒子系统,但速度太慢而无法播放。不幸的是,BufferedImage 转换非常缓慢。爆炸效果由大约 200 个从 .png 文件加载的白色 Sprite 组成,它们随机旋转、缩放和着色,以随机速度移动。

我尝试使用三重/双缓冲来提高性能,但遇到了一些问题。

我的第一次尝试是使用绘制游戏的 JPanel。我在 JFrame 的类 (Main) 中设置了缓冲区,然后在 Game (extends JPanel) 类中完成了绘图,但是没有 Graphics g = bufferstrategy.getDrawGraphics();。然后,在绘图方法结束时,如果缓冲区没有丢失,我会显示它。缓冲区总是“丢失”,因为我没有使用它的 Graphics 对象进行绘图。但!游戏跑得飞快!实际使用中无缓冲!但是怎么做呢?

这次尝试最终没有出现图形错误,并且性能得到了巨大提升 - 但仅限于 nVidia/AMD 卡。英特尔 GPU 无法处理此问题,屏幕呈白色闪烁。

所以,我最终正确设置和使用了 BufferStrategy。Game 类现在扩展了 Canvas,而不是 JPanel,因为从 JFrame 中获取 Graphics,并使用它在 JPanel 上绘制以偏移结束,因为它在标题栏下绘制。仍然很快,修复 60 FPS。

现在,当我在 JFrame(主类)中创建 BufferStrategy 时,根本没有图片。我通过在 Game 类(Canvas)中设置 BufferStrategy 来纠正这个问题。现在画面是正确的,但是游戏本身就像蜗牛一样慢。一次爆炸将 FPS 降至约 10,但仅限于 nVidia/AMD。讽刺。即使是旧的英特尔 GPU 也能以 60 FPS 的速度处理它,我设法在 5-6 年的集成英特尔 GPU 上以 60 FPS 的速度让 10000 个粒子运动。发生爆炸时,我的卡负载高达 100%。

这是我的主要代码(整个代码不清楚而且很长):

public class Game extends Canvas {
-snip-
public void tick() {
BufferStrategy bf = getBufferStrategy();
Graphics g = null;
try {
g = bf.getDrawGraphics();
paint(g);
} finally {
g.dispose();
}
if (!bf.contentsLost()) {
bf.show();
} else {
System.err.println("Buffer lost!");
}
Toolkit.getDefaultToolkit().sync();
}
public void setBuffers() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();

if (gc.getBufferCapabilities().isMultiBufferAvailable()) {
createBufferStrategy(3);
System.out.println("Triple buffering active");
} else {
createBufferStrategy(2);
System.err.println("Triple buffering not supported by the GPU");
System.out.println("Double buffering active");
}
System.out.println("FullScreen required: " + getBufferStrategy().getCapabilities().isFullScreenRequired());
System.out.println("Page flipping: " + getBufferStrategy().getCapabilities().isPageFlipping());
}
public void paint(Graphics g) {
super.paint(g);
//set up RenderingHints, draw stuff
}
-snip snip-
}

当然,我会在游戏一开始就调用 setBuffers()。

我希望你能帮助我,这个问题很重要,因为我认为使用 VolatileImage 不会提高性能,因为图像处理需要使用 BufferedImage 来完成。我敢打赌我错过了一些微不足道的事情,或者做错了事情。

这是我的电脑规范,只是为了表明这不是硬件问题:英特尔酷睿 i7-3770k @ 4.3GHz,英伟达 GTX 460,12GB 内存

“快速”计算机:英特尔酷睿 2 双核 @ 2.7 GHz,集成英特尔显卡,2 GB 内存

感谢您的帮助和时间! :)

编辑VolatileImage 有帮助吗?如果我没看错的话,图像处理必须使用 BufferedImages 来完成,但绘制它们很慢。

最佳答案

这里有几件事要检查:


如果不知道 setBuffers 函数的控制台/错误输出,就很难判断。英特尔是否使用 createBufferStrategy(2);而 NV 使用 createBufferStrategy(3); ?如果是这样,这可能是它使用额外内存的问题的一部分。


您尝试过 java2d System.properties 了吗? http://docs.oracle.com/javase/1.5.0/docs/guide/2d/flags.html特别是用于调试的跟踪属性。

仅限 Windows

System.setProperty("sun.java2d.transaccel", "True");
System.setProperty("sun.java2d.d3d", "True");
System.setProperty("sun.java2d.ddforcevram", "True");

所有平台

System.setProperty("sun.java2d.opengl", "True");

用于调试

System.setProperty("sun.java2d.trace", "timestamp,log,count");
//// -Dsun.java2d.trace=[log[,timestamp]],[count],[out:<filename>],[help],[verbose]

Toolkit.getDefaultToolkit().sync();实际上并不强制监控 VSync,这是由 BufferCapabilities(在您的 setBuffers 函数中)完成的。

    BufferStrategy bf = getBufferStrategy();
if (bf != null) {
BufferCapabilities caps = bf.getCapabilities();
try {
Class ebcClass = Class.forName(
"sun.java2d.pipe.hw.ExtendedBufferCapabilities");
Class vstClass = Class.forName(
"sun.java2d.pipe.hw.ExtendedBufferCapabilities$VSyncType");

Constructor ebcConstructor = ebcClass.getConstructor(
new Class[] { BufferCapabilities.class, vstClass });
Object vSyncType = vstClass.getField("VSYNC_ON").get(null);

BufferCapabilities newCaps = (BufferCapabilities)ebcConstructor.newInstance(
new Object[] { caps, vSyncType });

createBufferStrategy(2, newCaps);

// TODO: if success, setCanChangeRefreshRate(false) and setRefreshRate(60).
// Possibly override refreshRateSync()?
}
catch (Throwable t) {
// Ignore
t.printStackTrace();
}
}

编辑此代码来自 (http://pulpcore.googlecode.com/hg-history/3c4001969922b93048e0a166395115df059a2059/src/pulpcore/platform/applet/BufferStrategySurface.java)

此外,您应该在 Canvas 构造函数运行并将其添加到 JFrame 之后调用 setBuffers。


我“比较确定”你不需要调用 super.paint(g);我不知道它是否是导致您的具体问题的原因,但您应该从您的绘画功能中删除该行。


虽然您没有显示代码,但您使用 200 个随机移动 Sprite 的爆炸机制可能是导致错误的主要原因。计算出您希望一次在屏幕上发生的最大爆炸次数,并事先生成这些 Sprite N * 200,将它们放入数组列表 ArrayList(N) 中,然后在您的代码中循环引用它们。 ExplosionClass = explodeList.get(currentExplosionIndex % explodeList.size());

关于java - 奇怪的 BufferStrategy 问题 - 游戏仅在 Intel GPU 上运行快速,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14528657/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com