Google Open Source Peer Bonus

Update 2022: I am now a Google employee.

September 2020: I recently received a Google Open Source Peer Bonus award for my work on ANGLE/MetalANGLE project translating OpenGL ES to Metal.

Full list of winners has been updated here: https://opensource.googleblog.com/2020/10/announcing-latest-google-open-source.html

Several years ago, ANGLE was created to bring quality OpenGL (ES) implementation to Windows by translating GL draw calls & shaders to DirectX – a Microsoft proprietary graphics API. I came across it and was very impressed. Now I am contributing to it, this time doing the same thing for macOS/iOS, translating the graphics calls to Metal – Apple’s own API.

This project has brought me the most fun these days.

OpenGL ES to Metal translation library’s dev blog 2: Provoking provoking vertex

Recently while working on OpenGL ES version 3.0 to Metal translation layer (part 1 here), I discovered one obstacle that will prevent it from becoming 100% fully compliant to OpenGL ES 3.0 specification: Provoking Vertex.

OpenGL and many other Graphics APIs’ shader allows some fragment shader’s inputs to be optionally flat instead of  interpolated. In this case, the inputs will get the values from the “Provoking Vertex” of the primitive generating the fragment. OpenGL ES 3.0 by default chooses last vertex in the primitive to be “Provoking Vertex”, while most other Graphics API choose first vertex. I have no idea why they (OpenGL board) choose this convention. Why OpenGL have to be oddly different in many cases compare to other APIs like this?

There is currently no way to translate this Provoking Vertex convention between OpenGL ES and Metal without affecting the performance. ANGLE’s D3D11 translation uses geometry shader to re-order the primitive’s vertices to work-around this. However, Metal doesn’t have geometry shader, so this trick cannot be applied. So I have no choice but to keep this feature non-compliant for now.

 

OpenGL ES to Metal translation library’s development blog 1

Recently, I’m working on an open source project that translates OpenGL ES draw calls to Metal draw calls on Apple platforms (iOS & macOS). It is a fork of Google’s ANGLE project: https://github.com/kakashidinho/metalangle. This project is named MetalANGLE for now. Inspired by cross-API translation libraries such as MoltenVK (Vulkan to Metal), DXVK (DirectX to Vulkan), etc. that became increasingly popular recently. Though I think MetalANGLE won’t be as popular as those projects since many people have moved on from OpenGL by now.

There were many reasons leading me to start this project:

  1. Apple have deprecated OpenGL (ES) on their platforms and urge everyone to use Metal instead. Hence, developing a translation layer to convert OpenGL draw calls to Metal would help cross-platform apps (some of which might have been developed long ago) survive future removal of OpenGL from Apple platforms.
  2. Apple’s native OpenGL performance has become noticeably slower after recent OS updates. I don’t know the exact reason, but probably because it has been deprecated and they don’t allocate much resource to maintain or update it anymore.

Read more …

 

 

Amortized constant

Recently, I encountered a question about a data structure similar to a dynamic array.  When you push a new element to a dynamic array (e.g. std::vector in C++ and ArrayList in java) and if it doesn’t have anymore storage, a reallocation will occur.

I remember last time when I was 2nd year student, a very 1st book I read about game engine programming told me how to dynamically increase the storage of dynamic array by increasing its size by a fixed amount (example: increase storage size by 5 elements, hence you are allowed to push 5 more elements before next resize, and so on).

I kept adhering to this implementation for a while until at some point, I realized it is not the most efficient way of resizing the array. Actually I was told it is that way, and hadn’t really thought of why. So let’s analyse its performance complexity today.

Read more …

 

My Google Onsite Interview experience

First and foremost, I didn’t expect to be invited for an interview with Google (GG) at all. A GG recruiter contacted me telling there is an opening Software Engineer (SWE) position, and asked whether I want to participate or not. Probably, they are looking for more SWE during this period. A little doubt since I know in order to pass their interviews, you have to prepare a lot, I know some have to dedicate their 6 months just to be ready for GG gruesome interview questions. Ultimately, I said yes, why not, I might not pass, but that will be a good learning experience.

After 1st Phone Screen interview, I prepared 3 weeks for 2nd and true Technical Phone Screen interview round with a GG engineer from New York. I passed it since the questions are quite forgiving. One recursion and one Dynamic Programming question.

After a week, the recruiter contacted me and said I will be invited for onsite interviews at GG office in Singapore. This typically the last round deciding whether you get hired or not. There will be 5 interview sessions, each in 45 minutes conducted by different GG engineers asking algorithm and design questions. All 5 will be done in a single day. GG generally allow you to choose as many months to prepare as possible before the actual interviews. I chose a month to get myself ready. Thought I was only truly able to use half of that time to practice my problem solving skills.

So now enter the actual onsite interviews:

  • First interviewer is quite nice, he asked whether I am nervous or not, and said it’s OK. For the actual question, it’s an array based question. The type of questions will generally lead you to a Dynamic Programming (DP) solution. After discussing with the interviewer about my Memorization variant of DP, I suddenly realized there is a better approach without using DP at all, it doesn’t use memory and has better runtime. So that’s it, the 1st interview went quite well, boosted my confident a bit.
  • Second interview had two string based questions, first one is easy, the second one is tougher. For the second question, within the allowed time frame, I was able to come up with some what a two pointers solution, that’s the best I can think of at that moment. In the end, I couldn’t derive to a more optimal approach. Also I think I had some difficulties communicating with the interviewer. Honestly, this interview did impact my morale.
  • The 3rd one was a design challenge. Some kinds of file content parsing. For this challenge, I used state machine approach. I think it’s open ended question. Some followed up Q/A after that and some chit chats. The interviewer is very friendly, of course the design interview is supposed to be more lighthearted than algorithmic interviews.
  • So after the 3 interviews, I had a lunch with a GG engineer in their campus. He is not one of the interviewers. We had nice conversations, about video games, console emulators and works.
  • After the lunch, 4th interviewer invited me for another session. This time she asked me to implement a parser for a specific language, but only a subset of it syntax, not the full version. I implemented a state machine based parser which handles more general cases than what she asked for. And it took too damn long to code. In the end, she said my solution could be simpler as told me that I overthought too much. I think it was a mistake, I think there was supposedly a harder version of this question which we hadn’t enough time to tackle.
  • So then the last interviewer came in. And the communication difficulties happened again. From the look of it, he seemed to not enjoy my problem solving approach. There was some disappointments on his face. Unfortunately, that made me enter nervous mode. I came up with a linear solution, but seemed my explanation was not convincing enough for him. Then I coded, with nervous mode, I think it’s obvious that I left some bugs here and there. I’m not sure there was supposed to be another question or not. And his disappointing face made me think my final solution was not correct. (After going home and discussing with my friend who is an active competitive programmer, and is better in algorithm than I am. This time with a calm mind and more clear and refined explanation, we concluded that my solution is correct. However, I know being correct or not is not enough. You have to be able to convince your interviewer with good explanation of your thoughts. For this reason, I think I failed that interview).

That’s the end of the interviews, the interviewer walked me through the exit door, and that’s it. I couldn’t stop thinking I could have done better, but what’s being done is done. Overall, it’s still a good experience for me.

 

 

I thought things could be better

I though everything will be fine. Doing what I liked to do in the past. Let the time flow. I could find myself again like I always could.

But in the end, I haven’t never truly woken up. I don’t want to wake up. Every time I do, the ghost of the past comes back and haunts me. The questions keep coming back. Perhaps I chose a wrong path? It’s not because of outside reasons. All happened because of me. How can I truly forgive myself? I tried so hard, but I couldn’t. I keep letting people and myself disappointed.

The only thing I could do is writing my current thoughts here. Just hoping someday, people will understand why I am like this.