d3d11: enable DynamicBufferOffsetTests
This binds UAV slots all together at the same time. Bug: dawn:1816 Bug: dawn:1705 Change-Id: Iea7af9cf00caf126a3964cc43bbf2162b35f80e0 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/132600 Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Jie A Chen <jie.a.chen@intel.com> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
bfa1d3a870
commit
cd1fb68767
|
@ -266,6 +266,7 @@ MaybeError DeviceBase::Initialize(Ref<QueueBase> defaultQueue) {
|
||||||
mState = State::Alive;
|
mState = State::Alive;
|
||||||
|
|
||||||
DAWN_TRY_ASSIGN(mEmptyBindGroupLayout, CreateEmptyBindGroupLayout());
|
DAWN_TRY_ASSIGN(mEmptyBindGroupLayout, CreateEmptyBindGroupLayout());
|
||||||
|
DAWN_TRY_ASSIGN(mEmptyPipelineLayout, CreateEmptyPipelineLayout());
|
||||||
|
|
||||||
// If placeholder fragment shader module is needed, initialize it
|
// If placeholder fragment shader module is needed, initialize it
|
||||||
if (IsToggleEnabled(Toggle::UsePlaceholderFragmentInVertexOnlyPipeline)) {
|
if (IsToggleEnabled(Toggle::UsePlaceholderFragmentInVertexOnlyPipeline)) {
|
||||||
|
@ -481,6 +482,7 @@ void DeviceBase::Destroy() {
|
||||||
// Destroy() via APIGetQueue.
|
// Destroy() via APIGetQueue.
|
||||||
mDynamicUploader = nullptr;
|
mDynamicUploader = nullptr;
|
||||||
mEmptyBindGroupLayout = nullptr;
|
mEmptyBindGroupLayout = nullptr;
|
||||||
|
mEmptyPipelineLayout = nullptr;
|
||||||
mInternalPipelineStore = nullptr;
|
mInternalPipelineStore = nullptr;
|
||||||
mExternalTexturePlaceholderView = nullptr;
|
mExternalTexturePlaceholderView = nullptr;
|
||||||
|
|
||||||
|
@ -850,11 +852,24 @@ ResultOrError<Ref<BindGroupLayoutBase>> DeviceBase::CreateEmptyBindGroupLayout()
|
||||||
return GetOrCreateBindGroupLayout(&desc);
|
return GetOrCreateBindGroupLayout(&desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResultOrError<Ref<PipelineLayoutBase>> DeviceBase::CreateEmptyPipelineLayout() {
|
||||||
|
PipelineLayoutDescriptor desc = {};
|
||||||
|
desc.bindGroupLayoutCount = 0;
|
||||||
|
desc.bindGroupLayouts = nullptr;
|
||||||
|
|
||||||
|
return GetOrCreatePipelineLayout(&desc);
|
||||||
|
}
|
||||||
|
|
||||||
BindGroupLayoutBase* DeviceBase::GetEmptyBindGroupLayout() {
|
BindGroupLayoutBase* DeviceBase::GetEmptyBindGroupLayout() {
|
||||||
ASSERT(mEmptyBindGroupLayout != nullptr);
|
ASSERT(mEmptyBindGroupLayout != nullptr);
|
||||||
return mEmptyBindGroupLayout.Get();
|
return mEmptyBindGroupLayout.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PipelineLayoutBase* DeviceBase::GetEmptyPipelineLayout() {
|
||||||
|
ASSERT(mEmptyPipelineLayout != nullptr);
|
||||||
|
return mEmptyPipelineLayout.Get();
|
||||||
|
}
|
||||||
|
|
||||||
Ref<ComputePipelineBase> DeviceBase::GetCachedComputePipeline(
|
Ref<ComputePipelineBase> DeviceBase::GetCachedComputePipeline(
|
||||||
ComputePipelineBase* uninitializedComputePipeline) {
|
ComputePipelineBase* uninitializedComputePipeline) {
|
||||||
Ref<ComputePipelineBase> cachedPipeline;
|
Ref<ComputePipelineBase> cachedPipeline;
|
||||||
|
|
|
@ -197,6 +197,7 @@ class DeviceBase : public RefCountedWithExternalCount {
|
||||||
void UncacheBindGroupLayout(BindGroupLayoutBase* obj);
|
void UncacheBindGroupLayout(BindGroupLayoutBase* obj);
|
||||||
|
|
||||||
BindGroupLayoutBase* GetEmptyBindGroupLayout();
|
BindGroupLayoutBase* GetEmptyBindGroupLayout();
|
||||||
|
PipelineLayoutBase* GetEmptyPipelineLayout();
|
||||||
|
|
||||||
void UncacheComputePipeline(ComputePipelineBase* obj);
|
void UncacheComputePipeline(ComputePipelineBase* obj);
|
||||||
|
|
||||||
|
@ -506,6 +507,7 @@ class DeviceBase : public RefCountedWithExternalCount {
|
||||||
void FlushCallbackTaskQueue();
|
void FlushCallbackTaskQueue();
|
||||||
|
|
||||||
ResultOrError<Ref<BindGroupLayoutBase>> CreateEmptyBindGroupLayout();
|
ResultOrError<Ref<BindGroupLayoutBase>> CreateEmptyBindGroupLayout();
|
||||||
|
ResultOrError<Ref<PipelineLayoutBase>> CreateEmptyPipelineLayout();
|
||||||
|
|
||||||
Ref<ComputePipelineBase> GetCachedComputePipeline(
|
Ref<ComputePipelineBase> GetCachedComputePipeline(
|
||||||
ComputePipelineBase* uninitializedComputePipeline);
|
ComputePipelineBase* uninitializedComputePipeline);
|
||||||
|
@ -588,6 +590,7 @@ class DeviceBase : public RefCountedWithExternalCount {
|
||||||
std::unique_ptr<Caches> mCaches;
|
std::unique_ptr<Caches> mCaches;
|
||||||
|
|
||||||
Ref<BindGroupLayoutBase> mEmptyBindGroupLayout;
|
Ref<BindGroupLayoutBase> mEmptyBindGroupLayout;
|
||||||
|
Ref<PipelineLayoutBase> mEmptyPipelineLayout;
|
||||||
|
|
||||||
Ref<TextureViewBase> mExternalTexturePlaceholderView;
|
Ref<TextureViewBase> mExternalTexturePlaceholderView;
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
|
|
||||||
#include "dawn/native/d3d11/BindGroupTrackerD3D11.h"
|
#include "dawn/native/d3d11/BindGroupTrackerD3D11.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "dawn/common/Assert.h"
|
#include "dawn/common/Assert.h"
|
||||||
#include "dawn/native/Format.h"
|
#include "dawn/native/Format.h"
|
||||||
#include "dawn/native/d3d/D3DError.h"
|
#include "dawn/native/d3d/D3DError.h"
|
||||||
|
@ -68,23 +71,64 @@ bool CheckAllSlotsAreEmpty(CommandRecordingContext* commandContext) {
|
||||||
ASSERT(sampler == nullptr);
|
ASSERT(sampler == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check UAV slots
|
// Check UAV slots for compute
|
||||||
for (UINT slot = 0; slot < D3D11_1_UAV_SLOT_COUNT; ++slot) {
|
for (UINT slot = 0; slot < D3D11_1_UAV_SLOT_COUNT; ++slot) {
|
||||||
ID3D11UnorderedAccessView* uav = nullptr;
|
ID3D11UnorderedAccessView* uav = nullptr;
|
||||||
deviceContext1->CSGetUnorderedAccessViews(slot, 1, &uav);
|
deviceContext1->CSGetUnorderedAccessViews(slot, 1, &uav);
|
||||||
ASSERT(uav == nullptr);
|
ASSERT(uav == nullptr);
|
||||||
}
|
}
|
||||||
|
// Check UAV slots for render
|
||||||
|
for (UINT slot = 0; slot < commandContext->GetDevice()->GetUAVSlotCount(); ++slot) {
|
||||||
|
ID3D11UnorderedAccessView* uav = nullptr;
|
||||||
|
deviceContext1->OMGetRenderTargetsAndUnorderedAccessViews(0, nullptr, nullptr, slot, 1,
|
||||||
|
&uav);
|
||||||
|
ASSERT(uav == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ResetAllRenderSlots(CommandRecordingContext* commandContext) {
|
||||||
|
ID3D11DeviceContext1* deviceContext1 = commandContext->GetD3D11DeviceContext1();
|
||||||
|
|
||||||
|
// Reserve one slot for builtin constants.
|
||||||
|
constexpr uint32_t kReservedCBVSlots = 1;
|
||||||
|
|
||||||
|
ID3D11Buffer* d3d11Buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {};
|
||||||
|
uint32_t num = D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - kReservedCBVSlots;
|
||||||
|
deviceContext1->VSSetConstantBuffers1(0, num, d3d11Buffers, nullptr, nullptr);
|
||||||
|
deviceContext1->PSSetConstantBuffers1(0, num, d3d11Buffers, nullptr, nullptr);
|
||||||
|
|
||||||
|
ID3D11ShaderResourceView* d3d11SRVs[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {};
|
||||||
|
num = D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT;
|
||||||
|
deviceContext1->VSSetShaderResources(0, num, d3d11SRVs);
|
||||||
|
deviceContext1->PSSetShaderResources(0, num, d3d11SRVs);
|
||||||
|
|
||||||
|
ID3D11SamplerState* d3d11Samplers[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT] = {};
|
||||||
|
num = D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
|
||||||
|
deviceContext1->VSSetSamplers(0, num, d3d11Samplers);
|
||||||
|
deviceContext1->PSSetSamplers(0, num, d3d11Samplers);
|
||||||
|
|
||||||
|
ID3D11UnorderedAccessView* d3d11UAVs[D3D11_1_UAV_SLOT_COUNT] = {};
|
||||||
|
num = commandContext->GetDevice()->GetUAVSlotCount();
|
||||||
|
deviceContext1->OMSetRenderTargetsAndUnorderedAccessViews(
|
||||||
|
D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, 0, num, d3d11UAVs, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
BindGroupTracker::BindGroupTracker(CommandRecordingContext* commandContext)
|
BindGroupTracker::BindGroupTracker(CommandRecordingContext* commandContext, bool isRenderPass)
|
||||||
: mCommandContext(commandContext) {}
|
: mCommandContext(commandContext),
|
||||||
|
mIsRenderPass(isRenderPass),
|
||||||
|
mVisibleStages(isRenderPass ? wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment
|
||||||
|
: wgpu::ShaderStage::Compute) {
|
||||||
|
mLastAppliedPipelineLayout = commandContext->GetDevice()->GetEmptyPipelineLayout();
|
||||||
|
}
|
||||||
|
|
||||||
BindGroupTracker::~BindGroupTracker() {
|
BindGroupTracker::~BindGroupTracker() {
|
||||||
if (mLastAppliedPipelineLayout) {
|
if (mIsRenderPass) {
|
||||||
|
ResetAllRenderSlots(mCommandContext);
|
||||||
|
} else {
|
||||||
for (BindGroupIndex index :
|
for (BindGroupIndex index :
|
||||||
IterateBitSet(mLastAppliedPipelineLayout->GetBindGroupLayoutsMask())) {
|
IterateBitSet(mLastAppliedPipelineLayout->GetBindGroupLayoutsMask())) {
|
||||||
UnApplyBindGroup(index);
|
UnApplyBindGroup(index);
|
||||||
|
@ -97,15 +141,93 @@ BindGroupTracker::~BindGroupTracker() {
|
||||||
MaybeError BindGroupTracker::Apply() {
|
MaybeError BindGroupTracker::Apply() {
|
||||||
BeforeApply();
|
BeforeApply();
|
||||||
|
|
||||||
// A resource cannot be bound as both input resource and UAV at the same time, so to avoid this
|
if (mIsRenderPass) {
|
||||||
// conflict, we need to unbind groups which are not used by the new pipeline. and unbind groups
|
// As D3d11 requires to bind all UAVs slots at the same time for pixel shaders, we record
|
||||||
// which are not inherited by the new pipeline.
|
// all UAV slot assignments in the bind groups, and then bind them all together.
|
||||||
if (mLastAppliedPipelineLayout) {
|
const BindGroupLayoutMask uavBindGroups =
|
||||||
BindGroupLayoutMask lastGroups = mLastAppliedPipelineLayout->GetBindGroupLayoutsMask();
|
ToBackend(mPipelineLayout)->GetUAVBindGroupLayoutsMask();
|
||||||
BindGroupLayoutMask currentGroups = mPipelineLayout->GetBindGroupLayoutsMask();
|
std::vector<ComPtr<ID3D11UnorderedAccessView>> d3d11UAVs;
|
||||||
BindGroupLayoutMask unApplyGroups = (mDirtyBindGroups | ~currentGroups) & lastGroups;
|
for (BindGroupIndex index : IterateBitSet(uavBindGroups)) {
|
||||||
// Unset bind groups which are not used by the new pipeline and are not inherited.
|
BindGroupBase* group = mBindGroups[index];
|
||||||
for (BindGroupIndex index : IterateBitSet(unApplyGroups)) {
|
const ityp::vector<BindingIndex, uint64_t>& dynamicOffsets = mDynamicOffsets[index];
|
||||||
|
|
||||||
|
for (BindingIndex bindingIndex{0}; bindingIndex < group->GetLayout()->GetBindingCount();
|
||||||
|
++bindingIndex) {
|
||||||
|
const BindingInfo& bindingInfo = group->GetLayout()->GetBindingInfo(bindingIndex);
|
||||||
|
|
||||||
|
switch (bindingInfo.bindingType) {
|
||||||
|
case BindingInfoType::Buffer: {
|
||||||
|
BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
|
||||||
|
auto offset = binding.offset;
|
||||||
|
if (bindingInfo.buffer.hasDynamicOffset) {
|
||||||
|
// Dynamic buffers are packed at the front of BindingIndices.
|
||||||
|
offset += dynamicOffsets[bindingIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (bindingInfo.buffer.type) {
|
||||||
|
case wgpu::BufferBindingType::Storage:
|
||||||
|
case kInternalStorageBufferBinding: {
|
||||||
|
ASSERT(IsSubset(
|
||||||
|
bindingInfo.visibility,
|
||||||
|
wgpu::ShaderStage::Fragment | wgpu::ShaderStage::Compute));
|
||||||
|
ComPtr<ID3D11UnorderedAccessView> d3d11UAV;
|
||||||
|
DAWN_TRY_ASSIGN(d3d11UAV, ToBackend(binding.buffer)
|
||||||
|
->CreateD3D11UnorderedAccessView1(
|
||||||
|
offset, binding.size));
|
||||||
|
ToBackend(binding.buffer)->MarkMutated();
|
||||||
|
d3d11UAVs.insert(d3d11UAVs.begin(), std::move(d3d11UAV));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case wgpu::BufferBindingType::Uniform:
|
||||||
|
case wgpu::BufferBindingType::ReadOnlyStorage:
|
||||||
|
case wgpu::BufferBindingType::Undefined: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BindingInfoType::StorageTexture: {
|
||||||
|
ASSERT(bindingInfo.storageTexture.access ==
|
||||||
|
wgpu::StorageTextureAccess::WriteOnly);
|
||||||
|
ComPtr<ID3D11UnorderedAccessView> d3d11UAV;
|
||||||
|
TextureView* view = ToBackend(group->GetBindingAsTextureView(bindingIndex));
|
||||||
|
DAWN_TRY_ASSIGN(d3d11UAV, view->CreateD3D11UnorderedAccessView());
|
||||||
|
d3d11UAVs.insert(d3d11UAVs.begin(), std::move(d3d11UAV));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BindingInfoType::Texture:
|
||||||
|
case BindingInfoType::ExternalTexture:
|
||||||
|
case BindingInfoType::Sampler: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint32_t uavSlotCount = ToBackend(mPipelineLayout->GetDevice())->GetUAVSlotCount();
|
||||||
|
std::vector<ID3D11UnorderedAccessView*> views;
|
||||||
|
for (auto& uav : d3d11UAVs) {
|
||||||
|
views.push_back(uav.Get());
|
||||||
|
}
|
||||||
|
mCommandContext->GetD3D11DeviceContext1()->OMSetRenderTargetsAndUnorderedAccessViews(
|
||||||
|
D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr,
|
||||||
|
uavSlotCount - d3d11UAVs.size(), d3d11UAVs.size(), views.data(), nullptr);
|
||||||
|
d3d11UAVs.clear();
|
||||||
|
} else {
|
||||||
|
BindGroupLayoutMask inheritedGroups =
|
||||||
|
mPipelineLayout->InheritedGroupsMask(mLastAppliedPipelineLayout);
|
||||||
|
BindGroupLayoutMask previousGroups = mLastAppliedPipelineLayout->GetBindGroupLayoutsMask();
|
||||||
|
|
||||||
|
// To avoid UAV / SRV conflicts with bindings in previously bind groups, we unset the bind
|
||||||
|
// groups that aren't reused by the current pipeline.
|
||||||
|
// We also need to unset the inherited bind groups which are dirty as the group may have
|
||||||
|
// both SRV and UAV, and the same resource may change its binding from UAV to SRV next
|
||||||
|
// dispatch in the same group.
|
||||||
|
//
|
||||||
|
// Note: WebGPU API guarantees that resources are not used both as UAV and SRV in the same
|
||||||
|
// render pass. So we don't need to do this inside render passes.
|
||||||
|
BindGroupLayoutMask groupsToUnset = previousGroups & (~inheritedGroups | mDirtyBindGroups);
|
||||||
|
for (BindGroupIndex index : IterateBitSet(groupsToUnset)) {
|
||||||
UnApplyBindGroup(index);
|
UnApplyBindGroup(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,6 +251,7 @@ MaybeError BindGroupTracker::ApplyBindGroup(BindGroupIndex index) {
|
||||||
++bindingIndex) {
|
++bindingIndex) {
|
||||||
const BindingInfo& bindingInfo = group->GetLayout()->GetBindingInfo(bindingIndex);
|
const BindingInfo& bindingInfo = group->GetLayout()->GetBindingInfo(bindingIndex);
|
||||||
const uint32_t bindingSlot = indices[bindingIndex];
|
const uint32_t bindingSlot = indices[bindingIndex];
|
||||||
|
const auto bindingVisibility = bindingInfo.visibility & mVisibleStages;
|
||||||
|
|
||||||
switch (bindingInfo.bindingType) {
|
switch (bindingInfo.bindingType) {
|
||||||
case BindingInfoType::Buffer: {
|
case BindingInfoType::Buffer: {
|
||||||
|
@ -156,15 +279,15 @@ MaybeError BindGroupTracker::ApplyBindGroup(BindGroupIndex index) {
|
||||||
DAWN_ASSERT(offset + numConstants * 16 <=
|
DAWN_ASSERT(offset + numConstants * 16 <=
|
||||||
binding.buffer->GetAllocatedSize());
|
binding.buffer->GetAllocatedSize());
|
||||||
|
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) {
|
if (bindingVisibility & wgpu::ShaderStage::Vertex) {
|
||||||
deviceContext1->VSSetConstantBuffers1(bindingSlot, 1, &d3d11Buffer,
|
deviceContext1->VSSetConstantBuffers1(bindingSlot, 1, &d3d11Buffer,
|
||||||
&firstConstant, &numConstants);
|
&firstConstant, &numConstants);
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) {
|
if (bindingVisibility & wgpu::ShaderStage::Fragment) {
|
||||||
deviceContext1->PSSetConstantBuffers1(bindingSlot, 1, &d3d11Buffer,
|
deviceContext1->PSSetConstantBuffers1(bindingSlot, 1, &d3d11Buffer,
|
||||||
&firstConstant, &numConstants);
|
&firstConstant, &numConstants);
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Compute) {
|
if (bindingVisibility & wgpu::ShaderStage::Compute) {
|
||||||
deviceContext1->CSSetConstantBuffers1(bindingSlot, 1, &d3d11Buffer,
|
deviceContext1->CSSetConstantBuffers1(bindingSlot, 1, &d3d11Buffer,
|
||||||
&firstConstant, &numConstants);
|
&firstConstant, &numConstants);
|
||||||
}
|
}
|
||||||
|
@ -174,17 +297,12 @@ MaybeError BindGroupTracker::ApplyBindGroup(BindGroupIndex index) {
|
||||||
case kInternalStorageBufferBinding: {
|
case kInternalStorageBufferBinding: {
|
||||||
ASSERT(IsSubset(bindingInfo.visibility,
|
ASSERT(IsSubset(bindingInfo.visibility,
|
||||||
wgpu::ShaderStage::Fragment | wgpu::ShaderStage::Compute));
|
wgpu::ShaderStage::Fragment | wgpu::ShaderStage::Compute));
|
||||||
|
if (bindingVisibility & wgpu::ShaderStage::Compute) {
|
||||||
ComPtr<ID3D11UnorderedAccessView> d3d11UAV;
|
ComPtr<ID3D11UnorderedAccessView> d3d11UAV;
|
||||||
DAWN_TRY_ASSIGN(
|
DAWN_TRY_ASSIGN(d3d11UAV, ToBackend(binding.buffer)
|
||||||
d3d11UAV, ToBackend(binding.buffer)
|
->CreateD3D11UnorderedAccessView1(
|
||||||
->CreateD3D11UnorderedAccessView1(offset, binding.size));
|
offset, binding.size));
|
||||||
ToBackend(binding.buffer)->MarkMutated();
|
ToBackend(binding.buffer)->MarkMutated();
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) {
|
|
||||||
deviceContext1->OMSetRenderTargetsAndUnorderedAccessViews(
|
|
||||||
D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr,
|
|
||||||
bindingSlot, 1, d3d11UAV.GetAddressOf(), nullptr);
|
|
||||||
}
|
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Compute) {
|
|
||||||
deviceContext1->CSSetUnorderedAccessViews(
|
deviceContext1->CSSetUnorderedAccessViews(
|
||||||
bindingSlot, 1, d3d11UAV.GetAddressOf(), nullptr);
|
bindingSlot, 1, d3d11UAV.GetAddressOf(), nullptr);
|
||||||
}
|
}
|
||||||
|
@ -195,15 +313,15 @@ MaybeError BindGroupTracker::ApplyBindGroup(BindGroupIndex index) {
|
||||||
DAWN_TRY_ASSIGN(d3d11SRV,
|
DAWN_TRY_ASSIGN(d3d11SRV,
|
||||||
ToBackend(binding.buffer)
|
ToBackend(binding.buffer)
|
||||||
->CreateD3D11ShaderResourceView(offset, binding.size));
|
->CreateD3D11ShaderResourceView(offset, binding.size));
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) {
|
if (bindingVisibility & wgpu::ShaderStage::Vertex) {
|
||||||
deviceContext1->VSSetShaderResources(bindingSlot, 1,
|
deviceContext1->VSSetShaderResources(bindingSlot, 1,
|
||||||
d3d11SRV.GetAddressOf());
|
d3d11SRV.GetAddressOf());
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) {
|
if (bindingVisibility & wgpu::ShaderStage::Fragment) {
|
||||||
deviceContext1->PSSetShaderResources(bindingSlot, 1,
|
deviceContext1->PSSetShaderResources(bindingSlot, 1,
|
||||||
d3d11SRV.GetAddressOf());
|
d3d11SRV.GetAddressOf());
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Compute) {
|
if (bindingVisibility & wgpu::ShaderStage::Compute) {
|
||||||
deviceContext1->CSSetShaderResources(bindingSlot, 1,
|
deviceContext1->CSSetShaderResources(bindingSlot, 1,
|
||||||
d3d11SRV.GetAddressOf());
|
d3d11SRV.GetAddressOf());
|
||||||
}
|
}
|
||||||
|
@ -218,13 +336,13 @@ MaybeError BindGroupTracker::ApplyBindGroup(BindGroupIndex index) {
|
||||||
case BindingInfoType::Sampler: {
|
case BindingInfoType::Sampler: {
|
||||||
Sampler* sampler = ToBackend(group->GetBindingAsSampler(bindingIndex));
|
Sampler* sampler = ToBackend(group->GetBindingAsSampler(bindingIndex));
|
||||||
ID3D11SamplerState* d3d11SamplerState = sampler->GetD3D11SamplerState();
|
ID3D11SamplerState* d3d11SamplerState = sampler->GetD3D11SamplerState();
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) {
|
if (bindingVisibility & wgpu::ShaderStage::Vertex) {
|
||||||
deviceContext1->VSSetSamplers(bindingSlot, 1, &d3d11SamplerState);
|
deviceContext1->VSSetSamplers(bindingSlot, 1, &d3d11SamplerState);
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) {
|
if (bindingVisibility & wgpu::ShaderStage::Fragment) {
|
||||||
deviceContext1->PSSetSamplers(bindingSlot, 1, &d3d11SamplerState);
|
deviceContext1->PSSetSamplers(bindingSlot, 1, &d3d11SamplerState);
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Compute) {
|
if (bindingVisibility & wgpu::ShaderStage::Compute) {
|
||||||
deviceContext1->CSSetSamplers(bindingSlot, 1, &d3d11SamplerState);
|
deviceContext1->CSSetSamplers(bindingSlot, 1, &d3d11SamplerState);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -234,13 +352,13 @@ MaybeError BindGroupTracker::ApplyBindGroup(BindGroupIndex index) {
|
||||||
TextureView* view = ToBackend(group->GetBindingAsTextureView(bindingIndex));
|
TextureView* view = ToBackend(group->GetBindingAsTextureView(bindingIndex));
|
||||||
ComPtr<ID3D11ShaderResourceView> srv;
|
ComPtr<ID3D11ShaderResourceView> srv;
|
||||||
DAWN_TRY_ASSIGN(srv, view->CreateD3D11ShaderResourceView());
|
DAWN_TRY_ASSIGN(srv, view->CreateD3D11ShaderResourceView());
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) {
|
if (bindingVisibility & wgpu::ShaderStage::Vertex) {
|
||||||
deviceContext1->VSSetShaderResources(bindingSlot, 1, srv.GetAddressOf());
|
deviceContext1->VSSetShaderResources(bindingSlot, 1, srv.GetAddressOf());
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) {
|
if (bindingVisibility & wgpu::ShaderStage::Fragment) {
|
||||||
deviceContext1->PSSetShaderResources(bindingSlot, 1, srv.GetAddressOf());
|
deviceContext1->PSSetShaderResources(bindingSlot, 1, srv.GetAddressOf());
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Compute) {
|
if (bindingVisibility & wgpu::ShaderStage::Compute) {
|
||||||
deviceContext1->CSSetShaderResources(bindingSlot, 1, srv.GetAddressOf());
|
deviceContext1->CSSetShaderResources(bindingSlot, 1, srv.GetAddressOf());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -248,15 +366,10 @@ MaybeError BindGroupTracker::ApplyBindGroup(BindGroupIndex index) {
|
||||||
|
|
||||||
case BindingInfoType::StorageTexture: {
|
case BindingInfoType::StorageTexture: {
|
||||||
ASSERT(bindingInfo.storageTexture.access == wgpu::StorageTextureAccess::WriteOnly);
|
ASSERT(bindingInfo.storageTexture.access == wgpu::StorageTextureAccess::WriteOnly);
|
||||||
|
if (bindingVisibility & wgpu::ShaderStage::Compute) {
|
||||||
ComPtr<ID3D11UnorderedAccessView> d3d11UAV;
|
ComPtr<ID3D11UnorderedAccessView> d3d11UAV;
|
||||||
TextureView* view = ToBackend(group->GetBindingAsTextureView(bindingIndex));
|
TextureView* view = ToBackend(group->GetBindingAsTextureView(bindingIndex));
|
||||||
DAWN_TRY_ASSIGN(d3d11UAV, view->CreateD3D11UnorderedAccessView());
|
DAWN_TRY_ASSIGN(d3d11UAV, view->CreateD3D11UnorderedAccessView());
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) {
|
|
||||||
deviceContext1->OMSetRenderTargetsAndUnorderedAccessViews(
|
|
||||||
D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, bindingSlot,
|
|
||||||
1, d3d11UAV.GetAddressOf(), nullptr);
|
|
||||||
}
|
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Compute) {
|
|
||||||
deviceContext1->CSSetUnorderedAccessViews(bindingSlot, 1,
|
deviceContext1->CSSetUnorderedAccessViews(bindingSlot, 1,
|
||||||
d3d11UAV.GetAddressOf(), nullptr);
|
d3d11UAV.GetAddressOf(), nullptr);
|
||||||
}
|
}
|
||||||
|
@ -280,21 +393,22 @@ void BindGroupTracker::UnApplyBindGroup(BindGroupIndex index) {
|
||||||
++bindingIndex) {
|
++bindingIndex) {
|
||||||
const BindingInfo& bindingInfo = groupLayout->GetBindingInfo(bindingIndex);
|
const BindingInfo& bindingInfo = groupLayout->GetBindingInfo(bindingIndex);
|
||||||
const uint32_t bindingSlot = indices[bindingIndex];
|
const uint32_t bindingSlot = indices[bindingIndex];
|
||||||
|
const auto bindingVisibility = bindingInfo.visibility & mVisibleStages;
|
||||||
|
|
||||||
switch (bindingInfo.bindingType) {
|
switch (bindingInfo.bindingType) {
|
||||||
case BindingInfoType::Buffer: {
|
case BindingInfoType::Buffer: {
|
||||||
switch (bindingInfo.buffer.type) {
|
switch (bindingInfo.buffer.type) {
|
||||||
case wgpu::BufferBindingType::Uniform: {
|
case wgpu::BufferBindingType::Uniform: {
|
||||||
ID3D11Buffer* nullBuffer = nullptr;
|
ID3D11Buffer* nullBuffer = nullptr;
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) {
|
if (bindingVisibility & wgpu::ShaderStage::Vertex) {
|
||||||
deviceContext1->VSSetConstantBuffers1(bindingSlot, 1, &nullBuffer,
|
deviceContext1->VSSetConstantBuffers1(bindingSlot, 1, &nullBuffer,
|
||||||
nullptr, nullptr);
|
nullptr, nullptr);
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) {
|
if (bindingVisibility & wgpu::ShaderStage::Fragment) {
|
||||||
deviceContext1->PSSetConstantBuffers1(bindingSlot, 1, &nullBuffer,
|
deviceContext1->PSSetConstantBuffers1(bindingSlot, 1, &nullBuffer,
|
||||||
nullptr, nullptr);
|
nullptr, nullptr);
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Compute) {
|
if (bindingVisibility & wgpu::ShaderStage::Compute) {
|
||||||
deviceContext1->CSSetConstantBuffers1(bindingSlot, 1, &nullBuffer,
|
deviceContext1->CSSetConstantBuffers1(bindingSlot, 1, &nullBuffer,
|
||||||
nullptr, nullptr);
|
nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
@ -305,12 +419,12 @@ void BindGroupTracker::UnApplyBindGroup(BindGroupIndex index) {
|
||||||
ASSERT(IsSubset(bindingInfo.visibility,
|
ASSERT(IsSubset(bindingInfo.visibility,
|
||||||
wgpu::ShaderStage::Fragment | wgpu::ShaderStage::Compute));
|
wgpu::ShaderStage::Fragment | wgpu::ShaderStage::Compute));
|
||||||
ID3D11UnorderedAccessView* nullUAV = nullptr;
|
ID3D11UnorderedAccessView* nullUAV = nullptr;
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) {
|
if (bindingVisibility & wgpu::ShaderStage::Fragment) {
|
||||||
deviceContext1->OMSetRenderTargetsAndUnorderedAccessViews(
|
deviceContext1->OMSetRenderTargetsAndUnorderedAccessViews(
|
||||||
D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr,
|
D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr,
|
||||||
bindingSlot, 1, &nullUAV, nullptr);
|
bindingSlot, 1, &nullUAV, nullptr);
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Compute) {
|
if (bindingVisibility & wgpu::ShaderStage::Compute) {
|
||||||
deviceContext1->CSSetUnorderedAccessViews(bindingSlot, 1, &nullUAV,
|
deviceContext1->CSSetUnorderedAccessViews(bindingSlot, 1, &nullUAV,
|
||||||
nullptr);
|
nullptr);
|
||||||
}
|
}
|
||||||
|
@ -318,13 +432,13 @@ void BindGroupTracker::UnApplyBindGroup(BindGroupIndex index) {
|
||||||
}
|
}
|
||||||
case wgpu::BufferBindingType::ReadOnlyStorage: {
|
case wgpu::BufferBindingType::ReadOnlyStorage: {
|
||||||
ID3D11ShaderResourceView* nullSRV = nullptr;
|
ID3D11ShaderResourceView* nullSRV = nullptr;
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) {
|
if (bindingVisibility & wgpu::ShaderStage::Vertex) {
|
||||||
deviceContext1->VSSetShaderResources(bindingSlot, 1, &nullSRV);
|
deviceContext1->VSSetShaderResources(bindingSlot, 1, &nullSRV);
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) {
|
if (bindingVisibility & wgpu::ShaderStage::Fragment) {
|
||||||
deviceContext1->PSSetShaderResources(bindingSlot, 1, &nullSRV);
|
deviceContext1->PSSetShaderResources(bindingSlot, 1, &nullSRV);
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Compute) {
|
if (bindingVisibility & wgpu::ShaderStage::Compute) {
|
||||||
deviceContext1->CSSetShaderResources(bindingSlot, 1, &nullSRV);
|
deviceContext1->CSSetShaderResources(bindingSlot, 1, &nullSRV);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -337,13 +451,13 @@ void BindGroupTracker::UnApplyBindGroup(BindGroupIndex index) {
|
||||||
|
|
||||||
case BindingInfoType::Sampler: {
|
case BindingInfoType::Sampler: {
|
||||||
ID3D11SamplerState* nullSampler = nullptr;
|
ID3D11SamplerState* nullSampler = nullptr;
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) {
|
if (bindingVisibility & wgpu::ShaderStage::Vertex) {
|
||||||
deviceContext1->VSSetSamplers(bindingSlot, 1, &nullSampler);
|
deviceContext1->VSSetSamplers(bindingSlot, 1, &nullSampler);
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) {
|
if (bindingVisibility & wgpu::ShaderStage::Fragment) {
|
||||||
deviceContext1->PSSetSamplers(bindingSlot, 1, &nullSampler);
|
deviceContext1->PSSetSamplers(bindingSlot, 1, &nullSampler);
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Compute) {
|
if (bindingVisibility & wgpu::ShaderStage::Compute) {
|
||||||
deviceContext1->CSSetSamplers(bindingSlot, 1, &nullSampler);
|
deviceContext1->CSSetSamplers(bindingSlot, 1, &nullSampler);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -351,13 +465,13 @@ void BindGroupTracker::UnApplyBindGroup(BindGroupIndex index) {
|
||||||
|
|
||||||
case BindingInfoType::Texture: {
|
case BindingInfoType::Texture: {
|
||||||
ID3D11ShaderResourceView* nullSRV = nullptr;
|
ID3D11ShaderResourceView* nullSRV = nullptr;
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) {
|
if (bindingVisibility & wgpu::ShaderStage::Vertex) {
|
||||||
deviceContext1->VSSetShaderResources(bindingSlot, 1, &nullSRV);
|
deviceContext1->VSSetShaderResources(bindingSlot, 1, &nullSRV);
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) {
|
if (bindingVisibility & wgpu::ShaderStage::Fragment) {
|
||||||
deviceContext1->PSSetShaderResources(bindingSlot, 1, &nullSRV);
|
deviceContext1->PSSetShaderResources(bindingSlot, 1, &nullSRV);
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Compute) {
|
if (bindingVisibility & wgpu::ShaderStage::Compute) {
|
||||||
deviceContext1->CSSetShaderResources(bindingSlot, 1, &nullSRV);
|
deviceContext1->CSSetShaderResources(bindingSlot, 1, &nullSRV);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -366,12 +480,12 @@ void BindGroupTracker::UnApplyBindGroup(BindGroupIndex index) {
|
||||||
case BindingInfoType::StorageTexture: {
|
case BindingInfoType::StorageTexture: {
|
||||||
ASSERT(bindingInfo.storageTexture.access == wgpu::StorageTextureAccess::WriteOnly);
|
ASSERT(bindingInfo.storageTexture.access == wgpu::StorageTextureAccess::WriteOnly);
|
||||||
ID3D11UnorderedAccessView* nullUAV = nullptr;
|
ID3D11UnorderedAccessView* nullUAV = nullptr;
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) {
|
if (bindingVisibility & wgpu::ShaderStage::Fragment) {
|
||||||
deviceContext1->OMSetRenderTargetsAndUnorderedAccessViews(
|
deviceContext1->OMSetRenderTargetsAndUnorderedAccessViews(
|
||||||
D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, bindingSlot,
|
D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, bindingSlot,
|
||||||
1, &nullUAV, nullptr);
|
1, &nullUAV, nullptr);
|
||||||
}
|
}
|
||||||
if (bindingInfo.visibility & wgpu::ShaderStage::Compute) {
|
if (bindingVisibility & wgpu::ShaderStage::Compute) {
|
||||||
deviceContext1->CSSetUnorderedAccessViews(bindingSlot, 1, &nullUAV, nullptr);
|
deviceContext1->CSSetUnorderedAccessViews(bindingSlot, 1, &nullUAV, nullptr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -24,9 +24,9 @@ class CommandRecordingContext;
|
||||||
|
|
||||||
// We need convert WebGPU bind slot to d3d11 bind slot according a map in PipelineLayout, so we
|
// We need convert WebGPU bind slot to d3d11 bind slot according a map in PipelineLayout, so we
|
||||||
// cannot inherit BindGroupTrackerGroups.
|
// cannot inherit BindGroupTrackerGroups.
|
||||||
class BindGroupTracker : public BindGroupTrackerBase</*CanInheritBindGroups=*/false, uint64_t> {
|
class BindGroupTracker : public BindGroupTrackerBase</*CanInheritBindGroups=*/true, uint64_t> {
|
||||||
public:
|
public:
|
||||||
explicit BindGroupTracker(CommandRecordingContext* commandContext);
|
BindGroupTracker(CommandRecordingContext* commandContext, bool isRenderPass);
|
||||||
~BindGroupTracker();
|
~BindGroupTracker();
|
||||||
MaybeError Apply();
|
MaybeError Apply();
|
||||||
|
|
||||||
|
@ -35,6 +35,8 @@ class BindGroupTracker : public BindGroupTrackerBase</*CanInheritBindGroups=*/fa
|
||||||
void UnApplyBindGroup(BindGroupIndex index);
|
void UnApplyBindGroup(BindGroupIndex index);
|
||||||
|
|
||||||
CommandRecordingContext* const mCommandContext;
|
CommandRecordingContext* const mCommandContext;
|
||||||
|
const bool mIsRenderPass;
|
||||||
|
const wgpu::ShaderStage mVisibleStages;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dawn::native::d3d11
|
} // namespace dawn::native::d3d11
|
||||||
|
|
|
@ -322,7 +322,7 @@ MaybeError CommandBuffer::Execute() {
|
||||||
|
|
||||||
MaybeError CommandBuffer::ExecuteComputePass(CommandRecordingContext* commandContext) {
|
MaybeError CommandBuffer::ExecuteComputePass(CommandRecordingContext* commandContext) {
|
||||||
ComputePipeline* lastPipeline = nullptr;
|
ComputePipeline* lastPipeline = nullptr;
|
||||||
BindGroupTracker bindGroupTracker(commandContext);
|
BindGroupTracker bindGroupTracker(commandContext, /*isRenderPass=*/false);
|
||||||
|
|
||||||
Command type;
|
Command type;
|
||||||
while (mCommands.NextCommandId(&type)) {
|
while (mCommands.NextCommandId(&type)) {
|
||||||
|
@ -481,7 +481,7 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass,
|
||||||
d3d11DeviceContext1->RSSetScissorRects(1, &scissor);
|
d3d11DeviceContext1->RSSetScissorRects(1, &scissor);
|
||||||
|
|
||||||
RenderPipeline* lastPipeline = nullptr;
|
RenderPipeline* lastPipeline = nullptr;
|
||||||
BindGroupTracker bindGroupTracker(commandContext);
|
BindGroupTracker bindGroupTracker(commandContext, /*isRenderPass=*/true);
|
||||||
VertexBufferTracker vertexBufferTracker(commandContext);
|
VertexBufferTracker vertexBufferTracker(commandContext);
|
||||||
std::array<float, 4> blendColor = {0.0f, 0.0f, 0.0f, 0.0f};
|
std::array<float, 4> blendColor = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||||
uint32_t stencilReference = 0;
|
uint32_t stencilReference = 0;
|
||||||
|
|
|
@ -30,6 +30,7 @@ namespace dawn::native::d3d11 {
|
||||||
MaybeError CommandRecordingContext::Open(Device* device) {
|
MaybeError CommandRecordingContext::Open(Device* device) {
|
||||||
ASSERT(!IsOpen());
|
ASSERT(!IsOpen());
|
||||||
ASSERT(device);
|
ASSERT(device);
|
||||||
|
mDevice = device;
|
||||||
|
|
||||||
if (!mD3D11DeviceContext4) {
|
if (!mD3D11DeviceContext4) {
|
||||||
ID3D11Device* d3d11Device = device->GetD3D11Device();
|
ID3D11Device* d3d11Device = device->GetD3D11Device();
|
||||||
|
@ -106,11 +107,17 @@ Buffer* CommandRecordingContext::GetUniformBuffer() const {
|
||||||
return mUniformBuffer.Get();
|
return mUniformBuffer.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Device* CommandRecordingContext::GetDevice() const {
|
||||||
|
ASSERT(mDevice.Get());
|
||||||
|
return mDevice.Get();
|
||||||
|
}
|
||||||
|
|
||||||
void CommandRecordingContext::Release() {
|
void CommandRecordingContext::Release() {
|
||||||
if (mIsOpen) {
|
if (mIsOpen) {
|
||||||
mIsOpen = false;
|
mIsOpen = false;
|
||||||
mNeedsSubmit = false;
|
mNeedsSubmit = false;
|
||||||
mUniformBuffer = nullptr;
|
mUniformBuffer = nullptr;
|
||||||
|
mDevice = nullptr;
|
||||||
ID3D11Buffer* nullBuffer = nullptr;
|
ID3D11Buffer* nullBuffer = nullptr;
|
||||||
mD3D11DeviceContext4->VSSetConstantBuffers(PipelineLayout::kReservedConstantBufferSlot, 1,
|
mD3D11DeviceContext4->VSSetConstantBuffers(PipelineLayout::kReservedConstantBufferSlot, 1,
|
||||||
&nullBuffer);
|
&nullBuffer);
|
||||||
|
|
|
@ -41,6 +41,7 @@ class CommandRecordingContext {
|
||||||
ID3D11DeviceContext4* GetD3D11DeviceContext4() const;
|
ID3D11DeviceContext4* GetD3D11DeviceContext4() const;
|
||||||
ID3DUserDefinedAnnotation* GetD3DUserDefinedAnnotation() const;
|
ID3DUserDefinedAnnotation* GetD3DUserDefinedAnnotation() const;
|
||||||
Buffer* GetUniformBuffer() const;
|
Buffer* GetUniformBuffer() const;
|
||||||
|
Device* GetDevice() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mIsOpen = false;
|
bool mIsOpen = false;
|
||||||
|
@ -50,6 +51,7 @@ class CommandRecordingContext {
|
||||||
ComPtr<ID3DUserDefinedAnnotation> mD3D11UserDefinedAnnotation;
|
ComPtr<ID3DUserDefinedAnnotation> mD3D11UserDefinedAnnotation;
|
||||||
// The uniform buffer for built in variables.
|
// The uniform buffer for built in variables.
|
||||||
Ref<Buffer> mUniformBuffer;
|
Ref<Buffer> mUniformBuffer;
|
||||||
|
Ref<Device> mDevice;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dawn::native::d3d11
|
} // namespace dawn::native::d3d11
|
||||||
|
|
|
@ -468,4 +468,8 @@ Ref<TextureBase> Device::CreateD3DExternalTexture(const TextureDescriptor* descr
|
||||||
return {dawnTexture};
|
return {dawnTexture};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t Device::GetUAVSlotCount() const {
|
||||||
|
return ToBackend(GetPhysicalDevice())->GetUAVSlotCount();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dawn::native::d3d11
|
} // namespace dawn::native::d3d11
|
||||||
|
|
|
@ -83,6 +83,8 @@ class Device final : public d3d::Device {
|
||||||
ResultOrError<std::unique_ptr<d3d::ExternalImageDXGIImpl>> CreateExternalImageDXGIImplImpl(
|
ResultOrError<std::unique_ptr<d3d::ExternalImageDXGIImpl>> CreateExternalImageDXGIImplImpl(
|
||||||
const d3d::ExternalImageDescriptorDXGISharedHandle* descriptor) override;
|
const d3d::ExternalImageDescriptorDXGISharedHandle* descriptor) override;
|
||||||
|
|
||||||
|
uint32_t GetUAVSlotCount() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Base = d3d::Device;
|
using Base = d3d::Device;
|
||||||
using Base::Base;
|
using Base::Base;
|
||||||
|
|
|
@ -147,6 +147,7 @@ MaybeError PhysicalDevice::InitializeSupportedLimitsImpl(CombinedLimits* limits)
|
||||||
uint32_t maxUAVsAllStages = mFeatureLevel == D3D_FEATURE_LEVEL_11_1
|
uint32_t maxUAVsAllStages = mFeatureLevel == D3D_FEATURE_LEVEL_11_1
|
||||||
? D3D11_1_UAV_SLOT_COUNT
|
? D3D11_1_UAV_SLOT_COUNT
|
||||||
: D3D11_PS_CS_UAV_REGISTER_COUNT;
|
: D3D11_PS_CS_UAV_REGISTER_COUNT;
|
||||||
|
mUAVSlotCount = maxUAVsAllStages;
|
||||||
ASSERT(maxUAVsAllStages / 4 > limits->v1.maxStorageTexturesPerShaderStage);
|
ASSERT(maxUAVsAllStages / 4 > limits->v1.maxStorageTexturesPerShaderStage);
|
||||||
ASSERT(maxUAVsAllStages / 4 > limits->v1.maxStorageBuffersPerShaderStage);
|
ASSERT(maxUAVsAllStages / 4 > limits->v1.maxStorageBuffersPerShaderStage);
|
||||||
uint32_t maxUAVsPerStage = maxUAVsAllStages / 2;
|
uint32_t maxUAVsPerStage = maxUAVsAllStages / 2;
|
||||||
|
|
|
@ -37,6 +37,8 @@ class PhysicalDevice : public d3d::PhysicalDevice {
|
||||||
const DeviceInfo& GetDeviceInfo() const;
|
const DeviceInfo& GetDeviceInfo() const;
|
||||||
ResultOrError<ComPtr<ID3D11Device>> CreateD3D11Device();
|
ResultOrError<ComPtr<ID3D11Device>> CreateD3D11Device();
|
||||||
|
|
||||||
|
uint32_t GetUAVSlotCount() const { return mUAVSlotCount; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Base = d3d::PhysicalDevice;
|
using Base = d3d::PhysicalDevice;
|
||||||
|
|
||||||
|
@ -57,6 +59,7 @@ class PhysicalDevice : public d3d::PhysicalDevice {
|
||||||
ComPtr<ID3D11Device> mD3d11Device;
|
ComPtr<ID3D11Device> mD3d11Device;
|
||||||
D3D_FEATURE_LEVEL mFeatureLevel;
|
D3D_FEATURE_LEVEL mFeatureLevel;
|
||||||
DeviceInfo mDeviceInfo = {};
|
DeviceInfo mDeviceInfo = {};
|
||||||
|
uint32_t mUAVSlotCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dawn::native::d3d11
|
} // namespace dawn::native::d3d11
|
||||||
|
|
|
@ -37,10 +37,7 @@ MaybeError PipelineLayout::Initialize(Device* device) {
|
||||||
// resource slots when being written out. So we assign UAV binding index decreasingly here.
|
// resource slots when being written out. So we assign UAV binding index decreasingly here.
|
||||||
// https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-omsetrendertargetsandunorderedaccessviews
|
// https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-omsetrendertargetsandunorderedaccessviews
|
||||||
// TODO(dawn:1818): Support testing on both FL11_0 and FL11_1.
|
// TODO(dawn:1818): Support testing on both FL11_0 and FL11_1.
|
||||||
uint32_t unorderedAccessViewIndex =
|
uint32_t unorderedAccessViewIndex = device->GetUAVSlotCount();
|
||||||
device->GetD3D11Device()->GetFeatureLevel() == D3D_FEATURE_LEVEL_11_1
|
|
||||||
? D3D11_1_UAV_SLOT_COUNT
|
|
||||||
: D3D11_PS_CS_UAV_REGISTER_COUNT;
|
|
||||||
mTotalUAVBindingCount = unorderedAccessViewIndex;
|
mTotalUAVBindingCount = unorderedAccessViewIndex;
|
||||||
|
|
||||||
for (BindGroupIndex group : IterateBitSet(GetBindGroupLayoutsMask())) {
|
for (BindGroupIndex group : IterateBitSet(GetBindGroupLayoutsMask())) {
|
||||||
|
@ -58,6 +55,7 @@ MaybeError PipelineLayout::Initialize(Device* device) {
|
||||||
case wgpu::BufferBindingType::Storage:
|
case wgpu::BufferBindingType::Storage:
|
||||||
case kInternalStorageBufferBinding:
|
case kInternalStorageBufferBinding:
|
||||||
mIndexInfo[group][bindingIndex] = --unorderedAccessViewIndex;
|
mIndexInfo[group][bindingIndex] = --unorderedAccessViewIndex;
|
||||||
|
mUAVBindGroups.set(group);
|
||||||
break;
|
break;
|
||||||
case wgpu::BufferBindingType::ReadOnlyStorage:
|
case wgpu::BufferBindingType::ReadOnlyStorage:
|
||||||
mIndexInfo[group][bindingIndex] = shaderResourceViewIndex++;
|
mIndexInfo[group][bindingIndex] = shaderResourceViewIndex++;
|
||||||
|
@ -78,6 +76,7 @@ MaybeError PipelineLayout::Initialize(Device* device) {
|
||||||
|
|
||||||
case BindingInfoType::StorageTexture:
|
case BindingInfoType::StorageTexture:
|
||||||
mIndexInfo[group][bindingIndex] = --unorderedAccessViewIndex;
|
mIndexInfo[group][bindingIndex] = --unorderedAccessViewIndex;
|
||||||
|
mUAVBindGroups.set(group);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,4 +90,8 @@ const PipelineLayout::BindingIndexInfo& PipelineLayout::GetBindingIndexInfo() co
|
||||||
return mIndexInfo;
|
return mIndexInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const BindGroupLayoutMask& PipelineLayout::GetUAVBindGroupLayoutsMask() const {
|
||||||
|
return mUAVBindGroups;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dawn::native::d3d11
|
} // namespace dawn::native::d3d11
|
||||||
|
|
|
@ -51,6 +51,9 @@ class PipelineLayout final : public PipelineLayoutBase {
|
||||||
uint32_t GetUnusedUAVBindingCount() const { return mUnusedUAVBindingCount; }
|
uint32_t GetUnusedUAVBindingCount() const { return mUnusedUAVBindingCount; }
|
||||||
uint32_t GetTotalUAVBindingCount() const { return mTotalUAVBindingCount; }
|
uint32_t GetTotalUAVBindingCount() const { return mTotalUAVBindingCount; }
|
||||||
|
|
||||||
|
// Get the bind groups that use one or more UAV slots.
|
||||||
|
const BindGroupLayoutMask& GetUAVBindGroupLayoutsMask() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using PipelineLayoutBase::PipelineLayoutBase;
|
using PipelineLayoutBase::PipelineLayoutBase;
|
||||||
|
|
||||||
|
@ -62,6 +65,7 @@ class PipelineLayout final : public PipelineLayoutBase {
|
||||||
|
|
||||||
uint32_t mUnusedUAVBindingCount = 0u;
|
uint32_t mUnusedUAVBindingCount = 0u;
|
||||||
uint32_t mTotalUAVBindingCount = 0u;
|
uint32_t mTotalUAVBindingCount = 0u;
|
||||||
|
BindGroupLayoutMask mUAVBindGroups = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dawn::native::d3d11
|
} // namespace dawn::native::d3d11
|
||||||
|
|
|
@ -705,6 +705,91 @@ TEST_P(BindGroupTests, SetDynamicBindGroupBeforePipeline) {
|
||||||
EXPECT_PIXEL_RGBA8_EQ(notFilled, renderPass.color, max, max);
|
EXPECT_PIXEL_RGBA8_EQ(notFilled, renderPass.color, max, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that the same renderpass can use 3 more pipelines
|
||||||
|
TEST_P(BindGroupTests, ThreePipelinesInSameRenderpass) {
|
||||||
|
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
|
||||||
|
|
||||||
|
// Create a bind group layout which uses a single dynamic uniform buffer.
|
||||||
|
wgpu::BindGroupLayout uniformLayout = utils::MakeBindGroupLayout(
|
||||||
|
device, {{0, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Uniform, true}});
|
||||||
|
|
||||||
|
// Pipeline0 uses 2 bind groups, 'bindGroup00' and 'bindGroup01', respectively accommodated with
|
||||||
|
// 'color00' and 'color01'.
|
||||||
|
wgpu::RenderPipeline pipeline0 = MakeTestPipeline(
|
||||||
|
renderPass, {wgpu::BufferBindingType::Uniform, wgpu::BufferBindingType::Uniform},
|
||||||
|
{uniformLayout, uniformLayout});
|
||||||
|
|
||||||
|
// Pipeline1 uses 'bindGroup1', accommodated with 'color1'.
|
||||||
|
wgpu::RenderPipeline pipeline1 =
|
||||||
|
MakeTestPipeline(renderPass, {wgpu::BufferBindingType::Uniform}, {uniformLayout});
|
||||||
|
|
||||||
|
// Pipeline2 uses 'bindGroup2', accommodated with 'color2'.
|
||||||
|
wgpu::RenderPipeline pipeline2 =
|
||||||
|
MakeTestPipeline(renderPass, {wgpu::BufferBindingType::Uniform}, {uniformLayout});
|
||||||
|
|
||||||
|
// Sum up to (1, 1, 1, 1)
|
||||||
|
std::array<float, 4> color00 = {1, 0, 0, 0.5};
|
||||||
|
std::array<float, 4> color01 = {0, 1, 0, 0.5};
|
||||||
|
std::array<float, 4> color1 = {0, 0, 0.2, 0};
|
||||||
|
std::array<float, 4> color2 = {0, 0, 0.8, 0};
|
||||||
|
|
||||||
|
std::vector<uint8_t> data(sizeof(color00));
|
||||||
|
memcpy(data.data(), color00.data(), sizeof(color00));
|
||||||
|
wgpu::Buffer uniformBuffer00 =
|
||||||
|
utils::CreateBufferFromData(device, data.data(), data.size(), wgpu::BufferUsage::Uniform);
|
||||||
|
wgpu::BindGroup bindGroup00 =
|
||||||
|
utils::MakeBindGroup(device, uniformLayout, {{0, uniformBuffer00, 0, 4 * sizeof(float)}});
|
||||||
|
|
||||||
|
memcpy(data.data(), color01.data(), sizeof(color01));
|
||||||
|
wgpu::Buffer uniformBuffer01 =
|
||||||
|
utils::CreateBufferFromData(device, data.data(), data.size(), wgpu::BufferUsage::Uniform);
|
||||||
|
wgpu::BindGroup bindGroup01 =
|
||||||
|
utils::MakeBindGroup(device, uniformLayout, {{0, uniformBuffer01, 0, 4 * sizeof(float)}});
|
||||||
|
|
||||||
|
memcpy(data.data(), color1.data(), sizeof(color1));
|
||||||
|
wgpu::Buffer uniformBuffer1 =
|
||||||
|
utils::CreateBufferFromData(device, data.data(), data.size(), wgpu::BufferUsage::Uniform);
|
||||||
|
wgpu::BindGroup bindGroup1 =
|
||||||
|
utils::MakeBindGroup(device, uniformLayout, {{0, uniformBuffer1, 0, 4 * sizeof(float)}});
|
||||||
|
|
||||||
|
memcpy(data.data(), color2.data(), sizeof(color2));
|
||||||
|
wgpu::Buffer uniformBuffer2 =
|
||||||
|
utils::CreateBufferFromData(device, data.data(), data.size(), wgpu::BufferUsage::Uniform);
|
||||||
|
wgpu::BindGroup bindGroup2 =
|
||||||
|
utils::MakeBindGroup(device, uniformLayout, {{0, uniformBuffer2, 0, 4 * sizeof(float)}});
|
||||||
|
|
||||||
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
|
||||||
|
|
||||||
|
uint32_t dynamicOffset = 0;
|
||||||
|
|
||||||
|
pass.SetPipeline(pipeline0);
|
||||||
|
pass.SetBindGroup(0, bindGroup00, 1, &dynamicOffset);
|
||||||
|
pass.SetBindGroup(1, bindGroup01, 1, &dynamicOffset);
|
||||||
|
pass.Draw(3);
|
||||||
|
|
||||||
|
pass.SetBindGroup(0, bindGroup1, 1, &dynamicOffset);
|
||||||
|
pass.SetPipeline(pipeline1);
|
||||||
|
pass.Draw(3);
|
||||||
|
|
||||||
|
pass.SetBindGroup(0, bindGroup2, 1, &dynamicOffset);
|
||||||
|
pass.SetPipeline(pipeline2);
|
||||||
|
pass.Draw(3);
|
||||||
|
|
||||||
|
pass.End();
|
||||||
|
|
||||||
|
wgpu::CommandBuffer commands = encoder.Finish();
|
||||||
|
queue.Submit(1, &commands);
|
||||||
|
|
||||||
|
utils::RGBA8 filled(255, 255, 255, 255);
|
||||||
|
utils::RGBA8 notFilled(0, 0, 0, 0);
|
||||||
|
uint32_t min = 1, max = kRTSize - 3;
|
||||||
|
EXPECT_PIXEL_RGBA8_EQ(filled, renderPass.color, min, min);
|
||||||
|
EXPECT_PIXEL_RGBA8_EQ(filled, renderPass.color, max, min);
|
||||||
|
EXPECT_PIXEL_RGBA8_EQ(filled, renderPass.color, min, max);
|
||||||
|
EXPECT_PIXEL_RGBA8_EQ(notFilled, renderPass.color, max, max);
|
||||||
|
}
|
||||||
|
|
||||||
// Test that bind groups set for one pipeline are still set when the pipeline changes.
|
// Test that bind groups set for one pipeline are still set when the pipeline changes.
|
||||||
TEST_P(BindGroupTests, BindGroupsPersistAfterPipelineChange) {
|
TEST_P(BindGroupTests, BindGroupsPersistAfterPipelineChange) {
|
||||||
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
|
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
|
||||||
|
|
|
@ -297,6 +297,101 @@ TEST_P(DynamicBufferOffsetTests, SetDynamicOffsetsComputePipeline) {
|
||||||
mMinUniformBufferOffsetAlignment, expectedData.size());
|
mMinUniformBufferOffsetAlignment, expectedData.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test basic inherit on render pipeline
|
||||||
|
TEST_P(DynamicBufferOffsetTests, BasicInheritRenderPipeline) {
|
||||||
|
wgpu::ShaderModule vsModule = utils::CreateShaderModule(device, R"(
|
||||||
|
@vertex
|
||||||
|
fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4f {
|
||||||
|
var pos = array(
|
||||||
|
vec2f(-1.0, 0.0),
|
||||||
|
vec2f(-1.0, 1.0),
|
||||||
|
vec2f( 0.0, 1.0));
|
||||||
|
return vec4f(pos[VertexIndex], 0.0, 1.0);
|
||||||
|
})");
|
||||||
|
|
||||||
|
// Construct fragment shader source
|
||||||
|
std::ostringstream fs;
|
||||||
|
fs << R"(
|
||||||
|
struct Buf {
|
||||||
|
value : vec2u
|
||||||
|
}
|
||||||
|
|
||||||
|
@group(0) @binding(0) var<uniform> uBufferNotDynamic : Buf;
|
||||||
|
@group(0) @binding(1) var<storage, read_write> sBufferNotDynamic : Buf;
|
||||||
|
@group(1) @binding(3) var<uniform> uBuffer : Buf;
|
||||||
|
@group(1) @binding(4) var<storage, read_write> sBuffer : Buf;
|
||||||
|
|
||||||
|
@fragment fn main() -> @location(0) vec4f {
|
||||||
|
sBufferNotDynamic.value = uBufferNotDynamic.value.xy;
|
||||||
|
sBuffer.value = uBuffer.value.xy + uBufferNotDynamic.value.xy;
|
||||||
|
return vec4f(f32(uBuffer.value.x) / 255.0, f32(uBuffer.value.y) / 255.0,
|
||||||
|
1.0, 1.0);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
wgpu::ShaderModule fsModule = utils::CreateShaderModule(device, fs.str().c_str());
|
||||||
|
|
||||||
|
utils::ComboRenderPipelineDescriptor pipelineDescriptor;
|
||||||
|
pipelineDescriptor.vertex.module = vsModule;
|
||||||
|
pipelineDescriptor.cFragment.module = fsModule;
|
||||||
|
pipelineDescriptor.cTargets[0].format = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
|
||||||
|
wgpu::BindGroupLayout bindGroupLayouts[2];
|
||||||
|
bindGroupLayouts[0] = utils::MakeBindGroupLayout(
|
||||||
|
device, {{0, wgpu::ShaderStage::Compute | wgpu::ShaderStage::Fragment,
|
||||||
|
wgpu::BufferBindingType::Uniform},
|
||||||
|
{1, wgpu::ShaderStage::Compute | wgpu::ShaderStage::Fragment,
|
||||||
|
wgpu::BufferBindingType::Storage}});
|
||||||
|
bindGroupLayouts[1] = utils::MakeBindGroupLayout(
|
||||||
|
device, {{3, wgpu::ShaderStage::Compute | wgpu::ShaderStage::Fragment,
|
||||||
|
wgpu::BufferBindingType::Uniform, true},
|
||||||
|
{4, wgpu::ShaderStage::Compute | wgpu::ShaderStage::Fragment,
|
||||||
|
wgpu::BufferBindingType::Storage, true}});
|
||||||
|
|
||||||
|
wgpu::BindGroup bindGroups[2];
|
||||||
|
bindGroups[0] = utils::MakeBindGroup(device, bindGroupLayouts[0],
|
||||||
|
{
|
||||||
|
{0, mUniformBuffers[0], 0, kBindingSize},
|
||||||
|
{1, mStorageBuffers[0], 0, kBindingSize},
|
||||||
|
});
|
||||||
|
bindGroups[1] = utils::MakeBindGroup(
|
||||||
|
device, bindGroupLayouts[1],
|
||||||
|
{{3, mUniformBuffers[1], 0, kBindingSize}, {4, mStorageBuffers[1], 0, kBindingSize}});
|
||||||
|
|
||||||
|
wgpu::PipelineLayoutDescriptor pipelineLayoutDescriptor;
|
||||||
|
pipelineLayoutDescriptor.bindGroupLayoutCount = 2;
|
||||||
|
pipelineLayoutDescriptor.bindGroupLayouts = bindGroupLayouts;
|
||||||
|
pipelineDescriptor.layout = device.CreatePipelineLayout(&pipelineLayoutDescriptor);
|
||||||
|
|
||||||
|
wgpu::RenderPipeline pipeline0 = device.CreateRenderPipeline(&pipelineDescriptor);
|
||||||
|
wgpu::RenderPipeline pipeline1 = device.CreateRenderPipeline(&pipelineDescriptor);
|
||||||
|
|
||||||
|
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
|
||||||
|
|
||||||
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
|
std::array<uint32_t, 2> offsets0 = {0, 0};
|
||||||
|
std::array<uint32_t, 2> offsets1 = {mMinUniformBufferOffsetAlignment,
|
||||||
|
mMinUniformBufferOffsetAlignment};
|
||||||
|
wgpu::RenderPassEncoder renderPassEncoder =
|
||||||
|
commandEncoder.BeginRenderPass(&renderPass.renderPassInfo);
|
||||||
|
renderPassEncoder.SetPipeline(pipeline0);
|
||||||
|
renderPassEncoder.SetBindGroup(0, bindGroups[0]);
|
||||||
|
renderPassEncoder.SetBindGroup(1, bindGroups[1], offsets0.size(), offsets0.data());
|
||||||
|
renderPassEncoder.Draw(3);
|
||||||
|
renderPassEncoder.SetPipeline(pipeline1);
|
||||||
|
// bind group 0 should be inherited and still available.
|
||||||
|
renderPassEncoder.SetBindGroup(1, bindGroups[1], offsets1.size(), offsets1.data());
|
||||||
|
renderPassEncoder.Draw(3);
|
||||||
|
renderPassEncoder.End();
|
||||||
|
wgpu::CommandBuffer commands = commandEncoder.Finish();
|
||||||
|
queue.Submit(1, &commands);
|
||||||
|
|
||||||
|
std::vector<uint32_t> expectedData = {6, 8};
|
||||||
|
EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8(5, 6, 255, 255), renderPass.color, 0, 0);
|
||||||
|
EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), mStorageBuffers[1],
|
||||||
|
mMinUniformBufferOffsetAlignment, expectedData.size());
|
||||||
|
}
|
||||||
|
|
||||||
// Test inherit dynamic offsets on render pipeline
|
// Test inherit dynamic offsets on render pipeline
|
||||||
TEST_P(DynamicBufferOffsetTests, InheritDynamicOffsetsRenderPipeline) {
|
TEST_P(DynamicBufferOffsetTests, InheritDynamicOffsetsRenderPipeline) {
|
||||||
// Using default pipeline and setting dynamic offsets
|
// Using default pipeline and setting dynamic offsets
|
||||||
|
@ -576,6 +671,7 @@ TEST_P(ClampedOOBDynamicBufferOffsetTests, CheckOOBAccess) {
|
||||||
}
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(DynamicBufferOffsetTests,
|
DAWN_INSTANTIATE_TEST(DynamicBufferOffsetTests,
|
||||||
|
D3D11Backend(),
|
||||||
D3D12Backend(),
|
D3D12Backend(),
|
||||||
MetalBackend(),
|
MetalBackend(),
|
||||||
OpenGLBackend(),
|
OpenGLBackend(),
|
||||||
|
|
Loading…
Reference in New Issue