diff --git a/examples/21-deferred/common.sh b/examples/21-deferred/common.sh new file mode 100644 index 000000000..03333aeeb --- /dev/null +++ b/examples/21-deferred/common.sh @@ -0,0 +1,62 @@ +/* + * Copyright 2011-2018 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#include "../common/common.sh" + +vec2 blinn(vec3 _lightDir, vec3 _normal, vec3 _viewDir) +{ + float ndotl = dot(_normal, _lightDir); + vec3 reflected = _lightDir - 2.0*ndotl*_normal; // reflect(_lightDir, _normal); + float rdotv = dot(reflected, _viewDir); + return vec2(ndotl, rdotv); +} + +float fresnel(float _ndotl, float _bias, float _pow) +{ + float facing = (1.0 - _ndotl); + return max(_bias + (1.0 - _bias) * pow(facing, _pow), 0.0); +} + +vec4 lit(float _ndotl, float _rdotv, float _m) +{ + float diff = max(0.0, _ndotl); + float spec = step(0.0, _ndotl) * max(0.0, _rdotv * _m); + return vec4(1.0, diff, spec, 1.0); +} + +vec4 powRgba(vec4 _rgba, float _pow) +{ + vec4 result; + result.xyz = pow(_rgba.xyz, vec3_splat(_pow) ); + result.w = _rgba.w; + return result; +} + +vec3 calcLight(vec3 _wpos, vec3 _normal, vec3 _view, vec3 _lightPos, float _lightRadius, vec3 _lightRgb, float _lightInner) +{ + vec3 lp = _lightPos - _wpos; + float attn = 1.0 - smoothstep(_lightInner, 1.0, length(lp) / _lightRadius); + vec3 lightDir = normalize(lp); + vec2 bln = blinn(lightDir, _normal, _view); + vec4 lc = lit(bln.x, bln.y, 1.0); + vec3 rgb = _lightRgb * saturate(lc.y) * attn; + return rgb; +} + +float toClipSpaceDepth(float _depthTextureZ) +{ +#if BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_METAL + return _depthTextureZ; +#else + return _depthTextureZ * 2.0 - 1.0; +#endif // BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_METAL +} + +vec3 clipToWorld(mat4 _invViewProj, vec3 _clipPos) +{ + vec4 wpos = mul(_invViewProj, vec4(_clipPos, 1.0) ); + return wpos.xyz / wpos.w; +} + diff --git a/examples/21-deferred/deferred.cpp b/examples/21-deferred/deferred.cpp index 0ecbf287a..30933f6dd 100644 --- a/examples/21-deferred/deferred.cpp +++ b/examples/21-deferred/deferred.cpp @@ -282,6 +282,7 @@ public: m_lineProgram = loadProgram("vs_deferred_debug_line", "fs_deferred_debug_line"); m_useTArray = false; + m_useUav = false; if (0 != (BGFX_CAPS_TEXTURE_2D_ARRAY & bgfx::getCaps()->supported) ) { @@ -292,6 +293,17 @@ public: m_lightTaProgram = BGFX_INVALID_HANDLE; } + if(0 != (BGFX_CAPS_READ_WRITE_ATTACH & bgfx::getCaps()->supported)) + { + m_lightUavProgram = loadProgram("vs_deferred_light", "fs_deferred_light_uav"); + m_clearUavProgram = loadProgram("vs_deferred_light", "fs_deferred_clear_uav"); + } + else + { + m_lightUavProgram = BGFX_INVALID_HANDLE; + m_clearUavProgram = BGFX_INVALID_HANDLE; + } + // Load diffuse texture. m_textureColor = loadTexture("textures/fieldstone-rgba.dds"); @@ -423,6 +435,7 @@ public: || m_oldHeight != m_height || m_oldReset != m_reset || m_oldUseTArray != m_useTArray + || m_oldUseUav != m_useUav || !bgfx::isValid(m_gbuffer) ) { // Recreate variable size render targets when resolution changes. @@ -430,6 +443,7 @@ public: m_oldHeight = m_height; m_oldReset = m_reset; m_oldUseTArray = m_useTArray; + m_oldUseUav = m_useUav; if (bgfx::isValid(m_gbuffer) ) { @@ -440,7 +454,6 @@ public: } const uint64_t tsFlags = 0 - | BGFX_TEXTURE_RT | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT @@ -448,33 +461,48 @@ public: | BGFX_SAMPLER_V_CLAMP ; - bgfx::Attachment at[3]; + bgfx::Attachment gbufferAt[3]; - if (m_useTArray) + if(m_useTArray) { - m_gbufferTex[0] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 2, bgfx::TextureFormat::BGRA8, tsFlags); - at[0].init(m_gbufferTex[0], bgfx::Access::Write, 0); - at[1].init(m_gbufferTex[0], bgfx::Access::Write, 1); + m_gbufferTex[0] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 2, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_RT | tsFlags); + gbufferAt[0].init(m_gbufferTex[0], bgfx::Access::Write, 0); + gbufferAt[1].init(m_gbufferTex[0], bgfx::Access::Write, 1); } else { - m_gbufferTex[0] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, bgfx::TextureFormat::BGRA8, tsFlags); - m_gbufferTex[1] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, bgfx::TextureFormat::BGRA8, tsFlags); - at[0].init(m_gbufferTex[0]); - at[1].init(m_gbufferTex[1]); + m_gbufferTex[0] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_RT | tsFlags); + m_gbufferTex[1] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_RT | tsFlags); + gbufferAt[0].init(m_gbufferTex[0]); + gbufferAt[1].init(m_gbufferTex[1]); } - m_gbufferTex[2] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, bgfx::TextureFormat::D24S8, tsFlags); - at[2].init(m_gbufferTex[2]); + m_gbufferTex[2] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, bgfx::TextureFormat::D24S8, BGFX_TEXTURE_RT | tsFlags); + gbufferAt[2].init(m_gbufferTex[2]); - m_gbuffer = bgfx::createFrameBuffer(BX_COUNTOF(at), at, true); + m_gbuffer = bgfx::createFrameBuffer(BX_COUNTOF(gbufferAt), gbufferAt, true); - if (bgfx::isValid(m_lightBuffer) ) + if(bgfx::isValid(m_lightBuffer)) { bgfx::destroy(m_lightBuffer); } - m_lightBuffer = bgfx::createFrameBuffer(uint16_t(m_width), uint16_t(m_height), bgfx::TextureFormat::BGRA8, tsFlags); + if(m_useUav) + { + bgfx::Attachment lightAt[2]; + + bgfx::TextureHandle target = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_RT | tsFlags); + m_lightBufferTex = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_COMPUTE_WRITE | tsFlags); + lightAt[0].init(target); + lightAt[1].init(m_lightBufferTex, bgfx::Access::ReadWrite); + + m_lightBuffer = bgfx::createFrameBuffer(BX_COUNTOF(lightAt), lightAt, true); + } + else + { + m_lightBufferTex = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_RT | tsFlags); + m_lightBuffer = bgfx::createFrameBuffer(1, &m_lightBufferTex, true); + } } ImGui::SetNextWindowPos( @@ -503,6 +531,15 @@ public: ImGui::Text("Texture array frame buffer is not supported."); } + if(bgfx::isValid(m_lightUavProgram)) + { + ImGui::Checkbox("Use UAV frame buffer attachment.", &m_useUav); + } + else + { + ImGui::Text("UAV frame buffer attachment is not supported."); + } + ImGui::Checkbox("Animate mesh.", &m_animateMesh); ImGui::SliderFloat("Anim.speed", &m_lightAnimationSpeed, 0.0f, 0.4f); @@ -596,6 +633,17 @@ public: } } + // Clear UAV texture + if(m_useUav) + { + screenSpaceQuad((float)m_width, (float)m_height, s_texelHalf, m_caps->originBottomLeft); + bgfx::setState(0 + | BGFX_STATE_WRITE_RGB + | BGFX_STATE_WRITE_A + ); + bgfx::submit(RENDER_PASS_LIGHT_ID, m_clearUavProgram); + } + // Draw lights into light buffer. for (int32_t light = 0; light < m_numLights; ++light) { @@ -717,17 +765,18 @@ public: | BGFX_STATE_BLEND_ADD ); screenSpaceQuad( (float)m_width, (float)m_height, s_texelHalf, m_caps->originBottomLeft); - bgfx::submit(RENDER_PASS_LIGHT_ID - , bgfx::isValid(m_lightTaProgram) && m_useTArray - ? m_lightTaProgram - : m_lightProgram - ); + if(bgfx::isValid(m_lightTaProgram) && m_useTArray) + bgfx::submit(RENDER_PASS_LIGHT_ID, m_lightTaProgram); + else if(bgfx::isValid(m_lightUavProgram) && m_useUav) + bgfx::submit(RENDER_PASS_LIGHT_ID, m_lightUavProgram); + else + bgfx::submit(RENDER_PASS_LIGHT_ID, m_lightProgram); } } // Combine color and light buffers. - bgfx::setTexture(0, s_albedo, bgfx::getTexture(m_gbuffer, 0) ); - bgfx::setTexture(1, s_light, bgfx::getTexture(m_lightBuffer, 0) ); + bgfx::setTexture(0, s_albedo, m_gbufferTex[0]); + bgfx::setTexture(1, s_light, m_lightBufferTex); bgfx::setState(0 | BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A @@ -788,6 +837,8 @@ public: bgfx::ProgramHandle m_geomProgram; bgfx::ProgramHandle m_lightProgram; bgfx::ProgramHandle m_lightTaProgram; + bgfx::ProgramHandle m_lightUavProgram; + bgfx::ProgramHandle m_clearUavProgram; bgfx::ProgramHandle m_combineProgram; bgfx::ProgramHandle m_debugProgram; bgfx::ProgramHandle m_lineProgram; @@ -795,6 +846,7 @@ public: bgfx::TextureHandle m_textureNormal; bgfx::TextureHandle m_gbufferTex[3]; + bgfx::TextureHandle m_lightBufferTex; bgfx::FrameBufferHandle m_gbuffer; bgfx::FrameBufferHandle m_lightBuffer; @@ -810,6 +862,9 @@ public: bool m_useTArray; bool m_oldUseTArray; + bool m_useUav; + bool m_oldUseUav; + int32_t m_scrollArea; int32_t m_numLights; float m_lightAnimationSpeed; diff --git a/examples/21-deferred/fs_deferred_clear_uav.sc b/examples/21-deferred/fs_deferred_clear_uav.sc new file mode 100644 index 000000000..c7d013f3e --- /dev/null +++ b/examples/21-deferred/fs_deferred_clear_uav.sc @@ -0,0 +1,17 @@ +$input v_texcoord0 + +/* + * Copyright 2011-2018 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#include "common.sh" +#include + +IMAGE2D_RW(s_lights, rgba8, 1); + +void main() +{ + ivec2 coord = ivec2(gl_FragCoord.xy); + imageStore(s_lights, coord, vec4(0.0, 0.0, 0.0, 0.0)); +} diff --git a/examples/21-deferred/fs_deferred_light.sc b/examples/21-deferred/fs_deferred_light.sc index b727f2a6b..4857c663a 100644 --- a/examples/21-deferred/fs_deferred_light.sc +++ b/examples/21-deferred/fs_deferred_light.sc @@ -5,7 +5,7 @@ $input v_texcoord0 * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause */ -#include "../common/common.sh" +#include "common.sh" SAMPLER2D(s_normal, 0); SAMPLER2D(s_depth, 1); @@ -14,61 +14,6 @@ uniform vec4 u_lightPosRadius[1]; uniform vec4 u_lightRgbInnerR[1]; uniform mat4 u_mtx; -vec2 blinn(vec3 _lightDir, vec3 _normal, vec3 _viewDir) -{ - float ndotl = dot(_normal, _lightDir); - vec3 reflected = _lightDir - 2.0*ndotl*_normal; // reflect(_lightDir, _normal); - float rdotv = dot(reflected, _viewDir); - return vec2(ndotl, rdotv); -} - -float fresnel(float _ndotl, float _bias, float _pow) -{ - float facing = (1.0 - _ndotl); - return max(_bias + (1.0 - _bias) * pow(facing, _pow), 0.0); -} - -vec4 lit(float _ndotl, float _rdotv, float _m) -{ - float diff = max(0.0, _ndotl); - float spec = step(0.0, _ndotl) * max(0.0, _rdotv * _m); - return vec4(1.0, diff, spec, 1.0); -} - -vec4 powRgba(vec4 _rgba, float _pow) -{ - vec4 result; - result.xyz = pow(_rgba.xyz, vec3_splat(_pow) ); - result.w = _rgba.w; - return result; -} - -vec3 calcLight(int _idx, vec3 _wpos, vec3 _normal, vec3 _view) -{ - vec3 lp = u_lightPosRadius[_idx].xyz - _wpos; - float attn = 1.0 - smoothstep(u_lightRgbInnerR[_idx].w, 1.0, length(lp) / u_lightPosRadius[_idx].w); - vec3 lightDir = normalize(lp); - vec2 bln = blinn(lightDir, _normal, _view); - vec4 lc = lit(bln.x, bln.y, 1.0); - vec3 rgb = u_lightRgbInnerR[_idx].xyz * saturate(lc.y) * attn; - return rgb; -} - -float toClipSpaceDepth(float _depthTextureZ) -{ -#if BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_METAL - return _depthTextureZ; -#else - return _depthTextureZ * 2.0 - 1.0; -#endif // BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_METAL -} - -vec3 clipToWorld(mat4 _invViewProj, vec3 _clipPos) -{ - vec4 wpos = mul(_invViewProj, vec4(_clipPos, 1.0) ); - return wpos.xyz / wpos.w; -} - void main() { vec3 normal = decodeNormalUint(texture2D(s_normal, v_texcoord0).xyz); @@ -84,8 +29,7 @@ void main() vec3 view = mul(u_view, vec4(wpos, 0.0) ).xyz; view = -normalize(view); - vec3 lightColor; - lightColor = calcLight(0, wpos, normal, view); + vec3 lightColor = calcLight(wpos, normal, view, u_lightPosRadius[0].xyz, u_lightPosRadius[0].w, u_lightRgbInnerR[0].xyz, u_lightRgbInnerR[0].w); gl_FragColor.xyz = toGamma(lightColor.xyz); gl_FragColor.w = 1.0; } diff --git a/examples/21-deferred/fs_deferred_light_ta.sc b/examples/21-deferred/fs_deferred_light_ta.sc index 91180c0d0..9313b655a 100644 --- a/examples/21-deferred/fs_deferred_light_ta.sc +++ b/examples/21-deferred/fs_deferred_light_ta.sc @@ -5,7 +5,7 @@ $input v_texcoord0 * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause */ -#include "../common/common.sh" +#include "common.sh" SAMPLER2DARRAY(s_normal, 0); SAMPLER2D(s_depth, 1); @@ -14,61 +14,6 @@ uniform vec4 u_lightPosRadius[1]; uniform vec4 u_lightRgbInnerR[1]; uniform mat4 u_mtx; -vec2 blinn(vec3 _lightDir, vec3 _normal, vec3 _viewDir) -{ - float ndotl = dot(_normal, _lightDir); - vec3 reflected = _lightDir - 2.0*ndotl*_normal; // reflect(_lightDir, _normal); - float rdotv = dot(reflected, _viewDir); - return vec2(ndotl, rdotv); -} - -float fresnel(float _ndotl, float _bias, float _pow) -{ - float facing = (1.0 - _ndotl); - return max(_bias + (1.0 - _bias) * pow(facing, _pow), 0.0); -} - -vec4 lit(float _ndotl, float _rdotv, float _m) -{ - float diff = max(0.0, _ndotl); - float spec = step(0.0, _ndotl) * max(0.0, _rdotv * _m); - return vec4(1.0, diff, spec, 1.0); -} - -vec4 powRgba(vec4 _rgba, float _pow) -{ - vec4 result; - result.xyz = pow(_rgba.xyz, vec3_splat(_pow) ); - result.w = _rgba.w; - return result; -} - -vec3 calcLight(int _idx, vec3 _wpos, vec3 _normal, vec3 _view) -{ - vec3 lp = u_lightPosRadius[_idx].xyz - _wpos; - float attn = 1.0 - smoothstep(u_lightRgbInnerR[_idx].w, 1.0, length(lp) / u_lightPosRadius[_idx].w); - vec3 lightDir = normalize(lp); - vec2 bln = blinn(lightDir, _normal, _view); - vec4 lc = lit(bln.x, bln.y, 1.0); - vec3 rgb = u_lightRgbInnerR[_idx].xyz * saturate(lc.y) * attn; - return rgb; -} - -float toClipSpaceDepth(float _depthTextureZ) -{ -#if BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_METAL - return _depthTextureZ; -#else - return _depthTextureZ * 2.0 - 1.0; -#endif // BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_METAL -} - -vec3 clipToWorld(mat4 _invViewProj, vec3 _clipPos) -{ - vec4 wpos = mul(_invViewProj, vec4(_clipPos, 1.0) ); - return wpos.xyz / wpos.w; -} - void main() { vec3 normal = decodeNormalUint(texture2DArray(s_normal, vec3(v_texcoord0, 1.0) ).xyz); @@ -84,8 +29,7 @@ void main() vec3 view = mul(u_view, vec4(wpos, 0.0) ).xyz; view = -normalize(view); - vec3 lightColor; - lightColor = calcLight(0, wpos, normal, view); + vec3 lightColor = calcLight(wpos, normal, view, u_lightPosRadius[0].xyz, u_lightPosRadius[0].w, u_lightRgbInnerR[0].xyz, u_lightRgbInnerR[0].w); gl_FragColor.xyz = toGamma(lightColor.xyz); gl_FragColor.w = 1.0; } diff --git a/examples/21-deferred/fs_deferred_light_uav.sc b/examples/21-deferred/fs_deferred_light_uav.sc new file mode 100644 index 000000000..a1148cec1 --- /dev/null +++ b/examples/21-deferred/fs_deferred_light_uav.sc @@ -0,0 +1,40 @@ +$input v_texcoord0 + +/* + * Copyright 2011-2018 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#include "common.sh" +#include + +SAMPLER2D(s_normal, 0); +SAMPLER2D(s_depth, 1); + +IMAGE2D_RW(s_lights, rgba8, 1); + +uniform vec4 u_lightPosRadius[1]; +uniform vec4 u_lightRgbInnerR[1]; +uniform mat4 u_mtx; + +void main() +{ + vec3 normal = decodeNormalUint(texture2D(s_normal, v_texcoord0).xyz); + float deviceDepth = texture2D(s_depth, v_texcoord0).x; + float depth = toClipSpaceDepth(deviceDepth); + + vec3 clip = vec3(v_texcoord0 * 2.0 - 1.0, depth); +#if BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_METAL + clip.y = -clip.y; +#endif // BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_METAL + vec3 wpos = clipToWorld(u_mtx, clip); + + vec3 view = mul(u_view, vec4(wpos, 0.0) ).xyz; + view = -normalize(view); + + ivec2 coord = ivec2(gl_FragCoord.xy); + + vec3 lightColor = calcLight(wpos, normal, view, u_lightPosRadius[0].xyz, u_lightPosRadius[0].w, u_lightRgbInnerR[0].xyz, u_lightRgbInnerR[0].w); + vec4 color = imageLoad(s_lights, coord); + imageStore(s_lights, coord, color + vec4(toGamma(lightColor.xyz), 1.0)); +} diff --git a/examples/runtime/shaders/dx11/fs_deferred_clear_uav.bin b/examples/runtime/shaders/dx11/fs_deferred_clear_uav.bin new file mode 100644 index 000000000..0cdabef5f Binary files /dev/null and b/examples/runtime/shaders/dx11/fs_deferred_clear_uav.bin differ diff --git a/examples/runtime/shaders/dx11/fs_deferred_light_uav.bin b/examples/runtime/shaders/dx11/fs_deferred_light_uav.bin new file mode 100644 index 000000000..6991d1120 Binary files /dev/null and b/examples/runtime/shaders/dx11/fs_deferred_light_uav.bin differ diff --git a/examples/runtime/shaders/glsl/fs_deferred_clear_uav.bin b/examples/runtime/shaders/glsl/fs_deferred_clear_uav.bin new file mode 100644 index 000000000..38ddde3e0 Binary files /dev/null and b/examples/runtime/shaders/glsl/fs_deferred_clear_uav.bin differ diff --git a/examples/runtime/shaders/glsl/fs_deferred_light_uav.bin b/examples/runtime/shaders/glsl/fs_deferred_light_uav.bin new file mode 100644 index 000000000..ddee28a5b Binary files /dev/null and b/examples/runtime/shaders/glsl/fs_deferred_light_uav.bin differ diff --git a/include/bgfx/defines.h b/include/bgfx/defines.h index 3e1f01014..0ab8bea6a 100644 --- a/include/bgfx/defines.h +++ b/include/bgfx/defines.h @@ -502,6 +502,7 @@ #define BGFX_CAPS_VERTEX_ATTRIB_HALF UINT64_C(0x0000000001000000) //!< Vertex attribute half-float is supported. #define BGFX_CAPS_VERTEX_ATTRIB_UINT10 UINT64_C(0x0000000002000000) //!< Vertex attribute 10_10_10_2 is supported. #define BGFX_CAPS_VERTEX_ID UINT64_C(0x0000000004000000) //!< Rendering with VertexID only is supported. +#define BGFX_CAPS_READ_WRITE_ATTACH UINT64_C(0x0000000008000000) //!< Read/Write frame buffer attachments are supported. /// #define BGFX_CAPS_FORMAT_TEXTURE_NONE UINT16_C(0x0000) //!< Texture format is not supported. diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index dc0cda792..a6f797ed3 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -391,10 +391,12 @@ namespace bgfx { namespace d3d11 void clear() { + bx::memSet(m_uav, 0, sizeof(m_uav)); bx::memSet(m_srv, 0, sizeof(m_srv) ); bx::memSet(m_sampler, 0, sizeof(m_sampler) ); } + ID3D11UnorderedAccessView* m_uav[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS]; ID3D11ShaderResourceView* m_srv[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS]; ID3D11SamplerState* m_sampler[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS]; }; @@ -1178,6 +1180,9 @@ namespace bgfx { namespace d3d11 : 0) | BGFX_CAPS_TEXTURE_2D_ARRAY | BGFX_CAPS_TEXTURE_CUBE_ARRAY + | ((m_featureLevel >= D3D_FEATURE_LEVEL_11_1) + ? BGFX_CAPS_READ_WRITE_ATTACH + : 0) ); m_timerQuerySupport = m_featureLevel >= D3D_FEATURE_LEVEL_10_0; @@ -2503,7 +2508,7 @@ namespace bgfx { namespace d3d11 m_currentColor = m_backBufferColor; m_currentDepthStencil = m_backBufferDepthStencil; - m_deviceCtx->OMSetRenderTargets(1, &m_currentColor, m_currentDepthStencil); + m_deviceCtx->OMSetRenderTargetsAndUnorderedAccessViews(1, &m_currentColor, m_currentDepthStencil, 1, 0, NULL, NULL); m_needPresent |= _needPresent; } else @@ -4579,6 +4584,10 @@ namespace bgfx { namespace d3d11 { m_rtv[ii] = NULL; } + for(uint32_t ii = 0; ii < BX_COUNTOF(m_uav); ++ii) + { + m_uav[ii] = NULL; + } m_dsv = NULL; m_swapChain = NULL; @@ -4690,6 +4699,8 @@ namespace bgfx { namespace d3d11 if (0 < m_numTh) { m_num = 0; + m_numUav = 0; + for (uint32_t ii = 0; ii < m_numTh; ++ii) { const Attachment& at = m_attachment[ii]; @@ -4851,7 +4862,8 @@ namespace bgfx { namespace d3d11 } else { - BX_CHECK(false, ""); + m_uav[m_num + m_numUav] = texture.m_uav; + m_numUav++; } } } @@ -4924,7 +4936,7 @@ namespace bgfx { namespace d3d11 void FrameBufferD3D11::set() { - s_renderD3D11->m_deviceCtx->OMSetRenderTargets(m_num, m_rtv, m_dsv); + s_renderD3D11->m_deviceCtx->OMSetRenderTargetsAndUnorderedAccessViews(m_num, m_rtv, m_dsv, m_num, m_numUav, m_uav + m_num, NULL); m_needPresent = UINT16_MAX != m_denseIdx; s_renderD3D11->m_currentColor = m_rtv[0]; s_renderD3D11->m_currentDepthStencil = m_dsv; diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index d8c8f0a5b..3b49c88d6 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -330,6 +330,7 @@ namespace bgfx { namespace d3d11 , m_denseIdx(UINT16_MAX) , m_num(0) , m_numTh(0) + , m_numUav(0) , m_needPresent(false) { } @@ -345,6 +346,7 @@ namespace bgfx { namespace d3d11 HRESULT present(uint32_t _syncInterval); ID3D11RenderTargetView* m_rtv[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1]; + ID3D11UnorderedAccessView* m_uav[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1]; ID3D11ShaderResourceView* m_srv[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1]; ID3D11DepthStencilView* m_dsv; Dxgi::SwapChainI* m_swapChain; @@ -356,6 +358,7 @@ namespace bgfx { namespace d3d11 uint16_t m_denseIdx; uint8_t m_num; uint8_t m_numTh; + uint8_t m_numUav; bool m_needPresent; }; diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index a37a5572d..bd9eb4228 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -2434,12 +2434,18 @@ BX_TRACE("%d, %d, %d, %s", _array, _srgb, _mipAutogen, getName(_format) ); m_atocSupport = s_extension[Extension::ARB_multisample].m_supported; m_conservativeRasterSupport = s_extension[Extension::NV_conservative_raster].m_supported; + m_imageLoadStoreSupport = false + || s_extension[Extension::ARB_shader_image_load_store].m_supported + || s_extension[Extension::EXT_shader_image_load_store].m_supported + ; + g_caps.supported |= 0 | (m_atocSupport ? BGFX_CAPS_ALPHA_TO_COVERAGE : 0) | (m_conservativeRasterSupport ? BGFX_CAPS_CONSERVATIVE_RASTER : 0) | (m_occlusionQuerySupport ? BGFX_CAPS_OCCLUSION_QUERY : 0) | (m_depthTextureSupport ? BGFX_CAPS_TEXTURE_COMPARE_LEQUAL : 0) | (computeSupport ? BGFX_CAPS_COMPUTE : 0) + | (m_imageLoadStoreSupport ? BGFX_CAPS_READ_WRITE_ATTACH : 0) ; g_caps.supported |= m_glctx.getCaps(); @@ -3244,6 +3250,8 @@ BX_TRACE("%d, %d, %d, %s", _array, _srgb, _mipAutogen, getName(_format) ); m_glctx.makeCurrent(NULL); m_currentFbo = frameBuffer.m_fbo[0]; } + + frameBuffer.set(); } GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_currentFbo) ); @@ -3888,6 +3896,7 @@ BX_TRACE("%d, %d, %d, %s", _array, _srgb, _mipAutogen, getName(_format) ); bool m_occlusionQuerySupport; bool m_atocSupport; bool m_conservativeRasterSupport; + bool m_imageLoadStoreSupport; bool m_flip; uint64_t m_hash; @@ -5936,7 +5945,7 @@ BX_TRACE("%d, %d, %d, %s", _array, _srgb, _mipAutogen, getName(_format) ); attachment = GL_DEPTH_ATTACHMENT; } } - else + else if (Access::Write == at.access) { buffers[colorIdx] = attachment; ++colorIdx; @@ -5968,7 +5977,7 @@ BX_TRACE("%d, %d, %d, %s", _array, _srgb, _mipAutogen, getName(_format) ); ) ); } } - else if (Access::Write == at.access) + else { if (1 < texture.m_numLayers && !texture.isCubeMap()) @@ -5995,10 +6004,6 @@ BX_TRACE("%d, %d, %d, %s", _array, _srgb, _mipAutogen, getName(_format) ); ) ); } } - else - { - BX_CHECK(false, ""); - } needResolve |= (0 != texture.m_rbo) && (0 != texture.m_id); } @@ -6196,6 +6201,33 @@ BX_TRACE("%d, %d, %d, %s", _array, _srgb, _mipAutogen, getName(_format) ); GL_CHECK(glInvalidateFramebuffer(GL_FRAMEBUFFER, idx, buffers) ); } + void FrameBufferGL::set() + { + for(uint32_t ii = 0; ii < m_numTh; ++ii) + { + if(m_attachment[ii].access == Access::Write) + continue; + + TextureHandle handle = m_attachment[ii].handle; + if(isValid(handle)) + { + const TextureGL& texture = s_renderGL->m_textures[handle.idx]; + + if(0 != (texture.m_flags&BGFX_TEXTURE_COMPUTE_WRITE)) + { + GL_CHECK(glBindImageTexture(ii + , texture.m_id + , m_attachment[ii].mip + , GL_FALSE //texture.isLayered() ? GL_TRUE : GL_FALSE + , m_attachment[ii].layer + , s_access[Access::ReadWrite] + , s_imageFormat[texture.m_textureFormat]) + ); + } + } + } + } + void OcclusionQueryGL::create() { for (uint32_t ii = 0; ii < BX_COUNTOF(m_query); ++ii) diff --git a/src/renderer_gl.h b/src/renderer_gl.h index 2512aa09a..6c53ff3e3 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -1331,6 +1331,7 @@ namespace bgfx { namespace gl uint16_t destroy(); void resolve(); void discard(uint16_t _flags); + void set(); SwapChainGL* m_swapChain; GLuint m_fbo[2];