如何搭建开发OpenGLES的开发环境,包括软件和硬件环境包括哪些平台

I'm trying to profile my renderer, and I'm seeing some weird profiling behavior that I can't explain.
I'm using a glSurfaceView, which I have set to render continuously.
This is how my onDrawFrame() is structured
public void onDrawFrame(GL10 unused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
executeAllDrawCommands();
This was behaving slowly under light load, so I created a timer class and started to profile this some. I was quite surprised by what I saw.
I put some probes on my onDrawFrame method like so:
public void onDrawFrame(GL10 unused) {
swapTimer.end();
clearTimer.start();
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
clearTimer.end();
drawTimer.start();
executeAllDrawCommands();
drawTimer.end();
swapTimer.start();
clearTimer measures the time it takes to call glClear, drawTimer measures the time it takes to run all my draw calls, and swapTimer measures the time from when onDrawFrame exits and when it returns (the time taken to call eglSwapBuffers).
When I ran a very lightly loaded scene, I got some really strange numbers I can't explain:
: 20ms (average)
clearTimer : 11ms (average)
2ms (average)
I expected the swap time to be somewhat largish, as I believe the device has vsync forced enable at ~30fps, though I don't know why the actual 'clear' call is blocking for 11 milliseconds? I thought it was just supposed to issue an asynchronous command and return?
When I draw a much more busy scene, the numbers change quite a bit:
2ms (average)
clearTimer :
0ms (average)
: 44ms (average)
In this scene my draw calls are taking so much time that it looks like its hiding a lot of the vsync period, and the block on the clear call totally goes away.
Is there any explanation for why glClear is blocking on my lightly loaded scene?
Link to my 'Timer' class source code in case someone is suspicious of my measuring technique:
I put a glFinish (and finishTimer.start()/end() around it), and it takes all the time away from glClear. Instead now glFinish takes some number of milliseconds, and glClear becomes instant.
That explains it.
When your scene is very light and the drawings are rendered very fast, the time to clear and fill the pixels with the new color will take some time (it will always take time, otherwise the renderer is behind and is currenty drawing new stuff). The newer Android devices have fillrate limits. For example, Nexus One has a fillrate lock at 30 Hz - the screen will be synced at that frequency no matter how fast your actual drawings are going. If the drawings finishes under 30 Hz the renderer will sync up with the screen. This is why you notice this delay, which you should notice even if you remove the glClear() call. The renderer is before and faster than the screen's updates.
When the renderer have many objects to draw, the synchronization will halt (given your busy scene's profile data) because the renderer is now after the screen's updates.
When you use glFinish(), it removes the time the glClear() function otherwise would cause, which, by following the fillrate logic, means that glFinish() is now the function that is ensuring synchronization with the screen.
Calculations:
Easy scene:
F = 1/T = 1/((20+11+2)*10^-3) =~ 30 Hz
The synchronization's delay time appears in your profiler. Renderer is being synchronized with the screen. That means that if you remove the glClear() or the glFinish() call, the delay would appear somewhere else.
Heavy scene:
F = 1/T = 1/((2+0+44)*10^-3)) =~ 22 Hz
The synchronization's delay time does not appear in your profiler. Renderer is after the screen's update frequency.
It seems like this is all related to vsync
That seems to be correct.
本文地址: &
我想简介我的渲染器,而我看到一些奇怪的分析行为,我无法解释。
我使用的是glSurfaceView,我已经设置为连续呈现。
这是我的 onDrawFrame()的结构
公共无效onDrawFrame(GL10未使用){
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
executeAllDrawCommands();
这是在轻负载下表现得很慢,所以我创建了一个Timer类,并开始资料这个部分。我是相当通过我所看到的感到惊讶。
我把一些探头在我的onDrawFrame方法,像这样:
公共无效onDrawFrame(GL10未使用){
swapTimer.end();
clearTimer.start();
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
clearTimer.end();
drawTimer.start();
executeAllDrawCommands();
drawTimer.end();
swapTimer.start();
clearTimer 测量它需要调用glClear的时候, drawTimer 测量需要运行所有的抽奖时间电话,和 swapTimer 测量时间从什么时候onDrawFrame退出,当它返回(所花费的时间打电话eglSwapBuffers)。
当我跑了很轻负载的场景,我得到了一些非常陌生号码,我无法解释:
swapTimer:20毫秒(平均)
clearTimer:11毫秒(平均)
drawTimer:2毫秒(平均)
我希望交换的时间是有点相当大的,因为我相信该设备已VSYNC被迫使在?30fps的,虽然我不知道为什么实际的“清除”呼叫阻塞11毫秒?我以为这只是应该发出一个异步的命令,并返回?
当我画一个更忙碌的景象,这个数字改变了不少:
swapTimer:2毫秒(平均)
clearTimer:0毫秒(平均)
drawTimer:44ms(平均)
在这个场景我绘制调用正在服用了这么多时间,它看起来像它隐藏了许多的VSYNC周期中,并在清晰的通话块完全消失。
有没有为什么glClear阻止我的轻载场景中的任何解释?
链接到我的“定时器”类的源$ C $ C,以防有人怀疑我的测量技术:
我把glfinish在(和finishTimer.start()/结束()周围),它需要所有的时间远离glClear。代替现在glfinish在需要毫秒一些数目,和glClear变得一瞬间。
这也解释了它。
当你的场景是非常轻和附图渲染速度非常快,清除和填充像素新的颜色需要一定的时间(它总是需要时间的时候,否则渲染器后面,currenty绘制新东东)。较新的Android设备有填充率限制。例如,Nexus One的30赫兹有填充率锁 - 屏幕将在该频率再怎么快你的实际的图纸会被同步。如果图纸在30赫兹完成渲染器将同步上涨的屏幕。这就是为什么你看到这种延迟,你应该,如果你删除 glClear()电话通知均匀。该渲染器之前,比屏幕的更新速度加快。
在渲染器有许多对象绘制,同步将暂停(给你的繁忙景象的个人数据),因为渲染是现在屏幕的更新后。
在使用 glfinish在(),它消除了时间 glClear()功能,否则会引起,其中通过以下的填充率的逻辑,意味着 glfinish在()是现在正在保证与画面同步的功能。
轻松的场景
F = 1 / T = 1 /((20 + 11 + 2)* 10 ^ -3)=?30赫兹
同步的延迟时间将出现在您的探查。渲染器是与屏幕同步。这意味着,如果您删除 glClear()或 glfinish在()电话,延迟将出现在其他地方。
F = 1 / T = 1 /((2 + 0 + 44)* 10 ^ -3))=?22赫兹
同步的延迟时间不会出现在您的探查。渲染是屏幕的更新频率之后。
好像这一切与垂直同步
这似乎是正确的。
本文地址: &
扫一扫关注官方微信Java开发环境搭建过程中的一些问题
在上姜国海老师的Java课之前,我自己在网上找了一些简答的Java视频课程自学,感觉在有C和C++的基础之后Java是非常好上手的一门编程语言。按照网络视频课程中的步骤,我自己试着搭建了Java开发环境,并在此之上写了一些小程序;但是在这个过程中也遇到了一些问题;昨天听了姜老师的课,发现自己其实还有很多地方是不知道的,所以列出并解答如下:
Java开发环境的搭建
在Java开发环境搭建之前,我们需要知道Java中的一些重要的基本概念:JDK, JRE, JVM
JDK(Java Development
Kit),即Java开发工具包。JDK是整个Java的核心,它包括了Java运行环境、Java工具和Java基础类库。如果没有JDK,就无法编译Java程序。[摘自百度百科]
也就是说,你写了一个XX.java程序源文件希望运行它,但是如果你没有安装JDK,那么就无法把该源文件编译成计算机可以识别和运行的二进制文件,那么程序也就无从运行。当然,如果你已有编译好的Java程序,那么只需要安装相应的JRE就可以运行。
JRE(Java Runtime Environment),即Java运行环境。JRE包括两个部分:Java Runtime
Environment 和 Java Plug-in。其中Java Runtime
Environment是一个Java平台,在此之上能够运行、测试和传输应用程序;它包括Java虚拟机(JVM)、Java核心类库和支持文件,不包含开发工具(编译器、调试器和其它工具)。而Java
Plug-in作为JRE的辅助软件,便于在浏览器中运行applet(即用Java语言编写的小应用程序,可以直接嵌入到网页中)。[摘自百度百科]
JVM(Java Virtual
Machine),即Java虚拟机。在介绍JRE的时候提到JVM是JRE的一个组成部分,而JVM本身则包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。Java虚拟机屏蔽了与具体操作系统平台相关的信息,比如你写了一个Java程序,它会首先通过Java源码编译器被编译成能够在Java虚拟机上运行的目标代码-Java字节码,然后Java字节码则会通过JIT编译器被编译成具体平台上的机器指令,这样一个Java源程序就被“翻译”成了具体平台可执行的二进制文件;所以说Java程序的编译是一个二次编译的过程。
这个过程也简单的解释了为什么说Java是一个跨平台的编程语言(通过查阅资料,整理如下)。
我们说平台无关分为两种:源代码级和目标代码级。一般的高级语言例如C、C++,它们具有一定程度的源代码级平台无关;因为用C或C++写的程序不需要进行修改只需要重新编译就可以在不同的平台上运行。而对于Java语言来说,它通过使用JVM来实现目标代码级的平台无关。前面介绍了JVM其实一个抽象的机器,附着在具体的操作系统上,而其本身具有一套虚机器指令、栈、寄存器等。Java源文件一旦被编译,生成能够在Java虚拟机上执行的Java字节码之后,当在不同的平台上运行时只需要使用解释器把Java字节码解释成具体平台上的机器指令执行即可。也就是说,使用Java编写完软件后,通过Java编译器将源代码编译为JVM的字节码,而任何一台机器只要配备了Java解释器,就可以运行这个程序,而不管这种字节码是在何种平台上生成的。
这里需要注意,我们所提到的Java编译器和Java解释器等一系列的工具本身都是依赖于具体的操作系统的,因此只有它们的输入输出都符合统一的Java规范,才能保证其跨平台性。
除了以上两点,还有第三个因素,Java针对平台设计的库,也就是所谓的Jar包,这些jar包虽然大部分都是Java编写的,但是还是有不少地方是针对平台独特设计的,比如不同操作系统之间路径的表示,从这个角度讲,平台移植后的Java字节码已经被解释器改变了。
在我的理解中,其实Java就是使用了一个二次编译的机制,使用Java编译器生成了一个JVM上的“通用的中间结果”-Java字节码,然而实际上Java程序要想执行还是需要被翻译成适合具体平台的机器指令,这是一个必须经历的过程。而在解释成机器指令的过程中通过遵循既定规范和库设计,保证解释过程的一致和正确。因此Java语言的跨平台能力究竟应该怎么样定性,在网络上有很多的讨论,这里不做深究,等以后使用的多了便自有体会。
在上面的解释中提到了JIT编译器,解释如下[摘自百度百科]&&&&&
JIT编译器,英文写作Just-In-Time Compiler,中文意思是即时编译器。
在Java编程语言和环境中,即时编译器(JIT compiler,just-in-time
compiler)是一个把Java的字节码(包括需要被解释的指令的程序)转换成可以直接发送给处理器的指令的程序。当你写好一个Java程序后,源语言的语句将由Java编译器编译成字节码,而不是编译成与某个特定的处理器硬件平台对应的指令代码(比如,Intel的Pentium微处理器或IBM的System/390处理器)。字节码是可以发送给任何平台并且能在那个平台上运行的独立于平台的代码。
1.4 Java开发环境的搭建过程
如果想要编写Java程序,并且能够对它进行编译和运行,我们就需要安装Java JDK 和 Java JRE。
我们可以从Oracle的官网上下载Java JDK
下载的过程中注意是32位还是64位版本。(这里所谓的32位和64位是指计算机CPU处理信息的方式。一般来说如果你的计算机CPU是32位的,那么就只能支持32位操作系统和其它32位的应用程序;如果你的计算机CPU是64位的,那么同时支持32位和64位操作系统以及应用程序。CPU的位数是指CPU
GPRs(General-Purpose
Registers,通用寄存器)的数据库宽度,32位的CPU可以运行32位数据指令,即处理器一次可以提取4个字节数据或指令;64位CPU同理,一次可以提取8个字节的数据或指令,显然64位CPU的处理速度要快于32位CPU的处理速度。除此之外,64位处理器的优势还体现在系统对内存的控制上。64位处理器的寻址空间最大为2的64次方,约1800万TB;而32位处理器的寻址空间最大为2的32次方,约4G。因此64位的CPU更加能够充分使用内存空间。)
安装的过程中需要注意它里面也包含了JRE部分,因此JDK和JRE的安装时一定不要设置同一安装路径,因为会存在相同文件名覆盖问题导致安装出错。
在安装完之后,我们需要修改环境变量:计算机-&属性-&高级系统设置-&高级-&环境变量
首先在系统变量中添加JDK的bin文件路径,bin文件夹下放置的是可执行的Java命令,例如java,javac等。假设JDK是安装在D:\SetupSoftware\Java_JDK_7目录下,那么就在系统变量Path中添加该目录下的bin文件路径并以分号结束:D:\SetupSoftware\Java_JDK_7\然后在用户变量中新建变量名JAVA_HOME并添加D:\SetupSoftware\Java_JDK_7;作为变量名。JAVA_HOME环境变量存储的就是Java
JDK的安装路径,系统中的一些第三方软件会引用约定好的JAVA_HOME变量来获取并使用Java。&&&&&
&&&&&&检测是否安装成功,可以在命令行中输入java,如果出现以下界面就说明安装成功了。
安装成功之后,我们就可以在编辑器例如记事本、Notepad++中编写Java源程序,通过执行javac
XX.java命令进行编译,执行java XX命令运行编译成功的程序。
当然,我们也可以选择IDE(Integrated Development Environment,集成开发环境),如eclipse,
netbeans等。集成开发环境的安装很简单,属于傻瓜式,这里不做说明。
Java编码问题说明
我们有时会遇到这样一种情况,A编写好文件传输给B,但是B打开全是乱码,这是因为A在编写文件时采用的编码规则和B浏览文件时采用的解码规则是不对应的。比如A使用汉字国际码GB2312对文件进行编写,而B使用UTF-8编码规则对传输过来的文件进行解码就会出现问题;因为汉字国际码GB2312采用的是定长编码规则,对每个汉字都采用2个字节进行编码,而UTF-8则是变长编码规则,一个中文字符占3个字节。
Java使用的是Unicode编码,它也是定长编码,每个字符都用2个字节,即16比特位表示,也就是说Java支持的字符个数最多只能有65536个,所以Java是无法做到对世界上所有的文字字符予以支持的。
说到这里,我们对上面提到的汉字国际码GB2312、UTF-8、Unicode进行详细一点的了解。
2.1 汉字国际码GB2312
GB就是汉字“国标”拼音首字母的大写组合。从1975年开始,中国为了研究汉字的使用频度,进行了大规模的统计工作,涉及到工业、农业、军事、科技、政治、经济、文学、艺术、教育、体育、医药卫生、天文地理、自然、化学、文字改革、考古等多方面的出版物,在数以亿计的浩瀚文献资料中,统计出实际使用的不同的汉字数为6335个,而其中有
3000多个汉字的累计使用频度达到了99.9%,而另外的3000多个累计频度不到0.1%,说明了常用汉字与次常用汉字的数量不足7000个,这就为国家制定汉字库标准提供了依据。
1980年颁布了《信息交换用汉字编码字符集-基本集》的国标交换码,国家标准号为:GB2312-80,选入了6763个汉字,分为两级,一级字库中有3755个,是常用汉字,二级字库中有3008个,是次常用汉字;还选入了682个字符,包含有数字、一般符号、拉丁字母、日本假名、希腊字母、俄文字母、拼音符号、注音字母等。
2.2 Unicode与UTF-8、UTF-16
Unicode是一种字符集。
在所有的字符集中,我们最为熟悉的就是ASCII码字符集。ASCII是指American Standard Code for
Information
Interchange,即美国标准信息交换代码。它由7个比特位表示的128个字符组成,包括26个英文字母的大小写、数字0-9、标点符号、非打印字符(换行符、制表符等4个)以及控制字符组成。但是ASCII码字符集是远远不能满足地球上各个国家语言字符的庞大数量需求的,因此创建了Unicode字符集。
Unicode采用2字节定长编码,那么可表示的字符数量扩展到了65536,这样就能基本满足世界各国语言的常用字符数量。但是由于Unicode采用的是定长编码,其空间利用效率并不高,因此出现了一些中间格式的字符集,它们被统称为UTF(Universal
Transformation
Format,通用转换格式);UTF-8和UTF-16就是UTF家族中的成员。它们之间如何转换以及Java中的Unicode编码机制可以分别参考博客
集成开发环境eclipse使用中的一些小技巧
打开eclipse,首先会看到的界面如下:
在这里设置好自己想要的工作区路径,如果勾选了下面的选项,那么以后的工程文件都会存放在设置的工作区路径下。
3.1 eclipse的自动编译
Project -& Build
Automatically选项默认是勾选上的,即写好的代码保存之后会自动进行编译,只需运行即可;如果想手动编译,取消勾选即可。
3.2 创建Java工程和代码编写
在创建一个新的Java工程之后,添加源文件时,勾选上public static void main(String[]
args)就会自动生成程序入口main函数。
eclipse集成开发环境还提供了很多便捷操作,比如代码自动补齐、排版缩进快捷方式等,可以在Windows
-& Preferences -& General
-& Keys中设置相应的快捷键组合。
如果忘记勾选自动生成main函数,可以输入main然后按快捷键组合Alt+/,就会弹出生成main函数窗口,点击即可:&&&&&
对于Java中包(package)概念的认识
我们在平时使用电脑的过程中经常会遇到这样一种情况,比如在目录c:\下有一个名为Report.txt的文件,里面记录的是学生A的学习报告,而学生B恰好也把自己的学习报告命名为Report.txt,那么此时再向该路径下放置B的Report.txt文件时,系统会弹出文件重名的警告提示。Java中采用了包的概念来解决这个问题。
为了更好的组织类,Java提供了包机制。包是类的容器,提供类命名空间。如果没有指定包名,那么就默认为无名包。使用package指明源文件中的类属于哪个具体的包,一般来说一个包里存放的是都是相关的类。包语句的格式为:
package关键字 包名& 即& package
pkg1[.pkg2[.pkg3...]];
从包语句中,我们可以看出包名采用的是层次结构,各层之间以点分隔。一般约定俗成的是包名都全部由小写字母构成。需要注意的是,package语句只能出现在源文件可执行语句的首行,而且一个文件里最多只能有一条package语句。
下面举个例子来说明包的使用。
在C:\Users\Administrator\Desktop\test路径下新建一个txt文件,然后改名为Student.java,在里面编写java程序:
package person.china.
public class Student{
&&&&&&&&&&&&
public static void main(String[] args){
&&&&&&&&&&&&&&&&&&&&
System.out.println("I am a student!");&
&&&&&&&&&&&
同样在C:\Users\Administrator\Desktop\exec路径下新建一个名为Teacher.java的文件,编辑内容为:
package adult.american.
import person.china.child.S
&&&&&&public
class Teacher{
&&&&&&&&&&&&
&public static void main(String[] args){
&&&&&&&&&&&&&&&&&&&&
&System.out.println("I am a teacher!");
&&&&&&&&&&&&&
4.1 编译与运行
(1)Student类
编译过程:javac -d 编译后文件存放的路径 需要编译的java源文件
需要注意的是由于源文件中定义了包,那么编译后文件实际存放的路径就是指定路径+包映射路径,在这里就是C:\Users\Administrator\Desktop\person\china\child
运行过程:java -classpath
编译好的类位置(即package中类的位置或者说是class文件所在包映射路径的上层路径)类全名
需要注意的是-classpath后面跟的一定是package中的类位置,而不是class文件实际存放的位置;由于包提供了类命名空间,所以Student类的全名其实就是person.china.child.Student
(2)Teacher类
编译过程:javac -classpath import导入其它的类位置 -d 编译后文件存放的路径 需编译的java源文件
需要注意的是由于Teacher类中导入了Student类,所以在编译的时候需要给出Student类文件位置(即Student.class文件)
运行过程:java -classpath 编译好的类位置,有多个时以分号作为分隔符 类全名
需要注意的是由于Teacher类使用了Student类,所以想要运行Teacher类不仅需要Teacher类位置也需要Student类位置。
4.2 打包与解包
一般情况下我们写了的应用程序包含很多很多的类,如果采用像上面的显示指定加载的方式会很麻烦,而且如果在其他机器上运行还需要手工打包,经传输后解压、加载和运行。我们可以使用jar命令,来简化这一过程。在命令行中输入jar回车,我们可以看到jar命令的使用方式:
下面我们把上面已经编译好的Student.class文件和Teacher.class文件进行打包:
打包过程:jar cvf
打包后的文件路径和文件名 需要打包的文件,中间用空格做为分隔
这里是把Teacher.class文件和Student.class文件进行打包,打包后的文件命名为p.jar,放置在桌面。
下面向打包后的文件p.jar中添加文件Supervisor.class,然后再解压缩p.jar:
解压之后我们可以看到Student.class文件、Teacher.class文件和Supervisor.class文件;除此之外还显示了MANIFEST.MF文件,这个文件声明了jar包中的主类,即应用程序开始运行的main函数。
后记:老师上课节奏有些快,好多东西需要课下整理;其中有很多细节的部分比如Unicode编码、UTF-8和UTF-16它们之间的转换规则究竟是什么样的还需要进一步了解和学习。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。鏌ョ湅: 9016|鍥炲?: 5
褰撳墠绂荤嚎

我要回帖

更多关于 软硬件运行环境需求 的文章

 

随机推荐