Selaa lähdekoodia

VPRT support for D3D11, D3D12, GL (#2507)

* glsl-optimizer: whitelist ARB_shader_viewport_layer_array_enable

* D3D11: remove duplicate structs and enums

* D3D11: report BGFX_CAPS_VIEWPORT_LAYER_ARRAY

* D3D12: report BGFX_CAPS_VIEWPORT_LAYER_ARRAY

* GL: support for BGFX_CAPS_VIEWPORT_LAYER_ARRAY

* D3D11: multi-layer MSAA resolve

* D3D12: multi-layer MSAA resolve

* D3D12: fix binding multi-layer resolved textures

* GL: fix multi-layer rendertarget creation
pezcode 4 vuotta sitten
vanhempi
sitoutus
2c21f68998

+ 2 - 2
3rdparty/glsl-optimizer/src/glsl/builtin_variables.cpp

@@ -838,9 +838,9 @@ builtin_variable_generator::generate_vs_special_vars()
       add_system_value(SYSTEM_VALUE_INSTANCE_ID, int_t, "gl_InstanceIDEXT", glsl_precision_high);
    if (state->ARB_draw_instanced_enable || state->is_version(140, 300))
 	   add_system_value(SYSTEM_VALUE_INSTANCE_ID, state->metal_target ? uint_t : int_t, "gl_InstanceID", glsl_precision_high);
-   if (state->AMD_vertex_shader_layer_enable)
+   if (state->AMD_vertex_shader_layer_enable || state->ARB_shader_viewport_layer_array_enable)
       add_output(VARYING_SLOT_LAYER, int_t, "gl_Layer", glsl_precision_high);
-   if (state->AMD_vertex_shader_viewport_index_enable)
+   if (state->AMD_vertex_shader_viewport_index_enable || state->ARB_shader_viewport_layer_array_enable)
       add_output(VARYING_SLOT_VIEWPORT, int_t, "gl_ViewportIndex", glsl_precision_high);
    if (compatibility) {
       add_input(VERT_ATTRIB_POS, vec4_t, "gl_Vertex", glsl_precision_high);

+ 29 - 28
3rdparty/glsl-optimizer/src/glsl/glsl_parser_extras.cpp

@@ -516,34 +516,35 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
 
    /* ARB extensions go here, sorted alphabetically.
     */
-   EXT(ARB_arrays_of_arrays,           true,  false,     ARB_arrays_of_arrays),
-   EXT(ARB_compute_shader,             true,  false,     ARB_compute_shader),
-   EXT(ARB_conservative_depth,         true,  false,     ARB_conservative_depth),
-   EXT(ARB_derivative_control,         true,  false,     ARB_derivative_control),
-   EXT(ARB_draw_buffers,               true,  false,     dummy_true),
-   EXT(ARB_draw_instanced,             true,  false,     ARB_draw_instanced),
-   EXT(ARB_explicit_attrib_location,   true,  false,     ARB_explicit_attrib_location),
-   EXT(ARB_explicit_uniform_location,  true,  false,     ARB_explicit_uniform_location),
-   EXT(ARB_fragment_coord_conventions, true,  false,     ARB_fragment_coord_conventions),
-   EXT(ARB_fragment_layer_viewport,    true,  false,     ARB_fragment_layer_viewport),
-   EXT(ARB_gpu_shader5,                true,  false,     ARB_gpu_shader5),
-   EXT(ARB_sample_shading,             true,  false,     ARB_sample_shading),
-   EXT(ARB_separate_shader_objects,    true,  false,     dummy_true),
-   EXT(ARB_shader_atomic_counters,     true,  false,     ARB_shader_atomic_counters),
-   EXT(ARB_shader_bit_encoding,        true,  false,     ARB_shader_bit_encoding),
-   EXT(ARB_shader_image_load_store,    true,  false,     ARB_shader_image_load_store),
-   EXT(ARB_shader_stencil_export,      true,  false,     ARB_shader_stencil_export),
-   EXT(ARB_shader_texture_lod,         true,  false,     ARB_shader_texture_lod),
-   EXT(ARB_shading_language_420pack,   true,  false,     ARB_shading_language_420pack),
-   EXT(ARB_shading_language_packing,   true,  false,     ARB_shading_language_packing),
-   EXT(ARB_texture_cube_map_array,     true,  false,     ARB_texture_cube_map_array),
-   EXT(ARB_texture_gather,             true,  false,     ARB_texture_gather),
-   EXT(ARB_texture_multisample,        true,  false,     ARB_texture_multisample),
-   EXT(ARB_texture_query_levels,       true,  false,     ARB_texture_query_levels),
-   EXT(ARB_texture_query_lod,          true,  false,     ARB_texture_query_lod),
-   EXT(ARB_texture_rectangle,          true,  false,     dummy_true),
-   EXT(ARB_uniform_buffer_object,      true,  false,     ARB_uniform_buffer_object),
-   EXT(ARB_viewport_array,             true,  false,     ARB_viewport_array),
+   EXT(ARB_arrays_of_arrays,            true,  false,     ARB_arrays_of_arrays),
+   EXT(ARB_compute_shader,              true,  false,     ARB_compute_shader),
+   EXT(ARB_conservative_depth,          true,  false,     ARB_conservative_depth),
+   EXT(ARB_derivative_control,          true,  false,     ARB_derivative_control),
+   EXT(ARB_draw_buffers,                true,  false,     dummy_true),
+   EXT(ARB_draw_instanced,              true,  false,     ARB_draw_instanced),
+   EXT(ARB_explicit_attrib_location,    true,  false,     ARB_explicit_attrib_location),
+   EXT(ARB_explicit_uniform_location,   true,  false,     ARB_explicit_uniform_location),
+   EXT(ARB_fragment_coord_conventions,  true,  false,     ARB_fragment_coord_conventions),
+   EXT(ARB_fragment_layer_viewport,     true,  false,     ARB_fragment_layer_viewport),
+   EXT(ARB_gpu_shader5,                 true,  false,     ARB_gpu_shader5),
+   EXT(ARB_sample_shading,              true,  false,     ARB_sample_shading),
+   EXT(ARB_separate_shader_objects,     true,  false,     dummy_true),
+   EXT(ARB_shader_atomic_counters,      true,  false,     ARB_shader_atomic_counters),
+   EXT(ARB_shader_bit_encoding,         true,  false,     ARB_shader_bit_encoding),
+   EXT(ARB_shader_image_load_store,     true,  false,     ARB_shader_image_load_store),
+   EXT(ARB_shader_stencil_export,       true,  false,     ARB_shader_stencil_export),
+   EXT(ARB_shader_texture_lod,          true,  false,     ARB_shader_texture_lod),
+   EXT(ARB_shader_viewport_layer_array, true,  false,     ARB_shader_viewport_layer_array),
+   EXT(ARB_shading_language_420pack,    true,  false,     ARB_shading_language_420pack),
+   EXT(ARB_shading_language_packing,    true,  false,     ARB_shading_language_packing),
+   EXT(ARB_texture_cube_map_array,      true,  false,     ARB_texture_cube_map_array),
+   EXT(ARB_texture_gather,              true,  false,     ARB_texture_gather),
+   EXT(ARB_texture_multisample,         true,  false,     ARB_texture_multisample),
+   EXT(ARB_texture_query_levels,        true,  false,     ARB_texture_query_levels),
+   EXT(ARB_texture_query_lod,           true,  false,     ARB_texture_query_lod),
+   EXT(ARB_texture_rectangle,           true,  false,     dummy_true),
+   EXT(ARB_uniform_buffer_object,       true,  false,     ARB_uniform_buffer_object),
+   EXT(ARB_viewport_array,              true,  false,     ARB_viewport_array),
 
    /* KHR extensions go here, sorted alphabetically.
     */

+ 2 - 0
3rdparty/glsl-optimizer/src/glsl/glsl_parser_extras.h

@@ -426,6 +426,8 @@ struct _mesa_glsl_parse_state {
    bool ARB_shader_stencil_export_warn;
    bool ARB_shader_texture_lod_enable;
    bool ARB_shader_texture_lod_warn;
+   bool ARB_shader_viewport_layer_array_enable;
+   bool ARB_shader_viewport_layer_array_warn;
    bool ARB_shading_language_420pack_enable;
    bool ARB_shading_language_420pack_warn;
    bool ARB_shading_language_packing_enable;

+ 1 - 0
3rdparty/glsl-optimizer/src/glsl/standalone_scaffolding.cpp

@@ -93,6 +93,7 @@ void initialize_context_to_defaults(struct gl_context *ctx, gl_api api)
    ctx->Extensions.ARB_shader_bit_encoding = true;
    ctx->Extensions.ARB_shader_stencil_export = true;
    ctx->Extensions.ARB_shader_texture_lod = true;
+   ctx->Extensions.ARB_shader_viewport_layer_array = true;
    ctx->Extensions.ARB_shading_language_420pack = true;
    ctx->Extensions.ARB_shading_language_packing = true;
    ctx->Extensions.ARB_texture_cube_map_array = true;

+ 1 - 0
3rdparty/glsl-optimizer/src/mesa/main/mtypes.h

@@ -1447,6 +1447,7 @@ struct gl_extensions
    GLboolean ARB_shader_image_load_store;
    GLboolean ARB_shader_stencil_export;
    GLboolean ARB_shader_texture_lod;
+   GLboolean ARB_shader_viewport_layer_array;
    GLboolean ARB_shading_language_packing;
    GLboolean ARB_shading_language_420pack;
    GLboolean ARB_shadow;

+ 1 - 0
src/glimports.h

@@ -308,6 +308,7 @@ GL_IMPORT______(true,  PFNGLENDQUERYPROC,                          glEndQuery);
 GL_IMPORT______(false, PFNGLFINISHPROC,                            glFinish);
 GL_IMPORT______(false, PFNGLFLUSHPROC,                             glFlush);
 GL_IMPORT______(true,  PFNGLFRAMEBUFFERRENDERBUFFERPROC,           glFramebufferRenderbuffer);
+GL_IMPORT______(true,  PFNGLFRAMEBUFFERTEXTUREPROC,                glFramebufferTexture);
 GL_IMPORT______(true,  PFNGLFRAMEBUFFERTEXTURE2DPROC,              glFramebufferTexture2D);
 GL_IMPORT______(true,  PFNGLFRAMEBUFFERTEXTURELAYERPROC,           glFramebufferTextureLayer);
 GL_IMPORT______(false, PFNGLFRONTFACE,                             glFrontFace);

+ 29 - 33
src/renderer_d3d11.cpp

@@ -1273,11 +1273,6 @@ namespace bgfx { namespace d3d11
 				if (m_featureLevel == D3D_FEATURE_LEVEL_10_0
 				||  m_featureLevel == D3D_FEATURE_LEVEL_10_1)
 				{
-					struct D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS
-					{
-						BOOL ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x;
-					};
-
 					D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS data;
 					HRESULT hr = m_device->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &data, sizeof(data) );
 					if (SUCCEEDED(hr)
@@ -1298,13 +1293,8 @@ namespace bgfx { namespace d3d11
 				}
 				else
 				{
-					struct D3D11_FEATURE_DATA_D3D9_SIMPLE_INSTANCING_SUPPORT
-					{
-						BOOL SimpleInstancingSupported;
-					};
-
 					D3D11_FEATURE_DATA_D3D9_SIMPLE_INSTANCING_SUPPORT data;
-					HRESULT hr = m_device->CheckFeatureSupport(D3D11_FEATURE(11) /*D3D11_FEATURE_D3D9_SIMPLE_INSTANCING_SUPPORT*/, &data, sizeof(data) );
+					HRESULT hr = m_device->CheckFeatureSupport(D3D11_FEATURE_D3D9_SIMPLE_INSTANCING_SUPPORT, &data, sizeof(data) );
 					if (SUCCEEDED(hr)
 					&&  data.SimpleInstancingSupported)
 					{
@@ -1315,13 +1305,8 @@ namespace bgfx { namespace d3d11
 				// shadow compare is optional on 9_1 through 9_3 targets
 				if (m_featureLevel <= D3D_FEATURE_LEVEL_9_3)
 				{
-					struct D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT
-					{
-						BOOL SupportsDepthAsTextureWithLessEqualComparisonFilter;
-					};
-
 					D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT data;
-					HRESULT hr = m_device->CheckFeatureSupport(D3D11_FEATURE(9) /*D3D11_FEATURE_D3D9_SHADOW_SUPPORT*/, &data, sizeof(data) );
+					HRESULT hr = m_device->CheckFeatureSupport(D3D11_FEATURE_D3D9_SHADOW_SUPPORT, &data, sizeof(data) );
 					if (SUCCEEDED(hr)
 					&&  data.SupportsDepthAsTextureWithLessEqualComparisonFilter)
 					{
@@ -1329,6 +1314,17 @@ namespace bgfx { namespace d3d11
 					}
 				}
 
+				// support for SV_ViewportArrayIndex and SV_RenderTargetArrayIndex in the vertex shader is optional
+				{
+					D3D11_FEATURE_DATA_D3D11_OPTIONS3 data;
+					HRESULT hr = m_device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &data, sizeof(data) );
+					if (SUCCEEDED(hr)
+					&&  data.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer)
+					{
+						g_caps.supported |= BGFX_CAPS_VIEWPORT_LAYER_ARRAY;
+					}
+				}
+
 				for (uint32_t ii = 0; ii < TextureFormat::Count; ++ii)
 				{
 					uint16_t support = BGFX_CAPS_FORMAT_TEXTURE_NONE;
@@ -1343,13 +1339,7 @@ namespace bgfx { namespace d3d11
 					{
 						if (BX_ENABLED(BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT) )
 						{
-							struct D3D11_FEATURE_DATA_FORMAT_SUPPORT
-							{
-								DXGI_FORMAT InFormat;
-								UINT OutFormatSupport;
-							};
-
-							D3D11_FEATURE_DATA_FORMAT_SUPPORT data; // D3D11_FEATURE_DATA_FORMAT_SUPPORT2
+							D3D11_FEATURE_DATA_FORMAT_SUPPORT data;
 							data.InFormat = fmt;
 							HRESULT hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) );
 							if (SUCCEEDED(hr) )
@@ -1433,21 +1423,23 @@ namespace bgfx { namespace d3d11
 
 							if (0 != (support & BGFX_CAPS_FORMAT_TEXTURE_IMAGE_READ) )
 							{
+								D3D11_FEATURE_DATA_FORMAT_SUPPORT2 data2;
+
 								// clear image flag for additional testing
 								support &= ~BGFX_CAPS_FORMAT_TEXTURE_IMAGE_READ;
 
-								data.InFormat = s_textureFormat[ii].m_fmt;
-								hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT2, &data, sizeof(data) );
+								data2.InFormat = s_textureFormat[ii].m_fmt;
+								hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT2, &data2, sizeof(data2) );
 								if (SUCCEEDED(hr) )
 								{
-									support |= 0 != (data.OutFormatSupport & (0
+									support |= 0 != (data2.OutFormatSupport2 & (0
 											| D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD
 											) )
 											? BGFX_CAPS_FORMAT_TEXTURE_IMAGE_READ
 											: BGFX_CAPS_FORMAT_TEXTURE_NONE
 											;
 
-									support |= 0 != (data.OutFormatSupport & (0
+									support |= 0 != (data2.OutFormatSupport2 & (0
 											| D3D11_FORMAT_SUPPORT2_UAV_TYPED_STORE
 											) )
 											? BGFX_CAPS_FORMAT_TEXTURE_IMAGE_WRITE
@@ -1482,7 +1474,7 @@ namespace bgfx { namespace d3d11
 								UINT OutFormatSupport;
 							};
 
-							D3D11_FEATURE_DATA_FORMAT_SUPPORT data; // D3D11_FEATURE_DATA_FORMAT_SUPPORT2
+							D3D11_FEATURE_DATA_FORMAT_SUPPORT data;
 							data.InFormat = fmtSrgb;
 							HRESULT hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) );
 							if (SUCCEEDED(hr) )
@@ -4808,14 +4800,18 @@ namespace bgfx { namespace d3d11
 		ts.m_sampler[_stage] = s_renderD3D11->getSamplerState(flags, _palette[index]);
 	}
 
-	void TextureD3D11::resolve(uint8_t _resolve) const
+	void TextureD3D11::resolve(uint8_t _resolve, uint32_t _layer, uint32_t _numLayers, uint32_t _mip) const
 	{
 		ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
 
 		const bool needResolve = NULL != m_rt;
 		if (needResolve)
 		{
-			deviceCtx->ResolveSubresource(m_texture2d, 0, m_rt, 0, s_textureFormat[m_textureFormat].m_fmt);
+			for (uint32_t ii = _layer; ii < _numLayers; ++ii)
+			{
+				const UINT resource = _mip + (ii * m_numMips);
+				deviceCtx->ResolveSubresource(m_texture2d, resource, m_rt, resource, s_textureFormat[m_textureFormat].m_fmt);
+			}
 		}
 
 		const bool renderTarget = 0 != (m_flags&BGFX_TEXTURE_RT_MASK);
@@ -5090,7 +5086,7 @@ namespace bgfx { namespace d3d11
 								{
 									desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
 									desc.Texture2DMSArray.FirstArraySlice = at.layer;
-									desc.Texture2DMSArray.ArraySize       = 1;
+									desc.Texture2DMSArray.ArraySize       = at.numLayers;
 								}
 								else
 								{
@@ -5173,7 +5169,7 @@ namespace bgfx { namespace d3d11
 				if (isValid(at.handle) )
 				{
 					const TextureD3D11& texture = s_renderD3D11->m_textures[at.handle.idx];
-					texture.resolve(at.resolve);
+					texture.resolve(at.resolve, at.layer, at.numLayers, at.mip);
 				}
 			}
 		}

+ 1 - 1
src/renderer_d3d11.h

@@ -287,7 +287,7 @@ namespace bgfx { namespace d3d11
 		void overrideInternal(uintptr_t _ptr);
 		void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem);
 		void commit(uint8_t _stage, uint32_t _flags, const float _palette[][4]);
-		void resolve(uint8_t _resolve) const;
+		void resolve(uint8_t _resolve, uint32_t _layer, uint32_t _numLayers, uint32_t _mip) const;
 		TextureHandle getHandle() const;
 		DXGI_FORMAT getSrvFormat() const;
 

+ 42 - 26
src/renderer_d3d12.cpp

@@ -1164,6 +1164,7 @@ namespace bgfx { namespace d3d12
 					| BGFX_CAPS_TEXTURE_2D_ARRAY
 					| BGFX_CAPS_TEXTURE_CUBE_ARRAY
 					| BGFX_CAPS_IMAGE_RW
+					| BGFX_CAPS_VIEWPORT_LAYER_ARRAY
 					);
 				g_caps.limits.maxTextureSize     = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION;
 				g_caps.limits.maxTextureLayers   = D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
@@ -4884,27 +4885,37 @@ namespace bgfx { namespace d3d12
 
 				if (1 < ti.numLayers)
 				{
-					m_srvd.ViewDimension = 1 < msaa.Count
-						? D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY
-						: D3D12_SRV_DIMENSION_TEXTURE2DARRAY
-						;
-					m_srvd.Texture2DArray.MostDetailedMip     = 0;
-					m_srvd.Texture2DArray.MipLevels           = ti.numMips;
-					m_srvd.Texture2DArray.FirstArraySlice     = 0;
-					m_srvd.Texture2DArray.ArraySize           = ti.numLayers;
-					m_srvd.Texture2DArray.PlaneSlice          = 0;
-					m_srvd.Texture2DArray.ResourceMinLODClamp = 0.0f;
+					if (1 < msaa.Count && !needResolve)
+					{
+						m_srvd.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY;
+						m_srvd.Texture2DMSArray.FirstArraySlice = 0;
+						m_srvd.Texture2DMSArray.ArraySize       = ti.numLayers;
+					}
+					else
+					{
+						m_srvd.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
+						m_srvd.Texture2DArray.MostDetailedMip     = 0;
+						m_srvd.Texture2DArray.MipLevels           = ti.numMips;
+						m_srvd.Texture2DArray.FirstArraySlice     = 0;
+						m_srvd.Texture2DArray.ArraySize           = ti.numLayers;
+						m_srvd.Texture2DArray.PlaneSlice          = 0;
+						m_srvd.Texture2DArray.ResourceMinLODClamp = 0.0f;
+					}
 				}
 				else
 				{
-					m_srvd.ViewDimension = 1 < msaa.Count
-						? D3D12_SRV_DIMENSION_TEXTURE2DMS
-						: D3D12_SRV_DIMENSION_TEXTURE2D
-						;
-					m_srvd.Texture2D.MostDetailedMip     = 0;
-					m_srvd.Texture2D.MipLevels           = ti.numMips;
-					m_srvd.Texture2D.PlaneSlice          = 0;
-					m_srvd.Texture2D.ResourceMinLODClamp = 0.0f;
+					if (1 < msaa.Count && !needResolve)
+					{
+						m_srvd.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS;
+					}
+					else
+					{
+						m_srvd.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
+						m_srvd.Texture2D.MostDetailedMip     = 0;
+						m_srvd.Texture2D.MipLevels           = ti.numMips;
+						m_srvd.Texture2D.PlaneSlice          = 0;
+						m_srvd.Texture2D.ResourceMinLODClamp = 0.0f;
+					}
 				}
 
 				if (1 < ti.numLayers)
@@ -5153,7 +5164,7 @@ namespace bgfx { namespace d3d12
 		s_renderD3D12->m_cmd.release(staging);
 	}
 
-	void TextureD3D12::resolve(ID3D12GraphicsCommandList* _commandList, uint8_t _resolve)
+	void TextureD3D12::resolve(ID3D12GraphicsCommandList* _commandList, uint8_t _resolve, uint32_t _layer, uint32_t _numLayers, uint32_t _mip)
 	{
 		BX_UNUSED(_resolve);
 
@@ -5168,12 +5179,17 @@ namespace bgfx { namespace d3d12
 				, D3D12_RESOURCE_STATE_RESOLVE_DEST
 			);
 
-			_commandList->ResolveSubresource(m_singleMsaa
-				, 0
-				, m_ptr
-				, 0
-				, s_textureFormat[m_textureFormat].m_fmt
-			);
+			for (uint32_t ii = _layer; ii < _numLayers; ++ii)
+			{
+				const UINT resource = _mip + (ii * m_numMips);
+
+				_commandList->ResolveSubresource(m_singleMsaa
+					, resource
+					, m_ptr
+					, resource
+					, s_textureFormat[m_textureFormat].m_fmt
+				);
+			}
 
 			setResourceBarrier(_commandList
 				, m_singleMsaa
@@ -5498,7 +5514,7 @@ namespace bgfx { namespace d3d12
 				if (isValid(at.handle) )
 				{
 					TextureD3D12& texture = s_renderD3D12->m_textures[at.handle.idx];
-					texture.resolve(s_renderD3D12->m_commandList, at.resolve);
+					texture.resolve(s_renderD3D12->m_commandList, at.resolve, at.layer, at.numLayers, at.mip);
 				}
 			}
 		}

+ 1 - 1
src/renderer_d3d12.h

@@ -340,7 +340,7 @@ namespace bgfx { namespace d3d12
 		void destroy();
 		void overrideInternal(uintptr_t _ptr);
 		void update(ID3D12GraphicsCommandList* _commandList, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem);
-		void resolve(ID3D12GraphicsCommandList* _commandList, uint8_t _resolve);
+		void resolve(ID3D12GraphicsCommandList* _commandList, uint8_t _resolve, uint32_t _layer, uint32_t _numLayers, uint32_t _mip);
 		D3D12_RESOURCE_STATES setState(ID3D12GraphicsCommandList* _commandList, D3D12_RESOURCE_STATES _state);
 
 		D3D12_SHADER_RESOURCE_VIEW_DESC  m_srvd;

+ 63 - 10
src/renderer_gl.cpp

@@ -532,6 +532,7 @@ namespace bgfx { namespace gl
 			ARB_shader_image_load_store,
 			ARB_shader_storage_buffer_object,
 			ARB_shader_texture_lod,
+			ARB_shader_viewport_layer_array,
 			ARB_texture_compression_bptc,
 			ARB_texture_compression_rgtc,
 			ARB_texture_cube_map_array,
@@ -746,6 +747,7 @@ namespace bgfx { namespace gl
 		{ "ARB_shader_image_load_store",              BGFX_CONFIG_RENDERER_OPENGL >= 42, true  },
 		{ "ARB_shader_storage_buffer_object",         BGFX_CONFIG_RENDERER_OPENGL >= 43, true  },
 		{ "ARB_shader_texture_lod",                   BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
+		{ "ARB_shader_viewport_layer_array",          false,                             true  },
 		{ "ARB_texture_compression_bptc",             BGFX_CONFIG_RENDERER_OPENGL >= 44, true  },
 		{ "ARB_texture_compression_rgtc",             BGFX_CONFIG_RENDERER_OPENGL >= 30, true  },
 		{ "ARB_texture_cube_map_array",               BGFX_CONFIG_RENDERER_OPENGL >= 40, true  },
@@ -915,6 +917,13 @@ namespace bgfx { namespace gl
 		NULL
 	};
 
+	static const char* s_ARB_shader_viewport_layer_array[] =
+	{
+		"gl_ViewportIndex",
+		"gl_Layer",
+		NULL
+	};
+
 	static const char* s_EXT_shadow_samplers[] =
 	{
 		"shadow2D",
@@ -1054,6 +1063,16 @@ namespace bgfx { namespace gl
 	{
 	}
 
+	static void GL_APIENTRY stubFramebufferTexture(GLenum _target, GLenum _attachment, GLuint _texture, GLint _level)
+	{
+		GL_CHECK(glFramebufferTextureLayer(_target
+			, _attachment
+			, _texture
+			, _level
+			, 0
+			) );
+	}
+
 	static void GL_APIENTRY stubMultiDrawArraysIndirect(GLenum _mode, const void* _indirect, GLsizei _drawcount, GLsizei _stride)
 	{
 		const uint8_t* args = (const uint8_t*)_indirect;
@@ -2974,6 +2993,11 @@ namespace bgfx { namespace gl
 					}
 				}
 
+				g_caps.supported |= s_extension[Extension::ARB_shader_viewport_layer_array].m_supported
+					? BGFX_CAPS_VIEWPORT_LAYER_ARRAY
+					: 0
+					;
+
 				if (s_extension[Extension::ARB_debug_output].m_supported
 				||  s_extension[Extension::KHR_debug].m_supported)
 				{
@@ -3031,6 +3055,11 @@ namespace bgfx { namespace gl
 					glInvalidateFramebuffer = stubInvalidateFramebuffer;
 				}
 
+				if (NULL == glFramebufferTexture)
+				{
+					glFramebufferTexture = stubFramebufferTexture;
+				}
+
 				if (m_timerQuerySupport)
 				{
 					m_gpuTimer.create();
@@ -5187,12 +5216,14 @@ namespace bgfx { namespace gl
 		const bool writeOnly    = 0 != (m_flags&BGFX_TEXTURE_RT_WRITE_ONLY);
 		const bool computeWrite = 0 != (m_flags&BGFX_TEXTURE_COMPUTE_WRITE );
 		const bool srgb         = 0 != (m_flags&BGFX_TEXTURE_SRGB);
+		const bool renderTarget = 0 != (m_flags&BGFX_TEXTURE_RT_MASK);
 		const bool textureArray = false
 			|| _target == GL_TEXTURE_2D_ARRAY
 			|| _target == GL_TEXTURE_CUBE_MAP_ARRAY
 			;
 
-		if (!writeOnly)
+		if (!writeOnly
+		|| (renderTarget && textureArray) )
 		{
 			GL_CHECK(glGenTextures(1, &m_id) );
 			BX_ASSERT(0 != m_id, "Failed to generate texture id.");
@@ -5277,8 +5308,6 @@ namespace bgfx { namespace gl
 			}
 		}
 
-		const bool renderTarget = 0 != (m_flags&BGFX_TEXTURE_RT_MASK);
-
 		if (renderTarget)
 		{
 			uint32_t msaaQuality = ( (m_flags&BGFX_TEXTURE_RT_MSAA_MASK)>>BGFX_TEXTURE_RT_MSAA_SHIFT);
@@ -5287,7 +5316,8 @@ namespace bgfx { namespace gl
 			const bool msaaSample = 0 != (m_flags&BGFX_TEXTURE_MSAA_SAMPLE);
 
 			if (!msaaSample
-			&& (0 != msaaQuality || writeOnly) )
+			&& (0 != msaaQuality || writeOnly)
+			&&  !textureArray)
 			{
 				GL_CHECK(glGenRenderbuffers(1, &m_rbo) );
 				BX_ASSERT(0 != m_rbo, "Failed to generate renderbuffer id.");
@@ -6158,6 +6188,11 @@ namespace bgfx { namespace gl
 						&& !bx::findIdentifierMatch(code, s_ARB_gpu_shader5).isEmpty()
 						;
 
+					const bool usesViewportLayerArray = true
+						&& s_extension[Extension::ARB_shader_viewport_layer_array].m_supported
+						&& !bx::findIdentifierMatch(code, s_ARB_shader_viewport_layer_array).isEmpty()
+						;
+
 					const bool usesIUsamplers   = !bx::findIdentifierMatch(code, s_uisamplers).isEmpty();
 					const bool usesUint         = !bx::findIdentifierMatch(code, s_uint).isEmpty();
 					const bool usesTexelFetch   = !bx::findIdentifierMatch(code, s_texelFetch).isEmpty();
@@ -6212,6 +6247,11 @@ namespace bgfx { namespace gl
 						bx::write(&writer, "#extension GL_ARB_gpu_shader5 : enable\n");
 					}
 
+					if (usesViewportLayerArray)
+					{
+						bx::write(&writer, "#extension GL_ARB_shader_viewport_layer_array : enable\n");
+					}
+
 					if (usesPacking)
 					{
 						bx::write(&writer, "#extension GL_ARB_shading_language_packing : enable\n");
@@ -6621,12 +6661,25 @@ namespace bgfx { namespace gl
 						if (1 < texture.m_numLayers
 						&&  !texture.isCubeMap() )
 						{
-							GL_CHECK(glFramebufferTextureLayer(GL_FRAMEBUFFER
-								, attachment
-								, texture.m_id
-								, at.mip
-								, at.layer
-								) );
+							if (1 < at.numLayers)
+							{
+								BX_ASSERT(0 == at.layer, "Can't use start layer > 0 when binding multiple layers to a framebuffer.");
+
+								GL_CHECK(glFramebufferTexture(GL_FRAMEBUFFER
+									, attachment
+									, texture.m_id
+									, at.mip
+									) );
+							}
+							else
+							{
+								GL_CHECK(glFramebufferTextureLayer(GL_FRAMEBUFFER
+									, attachment
+									, texture.m_id
+									, at.mip
+									, at.layer
+									) );
+							}
 						}
 						else
 						{