Support cube map and cube map array

This patch implements cube map and cube map array texture views on
all back-ends and adds related end2end tests.

BUG=dawn:16
TEST=dawn_end2end_tests

Change-Id: I3ac3f493eb92ac551371041039bd5cf39df53050
Reviewed-on: https://dawn-review.googlesource.com/c/2220
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Jiawei Shao 2018-11-16 12:11:20 +00:00 committed by Commit Bot service account
parent 69b44ee6a1
commit 5ab84ec0a6
5 changed files with 152 additions and 8 deletions

View File

@ -210,7 +210,17 @@ namespace dawn_native { namespace d3d12 {
mSrvDesc.Texture2DArray.PlaneSlice = 0;
mSrvDesc.Texture2DArray.ResourceMinLODClamp = 0;
break;
case dawn::TextureViewDimension::Cube:
case dawn::TextureViewDimension::CubeArray:
ASSERT(texture->GetDimension() == dawn::TextureDimension::e2D);
ASSERT(descriptor->layerCount % 6 == 0);
mSrvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;
mSrvDesc.TextureCubeArray.First2DArrayFace = descriptor->baseArrayLayer;
mSrvDesc.TextureCubeArray.NumCubes = descriptor->layerCount / 6;
mSrvDesc.TextureCubeArray.MostDetailedMip = descriptor->baseMipLevel;
mSrvDesc.TextureCubeArray.MipLevels = descriptor->levelCount;
mSrvDesc.TextureCubeArray.ResourceMinLODClamp = 0;
break;
default:
UNREACHABLE();
}

View File

@ -76,6 +76,10 @@ namespace dawn_native { namespace metal {
return MTLTextureType2D;
case dawn::TextureViewDimension::e2DArray:
return MTLTextureType2DArray;
case dawn::TextureViewDimension::Cube:
return MTLTextureTypeCube;
case dawn::TextureViewDimension::CubeArray:
return MTLTextureTypeCubeArray;
default:
UNREACHABLE();
return MTLTextureType2D;

View File

@ -41,6 +41,10 @@ namespace dawn_native { namespace opengl {
return GL_TEXTURE_2D;
case dawn::TextureViewDimension::e2DArray:
return GL_TEXTURE_2D_ARRAY;
case dawn::TextureViewDimension::Cube:
return GL_TEXTURE_CUBE_MAP;
case dawn::TextureViewDimension::CubeArray:
return GL_TEXTURE_CUBE_MAP_ARRAY;
default:
UNREACHABLE();
return GL_TEXTURE_2D;

View File

@ -40,6 +40,10 @@ namespace dawn_native { namespace vulkan {
return VK_IMAGE_VIEW_TYPE_2D;
case dawn::TextureViewDimension::e2DArray:
return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
case dawn::TextureViewDimension::Cube:
return VK_IMAGE_VIEW_TYPE_CUBE;
case dawn::TextureViewDimension::CubeArray:
return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
default:
UNREACHABLE();
}

View File

@ -18,6 +18,8 @@
#include "common/Constants.h"
#include "utils/DawnHelpers.h"
#include <array>
constexpr static unsigned int kRTSize = 64;
class TextureViewTest : public DawnTest {
@ -55,6 +57,7 @@ protected:
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),
@ -62,7 +65,14 @@ protected:
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];
}
)");
}
@ -180,11 +190,12 @@ protected:
#version 450
layout(set = 0, binding = 0) uniform sampler sampler0;
layout(set = 0, binding = 1) uniform texture2D texture0;
layout(location = 0) in vec2 texCoord;
layout(location = 0) out vec4 fragColor;
void main() {
fragColor =
texture(sampler2D(texture0, sampler0), vec2(gl_FragCoord.xy / 2.0));
texture(sampler2D(texture0, sampler0), texCoord);
}
)";
@ -218,13 +229,14 @@ protected:
#version 450
layout(set = 0, binding = 0) uniform sampler sampler0;
layout(set = 0, binding = 1) uniform texture2DArray texture0;
layout(location = 0) in vec2 texCoord;
layout(location = 0) out vec4 fragColor;
void main() {
fragColor =
texture(sampler2DArray(texture0, sampler0), vec3(gl_FragCoord.xy / 2.0, 0)) +
texture(sampler2DArray(texture0, sampler0), vec3(gl_FragCoord.xy / 2.0, 1)) +
texture(sampler2DArray(texture0, sampler0), vec3(gl_FragCoord.xy / 2.0, 2));
texture(sampler2DArray(texture0, sampler0), vec3(texCoord, 0)) +
texture(sampler2DArray(texture0, sampler0), vec3(texCoord, 1)) +
texture(sampler2DArray(texture0, sampler0), vec3(texCoord, 2));
}
)";
@ -235,6 +247,74 @@ protected:
Verify(textureView, fragmentShader, expected);
}
std::string CreateFragmentShaderForCubeMapFace(uint32_t layer, bool isCubeMapArray) {
// Reference: https://en.wikipedia.org/wiki/Cube_mapping
const std::array<std::string, 6> kCoordsToCubeMapFace = {{
" 1.f, tc, -sc", // Positive X
"-1.f, tc, sc", // Negative X
" sc, 1.f, -tc", // Positive Y
" sc, -1.f, tc", // Negative Y
" sc, tc, 1.f", // Positive Z
" -sc, tc, -1.f", // Negative Z
}};
const std::string textureType = isCubeMapArray ? "textureCubeArray" : "textureCube";
const std::string samplerType = isCubeMapArray ? "samplerCubeArray" : "samplerCube";
const uint32_t cubeMapArrayIndex = layer / 6;
const std::string coordToCubeMapFace = kCoordsToCubeMapFace[layer % 6];
std::ostringstream stream;
stream << R"(
#version 450
layout(set = 0, binding = 0) uniform sampler sampler0;
layout(set = 0, binding = 1) uniform )" << textureType << R"( texture0;
layout(location = 0) in vec2 texCoord;
layout(location = 0) out vec4 fragColor;
void main() {
float sc = 2.f * texCoord.x - 1.f;
float tc = 2.f * texCoord.y - 1.f;
fragColor = texture()" << samplerType << "(texture0, sampler0), ";
if (isCubeMapArray) {
stream << "vec4(" << coordToCubeMapFace << ", " << cubeMapArrayIndex;
} else {
stream << "vec3(" << coordToCubeMapFace;
}
stream << R"());
})";
return stream.str();
}
void TextureCubeMapTest(uint32_t textureArrayLayers,
uint32_t textureViewBaseLayer,
uint32_t textureViewLayerCount,
bool isCubeMapArray) {
constexpr uint32_t kMipLevels = 1u;
initTexture(textureArrayLayers, kMipLevels);
ASSERT_TRUE((textureViewLayerCount == 6) ||
(isCubeMapArray && textureViewLayerCount % 6 == 0));
dawn::TextureViewDescriptor descriptor = mDefaultTextureViewDescriptor;
descriptor.dimension = (isCubeMapArray) ?
dawn::TextureViewDimension::CubeArray : dawn::TextureViewDimension::Cube;
descriptor.baseArrayLayer = textureViewBaseLayer;
descriptor.layerCount = textureViewLayerCount;
dawn::TextureView cubeMapTextureView = mTexture.CreateTextureView(&descriptor);
// Check the data in the every face of the cube map (array) texture view.
for (uint32_t layer = 0; layer < textureViewLayerCount; ++layer) {
const std::string &fragmentShader =
CreateFragmentShaderForCubeMapFace(layer, isCubeMapArray);
int expected = GenerateTestPixelValue(textureViewBaseLayer + layer, 0);
Verify(cubeMapTextureView, fragmentShader.c_str(), expected);
}
}
dawn::BindGroupLayout mBindGroupLayout;
dawn::PipelineLayout mPipelineLayout;
dawn::Sampler mSampler;
@ -259,13 +339,14 @@ TEST_P(TextureViewTest, Default2DArrayTexture) {
#version 450
layout(set = 0, binding = 0) uniform sampler sampler0;
layout(set = 0, binding = 1) uniform texture2DArray texture0;
layout(location = 0) in vec2 texCoord;
layout(location = 0) out vec4 fragColor;
void main() {
fragColor =
texture(sampler2DArray(texture0, sampler0), vec3(gl_FragCoord.xy / 2.0, 0)) +
texture(sampler2DArray(texture0, sampler0), vec3(gl_FragCoord.xy / 2.0, 1)) +
texture(sampler2DArray(texture0, sampler0), vec3(gl_FragCoord.xy / 2.0, 2));
texture(sampler2DArray(texture0, sampler0), vec3(texCoord, 0)) +
texture(sampler2DArray(texture0, sampler0), vec3(texCoord, 1)) +
texture(sampler2DArray(texture0, sampler0), vec3(texCoord, 2));
}
)";
@ -299,4 +380,45 @@ TEST_P(TextureViewTest, Texture2DArrayViewOnOneLevelOf2DArrayTexture) {
Texture2DArrayViewTest(6, 6, 2, 4);
}
// Test sampling from a cube map texture view that covers a whole 2D array texture.
TEST_P(TextureViewTest, 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) {
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) {
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, TextureCubeMapArrayaOnWholeTexture) {
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) {
TextureCubeMapTest(20, 3, 12, true);
}
// Test sampling from a cube map texture array view that covers the last layer of a 2D array texture.
TEST_P(TextureViewTest, TextureCubeMapArrayViewCoveringLastLayer) {
constexpr uint32_t kTotalLayers = 20;
constexpr uint32_t kBaseLayer = 8;
TextureCubeMapTest(kTotalLayers, kBaseLayer, kTotalLayers - kBaseLayer, true);
}
// Test sampling from a cube map array texture view that only has a single cube map.
TEST_P(TextureViewTest, TextureCubeMapArrayViewSingleCubeMap) {
TextureCubeMapTest(20, 7, 6, true);
}
DAWN_INSTANTIATE_TEST(TextureViewTest, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend)