Metal // Reading multisampled depth texture - macos

For some post-rendering effects I need to read the depth-texture. This works fine as long as multi-sampling is turned off. But with multi-sampling I have trouble reading the texture.
Trying to use the multisample-texture in the shader though an depth2d_ms argument the compiler will fail at run time with an error message "Internal Compiler Error".
I found that with OpenGL you'd first blit the multisample depth buffer to a resolved depth buffer to read the sampled values, but with Metal I get an assertion error stating that sample counts of blit textures need to match, so there is no chance blitting 4 samples into 1.
So how would I read sampled or unsampled values from the depth buffer whilst using multi-sampling?

I don't know the answer. But suggest to try below solution:
Set the storeAction of MTLRenderPassDepthAttachmentDescriptor as below:
depthAttachment.storeAction = MTLStoreActionMultisampleResolve;
and also set its resolveTexture to another texture:
depthAttachment.resolveTexture = targetResolvedDepthTexture.
at last, try to read the targetResolvedDepthTexture content.

MSAA depth resolve is only supported in iOS GPU Family 3 v1 (A9 GPU on iOS 9).
Take a look on the Feature Availability document:
https://developer.apple.com/library/ios/documentation/Miscellaneous/Conceptual/MetalProgrammingGuide/MetalFeatureSetTables/MetalFeatureSetTables.html#//apple_ref/doc/uid/TP40014221-CH13-DontLinkElementID_8

Related

Vulkan/OpenGL subpasses that fetch more than single fragment

So, Vulkan introduced subpasses and opengl implelemts similar behaviour with ARM_framebuffer_fetch
In the past, I have used framebuffer_fetch successfully for tonemapping post-effect shaders.
Back then the limitation was that one could only read the contents of the framebuffer at the location of the currently rendered fragment.
Now, what I wonder is whether there is any way by now in Vulkan (or even OpenGL ES) to read from multiple locations (for example to implement a blur kernel) without having a tiled hardware to store/load to RAM.
In theory I guess it should be possible, the first pass wpuld just need to render slightly larger than the blur subpass, based on kernel size (so for example if kernel size was 4 pixels then the tile resolved would need to be 4 pixels smaller than the in-tile buffer sizes) and some pixels would have to be rendered redundantly (on the overlaps of tiles).
Now, is there a way to do that?
I seem to recall having seen some Vulkan instruction related to subpasses that would allow to define the support size (which sounded like what I’m looking for now) but I can’t recall where I saw that.
So my questions:
With Vulkan on a mobile tiled renderer architecture, is it possible to forward-render some geometry and the render a full-screen blur over it, all within a single in-tile pass (without the hardware having to store the result of the intermediate pass to ram first and then load the texture from ram when bluring)? If so, how?
If the answer to 1 is yes, can it also be done in OpenGL ES?
Short answer, no. Vulkan subpasses still have the 1:1 fragment-to-pixel association requirements.

Three.js: Shader won't compile with gl.MAX_TEXTURE_IMAGE_UNITS textures

I'm using Three.js to build a scene in which I want to pack the maximum number of quads into each draw call. On my machine, the limiting factor is the number of textures I can display in each draw call.
What confuses me is that gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) returns 16, but if I try to pass exactly 16 textures into my THREE.RawShaderMaterial, I get the following error:
THREE.WebGLProgram: shader error: 0 gl.VALIDATE_STATUS false
gl.getProgramInfoLog ERROR: Implementation limit of 16 active fragment
shader samplers (e.g., maximum number of supported image units)
exceeded, fragment shader uses 17 samplers
If I pass exactly 15 textures in, the scene renders fine (though a texture is missing of course).
My question is: Does Three.js add an additional texture to each draw call somewhere? If not, does anyone know what might account for this off by one problem? Any help others can offer on this question would be greatly appreciated.
My question is: Does Three.js add an additional texture to each draw call somewhere? If not, does anyone know what might account for this off by one problem?
Yes, most of the materials inject various samplers related to various maps. It can be something as straightforward as an "albedo map" but it could also be a shadow map for example. Use RawShaderMaterial if you don't want three to inject stuff.
Well that's embarrassing. It turns out I was passing 16 textures to the shader, but I was trying to access texture2D(textures[16]) and it was this attempt to read from a sampler index > max textures that threw this error.
It's interesting that passing a material array longer than gl.MAX_TEXTURE_IMAGE_UNITS does not throw an error -- it's trying to access index value > gl.MAX_TEXTURE_IMAGE_UNITS-1 that throws an error.

Not calling glclear results in weird artifacts

im wanting to NOT call glClear for the depth or color bit because i want to be able to see all the previously rendered frames. And it does work except it repeats the model all over the x and y axis, and also causes some strange grey blocky lines. Is there a way to accomplish this? Im using opengl es 3 on android. Thank you for any help.
The contents of the default framebuffer at the start of a frame is undefined, especially on tile-based renderers, which most of the mobile GPUs are. Your "repeats" in the X and Y axis are likely just showing how big the tiles are on your particular GPU (e.g. it's just dumping out whatever is in the GPU local tile RAM, repeated N times to completely cover the screen).
If you want to render on top of the previous frame you need to configure the rendering context configuration to use EGL_BUFFER_PRESERVED (the default is EGL_BUFFER_DESTROYED). E.g:
eglSurfaceAttrib(m_display, m_surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
Note 1: this will incur some overhead (the surface is effectively copied back into tile-local memory), whereas starting with a surface discard or invalidate, or a clear is usually free.
Note 2: this will only preserve color data; there is no means to preserve depth or stencil across frames for the default framebuffer.

OpenGL ES Vertex buffer objects don't work with my drawTexture method

I have tried for some time now to use the Vertex Buffer Objects to render a texture on the screen. I have a working function here that use the classic method:
https://github.com/batiste/sdl2-opengl-es/blob/master/common.c#L546
This first method works. A bit down there is the Vertex Buffer modified version:
https://github.com/batiste/sdl2-opengl-es/blob/master/common.c#L586
I have tried many different ways, checked all the inputs and search on this site for similar problems but without success. I need a fresh, expert eye on this.
The second part of the question is about performance. I want to use then to display some simple textures on my Android phone. What kind of speed up can I expect from using vertex buffer? Is it really worth using for 2 triangles?
glVertexAttribPointers last parameter is a byte offset into the buffer. So looks like there's a sizeof(GLfloat) factor missing.

Max size for Vertex Buffer Objects (OpenGL ES 2.0)

Is there a max size for vertex buffer objects binded to GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER???
Originally, I was drawing a mesh composed of 16 submeshes. For each submesh, I created a vertex buffer and during the rendering phase, I called glDrawElements.
This worked fine on the iOS simulator, but when I tried to render to my device, the screen flashes constantly and the meshes aren't displayed.
I then did some reading and found that you shouldn't call glDrawElements too many times during a render phase.
I tried to combine all of my submeshes into one vertex buffer.
The buffer bound to GL_ARRAY_BUFFER contains 3969 vertices, where each vertex contains 20 floats. So the size of this buffer is 317520 bytes.
The indices bound to GL_ELEMENT_ARRAY_BUFFER are 16425 shorts. The size of this buffer is therefore 32850 bytes.
On the OpenGL wiki, it says that "1MB to 4MB is a nice size according to one nVidia document" for a Vertex Buffer Object.
I printed out the result of glGetError after binding each buffer object, and calling glDrawElements, and I don't see any errors.
However, my meshes aren't correctly displayed. It seems as though only the first mesh gets correctly drawn. Is there anything fishy in the way I've implemented this? I didn't want to make this question too long so if there's any extra information you need to answer this question let me know. If there's nothing in theory that seems wrong, perhaps I've just made a mistake in implementing it.
There is a maximum size, in the sense that the GPU can always issue a GL_OUT_OF_MEMORY error. But other than that, no.
See this:
http://www.sunsetlakesoftware.com/2008/08/05/lessons-molecules-opengl-es
There are some natural limits using smaller data types, like obviously ~65000 for using shorts as indexes.
But more importantly there is some additional help in the link, which is a very good tutorial, and includes some anecdotal evidence that shorts up to the natural functional limit work.
I know it is too late to answer this question. However, I wish the answer helps someone!
Based on The Specification of OpenG Graphics System (Version 4.5 (Core Profile) - May 28, 2015), it states:
"There is no limit to the number of vertices that may be specified, other than the size of the vertex arrays." please see page 322.
Sorry, also as Nicol Bolas mention here:
https://stackoverflow.com/a/7369392/4228827
Cheers,
Naif

Resources