Implement using a layer of a texture as color attachment - Part I
This patch implements using a layer of a texture as a color attachment on D3D12, Metal and Vulkan. This feature is not implemented on OpenGL back-ends in this patch. BUG=dawn:16 TEST=dawn_unittests Change-Id: Iffc194c6117f6e3e6506c6fcbfd51ca2fbe9ede8 Reviewed-on: https://dawn-review.googlesource.com/c/2660 Commit-Queue: Jiawei Shao <jiawei.shao@intel.com> Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
parent
66b024e499
commit
33af94fd8d
|
@ -103,19 +103,20 @@ namespace dawn_native {
|
|||
|
||||
RenderPassDescriptorBase* RenderPassDescriptorBuilder::GetResultImpl() {
|
||||
auto CheckOrSetSize = [this](const TextureViewBase* attachment) -> bool {
|
||||
uint32_t mipLevel = attachment->GetBaseMipLevel();
|
||||
if (this->mWidth == 0) {
|
||||
ASSERT(this->mHeight == 0);
|
||||
|
||||
this->mWidth = attachment->GetTexture()->GetSize().width;
|
||||
this->mHeight = attachment->GetTexture()->GetSize().height;
|
||||
this->mWidth = attachment->GetTexture()->GetSize().width >> mipLevel;
|
||||
this->mHeight = attachment->GetTexture()->GetSize().height >> mipLevel;
|
||||
ASSERT(this->mWidth != 0 && this->mHeight != 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ASSERT(this->mWidth != 0 && this->mHeight != 0);
|
||||
return this->mWidth == attachment->GetTexture()->GetSize().width &&
|
||||
this->mHeight == attachment->GetTexture()->GetSize().height;
|
||||
return this->mWidth == attachment->GetTexture()->GetSize().width >> mipLevel &&
|
||||
this->mHeight == attachment->GetTexture()->GetSize().height >> mipLevel;
|
||||
};
|
||||
|
||||
uint32_t attachmentCount = 0;
|
||||
|
|
|
@ -300,7 +300,9 @@ namespace dawn_native {
|
|||
: ObjectBase(texture->GetDevice()),
|
||||
mTexture(texture),
|
||||
mFormat(descriptor->format),
|
||||
mBaseMipLevel(descriptor->baseMipLevel),
|
||||
mLevelCount(descriptor->levelCount),
|
||||
mBaseArrayLayer(descriptor->baseArrayLayer),
|
||||
mLayerCount(descriptor->layerCount) {
|
||||
}
|
||||
|
||||
|
@ -316,10 +318,18 @@ namespace dawn_native {
|
|||
return mFormat;
|
||||
}
|
||||
|
||||
uint32_t TextureViewBase::GetBaseMipLevel() const {
|
||||
return mBaseMipLevel;
|
||||
}
|
||||
|
||||
uint32_t TextureViewBase::GetLevelCount() const {
|
||||
return mLevelCount;
|
||||
}
|
||||
|
||||
uint32_t TextureViewBase::GetBaseArrayLayer() const {
|
||||
return mBaseArrayLayer;
|
||||
}
|
||||
|
||||
uint32_t TextureViewBase::GetLayerCount() const {
|
||||
return mLayerCount;
|
||||
}
|
||||
|
|
|
@ -76,14 +76,18 @@ namespace dawn_native {
|
|||
TextureBase* GetTexture();
|
||||
|
||||
dawn::TextureFormat GetFormat() const;
|
||||
uint32_t GetBaseMipLevel() const;
|
||||
uint32_t GetLevelCount() const;
|
||||
uint32_t GetBaseArrayLayer() const;
|
||||
uint32_t GetLayerCount() const;
|
||||
|
||||
private:
|
||||
Ref<TextureBase> mTexture;
|
||||
|
||||
dawn::TextureFormat mFormat;
|
||||
uint32_t mBaseMipLevel;
|
||||
uint32_t mLevelCount;
|
||||
uint32_t mBaseArrayLayer;
|
||||
uint32_t mLayerCount;
|
||||
};
|
||||
|
||||
|
|
|
@ -226,22 +226,33 @@ namespace dawn_native { namespace d3d12 {
|
|||
}
|
||||
}
|
||||
|
||||
DXGI_FORMAT TextureView::GetD3D12Format() const {
|
||||
return D3D12TextureFormat(GetFormat());
|
||||
}
|
||||
|
||||
const D3D12_SHADER_RESOURCE_VIEW_DESC& TextureView::GetSRVDescriptor() const {
|
||||
return mSrvDesc;
|
||||
}
|
||||
|
||||
// TODO(jiawei.shao@intel.com): support rendering into a layer of a texture.
|
||||
D3D12_RENDER_TARGET_VIEW_DESC TextureView::GetRTVDescriptor() {
|
||||
D3D12_RENDER_TARGET_VIEW_DESC TextureView::GetRTVDescriptor() const {
|
||||
ASSERT(GetTexture()->GetDimension() == dawn::TextureDimension::e2D);
|
||||
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc;
|
||||
rtvDesc.Format = ToBackend(GetTexture())->GetD3D12Format();
|
||||
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||
rtvDesc.Texture2D.MipSlice = 0;
|
||||
rtvDesc.Texture2D.PlaneSlice = 0;
|
||||
rtvDesc.Format = GetD3D12Format();
|
||||
// Currently we always use D3D12_TEX2D_ARRAY_RTV because we cannot specify base array layer
|
||||
// and layer count in D3D12_TEX2D_RTV. For 2D texture views, we treat them as 1-layer 2D
|
||||
// array textures. (Just like how we treat SRVs)
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_tex2d_rtv
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_tex2d_array_rtv
|
||||
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
rtvDesc.Texture2DArray.FirstArraySlice = GetBaseArrayLayer();
|
||||
rtvDesc.Texture2DArray.ArraySize = GetLayerCount();
|
||||
rtvDesc.Texture2DArray.MipSlice = GetBaseMipLevel();
|
||||
rtvDesc.Texture2DArray.PlaneSlice = 0;
|
||||
return rtvDesc;
|
||||
}
|
||||
|
||||
// TODO(jiawei.shao@intel.com): support rendering into a layer of a texture.
|
||||
D3D12_DEPTH_STENCIL_VIEW_DESC TextureView::GetDSVDescriptor() {
|
||||
D3D12_DEPTH_STENCIL_VIEW_DESC TextureView::GetDSVDescriptor() const {
|
||||
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc;
|
||||
dsvDesc.Format = ToBackend(GetTexture())->GetD3D12Format();
|
||||
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
|
||||
|
|
|
@ -49,9 +49,11 @@ namespace dawn_native { namespace d3d12 {
|
|||
public:
|
||||
TextureView(TextureBase* texture, const TextureViewDescriptor* descriptor);
|
||||
|
||||
DXGI_FORMAT GetD3D12Format() const;
|
||||
|
||||
const D3D12_SHADER_RESOURCE_VIEW_DESC& GetSRVDescriptor() const;
|
||||
D3D12_RENDER_TARGET_VIEW_DESC GetRTVDescriptor();
|
||||
D3D12_DEPTH_STENCIL_VIEW_DESC GetDSVDescriptor();
|
||||
D3D12_RENDER_TARGET_VIEW_DESC GetRTVDescriptor() const;
|
||||
D3D12_DEPTH_STENCIL_VIEW_DESC GetDSVDescriptor() const;
|
||||
|
||||
private:
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC mSrvDesc;
|
||||
|
|
|
@ -63,9 +63,8 @@ namespace dawn_native { namespace metal {
|
|||
descriptor.colorAttachments[i].loadAction = MTLLoadActionLoad;
|
||||
}
|
||||
|
||||
// TODO(jiawei.shao@intel.com): support rendering into a layer of a texture.
|
||||
descriptor.colorAttachments[i].texture =
|
||||
ToBackend(attachmentInfo.view->GetTexture())->GetMTLTexture();
|
||||
ToBackend(attachmentInfo.view)->GetMTLTexture();
|
||||
descriptor.colorAttachments[i].storeAction = MTLStoreActionStore;
|
||||
}
|
||||
|
||||
|
|
|
@ -292,6 +292,7 @@ std::ostringstream& DawnTest::AddTextureExpectation(const char* file,
|
|||
uint32_t width,
|
||||
uint32_t height,
|
||||
uint32_t level,
|
||||
uint32_t slice,
|
||||
uint32_t pixelSize,
|
||||
detail::Expectation* expectation) {
|
||||
uint32_t rowPitch = Align(width * pixelSize, kTextureRowPitchAlignment);
|
||||
|
@ -302,7 +303,7 @@ std::ostringstream& DawnTest::AddTextureExpectation(const char* file,
|
|||
// We need to enqueue the copy immediately because by the time we resolve the expectation,
|
||||
// the texture might have been modified.
|
||||
dawn::TextureCopyView textureCopyView =
|
||||
utils::CreateTextureCopyView(texture, level, 0, {x, y, 0}, dawn::TextureAspect::Color);
|
||||
utils::CreateTextureCopyView(texture, level, slice, {x, y, 0}, dawn::TextureAspect::Color);
|
||||
dawn::BufferCopyView bufferCopyView =
|
||||
utils::CreateBufferCopyView(readback.buffer, readback.offset, rowPitch, 0);
|
||||
dawn::Extent3D copySize = {width, height, 1};
|
||||
|
|
|
@ -36,11 +36,12 @@
|
|||
|
||||
// Test a pixel of the mip level 0 of a 2D texture.
|
||||
#define EXPECT_PIXEL_RGBA8_EQ(expected, texture, x, y) \
|
||||
AddTextureExpectation(__FILE__, __LINE__, texture, x, y, 1, 1, 0, sizeof(RGBA8), \
|
||||
AddTextureExpectation(__FILE__, __LINE__, texture, x, y, 1, 1, 0, 0, sizeof(RGBA8), \
|
||||
new detail::ExpectEq<RGBA8>(expected))
|
||||
|
||||
#define EXPECT_TEXTURE_RGBA8_EQ(expected, texture, x, y, width, height, level) \
|
||||
AddTextureExpectation(__FILE__, __LINE__, texture, x, y, width, height, level, sizeof(RGBA8), \
|
||||
#define EXPECT_TEXTURE_RGBA8_EQ(expected, texture, x, y, width, height, level, slice) \
|
||||
AddTextureExpectation(__FILE__, __LINE__, texture, x, y, width, height, level, slice, \
|
||||
sizeof(RGBA8), \
|
||||
new detail::ExpectEq<RGBA8>(expected, (width) * (height)))
|
||||
|
||||
struct RGBA8 {
|
||||
|
@ -122,6 +123,7 @@ class DawnTest : public ::testing::TestWithParam<BackendType> {
|
|||
uint32_t width,
|
||||
uint32_t height,
|
||||
uint32_t level,
|
||||
uint32_t slice,
|
||||
uint32_t pixelSize,
|
||||
detail::Expectation* expectation);
|
||||
|
||||
|
|
|
@ -235,7 +235,7 @@ protected:
|
|||
std::vector<RGBA8> expected(rowPitch / kBytesPerTexel * (textureSpec.copyHeight - 1) + textureSpec.copyWidth);
|
||||
PackTextureData(&bufferData[bufferSpec.offset / kBytesPerTexel], textureSpec.copyWidth, textureSpec.copyHeight, bufferSpec.rowPitch / kBytesPerTexel, expected.data(), textureSpec.copyWidth);
|
||||
|
||||
EXPECT_TEXTURE_RGBA8_EQ(expected.data(), texture, textureSpec.x, textureSpec.y, textureSpec.copyWidth, textureSpec.copyHeight, textureSpec.level) <<
|
||||
EXPECT_TEXTURE_RGBA8_EQ(expected.data(), texture, textureSpec.x, textureSpec.y, textureSpec.copyWidth, textureSpec.copyHeight, textureSpec.level, 0) <<
|
||||
"Buffer to Texture copy failed copying "
|
||||
<< bufferSpec.size << "-byte buffer with offset " << bufferSpec.offset << " and row pitch " << bufferSpec.rowPitch << " to [("
|
||||
<< textureSpec.x << ", " << textureSpec.y << "), (" << textureSpec.x + textureSpec.copyWidth << ", " << textureSpec.y + textureSpec.copyHeight <<
|
||||
|
|
|
@ -133,10 +133,10 @@ TEST_P(RenderPassLoadOpTests, ColorClearThenLoadAndDraw) {
|
|||
auto commandsClearGreen = commandsClearGreenBuilder.GetResult();
|
||||
|
||||
queue.Submit(1, &commandsClearZero);
|
||||
EXPECT_TEXTURE_RGBA8_EQ(expectZero.data(), renderTarget, 0, 0, kRTSize, kRTSize, 0);
|
||||
EXPECT_TEXTURE_RGBA8_EQ(expectZero.data(), renderTarget, 0, 0, kRTSize, kRTSize, 0, 0);
|
||||
|
||||
queue.Submit(1, &commandsClearGreen);
|
||||
EXPECT_TEXTURE_RGBA8_EQ(expectGreen.data(), renderTarget, 0, 0, kRTSize, kRTSize, 0);
|
||||
EXPECT_TEXTURE_RGBA8_EQ(expectGreen.data(), renderTarget, 0, 0, kRTSize, kRTSize, 0, 0);
|
||||
|
||||
// Part 2: draw a blue quad into the right half of the render target, and check result
|
||||
|
||||
|
@ -155,9 +155,9 @@ TEST_P(RenderPassLoadOpTests, ColorClearThenLoadAndDraw) {
|
|||
|
||||
queue.Submit(1, &commandsLoad);
|
||||
// Left half should still be green
|
||||
EXPECT_TEXTURE_RGBA8_EQ(expectGreen.data(), renderTarget, 0, 0, kRTSize / 2, kRTSize, 0);
|
||||
EXPECT_TEXTURE_RGBA8_EQ(expectGreen.data(), renderTarget, 0, 0, kRTSize / 2, kRTSize, 0, 0);
|
||||
// Right half should now be blue
|
||||
EXPECT_TEXTURE_RGBA8_EQ(expectBlue.data(), renderTarget, kRTSize / 2, 0, kRTSize / 2, kRTSize, 0);
|
||||
EXPECT_TEXTURE_RGBA8_EQ(expectBlue.data(), renderTarget, kRTSize / 2, 0, kRTSize / 2, kRTSize, 0, 0);
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(RenderPassLoadOpTests, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend)
|
||||
|
|
|
@ -16,13 +16,59 @@
|
|||
|
||||
#include "common/Assert.h"
|
||||
#include "common/Constants.h"
|
||||
#include "common/Math.h"
|
||||
#include "utils/DawnHelpers.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
constexpr static unsigned int kRTSize = 64;
|
||||
constexpr dawn::TextureFormat kDefaultFormat = dawn::TextureFormat::R8G8B8A8Unorm;
|
||||
constexpr uint32_t kBytesPerTexel = 4;
|
||||
|
||||
class TextureViewTest : public DawnTest {
|
||||
namespace {
|
||||
dawn::Texture Create2DTexture(dawn::Device device,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
uint32_t layerCount,
|
||||
uint32_t levelCount,
|
||||
dawn::TextureUsageBit usage) {
|
||||
dawn::TextureDescriptor descriptor;
|
||||
descriptor.dimension = dawn::TextureDimension::e2D;
|
||||
descriptor.size.width = width;
|
||||
descriptor.size.height = height;
|
||||
descriptor.size.depth = 1;
|
||||
descriptor.arrayLayer = layerCount;
|
||||
descriptor.format = kDefaultFormat;
|
||||
descriptor.levelCount = levelCount;
|
||||
descriptor.usage = usage;
|
||||
return device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
dawn::ShaderModule CreateDefaultVertexShaderModule(dawn::Device device) {
|
||||
return utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, R"(
|
||||
#version 450
|
||||
layout (location = 0) out vec2 o_texCoord;
|
||||
void main() {
|
||||
const vec2 pos[6] = vec2[6](vec2(-2.f, -2.f),
|
||||
vec2(-2.f, 2.f),
|
||||
vec2( 2.f, -2.f),
|
||||
vec2(-2.f, 2.f),
|
||||
vec2( 2.f, -2.f),
|
||||
vec2( 2.f, 2.f));
|
||||
const vec2 texCoord[6] = vec2[6](vec2(0.f, 0.f),
|
||||
vec2(0.f, 1.f),
|
||||
vec2(1.f, 0.f),
|
||||
vec2(0.f, 1.f),
|
||||
vec2(1.f, 0.f),
|
||||
vec2(1.f, 1.f));
|
||||
gl_Position = vec4(pos[gl_VertexIndex], 0.f, 1.f);
|
||||
o_texCoord = texCoord[gl_VertexIndex];
|
||||
}
|
||||
)");
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
class TextureViewSamplingTest : public DawnTest {
|
||||
protected:
|
||||
// Generates an arbitrary pixel value per-layer-per-level, used for the "actual" uploaded
|
||||
// textures and the "expected" results.
|
||||
|
@ -55,50 +101,22 @@ protected:
|
|||
|
||||
mPipelineLayout = utils::MakeBasicPipelineLayout(device, &mBindGroupLayout);
|
||||
|
||||
mVSModule = utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, R"(
|
||||
#version 450
|
||||
layout (location = 0) out vec2 o_texCoord;
|
||||
void main() {
|
||||
const vec2 pos[6] = vec2[6](vec2(-2.f, -2.f),
|
||||
vec2(-2.f, 2.f),
|
||||
vec2( 2.f, -2.f),
|
||||
vec2(-2.f, 2.f),
|
||||
vec2( 2.f, -2.f),
|
||||
vec2( 2.f, 2.f));
|
||||
const vec2 texCoord[6] = vec2[6](vec2(0.f, 0.f),
|
||||
vec2(0.f, 1.f),
|
||||
vec2(1.f, 0.f),
|
||||
vec2(0.f, 1.f),
|
||||
vec2(1.f, 0.f),
|
||||
vec2(1.f, 1.f));
|
||||
gl_Position = vec4(pos[gl_VertexIndex], 0.f, 1.f);
|
||||
o_texCoord = texCoord[gl_VertexIndex];
|
||||
}
|
||||
)");
|
||||
mVSModule = CreateDefaultVertexShaderModule(device);
|
||||
}
|
||||
|
||||
void initTexture(uint32_t layerCount, uint32_t levelCount) {
|
||||
ASSERT(layerCount > 0 && levelCount > 0);
|
||||
|
||||
constexpr dawn::TextureFormat kFormat = dawn::TextureFormat::R8G8B8A8Unorm;
|
||||
|
||||
const uint32_t textureWidthLevel0 = 1 << levelCount;
|
||||
const uint32_t textureHeightLevel0 = 1 << levelCount;
|
||||
|
||||
dawn::TextureDescriptor descriptor;
|
||||
descriptor.dimension = dawn::TextureDimension::e2D;
|
||||
descriptor.size.width = textureWidthLevel0;
|
||||
descriptor.size.height = textureHeightLevel0;
|
||||
descriptor.size.depth = 1;
|
||||
descriptor.arrayLayer = layerCount;
|
||||
descriptor.format = kFormat;
|
||||
descriptor.levelCount = levelCount;
|
||||
descriptor.usage = dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::Sampled;
|
||||
mTexture = device.CreateTexture(&descriptor);
|
||||
constexpr dawn::TextureUsageBit kUsage =
|
||||
dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::Sampled;
|
||||
mTexture = Create2DTexture(
|
||||
device, textureWidthLevel0, textureHeightLevel0, layerCount, levelCount, kUsage);
|
||||
|
||||
mDefaultTextureViewDescriptor.nextInChain = nullptr;
|
||||
mDefaultTextureViewDescriptor.dimension = dawn::TextureViewDimension::e2DArray;
|
||||
mDefaultTextureViewDescriptor.format = kFormat;
|
||||
mDefaultTextureViewDescriptor.format = kDefaultFormat;
|
||||
mDefaultTextureViewDescriptor.baseMipLevel = 0;
|
||||
mDefaultTextureViewDescriptor.levelCount = levelCount;
|
||||
mDefaultTextureViewDescriptor.baseArrayLayer = 0;
|
||||
|
@ -328,7 +346,7 @@ protected:
|
|||
};
|
||||
|
||||
// Test drawing a rect with a 2D array texture.
|
||||
TEST_P(TextureViewTest, Default2DArrayTexture) {
|
||||
TEST_P(TextureViewSamplingTest, Default2DArrayTexture) {
|
||||
// TODO(cwallez@chromium.org) understand what the issue is
|
||||
DAWN_SKIP_TEST_IF(IsVulkan() && IsNvidia());
|
||||
|
||||
|
@ -359,58 +377,58 @@ TEST_P(TextureViewTest, Default2DArrayTexture) {
|
|||
}
|
||||
|
||||
// Test sampling from a 2D texture view created on a 2D array texture.
|
||||
TEST_P(TextureViewTest, Texture2DViewOn2DArrayTexture) {
|
||||
TEST_P(TextureViewSamplingTest, Texture2DViewOn2DArrayTexture) {
|
||||
Texture2DViewTest(6, 1, 4, 0);
|
||||
}
|
||||
|
||||
// Test sampling from a 2D array texture view created on a 2D array texture.
|
||||
TEST_P(TextureViewTest, Texture2DArrayViewOn2DArrayTexture) {
|
||||
TEST_P(TextureViewSamplingTest, Texture2DArrayViewOn2DArrayTexture) {
|
||||
DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
|
||||
Texture2DArrayViewTest(6, 1, 2, 0);
|
||||
}
|
||||
|
||||
// Test sampling from a 2D texture view created on a mipmap level of a 2D texture.
|
||||
TEST_P(TextureViewTest, Texture2DViewOnOneLevelOf2DTexture) {
|
||||
TEST_P(TextureViewSamplingTest, Texture2DViewOnOneLevelOf2DTexture) {
|
||||
Texture2DViewTest(1, 6, 0, 4);
|
||||
}
|
||||
|
||||
// Test sampling from a 2D texture view created on a mipmap level of a 2D array texture layer.
|
||||
TEST_P(TextureViewTest, Texture2DViewOnOneLevelOf2DArrayTexture) {
|
||||
TEST_P(TextureViewSamplingTest, Texture2DViewOnOneLevelOf2DArrayTexture) {
|
||||
Texture2DViewTest(6, 6, 3, 4);
|
||||
}
|
||||
|
||||
// Test sampling from a 2D array texture view created on a mipmap level of a 2D array texture.
|
||||
TEST_P(TextureViewTest, Texture2DArrayViewOnOneLevelOf2DArrayTexture) {
|
||||
TEST_P(TextureViewSamplingTest, Texture2DArrayViewOnOneLevelOf2DArrayTexture) {
|
||||
DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
|
||||
Texture2DArrayViewTest(6, 6, 2, 4);
|
||||
}
|
||||
|
||||
// Test sampling from a cube map texture view that covers a whole 2D array texture.
|
||||
TEST_P(TextureViewTest, TextureCubeMapOnWholeTexture) {
|
||||
TEST_P(TextureViewSamplingTest, TextureCubeMapOnWholeTexture) {
|
||||
constexpr uint32_t kTotalLayers = 6;
|
||||
TextureCubeMapTest(kTotalLayers, 0, kTotalLayers, false);
|
||||
}
|
||||
|
||||
// Test sampling from a cube map texture view that covers a sub part of a 2D array texture.
|
||||
TEST_P(TextureViewTest, TextureCubeMapViewOnPartOfTexture) {
|
||||
TEST_P(TextureViewSamplingTest, TextureCubeMapViewOnPartOfTexture) {
|
||||
TextureCubeMapTest(10, 2, 6, false);
|
||||
}
|
||||
|
||||
// Test sampling from a cube map texture view that covers the last layer of a 2D array texture.
|
||||
TEST_P(TextureViewTest, TextureCubeMapViewCoveringLastLayer) {
|
||||
TEST_P(TextureViewSamplingTest, TextureCubeMapViewCoveringLastLayer) {
|
||||
constexpr uint32_t kTotalLayers = 10;
|
||||
constexpr uint32_t kBaseLayer = 4;
|
||||
TextureCubeMapTest(kTotalLayers, kBaseLayer, kTotalLayers - kBaseLayer, false);
|
||||
}
|
||||
|
||||
// Test sampling from a cube map texture array view that covers a whole 2D array texture.
|
||||
TEST_P(TextureViewTest, TextureCubeMapArrayOnWholeTexture) {
|
||||
TEST_P(TextureViewSamplingTest, TextureCubeMapArrayOnWholeTexture) {
|
||||
constexpr uint32_t kTotalLayers = 12;
|
||||
TextureCubeMapTest(kTotalLayers, 0, kTotalLayers, true);
|
||||
}
|
||||
|
||||
// Test sampling from a cube map texture array view that covers a sub part of a 2D array texture.
|
||||
TEST_P(TextureViewTest, TextureCubeMapArrayViewOnPartOfTexture) {
|
||||
TEST_P(TextureViewSamplingTest, TextureCubeMapArrayViewOnPartOfTexture) {
|
||||
// Test failing on the GPU FYI Mac Pro (AMD), see
|
||||
// https://bugs.chromium.org/p/dawn/issues/detail?id=58
|
||||
DAWN_SKIP_TEST_IF(IsMacOS() && IsMetal() && IsAMD());
|
||||
|
@ -419,7 +437,7 @@ TEST_P(TextureViewTest, TextureCubeMapArrayViewOnPartOfTexture) {
|
|||
}
|
||||
|
||||
// Test sampling from a cube map texture array view that covers the last layer of a 2D array texture.
|
||||
TEST_P(TextureViewTest, TextureCubeMapArrayViewCoveringLastLayer) {
|
||||
TEST_P(TextureViewSamplingTest, TextureCubeMapArrayViewCoveringLastLayer) {
|
||||
// Test failing on the GPU FYI Mac Pro (AMD), see
|
||||
// https://bugs.chromium.org/p/dawn/issues/detail?id=58
|
||||
DAWN_SKIP_TEST_IF(IsMacOS() && IsMetal() && IsAMD());
|
||||
|
@ -430,7 +448,7 @@ TEST_P(TextureViewTest, TextureCubeMapArrayViewCoveringLastLayer) {
|
|||
}
|
||||
|
||||
// Test sampling from a cube map array texture view that only has a single cube map.
|
||||
TEST_P(TextureViewTest, TextureCubeMapArrayViewSingleCubeMap) {
|
||||
TEST_P(TextureViewSamplingTest, TextureCubeMapArrayViewSingleCubeMap) {
|
||||
// Test failing on the GPU FYI Mac Pro (AMD), see
|
||||
// https://bugs.chromium.org/p/dawn/issues/detail?id=58
|
||||
DAWN_SKIP_TEST_IF(IsMacOS() && IsMetal() && IsAMD());
|
||||
|
@ -438,4 +456,170 @@ TEST_P(TextureViewTest, TextureCubeMapArrayViewSingleCubeMap) {
|
|||
TextureCubeMapTest(20, 7, 6, true);
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(TextureViewTest, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend)
|
||||
class TextureViewRenderingTest : public DawnTest {
|
||||
protected:
|
||||
void TextureLayerAsColorAttachmentTest(dawn::TextureViewDimension dimension,
|
||||
uint32_t layerCount,
|
||||
uint32_t levelCount,
|
||||
uint32_t textureViewBaseLayer,
|
||||
uint32_t textureViewBaseLevel) {
|
||||
ASSERT(dimension == dawn::TextureViewDimension::e2D ||
|
||||
dimension == dawn::TextureViewDimension::e2DArray);
|
||||
ASSERT_LT(textureViewBaseLayer, layerCount);
|
||||
ASSERT_LT(textureViewBaseLevel, levelCount);
|
||||
|
||||
const uint32_t textureWidthLevel0 = 1 << levelCount;
|
||||
const uint32_t textureHeightLevel0 = 1 << levelCount;
|
||||
constexpr dawn::TextureUsageBit kUsage = dawn::TextureUsageBit::OutputAttachment |
|
||||
dawn::TextureUsageBit::TransferSrc;
|
||||
dawn::Texture texture = Create2DTexture(
|
||||
device, textureWidthLevel0, textureHeightLevel0, layerCount, levelCount, kUsage);
|
||||
|
||||
dawn::TextureViewDescriptor descriptor;
|
||||
descriptor.format = kDefaultFormat;
|
||||
descriptor.dimension = dimension;
|
||||
descriptor.baseArrayLayer = textureViewBaseLayer;
|
||||
descriptor.layerCount = 1;
|
||||
descriptor.baseMipLevel = textureViewBaseLevel;
|
||||
descriptor.levelCount = 1;
|
||||
dawn::TextureView textureView = texture.CreateTextureView(&descriptor);
|
||||
|
||||
dawn::ShaderModule vsModule = CreateDefaultVertexShaderModule(device);
|
||||
|
||||
// Clear textureView with Red(255, 0, 0, 255) and render Green(0, 255, 0, 255) into it
|
||||
dawn::RenderPassDescriptor renderPassInfo = device.CreateRenderPassDescriptorBuilder()
|
||||
.SetColorAttachment(0, textureView, dawn::LoadOp::Clear)
|
||||
.SetColorAttachmentClearColor(0, 1.0, 0.0, 0.0, 1.0)
|
||||
.GetResult();
|
||||
|
||||
const char* oneColorFragmentShader = R"(
|
||||
#version 450
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
fragColor = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
}
|
||||
)";
|
||||
dawn::ShaderModule oneColorFsModule =
|
||||
utils::CreateShaderModule(device, dawn::ShaderStage::Fragment, oneColorFragmentShader);
|
||||
|
||||
dawn::RenderPipeline oneColorPipeline = device.CreateRenderPipelineBuilder()
|
||||
.SetColorAttachmentFormat(0, kDefaultFormat)
|
||||
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
|
||||
.SetStage(dawn::ShaderStage::Fragment, oneColorFsModule, "main")
|
||||
.GetResult();
|
||||
dawn::CommandBufferBuilder commandBufferBuilder = device.CreateCommandBufferBuilder();
|
||||
{
|
||||
dawn::RenderPassEncoder pass =
|
||||
commandBufferBuilder.BeginRenderPass(renderPassInfo);
|
||||
pass.SetRenderPipeline(oneColorPipeline);
|
||||
pass.DrawArrays(6, 1, 0, 0);
|
||||
pass.EndPass();
|
||||
}
|
||||
|
||||
dawn::CommandBuffer commands = commandBufferBuilder.GetResult();
|
||||
queue.Submit(1, &commands);
|
||||
|
||||
// Check if the right pixels (Green) have been written into the right part of the texture.
|
||||
uint32_t textureViewWidth = textureWidthLevel0 >> textureViewBaseLevel;
|
||||
uint32_t textureViewHeight = textureHeightLevel0 >> textureViewBaseLevel;
|
||||
uint32_t rowPitch = Align(kBytesPerTexel * textureWidthLevel0, kTextureRowPitchAlignment);
|
||||
uint32_t expectedDataSize =
|
||||
rowPitch / kBytesPerTexel * (textureWidthLevel0 - 1) + textureHeightLevel0;
|
||||
constexpr RGBA8 kExpectedPixel(0, 255, 0, 255);
|
||||
std::vector<RGBA8> expected(expectedDataSize, kExpectedPixel);
|
||||
EXPECT_TEXTURE_RGBA8_EQ(
|
||||
expected.data(), texture, 0, 0, textureViewWidth, textureViewHeight,
|
||||
textureViewBaseLevel, textureViewBaseLayer);
|
||||
}
|
||||
};
|
||||
|
||||
// Test rendering into a 2D texture view created on a mipmap level of a 2D texture.
|
||||
TEST_P(TextureViewRenderingTest, Texture2DViewOnALevelOf2DTextureAsColorAttachment) {
|
||||
constexpr uint32_t kLayers = 1;
|
||||
constexpr uint32_t kMipLevels = 4;
|
||||
constexpr uint32_t kBaseLayer = 0;
|
||||
|
||||
// Rendering into the first level
|
||||
{
|
||||
constexpr uint32_t kBaseLevel = 0;
|
||||
TextureLayerAsColorAttachmentTest(
|
||||
dawn::TextureViewDimension::e2D, kLayers, kMipLevels, kBaseLayer, kBaseLevel);
|
||||
}
|
||||
|
||||
// Rendering into the last level
|
||||
{
|
||||
constexpr uint32_t kBaseLevel = kMipLevels - 1;
|
||||
TextureLayerAsColorAttachmentTest(
|
||||
dawn::TextureViewDimension::e2D, kLayers, kMipLevels, kBaseLayer, kBaseLevel);
|
||||
}
|
||||
}
|
||||
|
||||
// Test rendering into a 2D texture view created on a layer of a 2D array texture.
|
||||
TEST_P(TextureViewRenderingTest, Texture2DViewOnALayerOf2DArrayTextureAsColorAttachment) {
|
||||
constexpr uint32_t kMipLevels = 1;
|
||||
constexpr uint32_t kBaseLevel = 0;
|
||||
constexpr uint32_t kLayers = 10;
|
||||
|
||||
// Rendering into the first layer
|
||||
{
|
||||
constexpr uint32_t kBaseLayer = 0;
|
||||
TextureLayerAsColorAttachmentTest(
|
||||
dawn::TextureViewDimension::e2D, kLayers, kMipLevels, kBaseLayer, kBaseLevel);
|
||||
}
|
||||
|
||||
// Rendering into the last layer
|
||||
{
|
||||
constexpr uint32_t kBaseLayer = kLayers - 1;
|
||||
TextureLayerAsColorAttachmentTest(
|
||||
dawn::TextureViewDimension::e2D, kLayers, kMipLevels, kBaseLayer, kBaseLevel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Test rendering into a 1-layer 2D array texture view created on a mipmap level of a 2D texture.
|
||||
TEST_P(TextureViewRenderingTest, Texture2DArrayViewOnALevelOf2DTextureAsColorAttachment) {
|
||||
constexpr uint32_t kLayers = 1;
|
||||
constexpr uint32_t kMipLevels = 4;
|
||||
constexpr uint32_t kBaseLayer = 0;
|
||||
|
||||
// Rendering into the first level
|
||||
{
|
||||
constexpr uint32_t kBaseLevel = 0;
|
||||
TextureLayerAsColorAttachmentTest(
|
||||
dawn::TextureViewDimension::e2DArray, kLayers, kMipLevels, kBaseLayer, kBaseLevel);
|
||||
}
|
||||
|
||||
// Rendering into the last level
|
||||
{
|
||||
constexpr uint32_t kBaseLevel = kMipLevels - 1;
|
||||
TextureLayerAsColorAttachmentTest(
|
||||
dawn::TextureViewDimension::e2DArray, kLayers, kMipLevels, kBaseLayer, kBaseLevel);
|
||||
}
|
||||
}
|
||||
|
||||
// Test rendering into a 1-layer 2D array texture view created on a layer of a 2D array texture.
|
||||
TEST_P(TextureViewRenderingTest, Texture2DArrayViewOnALayerOf2DArrayTextureAsColorAttachment) {
|
||||
constexpr uint32_t kMipLevels = 1;
|
||||
constexpr uint32_t kBaseLevel = 0;
|
||||
constexpr uint32_t kLayers = 10;
|
||||
|
||||
// Rendering into the first layer
|
||||
{
|
||||
constexpr uint32_t kBaseLayer = 0;
|
||||
TextureLayerAsColorAttachmentTest(
|
||||
dawn::TextureViewDimension::e2DArray, kLayers, kMipLevels, kBaseLayer, kBaseLevel);
|
||||
}
|
||||
|
||||
// Rendering into the last layer
|
||||
{
|
||||
constexpr uint32_t kBaseLayer = kLayers - 1;
|
||||
TextureLayerAsColorAttachmentTest(
|
||||
dawn::TextureViewDimension::e2DArray, kLayers, kMipLevels, kBaseLayer, kBaseLevel);
|
||||
}
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(TextureViewSamplingTest, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend)
|
||||
|
||||
// TODO(jiawei.shao@intel.com): support using a layer of a texture as color attachment on OpenGL
|
||||
DAWN_INSTANTIATE_TEST(TextureViewRenderingTest, D3D12Backend, MetalBackend, VulkanBackend)
|
||||
|
|
Loading…
Reference in New Issue