diff --git a/src/core/short_vector.h b/src/core/short_vector.h index 7aeced84..b7193a8d 100644 --- a/src/core/short_vector.h +++ b/src/core/short_vector.h @@ -100,8 +100,8 @@ class short_vector /// Size constructor. short_vector(size_type size, const value_type& value) - : m_data(m_short_data) - , m_size(size) + : m_data((value_type*)m_short_data) + , m_size(0) , m_capacity(N) { if (size > m_capacity) @@ -112,7 +112,7 @@ class short_vector /// Initializer list constructor. short_vector(std::initializer_list list) - : m_data(m_short_data) + : m_data((value_type*)m_short_data) , m_size(0) , m_capacity(N) { diff --git a/src/wgpu/wgpu-command-encoder.cpp b/src/wgpu/wgpu-command-encoder.cpp index aca549aa..ea0a9df6 100644 --- a/src/wgpu/wgpu-command-encoder.cpp +++ b/src/wgpu/wgpu-command-encoder.cpp @@ -6,6 +6,7 @@ #include "wgpu-texture.h" #include "wgpu-device.h" #include "wgpu-transient-resource-heap.h" +#include "wgpu-util.h" namespace rhi::wgpu { @@ -295,12 +296,76 @@ void* RenderCommandEncoderImpl::getInterface(SlangUUID const& uuid) Result RenderCommandEncoderImpl::init(CommandBufferImpl* commandBuffer, const RenderPassDesc& desc) { CommandEncoderImpl::init(commandBuffer); + + short_vector colorAttachments(desc.colorAttachmentCount, {}); + for (GfxIndex i = 0; i < desc.colorAttachmentCount; ++i) + { + const RenderPassColorAttachment& attachmentIn = desc.colorAttachments[i]; + WGPURenderPassColorAttachment& attachment = colorAttachments[i]; + attachment.view = static_cast(attachmentIn.view)->m_textureView; + attachment.depthSlice = -1; // TODO not provided + attachment.resolveTarget = nullptr; // TODO not provided + attachment.loadOp = translateLoadOp(attachmentIn.loadOp); + attachment.storeOp = translateStoreOp(attachmentIn.storeOp); + attachment.clearValue.r = attachmentIn.clearValue[0]; + attachment.clearValue.g = attachmentIn.clearValue[1]; + attachment.clearValue.b = attachmentIn.clearValue[2]; + attachment.clearValue.a = attachmentIn.clearValue[3]; + } + + WGPURenderPassDepthStencilAttachment depthStencilAttachment = {}; + if (desc.depthStencilAttachment) + { + const RenderPassDepthStencilAttachment& attachmentIn = *desc.depthStencilAttachment; + WGPURenderPassDepthStencilAttachment& attachment = depthStencilAttachment; + attachment.view = static_cast(attachmentIn.view)->m_textureView; + attachment.depthLoadOp = translateLoadOp(attachmentIn.depthLoadOp); + attachment.depthStoreOp = translateStoreOp(attachmentIn.depthStoreOp); + attachment.depthClearValue = attachmentIn.depthClearValue; + attachment.depthReadOnly = attachmentIn.depthReadOnly; + attachment.stencilLoadOp = translateLoadOp(attachmentIn.stencilLoadOp); + attachment.stencilStoreOp = translateStoreOp(attachmentIn.stencilStoreOp); + attachment.stencilClearValue = attachmentIn.stencilClearValue; + attachment.stencilReadOnly = attachmentIn.stencilReadOnly; + } + WGPURenderPassDescriptor passDesc = {}; + passDesc.colorAttachmentCount = desc.colorAttachmentCount; + passDesc.colorAttachments = colorAttachments.data(); + passDesc.depthStencilAttachment = desc.depthStencilAttachment ? &depthStencilAttachment : nullptr; + // passDesc.occlusionQuerySet not supported + // passDesc.timestampWrites not supported + m_renderPassEncoder = m_device->m_ctx.api.wgpuCommandEncoderBeginRenderPass(m_commandBuffer->m_commandEncoder, &passDesc); return m_renderPassEncoder ? SLANG_OK : SLANG_FAIL; } +Result RenderCommandEncoderImpl::prepareDraw() +{ + auto pipeline = static_cast(m_currentPipeline.Ptr()); + if (!pipeline) + { + return SLANG_FAIL; + } + + RootBindingContext context; + SLANG_RETURN_ON_FAIL(bindPipelineImpl(context)); + + m_device->m_ctx.api.wgpuRenderPassEncoderSetPipeline(m_renderPassEncoder, m_currentPipeline->m_renderPipeline); + for (uint32_t groupIndex = 0; groupIndex < context.bindGroups.size(); groupIndex++) + { + m_device->m_ctx.api.wgpuRenderPassEncoderSetBindGroup( + m_renderPassEncoder, + groupIndex, + context.bindGroups[groupIndex], + 0, + nullptr + ); + } + return SLANG_OK; +} + void RenderCommandEncoderImpl::endEncoding() { endEncodingImpl(); @@ -319,9 +384,35 @@ Result RenderCommandEncoderImpl::bindPipelineWithRootObject(IPipeline* pipeline, return setPipelineWithRootObjectImpl(pipeline, rootObject); } -void RenderCommandEncoderImpl::setViewports(GfxCount count, const Viewport* viewports) {} +void RenderCommandEncoderImpl::setViewports(GfxCount count, const Viewport* viewports) +{ + if (count < 1) + return; + + m_device->m_ctx.api.wgpuRenderPassEncoderSetViewport( + m_renderPassEncoder, + viewports[0].originX, + viewports[0].originY, + viewports[0].extentX, + viewports[0].extentY, + viewports[0].minZ, + viewports[0].maxZ + ); +} -void RenderCommandEncoderImpl::setScissorRects(GfxCount count, const ScissorRect* rects) {} +void RenderCommandEncoderImpl::setScissorRects(GfxCount count, const ScissorRect* rects) +{ + if (count < 1) + return; + + m_device->m_ctx.api.wgpuRenderPassEncoderSetScissorRect( + m_renderPassEncoder, + rects[0].minX, + rects[0].minY, + rects[0].maxX - rects[0].minX, + rects[0].maxY - rects[0].minY + ); +} void RenderCommandEncoderImpl::setPrimitiveTopology(PrimitiveTopology topology) {} @@ -373,12 +464,14 @@ Result RenderCommandEncoderImpl::setSamplePositions( Result RenderCommandEncoderImpl::draw(GfxCount vertexCount, GfxIndex startVertex) { + SLANG_RETURN_ON_FAIL(prepareDraw()); m_device->m_ctx.api.wgpuRenderPassEncoderDraw(m_renderPassEncoder, vertexCount, 1, startVertex, 0); return SLANG_OK; } Result RenderCommandEncoderImpl::drawIndexed(GfxCount indexCount, GfxIndex startIndex, GfxIndex baseVertex) { + SLANG_RETURN_ON_FAIL(prepareDraw()); m_device->m_ctx.api.wgpuRenderPassEncoderDrawIndexed(m_renderPassEncoder, indexCount, 1, startIndex, baseVertex, 0); return SLANG_OK; } @@ -422,6 +515,7 @@ Result RenderCommandEncoderImpl::drawInstanced( GfxIndex startInstanceLocation ) { + SLANG_RETURN_ON_FAIL(prepareDraw()); m_device->m_ctx.api .wgpuRenderPassEncoderDraw(m_renderPassEncoder, vertexCount, instanceCount, startVertex, startInstanceLocation); return SLANG_OK; @@ -435,6 +529,7 @@ Result RenderCommandEncoderImpl::drawIndexedInstanced( GfxIndex startInstanceLocation ) { + SLANG_RETURN_ON_FAIL(prepareDraw()); m_device->m_ctx.api.wgpuRenderPassEncoderDrawIndexed( m_renderPassEncoder, indexCount, diff --git a/src/wgpu/wgpu-command-encoder.h b/src/wgpu/wgpu-command-encoder.h index e612d171..e98c052a 100644 --- a/src/wgpu/wgpu-command-encoder.h +++ b/src/wgpu/wgpu-command-encoder.h @@ -137,6 +137,8 @@ class RenderCommandEncoderImpl : public IRenderCommandEncoder, public CommandEnc Result init(CommandBufferImpl* commandBuffer, const RenderPassDesc& renderPass); + Result prepareDraw(); + // IRenderCommandEncoder implementation virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override; diff --git a/src/wgpu/wgpu-device.cpp b/src/wgpu/wgpu-device.cpp index 7834da3b..e761f250 100644 --- a/src/wgpu/wgpu-device.cpp +++ b/src/wgpu/wgpu-device.cpp @@ -136,7 +136,121 @@ Result DeviceImpl::readTexture( Size* outPixelSize ) { - return SLANG_E_NOT_IMPLEMENTED; + TextureImpl* textureImpl = static_cast(texture); + + if (textureImpl->m_desc.sampleCount > 1) + { + return SLANG_E_NOT_IMPLEMENTED; + } + + const TextureDesc& desc = textureImpl->m_desc; + GfxCount width = std::max(desc.size.width, 1); + GfxCount height = std::max(desc.size.height, 1); + GfxCount depth = std::max(desc.size.depth, 1); + FormatInfo formatInfo; + rhiGetFormatInfo(desc.format, &formatInfo); + Size bytesPerPixel = formatInfo.blockSizeInBytes / formatInfo.pixelsPerBlock; + Size bytesPerRow = Size(width) * bytesPerPixel; + Size bytesPerSlice = Size(height) * bytesPerRow; + Size bufferSize = Size(depth) * bytesPerSlice; + if (outRowPitch) + *outRowPitch = bytesPerRow; + if (outPixelSize) + *outPixelSize = bytesPerPixel; + + // create staging buffer + WGPUBufferDescriptor stagingBufferDesc = {}; + stagingBufferDesc.size = bufferSize; + stagingBufferDesc.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_MapRead; + WGPUBuffer stagingBuffer = m_ctx.api.wgpuDeviceCreateBuffer(m_ctx.device, &stagingBufferDesc); + if (!stagingBuffer) + { + return SLANG_FAIL; + } + SLANG_RHI_DEFERRED({ m_ctx.api.wgpuBufferRelease(stagingBuffer); }); + + WGPUCommandEncoder encoder = m_ctx.api.wgpuDeviceCreateCommandEncoder(m_ctx.device, nullptr); + if (!encoder) + { + return SLANG_FAIL; + } + SLANG_RHI_DEFERRED({ m_ctx.api.wgpuCommandEncoderRelease(encoder); }); + + WGPUImageCopyTexture source = {}; + source.texture = textureImpl->m_texture; + source.mipLevel = 0; + source.origin = {0, 0, 0}; + source.aspect = WGPUTextureAspect_All; + WGPUImageCopyBuffer destination = {}; + destination.layout.offset = 0; + destination.layout.bytesPerRow = bytesPerRow; + destination.layout.rowsPerImage = height; + destination.buffer = stagingBuffer; + WGPUExtent3D copySize = {(uint32_t)width, (uint32_t)height, (uint32_t)depth}; + m_ctx.api.wgpuCommandEncoderCopyTextureToBuffer(encoder, &source, &destination, ©Size); + WGPUCommandBuffer commandBuffer = m_ctx.api.wgpuCommandEncoderFinish(encoder, nullptr); + if (!commandBuffer) + { + return SLANG_FAIL; + } + SLANG_RHI_DEFERRED({ m_ctx.api.wgpuCommandBufferRelease(commandBuffer); }); + + WGPUQueue queue = m_ctx.api.wgpuDeviceGetQueue(m_ctx.device); + m_ctx.api.wgpuQueueSubmit(queue, 1, &commandBuffer); + + // Wait for the command buffer to finish executing + // TODO: we should switch to the new async API + { + WGPUQueueWorkDoneStatus status = WGPUQueueWorkDoneStatus_Unknown; + m_ctx.api.wgpuQueueOnSubmittedWorkDone( + queue, + [](WGPUQueueWorkDoneStatus status, void* userdata) { *(WGPUQueueWorkDoneStatus*)userdata = status; }, + &status + ); + while (status == WGPUQueueWorkDoneStatus_Unknown) + { + m_ctx.api.wgpuDeviceTick(m_ctx.device); + } + if (status != WGPUQueueWorkDoneStatus_Success) + { + return SLANG_FAIL; + } + } + + // Map the staging buffer + // TODO: we should switch to the new async API + { + WGPUBufferMapAsyncStatus status = WGPUBufferMapAsyncStatus_Unknown; + m_ctx.api.wgpuBufferMapAsync( + stagingBuffer, + WGPUMapMode_Read, + 0, + bufferSize, + [](WGPUBufferMapAsyncStatus status, void* userdata) { *(WGPUBufferMapAsyncStatus*)userdata = status; }, + &status + ); + while (status == WGPUBufferMapAsyncStatus_Unknown) + { + m_ctx.api.wgpuDeviceTick(m_ctx.device); + } + if (status != WGPUBufferMapAsyncStatus_Success) + { + return SLANG_FAIL; + } + } + SLANG_RHI_DEFERRED({ m_ctx.api.wgpuBufferUnmap(stagingBuffer); }); + + const void* data = m_ctx.api.wgpuBufferGetConstMappedRange(stagingBuffer, 0, bufferSize); + if (!data) + { + return SLANG_FAIL; + } + + auto blob = OwnedBlob::create(bufferSize); + ::memcpy((void*)blob->getBufferPointer(), data, bufferSize); + + returnComPtr(outBlob, blob); + return SLANG_OK; } Result DeviceImpl::readBuffer(IBuffer* buffer, Offset offset, Size size, ISlangBlob** outBlob) diff --git a/src/wgpu/wgpu-input-layout.cpp b/src/wgpu/wgpu-input-layout.cpp index 44b54a4d..c9455686 100644 --- a/src/wgpu/wgpu-input-layout.cpp +++ b/src/wgpu/wgpu-input-layout.cpp @@ -23,7 +23,7 @@ Result DeviceImpl::createInputLayout(InputLayoutDesc const& desc, IInputLayout** vertexAttribute.format = translateVertexFormat(elementDesc.format); vertexAttribute.offset = elementDesc.offset; // TODO determine shader location from name - vertexAttribute.shaderLocation = 0; + vertexAttribute.shaderLocation = i; layout->m_vertexAttributes[elementDesc.bufferSlotIndex].push_back(vertexAttribute); } diff --git a/src/wgpu/wgpu-pipeline.cpp b/src/wgpu/wgpu-pipeline.cpp index efffb9a9..ca3d08a3 100644 --- a/src/wgpu/wgpu-pipeline.cpp +++ b/src/wgpu/wgpu-pipeline.cpp @@ -1,7 +1,9 @@ #include "wgpu-pipeline.h" #include "wgpu-device.h" +#include "wgpu-input-layout.h" #include "wgpu-shader-program.h" #include "wgpu-shader-object-layout.h" +#include "wgpu-util.h" namespace rhi::wgpu { @@ -43,19 +45,109 @@ void PipelineImpl::init(const RayTracingPipelineDesc& desc) Result PipelineImpl::createRenderPipeline() { + ShaderProgramImpl* program = static_cast(m_program.get()); + InputLayoutImpl* inputLayout = static_cast(desc.graphics.inputLayout); + ShaderProgramImpl::Module* vertexModule = program->findModule(SlangStage::SLANG_STAGE_VERTEX); + ShaderProgramImpl::Module* fragmentModule = program->findModule(SlangStage::SLANG_STAGE_FRAGMENT); + if (!vertexModule || !fragmentModule) + { + return SLANG_FAIL; + } + WGPURenderPipelineDescriptor pipelineDesc = {}; + + pipelineDesc.layout = program->m_rootObjectLayout->m_pipelineLayout; + + pipelineDesc.vertex.module = vertexModule->module; + pipelineDesc.vertex.entryPoint = vertexModule->entryPointName.c_str(); + pipelineDesc.vertex.buffers = inputLayout->m_vertexBufferLayouts.data(); + pipelineDesc.vertex.bufferCount = (uint32_t)inputLayout->m_vertexBufferLayouts.size(); + + pipelineDesc.primitive.topology = translatePrimitiveTopology(desc.graphics.primitiveType); + // TODO support strip topologies + pipelineDesc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined; + pipelineDesc.primitive.frontFace = translateFrontFace(desc.graphics.rasterizer.frontFace); + pipelineDesc.primitive.cullMode = translateCullMode(desc.graphics.rasterizer.cullMode); + pipelineDesc.primitive.unclippedDepth = !desc.graphics.rasterizer.depthClipEnable; + + WGPUDepthStencilState depthStencil = {}; + if (desc.graphics.depthStencil.format != Format::Unknown) + { + const DepthStencilState& depthStencilIn = desc.graphics.depthStencil; + depthStencil.format = translateTextureFormat(depthStencilIn.format); + depthStencil.depthWriteEnabled = + depthStencilIn.depthWriteEnable ? WGPUOptionalBool_True : WGPUOptionalBool_False; + depthStencil.depthCompare = translateCompareFunction(depthStencilIn.depthFunc); + depthStencil.stencilFront.compare = translateCompareFunction(depthStencilIn.frontFace.stencilFunc); + depthStencil.stencilFront.failOp = translateStencilOp(depthStencilIn.frontFace.stencilFailOp); + depthStencil.stencilFront.depthFailOp = translateStencilOp(depthStencilIn.frontFace.stencilDepthFailOp); + depthStencil.stencilFront.passOp = translateStencilOp(depthStencilIn.frontFace.stencilPassOp); + depthStencil.stencilBack.compare = translateCompareFunction(depthStencilIn.backFace.stencilFunc); + depthStencil.stencilBack.failOp = translateStencilOp(depthStencilIn.backFace.stencilFailOp); + depthStencil.stencilBack.depthFailOp = translateStencilOp(depthStencilIn.backFace.stencilDepthFailOp); + depthStencil.stencilBack.passOp = translateStencilOp(depthStencilIn.backFace.stencilPassOp); + depthStencil.stencilReadMask = depthStencilIn.stencilReadMask; + depthStencil.stencilWriteMask = depthStencilIn.stencilWriteMask; + depthStencil.depthBias = desc.graphics.rasterizer.depthBias; + depthStencil.depthBiasSlopeScale = desc.graphics.rasterizer.slopeScaledDepthBias; + depthStencil.depthBiasClamp = desc.graphics.rasterizer.depthBiasClamp; + pipelineDesc.depthStencil = &depthStencil; + } + + pipelineDesc.multisample.count = desc.graphics.multisample.sampleCount; + pipelineDesc.multisample.mask = desc.graphics.multisample.sampleMask; + pipelineDesc.multisample.alphaToCoverageEnabled = desc.graphics.multisample.alphaToCoverageEnable; + // desc.graphics.multisample.alphaToOneEnable not supported + + short_vector targets(desc.graphics.targetCount, {}); + short_vector blendStates(desc.graphics.targetCount, {}); + for (GfxIndex i = 0; i < desc.graphics.targetCount; ++i) + { + const ColorTargetState& targetIn = desc.graphics.targets[i]; + WGPUColorTargetState& target = targets[i]; + WGPUBlendState& blend = blendStates[i]; + target.format = translateTextureFormat(targetIn.format); + if (targetIn.enableBlend) + { + blend.color.operation = translateBlendOperation(targetIn.color.op); + blend.color.srcFactor = translateBlendFactor(targetIn.color.srcFactor); + blend.color.dstFactor = translateBlendFactor(targetIn.color.dstFactor); + blend.alpha.operation = translateBlendOperation(targetIn.alpha.op); + blend.alpha.srcFactor = translateBlendFactor(targetIn.alpha.srcFactor); + blend.alpha.dstFactor = translateBlendFactor(targetIn.alpha.dstFactor); + target.blend = &blend; + } + target.writeMask = targetIn.writeMask; + } + + WGPUFragmentState fragment = {}; + fragment.module = fragmentModule->module; + fragment.entryPoint = fragmentModule->entryPointName.c_str(); + fragment.targetCount = (uint32_t)targets.size(); + fragment.targets = targets.data(); + pipelineDesc.fragment = &fragment; + m_renderPipeline = m_device->m_ctx.api.wgpuDeviceCreateRenderPipeline(m_device->m_ctx.device, &pipelineDesc); + return m_renderPipeline ? SLANG_OK : SLANG_FAIL; } Result PipelineImpl::createComputePipeline() { ShaderProgramImpl* program = static_cast(m_program.get()); + ShaderProgramImpl::Module* computeModule = program->findModule(SlangStage::SLANG_STAGE_FRAGMENT); + if (!computeModule) + { + return SLANG_FAIL; + } + WGPUComputePipelineDescriptor pipelineDesc = {}; - pipelineDesc.compute.module = program->m_modules[0].module; - pipelineDesc.compute.entryPoint = program->m_modules[0].entryPointName.c_str(); pipelineDesc.layout = program->m_rootObjectLayout->m_pipelineLayout; + pipelineDesc.compute.module = computeModule->module; + pipelineDesc.compute.entryPoint = computeModule->entryPointName.c_str(); + m_computePipeline = m_device->m_ctx.api.wgpuDeviceCreateComputePipeline(m_device->m_ctx.device, &pipelineDesc); + return m_computePipeline ? SLANG_OK : SLANG_FAIL; } diff --git a/src/wgpu/wgpu-shader-program.cpp b/src/wgpu/wgpu-shader-program.cpp index 32e5c1fc..429862b5 100644 --- a/src/wgpu/wgpu-shader-program.cpp +++ b/src/wgpu/wgpu-shader-program.cpp @@ -34,6 +34,16 @@ Result ShaderProgramImpl::createShaderModule(slang::EntryPointReflection* entryP return SLANG_OK; } +ShaderProgramImpl::Module* ShaderProgramImpl::findModule(SlangStage stage) +{ + for (Module& module : m_modules) + { + if (module.stage == stage) + return &module; + } + return nullptr; +} + Result DeviceImpl::createShaderProgram( const ShaderProgramDesc& desc, IShaderProgram** outProgram, diff --git a/src/wgpu/wgpu-shader-program.h b/src/wgpu/wgpu-shader-program.h index 3252b88b..a66d114d 100644 --- a/src/wgpu/wgpu-shader-program.h +++ b/src/wgpu/wgpu-shader-program.h @@ -25,6 +25,8 @@ class ShaderProgramImpl : public ShaderProgram virtual Result createShaderModule(slang::EntryPointReflection* entryPointInfo, ComPtr kernelCode) override; + + Module* findModule(SlangStage stage); }; } // namespace rhi::wgpu diff --git a/src/wgpu/wgpu-util.cpp b/src/wgpu/wgpu-util.cpp index 7ebc11d8..03fe22df 100644 --- a/src/wgpu/wgpu-util.cpp +++ b/src/wgpu/wgpu-util.cpp @@ -458,4 +458,165 @@ WGPUCompareFunction translateCompareFunction(ComparisonFunc func) } } +WGPUPrimitiveTopology translatePrimitiveTopology(PrimitiveType type) +{ + switch (type) + { + case PrimitiveType::Point: + return WGPUPrimitiveTopology_PointList; + case PrimitiveType::Line: + return WGPUPrimitiveTopology_LineList; + case PrimitiveType::Triangle: + return WGPUPrimitiveTopology_TriangleList; + case PrimitiveType::Patch: + SLANG_RHI_ASSERT_FAILURE("Patch topology not supported."); + default: + return WGPUPrimitiveTopology_Undefined; + } +} + +WGPUFrontFace translateFrontFace(FrontFaceMode mode) +{ + switch (mode) + { + case FrontFaceMode::CounterClockwise: + return WGPUFrontFace_CCW; + case FrontFaceMode::Clockwise: + return WGPUFrontFace_CW; + default: + return WGPUFrontFace_Undefined; + } +} + +WGPUCullMode translateCullMode(CullMode mode) +{ + switch (mode) + { + case CullMode::None: + return WGPUCullMode_None; + case CullMode::Front: + return WGPUCullMode_Front; + case CullMode::Back: + return WGPUCullMode_Back; + default: + return WGPUCullMode_Undefined; + } +} + +WGPUStencilOperation translateStencilOp(StencilOp op) +{ + switch (op) + { + case StencilOp::Keep: + return WGPUStencilOperation_Keep; + case StencilOp::Zero: + return WGPUStencilOperation_Zero; + case StencilOp::Replace: + return WGPUStencilOperation_Replace; + case StencilOp::IncrementSaturate: + return WGPUStencilOperation_IncrementClamp; + case StencilOp::DecrementSaturate: + return WGPUStencilOperation_DecrementClamp; + case StencilOp::Invert: + return WGPUStencilOperation_Invert; + case StencilOp::IncrementWrap: + return WGPUStencilOperation_IncrementWrap; + case StencilOp::DecrementWrap: + return WGPUStencilOperation_DecrementWrap; + default: + return WGPUStencilOperation_Undefined; + } +} + +WGPUBlendFactor translateBlendFactor(BlendFactor factor) +{ + switch (factor) + { + case BlendFactor::Zero: + return WGPUBlendFactor_Zero; + case BlendFactor::One: + return WGPUBlendFactor_One; + case BlendFactor::SrcColor: + return WGPUBlendFactor_Src; + case BlendFactor::InvSrcColor: + return WGPUBlendFactor_OneMinusSrc; + case BlendFactor::SrcAlpha: + return WGPUBlendFactor_SrcAlpha; + case BlendFactor::InvSrcAlpha: + return WGPUBlendFactor_OneMinusSrcAlpha; + case BlendFactor::DestAlpha: + return WGPUBlendFactor_DstAlpha; + case BlendFactor::InvDestAlpha: + return WGPUBlendFactor_OneMinusDstAlpha; + case BlendFactor::DestColor: + return WGPUBlendFactor_Dst; + case BlendFactor::InvDestColor: + return WGPUBlendFactor_OneMinusDst; + case BlendFactor::SrcAlphaSaturate: + return WGPUBlendFactor_SrcAlphaSaturated; + case BlendFactor::BlendColor: + return WGPUBlendFactor_Constant; + case BlendFactor::InvBlendColor: + return WGPUBlendFactor_OneMinusConstant; + case BlendFactor::SecondarySrcColor: + return WGPUBlendFactor_Src1; + case BlendFactor::InvSecondarySrcColor: + return WGPUBlendFactor_OneMinusSrc1; + case BlendFactor::SecondarySrcAlpha: + return WGPUBlendFactor_Src1Alpha; + case BlendFactor::InvSecondarySrcAlpha: + return WGPUBlendFactor_OneMinusSrc1Alpha; + default: + return WGPUBlendFactor_Undefined; + } +} + +WGPUBlendOperation translateBlendOperation(BlendOp op) +{ + switch (op) + { + case BlendOp::Add: + return WGPUBlendOperation_Add; + case BlendOp::Subtract: + return WGPUBlendOperation_Subtract; + case BlendOp::ReverseSubtract: + return WGPUBlendOperation_ReverseSubtract; + case BlendOp::Min: + return WGPUBlendOperation_Min; + case BlendOp::Max: + return WGPUBlendOperation_Max; + default: + return WGPUBlendOperation_Undefined; + } +} + +WGPULoadOp translateLoadOp(LoadOp op) +{ + switch (op) + { + case LoadOp::Load: + return WGPULoadOp_Load; + case LoadOp::Clear: + return WGPULoadOp_Clear; + case LoadOp::DontCare: + return WGPULoadOp_Undefined; + default: + return WGPULoadOp_Undefined; + } +} + +WGPUStoreOp translateStoreOp(StoreOp op) +{ + switch (op) + { + case StoreOp::Store: + return WGPUStoreOp_Store; + case StoreOp::DontCare: + return WGPUStoreOp_Undefined; + default: + return WGPUStoreOp_Undefined; + } +} + + } // namespace rhi::wgpu diff --git a/src/wgpu/wgpu-util.h b/src/wgpu/wgpu-util.h index 28f8fbc0..7f2c3c15 100644 --- a/src/wgpu/wgpu-util.h +++ b/src/wgpu/wgpu-util.h @@ -18,4 +18,14 @@ WGPUFilterMode translateFilterMode(TextureFilteringMode mode); WGPUMipmapFilterMode translateMipmapFilterMode(TextureFilteringMode mode); WGPUCompareFunction translateCompareFunction(ComparisonFunc func); +WGPUPrimitiveTopology translatePrimitiveTopology(PrimitiveType type); +WGPUFrontFace translateFrontFace(FrontFaceMode mode); +WGPUCullMode translateCullMode(CullMode mode); +WGPUStencilOperation translateStencilOp(StencilOp op); +WGPUBlendFactor translateBlendFactor(BlendFactor factor); +WGPUBlendOperation translateBlendOperation(BlendOp op); + +WGPULoadOp translateLoadOp(LoadOp op); +WGPUStoreOp translateStoreOp(StoreOp op); + } // namespace rhi::wgpu