1 // Copyright 2018 The Dawn Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "dawn_native/RenderPassEncoder.h" 16 17 #include "common/Constants.h" 18 #include "dawn_native/Buffer.h" 19 #include "dawn_native/CommandEncoder.h" 20 #include "dawn_native/Commands.h" 21 #include "dawn_native/Device.h" 22 #include "dawn_native/RenderBundle.h" 23 #include "dawn_native/RenderPipeline.h" 24 25 #include <math.h> 26 #include <cstring> 27 28 namespace dawn_native { 29 30 // The usage tracker is passed in here, because it is prepopulated with usages from the 31 // BeginRenderPassCmd. If we had RenderPassEncoder responsible for recording the 32 // command, then this wouldn't be necessary. RenderPassEncoder(DeviceBase * device,CommandEncoder * commandEncoder,EncodingContext * encodingContext,PassResourceUsageTracker usageTracker)33 RenderPassEncoder::RenderPassEncoder(DeviceBase* device, 34 CommandEncoder* commandEncoder, 35 EncodingContext* encodingContext, 36 PassResourceUsageTracker usageTracker) 37 : RenderEncoderBase(device, encodingContext), mCommandEncoder(commandEncoder) { 38 mUsageTracker = std::move(usageTracker); 39 } 40 RenderPassEncoder(DeviceBase * device,CommandEncoder * commandEncoder,EncodingContext * encodingContext,ErrorTag errorTag)41 RenderPassEncoder::RenderPassEncoder(DeviceBase* device, 42 CommandEncoder* commandEncoder, 43 EncodingContext* encodingContext, 44 ErrorTag errorTag) 45 : RenderEncoderBase(device, encodingContext, errorTag), mCommandEncoder(commandEncoder) { 46 } 47 MakeError(DeviceBase * device,CommandEncoder * commandEncoder,EncodingContext * encodingContext)48 RenderPassEncoder* RenderPassEncoder::MakeError(DeviceBase* device, 49 CommandEncoder* commandEncoder, 50 EncodingContext* encodingContext) { 51 return new RenderPassEncoder(device, commandEncoder, encodingContext, ObjectBase::kError); 52 } 53 EndPass()54 void RenderPassEncoder::EndPass() { 55 if (mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { 56 allocator->Allocate<EndRenderPassCmd>(Command::EndRenderPass); 57 58 return {}; 59 })) { 60 mEncodingContext->ExitPass(this, mUsageTracker.AcquireResourceUsage()); 61 } 62 } 63 SetStencilReference(uint32_t reference)64 void RenderPassEncoder::SetStencilReference(uint32_t reference) { 65 mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { 66 SetStencilReferenceCmd* cmd = 67 allocator->Allocate<SetStencilReferenceCmd>(Command::SetStencilReference); 68 cmd->reference = reference; 69 70 return {}; 71 }); 72 } 73 SetBlendColor(const Color * color)74 void RenderPassEncoder::SetBlendColor(const Color* color) { 75 mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { 76 SetBlendColorCmd* cmd = allocator->Allocate<SetBlendColorCmd>(Command::SetBlendColor); 77 cmd->color = *color; 78 79 return {}; 80 }); 81 } 82 SetViewport(float x,float y,float width,float height,float minDepth,float maxDepth)83 void RenderPassEncoder::SetViewport(float x, 84 float y, 85 float width, 86 float height, 87 float minDepth, 88 float maxDepth) { 89 mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { 90 if ((isnan(x) || isnan(y) || isnan(width) || isnan(height) || isnan(minDepth) || 91 isnan(maxDepth))) { 92 return DAWN_VALIDATION_ERROR("NaN is not allowed."); 93 } 94 95 // TODO(yunchao.he@intel.com): there are more restrictions for x, y, width and height in 96 // Vulkan, and height can be a negative value in Vulkan 1.1. Revisit this part later 97 // (say, for WebGPU v1). 98 if (width <= 0 || height <= 0) { 99 return DAWN_VALIDATION_ERROR("Width and height must be greater than 0."); 100 } 101 102 if (minDepth < 0 || minDepth > 1 || maxDepth < 0 || maxDepth > 1) { 103 return DAWN_VALIDATION_ERROR("minDepth and maxDepth must be in [0, 1]."); 104 } 105 106 SetViewportCmd* cmd = allocator->Allocate<SetViewportCmd>(Command::SetViewport); 107 cmd->x = x; 108 cmd->y = y; 109 cmd->width = width; 110 cmd->height = height; 111 cmd->minDepth = minDepth; 112 cmd->maxDepth = maxDepth; 113 114 return {}; 115 }); 116 } 117 SetScissorRect(uint32_t x,uint32_t y,uint32_t width,uint32_t height)118 void RenderPassEncoder::SetScissorRect(uint32_t x, 119 uint32_t y, 120 uint32_t width, 121 uint32_t height) { 122 mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { 123 if (width == 0 || height == 0) { 124 return DAWN_VALIDATION_ERROR("Width and height must be greater than 0."); 125 } 126 127 SetScissorRectCmd* cmd = 128 allocator->Allocate<SetScissorRectCmd>(Command::SetScissorRect); 129 cmd->x = x; 130 cmd->y = y; 131 cmd->width = width; 132 cmd->height = height; 133 134 return {}; 135 }); 136 } 137 ExecuteBundles(uint32_t count,RenderBundleBase * const * renderBundles)138 void RenderPassEncoder::ExecuteBundles(uint32_t count, RenderBundleBase* const* renderBundles) { 139 mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { 140 for (uint32_t i = 0; i < count; ++i) { 141 DAWN_TRY(GetDevice()->ValidateObject(renderBundles[i])); 142 } 143 144 ExecuteBundlesCmd* cmd = 145 allocator->Allocate<ExecuteBundlesCmd>(Command::ExecuteBundles); 146 cmd->count = count; 147 148 Ref<RenderBundleBase>* bundles = allocator->AllocateData<Ref<RenderBundleBase>>(count); 149 for (uint32_t i = 0; i < count; ++i) { 150 bundles[i] = renderBundles[i]; 151 152 const PassResourceUsage& usages = bundles[i]->GetResourceUsage(); 153 for (uint32_t i = 0; i < usages.buffers.size(); ++i) { 154 mUsageTracker.BufferUsedAs(usages.buffers[i], usages.bufferUsages[i]); 155 } 156 for (uint32_t i = 0; i < usages.textures.size(); ++i) { 157 mUsageTracker.TextureUsedAs(usages.textures[i], usages.textureUsages[i]); 158 } 159 } 160 161 return {}; 162 }); 163 } 164 165 } // namespace dawn_native 166