Implement WGPUTextureDescriptor.viewFormats and sampling reinterpretation
Reinterpretation for render/resolve attachments not yet implemented. Bug: dawn:1276 Change-Id: I43d73ce5c943c4ba49df06c6865867f378f2de25 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/84280 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
10ec4ee7ef
commit
8e02ebf6c6
|
@ -2536,8 +2536,8 @@
|
||||||
{"name": "format", "type": "texture format"},
|
{"name": "format", "type": "texture format"},
|
||||||
{"name": "mip level count", "type": "uint32_t", "default": 1},
|
{"name": "mip level count", "type": "uint32_t", "default": 1},
|
||||||
{"name": "sample count", "type": "uint32_t", "default": 1},
|
{"name": "sample count", "type": "uint32_t", "default": 1},
|
||||||
{"name": "view format count", "type": "uint32_t", "default": 0, "tags": ["upstream"]},
|
{"name": "view format count", "type": "uint32_t", "default": 0},
|
||||||
{"name": "view formats", "type": "texture format", "annotation": "const*", "length": "view format count", "tags": ["upstream"]}
|
{"name": "view formats", "type": "texture format", "annotation": "const*", "length": "view format count"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"texture dimension": {
|
"texture dimension": {
|
||||||
|
|
|
@ -34,6 +34,8 @@ namespace ityp {
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using reference = typename Base::reference;
|
||||||
|
|
||||||
constexpr bitset() noexcept : Base() {
|
constexpr bitset() noexcept : Base() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -681,7 +681,7 @@ namespace dawn::native {
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<const Format*> DeviceBase::GetInternalFormat(wgpu::TextureFormat format) const {
|
ResultOrError<const Format*> DeviceBase::GetInternalFormat(wgpu::TextureFormat format) const {
|
||||||
size_t index = ComputeFormatIndex(format);
|
FormatIndex index = ComputeFormatIndex(format);
|
||||||
DAWN_INVALID_IF(index >= mFormatTable.size(), "Unknown texture format %s.", format);
|
DAWN_INVALID_IF(index >= mFormatTable.size(), "Unknown texture format %s.", format);
|
||||||
|
|
||||||
const Format* internalFormat = &mFormatTable[index];
|
const Format* internalFormat = &mFormatTable[index];
|
||||||
|
@ -691,7 +691,13 @@ namespace dawn::native {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Format& DeviceBase::GetValidInternalFormat(wgpu::TextureFormat format) const {
|
const Format& DeviceBase::GetValidInternalFormat(wgpu::TextureFormat format) const {
|
||||||
size_t index = ComputeFormatIndex(format);
|
FormatIndex index = ComputeFormatIndex(format);
|
||||||
|
ASSERT(index < mFormatTable.size());
|
||||||
|
ASSERT(mFormatTable[index].isSupported);
|
||||||
|
return mFormatTable[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
const Format& DeviceBase::GetValidInternalFormat(FormatIndex index) const {
|
||||||
ASSERT(index < mFormatTable.size());
|
ASSERT(index < mFormatTable.size());
|
||||||
ASSERT(mFormatTable[index].isSupported);
|
ASSERT(mFormatTable[index].isSupported);
|
||||||
return mFormatTable[index];
|
return mFormatTable[index];
|
||||||
|
|
|
@ -137,6 +137,7 @@ namespace dawn::native {
|
||||||
// valid and supported.
|
// valid and supported.
|
||||||
// The reference returned has the same lifetime as the device.
|
// The reference returned has the same lifetime as the device.
|
||||||
const Format& GetValidInternalFormat(wgpu::TextureFormat format) const;
|
const Format& GetValidInternalFormat(wgpu::TextureFormat format) const;
|
||||||
|
const Format& GetValidInternalFormat(FormatIndex formatIndex) const;
|
||||||
|
|
||||||
virtual ResultOrError<Ref<CommandBufferBase>> CreateCommandBuffer(
|
virtual ResultOrError<Ref<CommandBufferBase>> CreateCommandBuffer(
|
||||||
CommandEncoder* encoder,
|
CommandEncoder* encoder,
|
||||||
|
|
|
@ -100,6 +100,12 @@ namespace dawn::native {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Format::CopyCompatibleWith(const Format& format) const {
|
bool Format::CopyCompatibleWith(const Format& format) const {
|
||||||
|
// TODO(crbug.com/dawn/1332): Add a Format compatibility matrix.
|
||||||
|
return baseFormat == format.baseFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Format::ViewCompatibleWith(const Format& format) const {
|
||||||
|
// TODO(crbug.com/dawn/1332): Add a Format compatibility matrix.
|
||||||
return baseFormat == format.baseFormat;
|
return baseFormat == format.baseFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,31 +121,41 @@ namespace dawn::native {
|
||||||
return aspectInfo[aspectIndex];
|
return aspectInfo[aspectIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Format::GetIndex() const {
|
FormatIndex Format::GetIndex() const {
|
||||||
return ComputeFormatIndex(format);
|
return ComputeFormatIndex(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FormatSet implementation
|
||||||
|
|
||||||
|
bool FormatSet::operator[](const Format& format) const {
|
||||||
|
return Base::operator[](format.GetIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
typename std::bitset<kKnownFormatCount>::reference FormatSet::operator[](const Format& format) {
|
||||||
|
return Base::operator[](format.GetIndex());
|
||||||
|
}
|
||||||
|
|
||||||
// Implementation details of the format table of the DeviceBase
|
// Implementation details of the format table of the DeviceBase
|
||||||
|
|
||||||
// For the enum for formats are packed but this might change when we have a broader feature
|
// For the enum for formats are packed but this might change when we have a broader feature
|
||||||
// mechanism for webgpu.h. Formats start at 1 because 0 is the undefined format.
|
// mechanism for webgpu.h. Formats start at 1 because 0 is the undefined format.
|
||||||
size_t ComputeFormatIndex(wgpu::TextureFormat format) {
|
FormatIndex ComputeFormatIndex(wgpu::TextureFormat format) {
|
||||||
// This takes advantage of overflows to make the index of TextureFormat::Undefined outside
|
// This takes advantage of overflows to make the index of TextureFormat::Undefined outside
|
||||||
// of the range of the FormatTable.
|
// of the range of the FormatTable.
|
||||||
static_assert(static_cast<uint32_t>(wgpu::TextureFormat::Undefined) - 1 >
|
static_assert(static_cast<uint32_t>(wgpu::TextureFormat::Undefined) - 1 >
|
||||||
kKnownFormatCount);
|
kKnownFormatCount);
|
||||||
return static_cast<size_t>(static_cast<uint32_t>(format) - 1);
|
return static_cast<FormatIndex>(static_cast<uint32_t>(format) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
FormatTable BuildFormatTable(const DeviceBase* device) {
|
FormatTable BuildFormatTable(const DeviceBase* device) {
|
||||||
FormatTable table;
|
FormatTable table;
|
||||||
std::bitset<kKnownFormatCount> formatsSet;
|
FormatSet formatsSet;
|
||||||
|
|
||||||
static constexpr SampleTypeBit kAnyFloat =
|
static constexpr SampleTypeBit kAnyFloat =
|
||||||
SampleTypeBit::Float | SampleTypeBit::UnfilterableFloat;
|
SampleTypeBit::Float | SampleTypeBit::UnfilterableFloat;
|
||||||
|
|
||||||
auto AddFormat = [&table, &formatsSet](Format format) {
|
auto AddFormat = [&table, &formatsSet](Format format) {
|
||||||
size_t index = ComputeFormatIndex(format.format);
|
FormatIndex index = ComputeFormatIndex(format.format);
|
||||||
ASSERT(index < table.size());
|
ASSERT(index < table.size());
|
||||||
|
|
||||||
// This checks that each format is set at most once, the first part of checking that all
|
// This checks that each format is set at most once, the first part of checking that all
|
||||||
|
@ -211,11 +227,11 @@ namespace dawn::native {
|
||||||
AddFormat(internalFormat);
|
AddFormat(internalFormat);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto AddDepthFormat = [&AddFormat](
|
auto AddDepthFormat = [&AddFormat](wgpu::TextureFormat format, uint32_t byteSize,
|
||||||
wgpu::TextureFormat format, uint32_t byteSize, bool isSupported,
|
bool isSupported) {
|
||||||
wgpu::TextureFormat baseFormat = wgpu::TextureFormat::Undefined) {
|
|
||||||
Format internalFormat;
|
Format internalFormat;
|
||||||
internalFormat.format = format;
|
internalFormat.format = format;
|
||||||
|
internalFormat.baseFormat = format;
|
||||||
internalFormat.isRenderable = true;
|
internalFormat.isRenderable = true;
|
||||||
internalFormat.isCompressed = false;
|
internalFormat.isCompressed = false;
|
||||||
internalFormat.isSupported = isSupported;
|
internalFormat.isSupported = isSupported;
|
||||||
|
@ -225,13 +241,6 @@ namespace dawn::native {
|
||||||
internalFormat.aspects = Aspect::Depth;
|
internalFormat.aspects = Aspect::Depth;
|
||||||
internalFormat.componentCount = 1;
|
internalFormat.componentCount = 1;
|
||||||
|
|
||||||
// Default baseFormat of each depth formats should be themselves.
|
|
||||||
if (baseFormat == wgpu::TextureFormat::Undefined) {
|
|
||||||
internalFormat.baseFormat = format;
|
|
||||||
} else {
|
|
||||||
internalFormat.baseFormat = baseFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
AspectInfo* firstAspect = internalFormat.aspectInfo.data();
|
AspectInfo* firstAspect = internalFormat.aspectInfo.data();
|
||||||
firstAspect->block.byteSize = byteSize;
|
firstAspect->block.byteSize = byteSize;
|
||||||
firstAspect->block.width = 1;
|
firstAspect->block.width = 1;
|
||||||
|
@ -242,11 +251,10 @@ namespace dawn::native {
|
||||||
AddFormat(internalFormat);
|
AddFormat(internalFormat);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto AddStencilFormat = [&AddFormat](wgpu::TextureFormat format, bool isSupported,
|
auto AddStencilFormat = [&AddFormat](wgpu::TextureFormat format, bool isSupported) {
|
||||||
wgpu::TextureFormat baseFormat =
|
|
||||||
wgpu::TextureFormat::Undefined) {
|
|
||||||
Format internalFormat;
|
Format internalFormat;
|
||||||
internalFormat.format = format;
|
internalFormat.format = format;
|
||||||
|
internalFormat.baseFormat = format;
|
||||||
internalFormat.isRenderable = true;
|
internalFormat.isRenderable = true;
|
||||||
internalFormat.isCompressed = false;
|
internalFormat.isCompressed = false;
|
||||||
internalFormat.isSupported = isSupported;
|
internalFormat.isSupported = isSupported;
|
||||||
|
@ -255,14 +263,6 @@ namespace dawn::native {
|
||||||
internalFormat.supportsResolveTarget = false;
|
internalFormat.supportsResolveTarget = false;
|
||||||
internalFormat.aspects = Aspect::Stencil;
|
internalFormat.aspects = Aspect::Stencil;
|
||||||
internalFormat.componentCount = 1;
|
internalFormat.componentCount = 1;
|
||||||
internalFormat.baseFormat = baseFormat;
|
|
||||||
|
|
||||||
// Default baseFormat of each stencil formats should be themselves.
|
|
||||||
if (baseFormat == wgpu::TextureFormat::Undefined) {
|
|
||||||
internalFormat.baseFormat = format;
|
|
||||||
} else {
|
|
||||||
internalFormat.baseFormat = baseFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Duplicate the data for the stencil aspect in both the first and second aspect info.
|
// Duplicate the data for the stencil aspect in both the first and second aspect info.
|
||||||
// - aspectInfo[0] is used by AddMultiAspectFormat to copy the info for the whole
|
// - aspectInfo[0] is used by AddMultiAspectFormat to copy the info for the whole
|
||||||
|
@ -319,10 +319,10 @@ namespace dawn::native {
|
||||||
[&AddFormat, &table](wgpu::TextureFormat format, Aspect aspects,
|
[&AddFormat, &table](wgpu::TextureFormat format, Aspect aspects,
|
||||||
wgpu::TextureFormat firstFormat, wgpu::TextureFormat secondFormat,
|
wgpu::TextureFormat firstFormat, wgpu::TextureFormat secondFormat,
|
||||||
bool isRenderable, bool isSupported, bool supportsMultisample,
|
bool isRenderable, bool isSupported, bool supportsMultisample,
|
||||||
uint8_t componentCount,
|
uint8_t componentCount) {
|
||||||
wgpu::TextureFormat baseFormat = wgpu::TextureFormat::Undefined) {
|
|
||||||
Format internalFormat;
|
Format internalFormat;
|
||||||
internalFormat.format = format;
|
internalFormat.format = format;
|
||||||
|
internalFormat.baseFormat = format;
|
||||||
internalFormat.isRenderable = isRenderable;
|
internalFormat.isRenderable = isRenderable;
|
||||||
internalFormat.isCompressed = false;
|
internalFormat.isCompressed = false;
|
||||||
internalFormat.isSupported = isSupported;
|
internalFormat.isSupported = isSupported;
|
||||||
|
@ -332,18 +332,11 @@ namespace dawn::native {
|
||||||
internalFormat.aspects = aspects;
|
internalFormat.aspects = aspects;
|
||||||
internalFormat.componentCount = componentCount;
|
internalFormat.componentCount = componentCount;
|
||||||
|
|
||||||
// Default baseFormat of each multi aspect formats should be themselves.
|
|
||||||
if (baseFormat == wgpu::TextureFormat::Undefined) {
|
|
||||||
internalFormat.baseFormat = format;
|
|
||||||
} else {
|
|
||||||
internalFormat.baseFormat = baseFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Multi aspect formats just copy information about single-aspect formats. This
|
// Multi aspect formats just copy information about single-aspect formats. This
|
||||||
// means that the single-plane formats must have been added before multi-aspect
|
// means that the single-plane formats must have been added before multi-aspect
|
||||||
// ones. (it is ASSERTed below).
|
// ones. (it is ASSERTed below).
|
||||||
const size_t firstFormatIndex = ComputeFormatIndex(firstFormat);
|
const FormatIndex firstFormatIndex = ComputeFormatIndex(firstFormat);
|
||||||
const size_t secondFormatIndex = ComputeFormatIndex(secondFormat);
|
const FormatIndex secondFormatIndex = ComputeFormatIndex(secondFormat);
|
||||||
|
|
||||||
ASSERT(table[firstFormatIndex].aspectInfo[0].format !=
|
ASSERT(table[firstFormatIndex].aspectInfo[0].format !=
|
||||||
wgpu::TextureFormat::Undefined);
|
wgpu::TextureFormat::Undefined);
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#include "dawn/native/dawn_platform.h"
|
#include "dawn/native/dawn_platform.h"
|
||||||
|
|
||||||
|
#include "dawn/common/TypedInteger.h"
|
||||||
|
#include "dawn/common/ityp_array.h"
|
||||||
#include "dawn/common/ityp_bitset.h"
|
#include "dawn/common/ityp_bitset.h"
|
||||||
#include "dawn/native/EnumClassBitmasks.h"
|
#include "dawn/native/EnumClassBitmasks.h"
|
||||||
#include "dawn/native/Error.h"
|
#include "dawn/native/Error.h"
|
||||||
|
@ -77,15 +79,18 @@ namespace dawn::native {
|
||||||
|
|
||||||
// The number of formats Dawn knows about. Asserts in BuildFormatTable ensure that this is the
|
// The number of formats Dawn knows about. Asserts in BuildFormatTable ensure that this is the
|
||||||
// exact number of known format.
|
// exact number of known format.
|
||||||
static constexpr size_t kKnownFormatCount = 96;
|
static constexpr uint32_t kKnownFormatCount = 96;
|
||||||
|
|
||||||
|
using FormatIndex = TypedInteger<struct FormatIndexT, uint32_t>;
|
||||||
|
|
||||||
struct Format;
|
struct Format;
|
||||||
using FormatTable = std::array<Format, kKnownFormatCount>;
|
using FormatTable = ityp::array<FormatIndex, Format, kKnownFormatCount>;
|
||||||
|
|
||||||
// A wgpu::TextureFormat along with all the information about it necessary for validation.
|
// A wgpu::TextureFormat along with all the information about it necessary for validation.
|
||||||
struct Format {
|
struct Format {
|
||||||
wgpu::TextureFormat format;
|
wgpu::TextureFormat format;
|
||||||
|
|
||||||
|
// TODO(crbug.com/dawn/1332): These members could be stored in a Format capability matrix.
|
||||||
bool isRenderable;
|
bool isRenderable;
|
||||||
bool isCompressed;
|
bool isCompressed;
|
||||||
// A format can be known but not supported because it is part of a disabled extension.
|
// A format can be known but not supported because it is part of a disabled extension.
|
||||||
|
@ -111,16 +116,21 @@ namespace dawn::native {
|
||||||
|
|
||||||
// The index of the format in the list of all known formats: a unique number for each format
|
// The index of the format in the list of all known formats: a unique number for each format
|
||||||
// in [0, kKnownFormatCount)
|
// in [0, kKnownFormatCount)
|
||||||
size_t GetIndex() const;
|
FormatIndex GetIndex() const;
|
||||||
|
|
||||||
// baseFormat represents the memory layout of the format.
|
// baseFormat represents the memory layout of the format.
|
||||||
// If two formats has the same baseFormat, they could copy to each other.
|
// If two formats has the same baseFormat, they could copy to and be viewed as the other
|
||||||
|
// format. Currently two formats have the same baseFormat if they differ only in sRGB-ness.
|
||||||
wgpu::TextureFormat baseFormat;
|
wgpu::TextureFormat baseFormat;
|
||||||
|
|
||||||
// CopyCompatibleWith() returns true if the input format has the same baseFormat
|
// Returns true if the formats are copy compatible.
|
||||||
// with current format.
|
// Currently means they differ only in sRGB-ness.
|
||||||
bool CopyCompatibleWith(const Format& format) const;
|
bool CopyCompatibleWith(const Format& format) const;
|
||||||
|
|
||||||
|
// Returns true if the formats are texture view format compatible.
|
||||||
|
// Currently means they differ only in sRGB-ness.
|
||||||
|
bool ViewCompatibleWith(const Format& format) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Used to store the aspectInfo for one or more planes. For single plane "color" formats,
|
// Used to store the aspectInfo for one or more planes. For single plane "color" formats,
|
||||||
// only the first aspect info or aspectInfo[0] is valid. For depth-stencil, the first aspect
|
// only the first aspect info or aspectInfo[0] is valid. For depth-stencil, the first aspect
|
||||||
|
@ -131,10 +141,21 @@ namespace dawn::native {
|
||||||
friend FormatTable BuildFormatTable(const DeviceBase* device);
|
friend FormatTable BuildFormatTable(const DeviceBase* device);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FormatSet : public ityp::bitset<FormatIndex, kKnownFormatCount> {
|
||||||
|
using Base = ityp::bitset<FormatIndex, kKnownFormatCount>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using Base::Base;
|
||||||
|
using Base::operator[];
|
||||||
|
|
||||||
|
bool operator[](const Format& format) const;
|
||||||
|
typename Base::reference operator[](const Format& format);
|
||||||
|
};
|
||||||
|
|
||||||
// Implementation details of the format table in the device.
|
// Implementation details of the format table in the device.
|
||||||
|
|
||||||
// Returns the index of a format in the FormatTable.
|
// Returns the index of a format in the FormatTable.
|
||||||
size_t ComputeFormatIndex(wgpu::TextureFormat format);
|
FormatIndex ComputeFormatIndex(wgpu::TextureFormat format);
|
||||||
// Builds the format table with the extensions enabled on the device.
|
// Builds the format table with the extensions enabled on the device.
|
||||||
FormatTable BuildFormatTable(const DeviceBase* device);
|
FormatTable BuildFormatTable(const DeviceBase* device);
|
||||||
|
|
||||||
|
|
|
@ -29,21 +29,68 @@
|
||||||
|
|
||||||
namespace dawn::native {
|
namespace dawn::native {
|
||||||
namespace {
|
namespace {
|
||||||
// WebGPU currently does not have texture format reinterpretation. If it does, the
|
|
||||||
// code to check for it might go here.
|
MaybeError ValidateTextureViewFormatCompatibility(const DeviceBase* device,
|
||||||
MaybeError ValidateTextureViewFormatCompatibility(const TextureBase* texture,
|
const Format& format,
|
||||||
const TextureViewDescriptor* descriptor) {
|
wgpu::TextureFormat viewFormatEnum) {
|
||||||
if (texture->GetFormat().format != descriptor->format) {
|
const Format* viewFormat;
|
||||||
if (descriptor->aspect != wgpu::TextureAspect::All &&
|
DAWN_TRY_ASSIGN(viewFormat, device->GetInternalFormat(viewFormatEnum));
|
||||||
texture->GetFormat().GetAspectInfo(descriptor->aspect).format ==
|
|
||||||
descriptor->format) {
|
DAWN_INVALID_IF(!format.ViewCompatibleWith(*viewFormat),
|
||||||
|
"The texture view format (%s) is not texture view format compatible "
|
||||||
|
"with the texture format (%s).",
|
||||||
|
viewFormatEnum, format.format);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return DAWN_VALIDATION_ERROR(
|
MaybeError ValidateCanViewTextureAs(const DeviceBase* device,
|
||||||
"The format of texture view is not compatible to the original texture");
|
const TextureBase* texture,
|
||||||
|
const Format& viewFormat,
|
||||||
|
wgpu::TextureAspect aspect) {
|
||||||
|
const Format& format = texture->GetFormat();
|
||||||
|
|
||||||
|
if (format.format == viewFormat.format) {
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aspect != wgpu::TextureAspect::All) {
|
||||||
|
wgpu::TextureFormat aspectFormat = format.GetAspectInfo(aspect).format;
|
||||||
|
if (viewFormat.format == aspectFormat) {
|
||||||
|
return {};
|
||||||
|
} else {
|
||||||
|
return DAWN_FORMAT_VALIDATION_ERROR(
|
||||||
|
"The view format (%s) is not compatible with %s of %s (%s).",
|
||||||
|
viewFormat.format, aspect, format.format, aspectFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const FormatSet& compatibleViewFormats = texture->GetViewFormats();
|
||||||
|
if (compatibleViewFormats[viewFormat]) {
|
||||||
|
// Validation of this list is done on texture creation, so we don't need to
|
||||||
|
// handle the case where a format is in the list, but not compatible.
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// |viewFormat| is not in the list. Check compatibility to generate an error message
|
||||||
|
// depending on whether it could be compatible, but needs to be explicitly listed,
|
||||||
|
// or it could never be compatible.
|
||||||
|
if (!format.ViewCompatibleWith(viewFormat)) {
|
||||||
|
// The view format isn't compatible with the format at all. Return an error
|
||||||
|
// that indicates this, in addition to reporting that it's missing from the
|
||||||
|
// list.
|
||||||
|
return DAWN_FORMAT_VALIDATION_ERROR(
|
||||||
|
"The texture view format (%s) is not compatible with the "
|
||||||
|
"texture format (%s)."
|
||||||
|
"The formats must be compatible, and the view format "
|
||||||
|
"must be passed in the list of view formats on texture creation.",
|
||||||
|
viewFormat.format, format.format);
|
||||||
|
} else {
|
||||||
|
// The view format is compatible, but not in the list.
|
||||||
|
return DAWN_FORMAT_VALIDATION_ERROR(
|
||||||
|
"%s was not created with the texture view format (%s) "
|
||||||
|
"in the list of compatible view formats.",
|
||||||
|
texture, viewFormat.format);
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,6 +342,12 @@ namespace dawn::native {
|
||||||
const Format* format;
|
const Format* format;
|
||||||
DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format));
|
DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format));
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < descriptor->viewFormatCount; ++i) {
|
||||||
|
DAWN_TRY_CONTEXT(
|
||||||
|
ValidateTextureViewFormatCompatibility(device, *format, descriptor->viewFormats[i]),
|
||||||
|
"validating viewFormats[%u]", i);
|
||||||
|
}
|
||||||
|
|
||||||
wgpu::TextureUsage usage = descriptor->usage;
|
wgpu::TextureUsage usage = descriptor->usage;
|
||||||
if (internalUsageDesc != nullptr) {
|
if (internalUsageDesc != nullptr) {
|
||||||
usage |= internalUsageDesc->internalUsage;
|
usage |= internalUsageDesc->internalUsage;
|
||||||
|
@ -357,10 +410,13 @@ namespace dawn::native {
|
||||||
DAWN_TRY(ValidateTextureFormat(descriptor->format));
|
DAWN_TRY(ValidateTextureFormat(descriptor->format));
|
||||||
DAWN_TRY(ValidateTextureAspect(descriptor->aspect));
|
DAWN_TRY(ValidateTextureAspect(descriptor->aspect));
|
||||||
|
|
||||||
|
const Format& format = texture->GetFormat();
|
||||||
|
const Format& viewFormat = device->GetValidInternalFormat(descriptor->format);
|
||||||
|
|
||||||
DAWN_INVALID_IF(
|
DAWN_INVALID_IF(
|
||||||
SelectFormatAspects(texture->GetFormat(), descriptor->aspect) == Aspect::None,
|
SelectFormatAspects(format, descriptor->aspect) == Aspect::None,
|
||||||
"Texture format (%s) does not have the texture view's selected aspect (%s).",
|
"Texture format (%s) does not have the texture view's selected aspect (%s).",
|
||||||
texture->GetFormat().format, descriptor->aspect);
|
format.format, descriptor->aspect);
|
||||||
|
|
||||||
DAWN_INVALID_IF(descriptor->arrayLayerCount == 0 || descriptor->mipLevelCount == 0,
|
DAWN_INVALID_IF(descriptor->arrayLayerCount == 0 || descriptor->mipLevelCount == 0,
|
||||||
"The texture view's arrayLayerCount (%u) or mipLevelCount (%u) is zero.",
|
"The texture view's arrayLayerCount (%u) or mipLevelCount (%u) is zero.",
|
||||||
|
@ -380,7 +436,7 @@ namespace dawn::native {
|
||||||
"texture's mip level count (%u).",
|
"texture's mip level count (%u).",
|
||||||
descriptor->baseMipLevel, descriptor->mipLevelCount, texture->GetNumMipLevels());
|
descriptor->baseMipLevel, descriptor->mipLevelCount, texture->GetNumMipLevels());
|
||||||
|
|
||||||
DAWN_TRY(ValidateTextureViewFormatCompatibility(texture, descriptor));
|
DAWN_TRY(ValidateCanViewTextureAs(device, texture, viewFormat, descriptor->aspect));
|
||||||
DAWN_TRY(ValidateTextureViewDimensionCompatibility(texture, descriptor));
|
DAWN_TRY(ValidateTextureViewDimensionCompatibility(texture, descriptor));
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -476,6 +532,15 @@ namespace dawn::native {
|
||||||
mMipLevelCount * GetArrayLayers() * GetAspectCount(mFormat.aspects);
|
mMipLevelCount * GetArrayLayers() * GetAspectCount(mFormat.aspects);
|
||||||
mIsSubresourceContentInitializedAtIndex = std::vector<bool>(subresourceCount, false);
|
mIsSubresourceContentInitializedAtIndex = std::vector<bool>(subresourceCount, false);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < descriptor->viewFormatCount; ++i) {
|
||||||
|
if (descriptor->viewFormats[i] == descriptor->format) {
|
||||||
|
// Skip our own format, so the backends don't allocate the texture for
|
||||||
|
// reinterpretation if it's not needed.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mViewFormats[device->GetValidInternalFormat(descriptor->viewFormats[i])] = true;
|
||||||
|
}
|
||||||
|
|
||||||
const DawnTextureInternalUsageDescriptor* internalUsageDesc = nullptr;
|
const DawnTextureInternalUsageDescriptor* internalUsageDesc = nullptr;
|
||||||
FindInChain(descriptor->nextInChain, &internalUsageDesc);
|
FindInChain(descriptor->nextInChain, &internalUsageDesc);
|
||||||
if (internalUsageDesc != nullptr) {
|
if (internalUsageDesc != nullptr) {
|
||||||
|
@ -517,6 +582,10 @@ namespace dawn::native {
|
||||||
ASSERT(!IsError());
|
ASSERT(!IsError());
|
||||||
return mFormat;
|
return mFormat;
|
||||||
}
|
}
|
||||||
|
const FormatSet& TextureBase::GetViewFormats() const {
|
||||||
|
ASSERT(!IsError());
|
||||||
|
return mViewFormats;
|
||||||
|
}
|
||||||
const Extent3D& TextureBase::GetSize() const {
|
const Extent3D& TextureBase::GetSize() const {
|
||||||
ASSERT(!IsError());
|
ASSERT(!IsError());
|
||||||
return mSize;
|
return mSize;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "dawn/common/ityp_array.h"
|
#include "dawn/common/ityp_array.h"
|
||||||
#include "dawn/common/ityp_bitset.h"
|
#include "dawn/common/ityp_bitset.h"
|
||||||
#include "dawn/native/Error.h"
|
#include "dawn/native/Error.h"
|
||||||
|
#include "dawn/native/Format.h"
|
||||||
#include "dawn/native/Forward.h"
|
#include "dawn/native/Forward.h"
|
||||||
#include "dawn/native/ObjectBase.h"
|
#include "dawn/native/ObjectBase.h"
|
||||||
#include "dawn/native/Subresource.h"
|
#include "dawn/native/Subresource.h"
|
||||||
|
@ -55,6 +56,7 @@ namespace dawn::native {
|
||||||
|
|
||||||
wgpu::TextureDimension GetDimension() const;
|
wgpu::TextureDimension GetDimension() const;
|
||||||
const Format& GetFormat() const;
|
const Format& GetFormat() const;
|
||||||
|
const FormatSet& GetViewFormats() const;
|
||||||
const Extent3D& GetSize() const;
|
const Extent3D& GetSize() const;
|
||||||
uint32_t GetWidth() const;
|
uint32_t GetWidth() const;
|
||||||
uint32_t GetHeight() const;
|
uint32_t GetHeight() const;
|
||||||
|
@ -109,6 +111,7 @@ namespace dawn::native {
|
||||||
MaybeError ValidateDestroy() const;
|
MaybeError ValidateDestroy() const;
|
||||||
wgpu::TextureDimension mDimension;
|
wgpu::TextureDimension mDimension;
|
||||||
const Format& mFormat;
|
const Format& mFormat;
|
||||||
|
FormatSet mViewFormats;
|
||||||
Extent3D mSize;
|
Extent3D mSize;
|
||||||
uint32_t mMipLevelCount;
|
uint32_t mMipLevelCount;
|
||||||
uint32_t mSampleCount;
|
uint32_t mSampleCount;
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace dawn::native::opengl {
|
||||||
|
|
||||||
auto AddFormat = [&table](wgpu::TextureFormat dawnFormat, GLenum internalFormat,
|
auto AddFormat = [&table](wgpu::TextureFormat dawnFormat, GLenum internalFormat,
|
||||||
GLenum format, GLenum type, Type componentType) {
|
GLenum format, GLenum type, Type componentType) {
|
||||||
size_t index = ComputeFormatIndex(dawnFormat);
|
FormatIndex index = ComputeFormatIndex(dawnFormat);
|
||||||
ASSERT(index < table.size());
|
ASSERT(index < table.size());
|
||||||
|
|
||||||
table[index].internalFormat = internalFormat;
|
table[index].internalFormat = internalFormat;
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace dawn::native::opengl {
|
||||||
ComponentType componentType;
|
ComponentType componentType;
|
||||||
};
|
};
|
||||||
|
|
||||||
using GLFormatTable = std::array<GLFormat, kKnownFormatCount>;
|
using GLFormatTable = ityp::array<FormatIndex, GLFormat, kKnownFormatCount>;
|
||||||
GLFormatTable BuildGLFormatTable();
|
GLFormatTable BuildGLFormatTable();
|
||||||
|
|
||||||
} // namespace dawn::native::opengl
|
} // namespace dawn::native::opengl
|
||||||
|
|
|
@ -655,17 +655,33 @@ namespace dawn::native::vulkan {
|
||||||
VkImageCreateInfo createInfo = {};
|
VkImageCreateInfo createInfo = {};
|
||||||
FillVulkanCreateInfoSizesAndType(*this, &createInfo);
|
FillVulkanCreateInfoSizesAndType(*this, &createInfo);
|
||||||
|
|
||||||
|
PNextChainBuilder createInfoChain(&createInfo);
|
||||||
|
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||||
createInfo.pNext = nullptr;
|
|
||||||
createInfo.flags = 0;
|
|
||||||
createInfo.format = VulkanImageFormat(device, GetFormat().format);
|
createInfo.format = VulkanImageFormat(device, GetFormat().format);
|
||||||
createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
createInfo.usage = VulkanImageUsage(GetInternalUsage(), GetFormat()) | extraUsages;
|
createInfo.usage = VulkanImageUsage(GetInternalUsage(), GetFormat()) | extraUsages;
|
||||||
createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
createInfo.queueFamilyIndexCount = 0;
|
|
||||||
createInfo.pQueueFamilyIndices = nullptr;
|
|
||||||
createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
||||||
|
VkImageFormatListCreateInfo imageFormatListInfo = {};
|
||||||
|
std::vector<VkFormat> viewFormats;
|
||||||
|
if (GetViewFormats().any()) {
|
||||||
|
createInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
|
||||||
|
if (device->GetDeviceInfo().HasExt(DeviceExt::ImageFormatList)) {
|
||||||
|
createInfoChain.Add(&imageFormatListInfo,
|
||||||
|
VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO);
|
||||||
|
viewFormats.push_back(VulkanImageFormat(device, GetFormat().format));
|
||||||
|
for (FormatIndex i : IterateBitSet(GetViewFormats())) {
|
||||||
|
const Format& viewFormat = device->GetValidInternalFormat(i);
|
||||||
|
viewFormats.push_back(VulkanImageFormat(device, viewFormat.format));
|
||||||
|
}
|
||||||
|
|
||||||
|
imageFormatListInfo.viewFormatCount = viewFormats.size();
|
||||||
|
imageFormatListInfo.pViewFormats = viewFormats.data();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT(IsSampleCountSupported(device, createInfo));
|
ASSERT(IsSampleCountSupported(device, createInfo));
|
||||||
|
|
||||||
if (GetArrayLayers() >= 6 && GetWidth() == GetHeight()) {
|
if (GetArrayLayers() >= 6 && GetWidth() == GetHeight()) {
|
||||||
|
@ -707,7 +723,8 @@ namespace dawn::native::vulkan {
|
||||||
// Internally managed, but imported from external handle
|
// Internally managed, but imported from external handle
|
||||||
MaybeError Texture::InitializeFromExternal(const ExternalImageDescriptorVk* descriptor,
|
MaybeError Texture::InitializeFromExternal(const ExternalImageDescriptorVk* descriptor,
|
||||||
external_memory::Service* externalMemoryService) {
|
external_memory::Service* externalMemoryService) {
|
||||||
VkFormat format = VulkanImageFormat(ToBackend(GetDevice()), GetFormat().format);
|
Device* device = ToBackend(GetDevice());
|
||||||
|
VkFormat format = VulkanImageFormat(device, GetFormat().format);
|
||||||
VkImageUsageFlags usage = VulkanImageUsage(GetInternalUsage(), GetFormat());
|
VkImageUsageFlags usage = VulkanImageUsage(GetInternalUsage(), GetFormat());
|
||||||
DAWN_INVALID_IF(!externalMemoryService->SupportsCreateImage(descriptor, format, usage,
|
DAWN_INVALID_IF(!externalMemoryService->SupportsCreateImage(descriptor, format, usage,
|
||||||
&mSupportsDisjointVkImage),
|
&mSupportsDisjointVkImage),
|
||||||
|
@ -728,8 +745,9 @@ namespace dawn::native::vulkan {
|
||||||
VkImageCreateInfo baseCreateInfo = {};
|
VkImageCreateInfo baseCreateInfo = {};
|
||||||
FillVulkanCreateInfoSizesAndType(*this, &baseCreateInfo);
|
FillVulkanCreateInfoSizesAndType(*this, &baseCreateInfo);
|
||||||
|
|
||||||
|
PNextChainBuilder createInfoChain(&baseCreateInfo);
|
||||||
|
|
||||||
baseCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
baseCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||||
baseCreateInfo.pNext = nullptr;
|
|
||||||
baseCreateInfo.format = format;
|
baseCreateInfo.format = format;
|
||||||
baseCreateInfo.usage = usage;
|
baseCreateInfo.usage = usage;
|
||||||
baseCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
baseCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
@ -741,6 +759,23 @@ namespace dawn::native::vulkan {
|
||||||
// also required for the implementation of robust resource initialization.
|
// also required for the implementation of robust resource initialization.
|
||||||
baseCreateInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
baseCreateInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||||
|
|
||||||
|
VkImageFormatListCreateInfo imageFormatListInfo = {};
|
||||||
|
std::vector<VkFormat> viewFormats;
|
||||||
|
if (GetViewFormats().any()) {
|
||||||
|
baseCreateInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
|
||||||
|
if (device->GetDeviceInfo().HasExt(DeviceExt::ImageFormatList)) {
|
||||||
|
createInfoChain.Add(&imageFormatListInfo,
|
||||||
|
VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO);
|
||||||
|
for (FormatIndex i : IterateBitSet(GetViewFormats())) {
|
||||||
|
const Format& viewFormat = device->GetValidInternalFormat(i);
|
||||||
|
viewFormats.push_back(VulkanImageFormat(device, viewFormat.format));
|
||||||
|
}
|
||||||
|
|
||||||
|
imageFormatListInfo.viewFormatCount = viewFormats.size();
|
||||||
|
imageFormatListInfo.pViewFormats = viewFormats.data();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DAWN_TRY_ASSIGN(mHandle, externalMemoryService->CreateImage(descriptor, baseCreateInfo));
|
DAWN_TRY_ASSIGN(mHandle, externalMemoryService->CreateImage(descriptor, baseCreateInfo));
|
||||||
|
|
||||||
SetLabelHelper("Dawn_ExternalTexture");
|
SetLabelHelper("Dawn_ExternalTexture");
|
||||||
|
|
|
@ -59,7 +59,9 @@ namespace dawn::native::vulkan {
|
||||||
template <typename VK_STRUCT_TYPE>
|
template <typename VK_STRUCT_TYPE>
|
||||||
explicit PNextChainBuilder(VK_STRUCT_TYPE* head)
|
explicit PNextChainBuilder(VK_STRUCT_TYPE* head)
|
||||||
: mCurrent(reinterpret_cast<VkBaseOutStructure*>(head)) {
|
: mCurrent(reinterpret_cast<VkBaseOutStructure*>(head)) {
|
||||||
ASSERT(head->pNext == nullptr);
|
while (mCurrent->pNext != nullptr) {
|
||||||
|
mCurrent = mCurrent->pNext;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add one item to the chain. |vk_struct| must be a Vulkan structure
|
// Add one item to the chain. |vk_struct| must be a Vulkan structure
|
||||||
|
|
|
@ -305,8 +305,8 @@ namespace dawn::native { namespace vulkan::external_memory {
|
||||||
|
|
||||||
VkImageCreateInfo createInfo = baseCreateInfo;
|
VkImageCreateInfo createInfo = baseCreateInfo;
|
||||||
createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
createInfo.flags = 0;
|
|
||||||
createInfo.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
|
createInfo.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
|
||||||
|
|
||||||
PNextChainBuilder createInfoChain(&createInfo);
|
PNextChainBuilder createInfoChain(&createInfo);
|
||||||
|
|
||||||
VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = {};
|
VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = {};
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "dawn/native/vulkan/BackendVk.h"
|
#include "dawn/native/vulkan/BackendVk.h"
|
||||||
#include "dawn/native/vulkan/DeviceVk.h"
|
#include "dawn/native/vulkan/DeviceVk.h"
|
||||||
#include "dawn/native/vulkan/TextureVk.h"
|
#include "dawn/native/vulkan/TextureVk.h"
|
||||||
|
#include "dawn/native/vulkan/UtilsVulkan.h"
|
||||||
#include "dawn/native/vulkan/VulkanError.h"
|
#include "dawn/native/vulkan/VulkanError.h"
|
||||||
#include "dawn/native/vulkan/external_memory/MemoryService.h"
|
#include "dawn/native/vulkan/external_memory/MemoryService.h"
|
||||||
|
|
||||||
|
@ -133,16 +134,19 @@ namespace dawn::native { namespace vulkan::external_memory {
|
||||||
|
|
||||||
ResultOrError<VkImage> Service::CreateImage(const ExternalImageDescriptor* descriptor,
|
ResultOrError<VkImage> Service::CreateImage(const ExternalImageDescriptor* descriptor,
|
||||||
const VkImageCreateInfo& baseCreateInfo) {
|
const VkImageCreateInfo& baseCreateInfo) {
|
||||||
|
VkImageCreateInfo createInfo = baseCreateInfo;
|
||||||
|
createInfo.flags |= VK_IMAGE_CREATE_ALIAS_BIT_KHR;
|
||||||
|
createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
|
createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
||||||
VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo;
|
VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo;
|
||||||
externalMemoryImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
|
externalMemoryImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
|
||||||
externalMemoryImageCreateInfo.pNext = nullptr;
|
externalMemoryImageCreateInfo.pNext = nullptr;
|
||||||
externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
|
externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
|
||||||
|
|
||||||
VkImageCreateInfo createInfo = baseCreateInfo;
|
PNextChainBuilder createInfoChain(&createInfo);
|
||||||
createInfo.pNext = &externalMemoryImageCreateInfo;
|
createInfoChain.Add(&externalMemoryImageCreateInfo,
|
||||||
createInfo.flags = VK_IMAGE_CREATE_ALIAS_BIT_KHR;
|
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO);
|
||||||
createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
|
||||||
createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
|
|
||||||
ASSERT(IsSampleCountSupported(mDevice, createInfo));
|
ASSERT(IsSampleCountSupported(mDevice, createInfo));
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "dawn/native/vulkan/BackendVk.h"
|
#include "dawn/native/vulkan/BackendVk.h"
|
||||||
#include "dawn/native/vulkan/DeviceVk.h"
|
#include "dawn/native/vulkan/DeviceVk.h"
|
||||||
#include "dawn/native/vulkan/TextureVk.h"
|
#include "dawn/native/vulkan/TextureVk.h"
|
||||||
|
#include "dawn/native/vulkan/UtilsVulkan.h"
|
||||||
#include "dawn/native/vulkan/VulkanError.h"
|
#include "dawn/native/vulkan/VulkanError.h"
|
||||||
#include "dawn/native/vulkan/external_memory/MemoryService.h"
|
#include "dawn/native/vulkan/external_memory/MemoryService.h"
|
||||||
|
|
||||||
|
@ -134,17 +135,20 @@ namespace dawn::native { namespace vulkan::external_memory {
|
||||||
|
|
||||||
ResultOrError<VkImage> Service::CreateImage(const ExternalImageDescriptor* descriptor,
|
ResultOrError<VkImage> Service::CreateImage(const ExternalImageDescriptor* descriptor,
|
||||||
const VkImageCreateInfo& baseCreateInfo) {
|
const VkImageCreateInfo& baseCreateInfo) {
|
||||||
|
VkImageCreateInfo createInfo = baseCreateInfo;
|
||||||
|
createInfo.flags |= VK_IMAGE_CREATE_ALIAS_BIT_KHR;
|
||||||
|
createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
|
createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
||||||
VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo;
|
VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo;
|
||||||
externalMemoryImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
|
externalMemoryImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
|
||||||
externalMemoryImageCreateInfo.pNext = nullptr;
|
externalMemoryImageCreateInfo.pNext = nullptr;
|
||||||
externalMemoryImageCreateInfo.handleTypes =
|
externalMemoryImageCreateInfo.handleTypes =
|
||||||
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA;
|
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA;
|
||||||
|
|
||||||
VkImageCreateInfo createInfo = baseCreateInfo;
|
PNextChainBuilder createInfoChain(&createInfo);
|
||||||
createInfo.pNext = &externalMemoryImageCreateInfo;
|
createInfoChain.Add(&externalMemoryImageCreateInfo,
|
||||||
createInfo.flags = VK_IMAGE_CREATE_ALIAS_BIT_KHR;
|
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO);
|
||||||
createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
|
||||||
createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
|
|
||||||
ASSERT(IsSampleCountSupported(mDevice, createInfo));
|
ASSERT(IsSampleCountSupported(mDevice, createInfo));
|
||||||
|
|
||||||
|
|
|
@ -438,6 +438,98 @@ TEST_P(TextureViewSamplingTest, Texture2DArrayViewOnOneLevelOf2DArrayTexture) {
|
||||||
Texture2DArrayViewTest(6, 6, 2, 4);
|
Texture2DArrayViewTest(6, 6, 2, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that an RGBA8 texture may be interpreted as RGBA8UnormSrgb
|
||||||
|
// More extensive color value checks and format tests are left for the CTS.
|
||||||
|
TEST_P(TextureViewSamplingTest, SRGBReinterpretation) {
|
||||||
|
// TODO(crbug.com/dawn/593): This test requires glTextureView, which is unsupported on GLES.
|
||||||
|
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
|
||||||
|
|
||||||
|
wgpu::TextureViewDescriptor viewDesc = {};
|
||||||
|
viewDesc.format = wgpu::TextureFormat::RGBA8UnormSrgb;
|
||||||
|
|
||||||
|
wgpu::TextureDescriptor textureDesc = {};
|
||||||
|
textureDesc.size = {2, 2, 1};
|
||||||
|
textureDesc.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::TextureBinding;
|
||||||
|
textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
textureDesc.viewFormats = &viewDesc.format;
|
||||||
|
textureDesc.viewFormatCount = 1;
|
||||||
|
wgpu::Texture texture = device.CreateTexture(&textureDesc);
|
||||||
|
|
||||||
|
wgpu::ImageCopyTexture dst = {};
|
||||||
|
dst.texture = texture;
|
||||||
|
std::array<RGBA8, 4> rgbaTextureData = {
|
||||||
|
RGBA8(180, 0, 0, 255),
|
||||||
|
RGBA8(0, 84, 0, 127),
|
||||||
|
RGBA8(0, 0, 62, 100),
|
||||||
|
RGBA8(62, 180, 84, 90),
|
||||||
|
};
|
||||||
|
|
||||||
|
wgpu::TextureDataLayout dataLayout = {};
|
||||||
|
dataLayout.bytesPerRow = textureDesc.size.width * sizeof(RGBA8);
|
||||||
|
|
||||||
|
queue.WriteTexture(&dst, rgbaTextureData.data(), rgbaTextureData.size() * sizeof(RGBA8),
|
||||||
|
&dataLayout, &textureDesc.size);
|
||||||
|
|
||||||
|
wgpu::TextureView textureView = texture.CreateView(&viewDesc);
|
||||||
|
|
||||||
|
utils::ComboRenderPipelineDescriptor pipelineDesc;
|
||||||
|
pipelineDesc.vertex.module = utils::CreateShaderModule(device, R"(
|
||||||
|
@stage(vertex)
|
||||||
|
fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4<f32> {
|
||||||
|
var pos = array<vec2<f32>, 6>(
|
||||||
|
vec2<f32>(-1.0, -1.0),
|
||||||
|
vec2<f32>(-1.0, 1.0),
|
||||||
|
vec2<f32>( 1.0, -1.0),
|
||||||
|
vec2<f32>(-1.0, 1.0),
|
||||||
|
vec2<f32>( 1.0, -1.0),
|
||||||
|
vec2<f32>( 1.0, 1.0));
|
||||||
|
return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
pipelineDesc.cFragment.module = utils::CreateShaderModule(device, R"(
|
||||||
|
@group(0) @binding(0) var texture : texture_2d<f32>;
|
||||||
|
|
||||||
|
@stage(fragment)
|
||||||
|
fn main(@builtin(position) coord: vec4<f32>) -> @location(0) vec4<f32> {
|
||||||
|
return textureLoad(texture, vec2<i32>(coord.xy), 0);
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
|
||||||
|
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(
|
||||||
|
device, textureDesc.size.width, textureDesc.size.height, wgpu::TextureFormat::RGBA8Unorm);
|
||||||
|
pipelineDesc.cTargets[0].format = renderPass.colorFormat;
|
||||||
|
|
||||||
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
{
|
||||||
|
wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDesc);
|
||||||
|
|
||||||
|
wgpu::BindGroup bindGroup =
|
||||||
|
utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), {{0, textureView}});
|
||||||
|
|
||||||
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
|
||||||
|
pass.SetPipeline(pipeline);
|
||||||
|
pass.SetBindGroup(0, bindGroup);
|
||||||
|
pass.Draw(6);
|
||||||
|
pass.End();
|
||||||
|
}
|
||||||
|
|
||||||
|
wgpu::CommandBuffer commands = encoder.Finish();
|
||||||
|
queue.Submit(1, &commands);
|
||||||
|
|
||||||
|
EXPECT_PIXEL_RGBA8_BETWEEN( //
|
||||||
|
RGBA8(116, 0, 0, 255), //
|
||||||
|
RGBA8(117, 0, 0, 255), renderPass.color, 0, 0);
|
||||||
|
EXPECT_PIXEL_RGBA8_BETWEEN( //
|
||||||
|
RGBA8(0, 23, 0, 127), //
|
||||||
|
RGBA8(0, 24, 0, 127), renderPass.color, 1, 0);
|
||||||
|
EXPECT_PIXEL_RGBA8_BETWEEN( //
|
||||||
|
RGBA8(0, 0, 12, 100), //
|
||||||
|
RGBA8(0, 0, 13, 100), renderPass.color, 0, 1);
|
||||||
|
EXPECT_PIXEL_RGBA8_BETWEEN( //
|
||||||
|
RGBA8(12, 116, 23, 90), //
|
||||||
|
RGBA8(13, 117, 24, 90), renderPass.color, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
// Test sampling from a cube map texture view that covers a whole 2D array texture.
|
// Test sampling from a cube map texture view that covers a whole 2D array texture.
|
||||||
TEST_P(TextureViewSamplingTest, TextureCubeMapOnWholeTexture) {
|
TEST_P(TextureViewSamplingTest, TextureCubeMapOnWholeTexture) {
|
||||||
constexpr uint32_t kTotalLayers = 6;
|
constexpr uint32_t kTotalLayers = 6;
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#include "dawn/tests/unittests/validation/ValidationTest.h"
|
#include "dawn/tests/unittests/validation/ValidationTest.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class TextureViewValidationTest : public ValidationTest {};
|
class TextureViewValidationTest : public ValidationTest {};
|
||||||
|
@ -667,18 +669,147 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test the format compatibility rules when creating a texture view.
|
// Test the format compatibility rules when creating a texture view.
|
||||||
// TODO(jiawei.shao@intel.com): add more tests when the rules are fully implemented.
|
|
||||||
TEST_F(TextureViewValidationTest, TextureViewFormatCompatibility) {
|
TEST_F(TextureViewValidationTest, TextureViewFormatCompatibility) {
|
||||||
wgpu::Texture texture = Create2DArrayTexture(device, 1);
|
wgpu::TextureDescriptor textureDesc = {};
|
||||||
|
textureDesc.size.width = 4;
|
||||||
|
textureDesc.size.height = 4;
|
||||||
|
textureDesc.usage = wgpu::TextureUsage::TextureBinding;
|
||||||
|
|
||||||
wgpu::TextureViewDescriptor base2DTextureViewDescriptor =
|
wgpu::TextureViewDescriptor viewDesc = {};
|
||||||
CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D);
|
|
||||||
|
|
||||||
// It is an error to create a texture view in depth-stencil format on a RGBA texture.
|
// It is an error to create an sRGB texture view from an RGB texture, without viewFormats.
|
||||||
{
|
{
|
||||||
wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor;
|
textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
descriptor.format = wgpu::TextureFormat::Depth24PlusStencil8;
|
viewDesc.format = wgpu::TextureFormat::RGBA8UnormSrgb;
|
||||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
wgpu::Texture texture = device.CreateTexture(&textureDesc);
|
||||||
|
ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc));
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is an error to create an RGB texture view from an sRGB texture, without viewFormats.
|
||||||
|
{
|
||||||
|
textureDesc.format = wgpu::TextureFormat::BGRA8UnormSrgb;
|
||||||
|
viewDesc.format = wgpu::TextureFormat::BGRA8Unorm;
|
||||||
|
wgpu::Texture texture = device.CreateTexture(&textureDesc);
|
||||||
|
ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc));
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is an error to create a texture view with a depth-stencil format of an RGBA texture.
|
||||||
|
{
|
||||||
|
textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
viewDesc.format = wgpu::TextureFormat::Depth24PlusStencil8;
|
||||||
|
wgpu::Texture texture = device.CreateTexture(&textureDesc);
|
||||||
|
ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc));
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is an error to create a texture view with a depth format of a depth-stencil texture.
|
||||||
|
{
|
||||||
|
textureDesc.format = wgpu::TextureFormat::Depth24PlusStencil8;
|
||||||
|
viewDesc.format = wgpu::TextureFormat::Depth24Plus;
|
||||||
|
wgpu::Texture texture = device.CreateTexture(&textureDesc);
|
||||||
|
ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc));
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is valid to create a texture view with a depth format of a depth-stencil texture
|
||||||
|
// if the depth only aspect is selected.
|
||||||
|
{
|
||||||
|
textureDesc.format = wgpu::TextureFormat::Depth24PlusStencil8;
|
||||||
|
viewDesc.format = wgpu::TextureFormat::Depth24Plus;
|
||||||
|
viewDesc.aspect = wgpu::TextureAspect::DepthOnly;
|
||||||
|
wgpu::Texture texture = device.CreateTexture(&textureDesc);
|
||||||
|
texture.CreateView(&viewDesc);
|
||||||
|
|
||||||
|
viewDesc = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prep for testing a single view format in viewFormats.
|
||||||
|
wgpu::TextureFormat viewFormat;
|
||||||
|
textureDesc.viewFormats = &viewFormat;
|
||||||
|
textureDesc.viewFormatCount = 1;
|
||||||
|
|
||||||
|
// An aspect format is not a valid view format of a depth-stencil texture.
|
||||||
|
{
|
||||||
|
textureDesc.format = wgpu::TextureFormat::Depth24PlusStencil8;
|
||||||
|
viewFormat = wgpu::TextureFormat::Depth24Plus;
|
||||||
|
ASSERT_DEVICE_ERROR(device.CreateTexture(&textureDesc));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that a RGBA texture can be viewed as both RGBA and RGBASrgb, but not BGRA or
|
||||||
|
// BGRASrgb
|
||||||
|
{
|
||||||
|
textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
viewFormat = wgpu::TextureFormat::RGBA8UnormSrgb;
|
||||||
|
wgpu::Texture texture = device.CreateTexture(&textureDesc);
|
||||||
|
|
||||||
|
viewDesc.format = wgpu::TextureFormat::RGBA8UnormSrgb;
|
||||||
|
texture.CreateView(&viewDesc);
|
||||||
|
|
||||||
|
viewDesc.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
texture.CreateView(&viewDesc);
|
||||||
|
|
||||||
|
viewDesc.format = wgpu::TextureFormat::BGRA8Unorm;
|
||||||
|
ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc));
|
||||||
|
|
||||||
|
viewDesc.format = wgpu::TextureFormat::BGRA8UnormSrgb;
|
||||||
|
ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that a BGRASrgb texture can be viewed as both BGRA and BGRASrgb, but not RGBA or
|
||||||
|
// RGBASrgb
|
||||||
|
{
|
||||||
|
textureDesc.format = wgpu::TextureFormat::BGRA8UnormSrgb;
|
||||||
|
viewFormat = wgpu::TextureFormat::BGRA8Unorm;
|
||||||
|
wgpu::Texture texture = device.CreateTexture(&textureDesc);
|
||||||
|
|
||||||
|
viewDesc.format = wgpu::TextureFormat::BGRA8Unorm;
|
||||||
|
texture.CreateView(&viewDesc);
|
||||||
|
|
||||||
|
viewDesc.format = wgpu::TextureFormat::BGRA8UnormSrgb;
|
||||||
|
texture.CreateView(&viewDesc);
|
||||||
|
|
||||||
|
viewDesc.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc));
|
||||||
|
|
||||||
|
viewDesc.format = wgpu::TextureFormat::RGBA8UnormSrgb;
|
||||||
|
ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test an RGBA format may be viewed as RGBA (same)
|
||||||
|
{
|
||||||
|
textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
viewFormat = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
wgpu::Texture texture = device.CreateTexture(&textureDesc);
|
||||||
|
|
||||||
|
viewDesc.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
texture.CreateView(&viewDesc);
|
||||||
|
|
||||||
|
viewDesc.format = wgpu::TextureFormat::RGBA8UnormSrgb;
|
||||||
|
ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that duplicate, and multiple view formats are allowed.
|
||||||
|
{
|
||||||
|
std::array<wgpu::TextureFormat, 5> viewFormats = {
|
||||||
|
wgpu::TextureFormat::RGBA8UnormSrgb, wgpu::TextureFormat::RGBA8Unorm,
|
||||||
|
wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureFormat::RGBA8UnormSrgb,
|
||||||
|
wgpu::TextureFormat::RGBA8Unorm,
|
||||||
|
};
|
||||||
|
textureDesc.viewFormats = viewFormats.data();
|
||||||
|
textureDesc.viewFormatCount = viewFormats.size();
|
||||||
|
|
||||||
|
textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
wgpu::Texture texture = device.CreateTexture(&textureDesc);
|
||||||
|
|
||||||
|
viewDesc.format = wgpu::TextureFormat::RGBA8UnormSrgb;
|
||||||
|
texture.CreateView(&viewDesc);
|
||||||
|
|
||||||
|
viewDesc.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
texture.CreateView(&viewDesc);
|
||||||
|
|
||||||
|
viewDesc.format = wgpu::TextureFormat::BGRA8Unorm;
|
||||||
|
ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc));
|
||||||
|
|
||||||
|
viewDesc.format = wgpu::TextureFormat::BGRA8UnormSrgb;
|
||||||
|
ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "dawn/native/vulkan/AdapterVk.h"
|
#include "dawn/native/vulkan/AdapterVk.h"
|
||||||
#include "dawn/native/vulkan/DeviceVk.h"
|
#include "dawn/native/vulkan/DeviceVk.h"
|
||||||
#include "dawn/tests/DawnTest.h"
|
#include "dawn/tests/DawnTest.h"
|
||||||
|
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
|
||||||
#include "dawn/utils/WGPUHelpers.h"
|
#include "dawn/utils/WGPUHelpers.h"
|
||||||
|
|
||||||
namespace dawn::native { namespace vulkan {
|
namespace dawn::native { namespace vulkan {
|
||||||
|
@ -780,6 +781,106 @@ namespace dawn::native { namespace vulkan {
|
||||||
IgnoreSignalSemaphore(nextWrappedTexture);
|
IgnoreSignalSemaphore(nextWrappedTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that texture descriptor view formats are passed to the backend for wrapped external
|
||||||
|
// textures, and that contents may be reinterpreted as sRGB.
|
||||||
|
TEST_P(VulkanImageWrappingUsageTests, SRGBReinterpretation) {
|
||||||
|
wgpu::TextureViewDescriptor viewDesc = {};
|
||||||
|
viewDesc.format = wgpu::TextureFormat::RGBA8UnormSrgb;
|
||||||
|
|
||||||
|
wgpu::TextureDescriptor textureDesc = {};
|
||||||
|
textureDesc.size = {2, 2, 1};
|
||||||
|
textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
textureDesc.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::TextureBinding;
|
||||||
|
textureDesc.viewFormatCount = 1;
|
||||||
|
textureDesc.viewFormats = &viewDesc.format;
|
||||||
|
|
||||||
|
std::unique_ptr<ExternalTexture> backendTexture = mBackend->CreateTexture(
|
||||||
|
textureDesc.size.width, textureDesc.size.height, textureDesc.format, textureDesc.usage);
|
||||||
|
|
||||||
|
// Import the image on |device|
|
||||||
|
wgpu::Texture texture =
|
||||||
|
WrapVulkanImage(device, &textureDesc, backendTexture.get(), {},
|
||||||
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
ASSERT_NE(texture.Get(), nullptr);
|
||||||
|
|
||||||
|
wgpu::ImageCopyTexture dst = {};
|
||||||
|
dst.texture = texture;
|
||||||
|
std::array<RGBA8, 4> rgbaTextureData = {
|
||||||
|
RGBA8(180, 0, 0, 255),
|
||||||
|
RGBA8(0, 84, 0, 127),
|
||||||
|
RGBA8(0, 0, 62, 100),
|
||||||
|
RGBA8(62, 180, 84, 90),
|
||||||
|
};
|
||||||
|
|
||||||
|
wgpu::TextureDataLayout dataLayout = {};
|
||||||
|
dataLayout.bytesPerRow = textureDesc.size.width * sizeof(RGBA8);
|
||||||
|
|
||||||
|
queue.WriteTexture(&dst, rgbaTextureData.data(), rgbaTextureData.size() * sizeof(RGBA8),
|
||||||
|
&dataLayout, &textureDesc.size);
|
||||||
|
|
||||||
|
wgpu::TextureView textureView = texture.CreateView(&viewDesc);
|
||||||
|
|
||||||
|
utils::ComboRenderPipelineDescriptor pipelineDesc;
|
||||||
|
pipelineDesc.vertex.module = utils::CreateShaderModule(device, R"(
|
||||||
|
@stage(vertex)
|
||||||
|
fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4<f32> {
|
||||||
|
var pos = array<vec2<f32>, 6>(
|
||||||
|
vec2<f32>(-1.0, -1.0),
|
||||||
|
vec2<f32>(-1.0, 1.0),
|
||||||
|
vec2<f32>( 1.0, -1.0),
|
||||||
|
vec2<f32>(-1.0, 1.0),
|
||||||
|
vec2<f32>( 1.0, -1.0),
|
||||||
|
vec2<f32>( 1.0, 1.0));
|
||||||
|
return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
pipelineDesc.cFragment.module = utils::CreateShaderModule(device, R"(
|
||||||
|
@group(0) @binding(0) var texture : texture_2d<f32>;
|
||||||
|
|
||||||
|
@stage(fragment)
|
||||||
|
fn main(@builtin(position) coord: vec4<f32>) -> @location(0) vec4<f32> {
|
||||||
|
return textureLoad(texture, vec2<i32>(coord.xy), 0);
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
|
||||||
|
utils::BasicRenderPass renderPass =
|
||||||
|
utils::CreateBasicRenderPass(device, textureDesc.size.width, textureDesc.size.height,
|
||||||
|
wgpu::TextureFormat::RGBA8Unorm);
|
||||||
|
pipelineDesc.cTargets[0].format = renderPass.colorFormat;
|
||||||
|
|
||||||
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
{
|
||||||
|
wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDesc);
|
||||||
|
|
||||||
|
wgpu::BindGroup bindGroup =
|
||||||
|
utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), {{0, textureView}});
|
||||||
|
|
||||||
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
|
||||||
|
pass.SetPipeline(pipeline);
|
||||||
|
pass.SetBindGroup(0, bindGroup);
|
||||||
|
pass.Draw(6);
|
||||||
|
pass.End();
|
||||||
|
}
|
||||||
|
|
||||||
|
wgpu::CommandBuffer commands = encoder.Finish();
|
||||||
|
queue.Submit(1, &commands);
|
||||||
|
|
||||||
|
EXPECT_PIXEL_RGBA8_BETWEEN( //
|
||||||
|
RGBA8(116, 0, 0, 255), //
|
||||||
|
RGBA8(117, 0, 0, 255), renderPass.color, 0, 0);
|
||||||
|
EXPECT_PIXEL_RGBA8_BETWEEN( //
|
||||||
|
RGBA8(0, 23, 0, 127), //
|
||||||
|
RGBA8(0, 24, 0, 127), renderPass.color, 1, 0);
|
||||||
|
EXPECT_PIXEL_RGBA8_BETWEEN( //
|
||||||
|
RGBA8(0, 0, 12, 100), //
|
||||||
|
RGBA8(0, 0, 13, 100), renderPass.color, 0, 1);
|
||||||
|
EXPECT_PIXEL_RGBA8_BETWEEN( //
|
||||||
|
RGBA8(12, 116, 23, 90), //
|
||||||
|
RGBA8(13, 117, 24, 90), renderPass.color, 1, 1);
|
||||||
|
|
||||||
|
IgnoreSignalSemaphore(texture);
|
||||||
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(VulkanImageWrappingValidationTests, VulkanBackend());
|
DAWN_INSTANTIATE_TEST(VulkanImageWrappingValidationTests, VulkanBackend());
|
||||||
DAWN_INSTANTIATE_TEST(VulkanImageWrappingUsageTests, VulkanBackend());
|
DAWN_INSTANTIATE_TEST(VulkanImageWrappingUsageTests, VulkanBackend());
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue