diff --git a/qrenderdoc/Windows/TextureViewer.cpp b/qrenderdoc/Windows/TextureViewer.cpp index 4e64b27d0..9048f2c97 100644 --- a/qrenderdoc/Windows/TextureViewer.cpp +++ b/qrenderdoc/Windows/TextureViewer.cpp @@ -975,7 +975,8 @@ void TextureViewer::UI_UpdateStatusText() !yuv) compType = m_TexDisplay.typeCast; - bool dsv = (tex.creationFlags & TextureCategory::DepthTarget) || (compType == CompType::Depth); + bool dsv = (tex.creationFlags & TextureCategory::DepthTarget) || (compType == CompType::Depth) || + (tex.format.type == ResourceFormatType::S8); bool uintTex = (compType == CompType::UInt); bool sintTex = (compType == CompType::SInt); @@ -1100,9 +1101,14 @@ void TextureViewer::UI_UpdateStatusText() int stencil = (int)(255.0f * val.floatValue[1]); if(tex.format.type == ResourceFormatType::S8) + { pickedText.clear(); + stencil = val.uintValue[0]; + } else + { pickedText += lit(", "); + } pickedText += tr("Stencil 0x%1").arg(Formatter::Format(uint8_t(stencil & 0xff), true)); @@ -1598,6 +1604,15 @@ void TextureViewer::UI_OnTextureSelectionChanged(bool newAction) m_NoRangePaint = false; } + ui->depthDisplay->setEnabled(true); + + if(tex.format.type == ResourceFormatType::S8) + { + ui->depthDisplay->setEnabled(false); + ui->depthDisplay->setChecked(false); + ui->stencilDisplay->setChecked(true); + } + // reset the range if desired if(m_Ctx.Config().TextureViewer_ResetRange) { @@ -1712,6 +1727,9 @@ void TextureViewer::UI_UpdateChannels() SHOW(ui->depthDisplay); SHOW(ui->stencilDisplay); + if(tex != NULL && tex->format.type == ResourceFormatType::S8) + HIDE(ui->depthDisplay); + m_TexDisplay.red = ui->depthDisplay->isChecked(); m_TexDisplay.green = ui->stencilDisplay->isChecked(); m_TexDisplay.blue = false; diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index 3f7c9ca23..732778d62 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -2317,6 +2317,10 @@ void ReplayProxy::RemapProxyTextureIfNeeded(TextureDescription &tex, GetTextureD switch(tex.format.type) { case ResourceFormatType::S8: + tex.format.compType = CompType::UInt; + params.remap = RemapTexture::RGBA8; + tex.creationFlags &= ~TextureCategory::DepthTarget; + break; case ResourceFormatType::D16S8: case ResourceFormatType::D24S8: case ResourceFormatType::D32S8: diff --git a/renderdoc/driver/d3d11/d3d11_rendertexture.cpp b/renderdoc/driver/d3d11/d3d11_rendertexture.cpp index 1a0a106d5..2bd1f7062 100644 --- a/renderdoc/driver/d3d11/d3d11_rendertexture.cpp +++ b/renderdoc/driver/d3d11/d3d11_rendertexture.cpp @@ -511,7 +511,9 @@ bool D3D11Replay::RenderTextureInternal(TextureDisplay cfg, TexDisplayFlags flag // we create all proxy textures as typeless to allow us to cast, but that means if the remote API // gave us a typed texture and then wants to view it 'typeless' (i.e. as it was created) we need // to restore that type here. - if(typeCast == CompType::Typeless) + // + // we also override the typecast for depth here, to allow handling of S8 textures + if(typeCast == CompType::Typeless || typeCast == CompType::Depth) { auto it = m_ProxyResourceOrigInfo.find(cfg.resourceId); if(it != m_ProxyResourceOrigInfo.end()) diff --git a/renderdoc/driver/gl/gl_debug.cpp b/renderdoc/driver/gl/gl_debug.cpp index 4dcbe09fc..c1e28309a 100644 --- a/renderdoc/driver/gl/gl_debug.cpp +++ b/renderdoc/driver/gl/gl_debug.cpp @@ -1665,8 +1665,7 @@ void GLReplay::PickPixel(ResourceId texture, uint32_t x, uint32_t y, const Subre // at the same time. if(texDetails.internalFormat == eGL_DEPTH24_STENCIL8 || texDetails.internalFormat == eGL_DEPTH32F_STENCIL8 || - texDetails.internalFormat == eGL_DEPTH_STENCIL || - texDetails.internalFormat == eGL_STENCIL_INDEX8) + texDetails.internalFormat == eGL_DEPTH_STENCIL) { texDisplay.red = texDisplay.blue = texDisplay.alpha = false; @@ -1688,14 +1687,6 @@ void GLReplay::PickPixel(ResourceId texture, uint32_t x, uint32_t y, const Subre // not sure whether [0] or [1] will return stencil values, so use // max of two because other channel should be 0 pixel[1] = float(RDCMAX(stencilpixel[0], stencilpixel[1])) / 255.0f; - - // the first depth read will have read stencil instead. - // NULL it out so the UI sees only stencil - if(texDetails.internalFormat == eGL_STENCIL_INDEX8) - { - pixel[1] = float(RDCMAX(stencilpixel[0], stencilpixel[1])) / 255.0f; - pixel[0] = 0.0f; - } } } } diff --git a/renderdoc/driver/gl/gl_rendertexture.cpp b/renderdoc/driver/gl/gl_rendertexture.cpp index b7a3d7008..4f58b96d1 100644 --- a/renderdoc/driver/gl/gl_rendertexture.cpp +++ b/renderdoc/driver/gl/gl_rendertexture.cpp @@ -341,9 +341,14 @@ bool GLReplay::RenderTextureInternal(TextureDisplay cfg, TexDisplayFlags flags) } cfg.rangeMin *= rangeScale; cfg.rangeMax *= rangeScale; + + if(displayFormat == eGL_STENCIL_INDEX8) + cfg.red = true; } else + { dsTexMode = eGL_DEPTH_COMPONENT; + } } else { diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index a46fe018b..69fa5e8ad 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -2612,7 +2612,7 @@ void GLReplay::GetTextureData(ResourceId tex, const Subresource &sub, } // do one more time for the stencil - if(baseFormat == eGL_DEPTH_STENCIL) + if(baseFormat == eGL_DEPTH_STENCIL || baseFormat == eGL_STENCIL_INDEX) { TextureDisplay texDisplay; @@ -2640,6 +2640,8 @@ void GLReplay::GetTextureData(ResourceId tex, const Subresource &sub, GLboolean color_mask[4]; drv.glGetBooleanv(eGL_COLOR_WRITEMASK, color_mask); drv.glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE); + if(baseFormat == eGL_STENCIL_INDEX) + drv.glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_FALSE); flags = TexDisplayFlags( flags & ~(eTexDisplay_RemapFloat | eTexDisplay_RemapUInt | eTexDisplay_RemapSInt)); diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index 3f33c851e..bce509648 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -3398,7 +3398,7 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub, imCreateInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; // we'll need to cast to remap the stencil part - if(IsDepthAndStencilFormat(imInfo.format)) + if(IsStencilFormat(imInfo.format)) imCreateInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; imCreateInfo.extent.width = RDCMAX(1U, imCreateInfo.extent.width >> s.mip); @@ -3488,7 +3488,7 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub, numFBs = imCreateInfo.arrayLayers; // we'll need twice as many temp views/FBs for stencil views - if(IsDepthAndStencilFormat(imInfo.format)) + if(IsStencilFormat(imInfo.format)) { tmpFB = new VkFramebuffer[numFBs * 2]; tmpView = new VkImageView[numFBs * 2]; @@ -3612,6 +3612,15 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub, stencilFlags |= eTexDisplay_RemapUInt | eTexDisplay_GreenOnly; texDisplay.red = texDisplay.blue = texDisplay.alpha = false; + + // S8 renders into red + if(IsStencilOnlyFormat(imInfo.format)) + { + texDisplay.red = true; + texDisplay.green = false; + stencilFlags &= ~eTexDisplay_GreenOnly; + } + RenderTextureInternal(texDisplay, *srcImageState, rpbegin, stencilFlags); renderCount++; } @@ -4169,7 +4178,7 @@ void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub, if(tmpFB != NULL) { - if(IsDepthAndStencilFormat(imInfo.format)) + if(IsStencilFormat(imInfo.format)) numFBs *= 2; for(uint32_t i = 0; i < numFBs; i++) diff --git a/util/test/demos/gl/gl_texture_zoo.cpp b/util/test/demos/gl/gl_texture_zoo.cpp index f76d1d9e0..f3d77ff7a 100644 --- a/util/test/demos/gl/gl_texture_zoo.cpp +++ b/util/test/demos/gl/gl_texture_zoo.cpp @@ -401,7 +401,8 @@ void main() Vec4i dimensions(texWidth, texHeight, texDepth); bool isCompressed = - (test.fmt.cfg.type != TextureType::R9G9B9E5 && test.fmt.cfg.type != TextureType::Regular); + (test.fmt.cfg.type != TextureType::R9G9B9E5 && test.fmt.cfg.type != TextureType::Regular) || + test.fmt.internalFormat == GL_STENCIL_INDEX8; // Some GL drivers report that block compressed textures are supported for MSAA and color // rendering. Save them from themselves. Similarly they report support for 1D and 3D but then it @@ -590,6 +591,9 @@ void main() else if(test.fmt.cfg.componentCount == 1) format = isInt ? GL_RED_INTEGER : GL_RED; + if(test.fmt.internalFormat == GL_STENCIL_INDEX8) + format = GL_STENCIL_INDEX; + if(test.fmt.cfg.type == TextureType::R9G9B9E5) { format = GL_RGB; @@ -881,6 +885,8 @@ void main() TEST_CASE(TextureType::Unknown, GL_DEPTH_COMPONENT24, 0, 0, DataType::Float), TEST_CASE(TextureType::Unknown, GL_DEPTH_COMPONENT16, 0, 0, DataType::Float), + + TEST_CASE(TextureType::Regular, GL_STENCIL_INDEX8, 1, 1, DataType::UInt), }; for(GLFormat f : depth_tests) diff --git a/util/test/rdtest/shared/Texture_Zoo.py b/util/test/rdtest/shared/Texture_Zoo.py index 3d3f4bed0..a666d5c93 100644 --- a/util/test/rdtest/shared/Texture_Zoo.py +++ b/util/test/rdtest/shared/Texture_Zoo.py @@ -74,6 +74,9 @@ class Texture_Zoo(): pickCompType = testCompType + if tex.format.type == rd.ResourceFormatType.S8: + pickCompType = rd.CompType.UInt + # When not running proxied, save non-typecasted textures to disk if not image_view and not self.proxied and (tex.format.compType == testCompType or tex.format.type == rd.ResourceFormatType.D24S8 or @@ -122,8 +125,6 @@ class Texture_Zoo(): except Exception: pass - value0 = [] - # When viewing PNGs only compare the components that the original texture had if test_mode == Texture_Zoo.TEST_PNG: tex.format = self.textures[self.filename].format @@ -132,6 +133,10 @@ class Texture_Zoo(): tex.arraysize = 1 tex.depth = 1 self.fake_msaa = 'MSAA' in name + + orig_format = self.textures[self.filename].format + if orig_format.type == rd.ResourceFormatType.S8: + pickCompType = rd.CompType.UInt elif test_mode == Texture_Zoo.TEST_DDS: tex_format = tex.format orig_format = self.textures[self.filename].format @@ -148,6 +153,11 @@ class Texture_Zoo(): if orig_format.compType == rd.CompType.UNormSRGB and tex_format.compCount < 4: tex_format.compType = orig_format.compType + # S8 will be loaded up as R8_UINT + if orig_format.type == rd.ResourceFormatType.S8: + tex_format = orig_format + pickCompType = rd.CompType.UInt + if tex_format.type == rd.ResourceFormatType.D24S8 or tex_format.type == rd.ResourceFormatType.D16S8 or tex_format.type == rd.ResourceFormatType.D32S8: if tex_format.type != orig_format.type: raise rdtest.TestFailureException( @@ -202,7 +212,7 @@ class Texture_Zoo(): eps = (eps_significand / 127.0) elif tex.format.compByteWidth == 1: eps = (eps_significand / 255.0) - elif testCompType == rd.CompType.Depth and tex.format.compCount == 2: + elif testCompType == rd.CompType.Depth and tex.format.compCount == 2 or tex.format.type == rd.ResourceFormatType.S8: eps = (eps_significand / 255.0) # stencil is only 8-bit elif tex.format.type == rd.ResourceFormatType.A8: eps = (eps_significand / 255.0) @@ -348,7 +358,7 @@ class Texture_Zoo(): picked = self.get_picked_pixel_value(comp_count, pickCompType, cur_sub, tex, tex_id, x, y) if mp == 0 and sl == 0 and sm == 0 and x == 0 and y == 0: - value0 = picked + pass if not rdtest.value_compare(picked, expected, eps): raise rdtest.TestFailureException( @@ -374,9 +384,7 @@ class Texture_Zoo(): # Clamp to number of components in the texture picked = picked[0:comp_count] - # If we didn't get a value0 (because we did all texture render compares) then fetch it here - if len(value0) == 0: - value0 = self.get_picked_pixel_value(comp_count, pickCompType, rd.Subresource(), tex, tex_id, 0, 0) + value0 = self.get_picked_pixel_value(comp_count, pickCompType, rd.Subresource(), tex, tex_id, 0, 0) # Up-convert any non-float expected values to floats value0 = [float(x) for x in value0] @@ -398,6 +406,8 @@ class Texture_Zoo(): value0[1] = 0.0 if picked[1] > 1.0: picked[1] /= 255.0 + elif tex.format.type == rd.ResourceFormatType.S8: + picked[0] /= 255.0 if not rdtest.value_compare(picked, value0, eps): raise rdtest.TestFailureException( @@ -421,13 +431,17 @@ class Texture_Zoo(): if tex.arraysize > 1 and ((sl % 2) == 1) and ((int(x / 2) % 2) != (int(y / 2) % 2)): inverted = not inverted - if comp_type == rd.CompType.UInt or comp_type == rd.CompType.SInt: + if comp_type == rd.CompType.UInt or comp_type == rd.CompType.SInt or tex.format.type == rd.ResourceFormatType.S8: expected = [10.0, 40.0, 70.0, 100.0] if inverted: expected = list(reversed(expected)) expected = [c + 10.0 * (sm + mp) for c in expected] + + # Normalise stencil value + if tex.format.type == rd.ResourceFormatType.S8: + expected[0] = expected[0] / 255.0 elif (tex.format.type == rd.ResourceFormatType.D16S8 or tex.format.type == rd.ResourceFormatType.D24S8 or tex.format.type == rd.ResourceFormatType.D32S8): @@ -510,6 +524,10 @@ class Texture_Zoo(): if tex.format.type == rd.ResourceFormatType.A8: picked[0] = picked[3] + # Normalise stencil values + if tex.format.type == rd.ResourceFormatType.S8: + picked[0] /= 255.0 + # Clamp to number of components in the texture picked = picked[0:comp_count]