Set up D3D textures and draw buffers

Change-Id: Ice6676acc33cc245ee62bea587181c1459dbba33
Bug: skia:9935
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/290829
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Jim Van Verth 2020-05-20 09:35:42 -04:00 committed by Skia Commit-Bot
parent 682fca9299
commit 40b4de2dbd
7 changed files with 209 additions and 31 deletions

View File

@ -148,16 +148,6 @@ void GrD3DCommandList::copyTextureRegion(sk_sp<GrManagedResource> dst,
fCommandList->CopyTextureRegion(dstLocation, dstX, dstY, 0, srcLocation, srcBox);
}
void GrD3DCommandList::clearRenderTargetView(GrD3DRenderTarget* renderTarget,
const SkPMColor4f& color,
const GrFixedClip& clip) {
this->addingWork();
this->addResource(renderTarget->resource());
fCommandList->ClearRenderTargetView(renderTarget->colorRenderTargetView(),
color.vec(),
0, NULL); // no cliprects for now
}
void GrD3DCommandList::addingWork() {
this->submitResourceBarriers();
fHasWork = true;
@ -218,6 +208,51 @@ void GrD3DDirectCommandList::setViewports(unsigned int numViewports,
fCommandList->RSSetViewports(numViewports, viewports);
}
void GrD3DDirectCommandList::setVertexBuffers(unsigned int startSlot,
const GrD3DBuffer* vertexBuffer,
size_t vertexStride,
const GrD3DBuffer* instanceBuffer,
size_t instanceStride) {
this->addingWork();
this->addResource(vertexBuffer->resource());
D3D12_VERTEX_BUFFER_VIEW views[2];
int numViews = 0;
views[numViews].BufferLocation = vertexBuffer->d3dResource()->GetGPUVirtualAddress();
views[numViews].SizeInBytes = vertexBuffer->size();
views[numViews++].StrideInBytes = vertexStride;
if (instanceBuffer) {
this->addResource(instanceBuffer->resource());
views[numViews].BufferLocation = instanceBuffer->d3dResource()->GetGPUVirtualAddress();
views[numViews].SizeInBytes = instanceBuffer->size();
views[numViews++].StrideInBytes = instanceStride;
}
fCommandList->IASetVertexBuffers(startSlot, numViews, views);
}
void GrD3DDirectCommandList::setIndexBuffer(const GrD3DBuffer* indexBuffer) {
this->addingWork();
this->addResource(indexBuffer->resource());
D3D12_INDEX_BUFFER_VIEW view = {};
view.BufferLocation = indexBuffer->d3dResource()->GetGPUVirtualAddress();
view.SizeInBytes = indexBuffer->size();
view.Format = DXGI_FORMAT_R16_UINT;
fCommandList->IASetIndexBuffer(&view);
}
void GrD3DDirectCommandList::clearRenderTargetView(GrD3DRenderTarget* renderTarget,
const SkPMColor4f& color,
const GrFixedClip& clip) {
this->addingWork();
this->addResource(renderTarget->resource());
fCommandList->ClearRenderTargetView(renderTarget->colorRenderTargetView(),
color.vec(),
0, NULL); // no cliprects for now
}
////////////////////////////////////////////////////////////////////////////////////////////////////
std::unique_ptr<GrD3DCopyCommandList> GrD3DCopyCommandList::Make(ID3D12Device* device) {

View File

@ -62,9 +62,6 @@ public:
const D3D12_TEXTURE_COPY_LOCATION* srcLocation,
const D3D12_BOX* srcBox);
void clearRenderTargetView(GrD3DRenderTarget* renderTarget, const SkPMColor4f& color,
const GrFixedClip& clip);
// Add ref-counted resource that will be tracked and released when this command buffer finishes
// execution
void addResource(sk_sp<GrManagedResource> resource) {
@ -121,7 +118,13 @@ public:
void setPrimitiveTopology(D3D12_PRIMITIVE_TOPOLOGY primitiveTopology);
void setScissorRects(unsigned int numRects, const D3D12_RECT* rects);
void setViewports(unsigned int numViewports, const D3D12_VIEWPORT* viewports);
void setVertexBuffers(unsigned int startSlot,
const GrD3DBuffer* vertexBuffer, size_t vertexStride,
const GrD3DBuffer* instanceBuffer, size_t instanceStride);
void setIndexBuffer(const GrD3DBuffer* indexBuffer);
void clearRenderTargetView(GrD3DRenderTarget* renderTarget, const SkPMColor4f& color,
const GrFixedClip& clip);
private:
GrD3DDirectCommandList(gr_cp<ID3D12CommandAllocator> allocator,
gr_cp<ID3D12GraphicsCommandList> commandList);

View File

@ -12,9 +12,12 @@
#include "src/gpu/GrProgramDesc.h"
#include "src/gpu/GrRenderTargetPriv.h"
#include "src/gpu/GrStencilSettings.h"
#include "src/gpu/d3d/GrD3DBuffer.h"
#include "src/gpu/d3d/GrD3DGpu.h"
#include "src/gpu/d3d/GrD3DPipelineState.h"
#include "src/gpu/d3d/GrD3DPipelineStateBuilder.h"
#include "src/gpu/d3d/GrD3DRenderTarget.h"
#include "src/gpu/d3d/GrD3DTexture.h"
GrD3DOpsRenderPass::GrD3DOpsRenderPass(GrD3DGpu* gpu) : fGpu(gpu) {}
@ -41,6 +44,13 @@ GrD3DOpsRenderPass::~GrD3DOpsRenderPass() {}
GrGpu* GrD3DOpsRenderPass::gpu() { return fGpu; }
void GrD3DOpsRenderPass::onBegin() {
if (GrLoadOp::kClear == fColorLoadOp) {
GrFixedClip clip;
fGpu->clear(clip, fClearColor, fRenderTarget);
}
}
void set_stencil_ref(GrD3DGpu* gpu, const GrProgramInfo& info) {
GrStencilSettings stencilSettings = info.nonGLStencilSettings();
if (!stencilSettings.isDisabled()) {
@ -139,14 +149,16 @@ bool GrD3DOpsRenderPass::onBindPipeline(const GrProgramInfo& info, const SkRect&
fCurrentPipelineBounds.setEmpty();
}
sk_sp<GrD3DPipelineState> pipelineState =
fCurrentPipelineState =
fGpu->resourceProvider().findOrCreateCompatiblePipelineState(fRenderTarget, info);
if (!pipelineState) {
if (!fCurrentPipelineState) {
return false;
}
pipelineState->setData(fRenderTarget, info);
fGpu->currentCommandList()->setPipelineState(std::move(pipelineState));
fCurrentPipelineState->setData(fRenderTarget, info);
fGpu->currentCommandList()->setPipelineState(fCurrentPipelineState);
// TODO: bind uniforms (either a new method or in pipelineState->setData())
set_stencil_ref(fGpu, info);
set_blend_factor(fGpu, info);
@ -160,11 +172,49 @@ bool GrD3DOpsRenderPass::onBindPipeline(const GrProgramInfo& info, const SkRect&
return true;
}
void GrD3DOpsRenderPass::onBegin() {
if (GrLoadOp::kClear == fColorLoadOp) {
GrFixedClip clip;
fGpu->clear(clip, fClearColor, fRenderTarget);
void update_resource_state(GrTexture* tex, GrRenderTarget* rt, GrD3DGpu* gpu) {
SkASSERT(!tex->isProtected() || (rt->isProtected() && gpu->protectedContext()));
GrD3DTexture* d3dTex = static_cast<GrD3DTexture*>(tex);
SkASSERT(d3dTex);
d3dTex->setResourceState(gpu, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
}
bool GrD3DOpsRenderPass::onBindTextures(const GrPrimitiveProcessor& primProc,
const GrSurfaceProxy* const primProcTextures[],
const GrPipeline& pipeline) {
SkASSERT(fCurrentPipelineState);
// update textures to sampled resource state
for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
update_resource_state(primProcTextures[i]->peekTexture(), fRenderTarget, fGpu);
}
GrFragmentProcessor::PipelineTextureSamplerRange textureSamplerRange(pipeline);
for (auto [sampler, fp] : textureSamplerRange) {
update_resource_state(sampler.peekTexture(), fRenderTarget, fGpu);
}
if (GrTexture* dstTexture = pipeline.peekDstTexture()) {
update_resource_state(dstTexture, fRenderTarget, fGpu);
}
// TODO: possibly check for success once we start binding properly
fCurrentPipelineState->setAndBindTextures(primProc, primProcTextures, pipeline);
return true;
}
void GrD3DOpsRenderPass::onBindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
const GrBuffer* vertexBuffer,
GrPrimitiveRestart primRestart) {
SkASSERT(GrPrimitiveRestart::kNo == primRestart);
SkASSERT(fCurrentPipelineState);
SkASSERT(!fGpu->caps()->usePrimitiveRestart()); // Ignore primitiveRestart parameter.
GrD3DDirectCommandList* currCmdList = fGpu->currentCommandList();
SkASSERT(currCmdList);
// TODO: do we need a memory barrier here?
fCurrentPipelineState->bindBuffers(indexBuffer, instanceBuffer, vertexBuffer, currCmdList);
}
void GrD3DOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& color) {

View File

@ -14,6 +14,7 @@
#include "include/private/GrTypesPriv.h"
class GrD3DGpu;
class GrD3DPipelineState;
class GrD3DOpsRenderPass : public GrOpsRenderPass {
public:
@ -38,11 +39,9 @@ private:
bool onBindPipeline(const GrProgramInfo&, const SkRect& drawBounds) override;
void onSetScissorRect(const SkIRect&) override {}
bool onBindTextures(const GrPrimitiveProcessor&, const GrSurfaceProxy* const primProcTextures[],
const GrPipeline&) override {
return true;
}
const GrPipeline&) override;
void onBindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
const GrBuffer* vertexBuffer, GrPrimitiveRestart) override {}
const GrBuffer* vertexBuffer, GrPrimitiveRestart) override;
void onDraw(int vertexCount, int baseVertex) override {}
void onDrawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
uint16_t maxIndexValue, int baseVertex) override {}
@ -56,6 +55,9 @@ private:
void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) override {}
GrD3DGpu* fGpu;
sk_sp<GrD3DPipelineState> fCurrentPipelineState;
SkIRect fBounds;
SkIRect fCurrentPipelineBounds;

View File

@ -10,8 +10,10 @@
#include "include/private/SkTemplates.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrStencilSettings.h"
#include "src/gpu/d3d/GrD3DBuffer.h"
#include "src/gpu/d3d/GrD3DGpu.h"
#include "src/gpu/d3d/GrD3DRootSignature.h"
#include "src/gpu/d3d/GrD3DTexture.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
#include "src/gpu/glsl/GrGLSLXferProcessor.h"
@ -20,17 +22,23 @@ GrD3DPipelineState::GrD3DPipelineState(
gr_cp<ID3D12PipelineState> pipelineState,
const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
const UniformInfoArray& uniforms, uint32_t uniformSize,
uint32_t numSamplers,
std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,
int fragmentProcessorCnt)
int fragmentProcessorCnt,
size_t vertexStride,
size_t instanceStride)
: fPipelineState(std::move(pipelineState))
, fBuiltinUniformHandles(builtinUniformHandles)
, fGeometryProcessor(std::move(geometryProcessor))
, fXferProcessor(std::move(xferProcessor))
, fFragmentProcessors(std::move(fragmentProcessors))
, fFragmentProcessorCnt(fragmentProcessorCnt)
, fDataManager(uniforms, uniformSize) {}
, fDataManager(uniforms, uniformSize)
, fNumSamplers(numSamplers)
, fVertexStride(vertexStride)
, fInstanceStride(instanceStride) {}
void GrD3DPipelineState::setData(const GrRenderTarget* renderTarget,
const GrProgramInfo& programInfo) {
@ -55,7 +63,6 @@ void GrD3DPipelineState::setData(const GrRenderTarget* renderTarget,
}
void GrD3DPipelineState::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin) {
// Load the RT height uniform if it is needed to y-flip gl_FragCoord.
if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) {
@ -75,3 +82,65 @@ void GrD3DPipelineState::setRenderTargetState(const GrRenderTarget* rt, GrSurfac
fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
}
}
void GrD3DPipelineState::setAndBindTextures(const GrPrimitiveProcessor& primProc,
const GrSurfaceProxy* const primProcTextures[],
const GrPipeline& pipeline) {
SkASSERT(primProcTextures || !primProc.numTextureSamplers());
struct SamplerBindings {
GrSamplerState fState;
GrD3DTexture* fTexture;
};
SkAutoSTMalloc<8, SamplerBindings> samplerBindings(fNumSamplers);
int currTextureBinding = 0;
for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
SkASSERT(primProcTextures[i]->asTextureProxy());
const auto& sampler = primProc.textureSampler(i);
auto texture = static_cast<GrD3DTexture*>(primProcTextures[i]->peekTexture());
samplerBindings[currTextureBinding++] = { sampler.samplerState(), texture };
}
GrFragmentProcessor::CIter fpIter(pipeline);
GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
for (; fpIter && glslIter; ++fpIter, ++glslIter) {
for (int i = 0; i < fpIter->numTextureSamplers(); ++i) {
const auto& sampler = fpIter->textureSampler(i);
samplerBindings[currTextureBinding++] =
{ sampler.samplerState(), static_cast<GrD3DTexture*>(sampler.peekTexture()) };
}
}
SkASSERT(!fpIter && !glslIter);
if (GrTexture* dstTexture = pipeline.peekDstTexture()) {
samplerBindings[currTextureBinding++] = {
GrSamplerState::Filter::kNearest, static_cast<GrD3DTexture*>(dstTexture) };
}
// TODO: bind descriptors
SkASSERT(fNumSamplers == currTextureBinding);
}
void GrD3DPipelineState::bindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
const GrBuffer* vertexBuffer,
GrD3DDirectCommandList* commandList) {
// Here our vertex and instance inputs need to match the same 0-based bindings they were
// assigned in the PipelineState. That is, vertex first (if any) followed by instance.
if (auto* d3dVertexBuffer = static_cast<const GrD3DBuffer*>(vertexBuffer)) {
SkASSERT(!d3dVertexBuffer->isCpuBuffer());
SkASSERT(!d3dVertexBuffer->isMapped());
auto* d3dInstanceBuffer = static_cast<const GrD3DBuffer*>(instanceBuffer);
if (d3dInstanceBuffer) {
SkASSERT(!d3dInstanceBuffer->isCpuBuffer());
SkASSERT(!d3dInstanceBuffer->isMapped());
}
commandList->setVertexBuffers(0, d3dVertexBuffer, fVertexStride,
d3dInstanceBuffer, fInstanceStride);
}
if (auto* d3dIndexBuffer = static_cast<const GrD3DBuffer*>(indexBuffer)) {
SkASSERT(!d3dIndexBuffer->isCpuBuffer());
SkASSERT(!d3dIndexBuffer->isMapped());
commandList->setIndexBuffer(d3dIndexBuffer);
}
}

View File

@ -15,6 +15,7 @@
#include "src/gpu/d3d/GrD3DPipelineStateDataManager.h"
#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
class GrD3DDirectCommandList;
class GrD3DGpu;
class GrD3DRootSignature;
class GrProgramInfo;
@ -27,10 +28,13 @@ public:
const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
const UniformInfoArray& uniforms,
uint32_t uniformSize,
uint32_t numSamplers,
std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragProcessors,
int fragmentProcessorCnt);
int fragmentProcessorCnt,
size_t vertexStride,
size_t instanceStride);
#ifdef SK_TRACE_MANAGED_RESOURCES
/** Output a human-readable dump of this resource's information
@ -48,6 +52,13 @@ public:
void setData(const GrRenderTarget* renderTarget, const GrProgramInfo& programInfo);
void setAndBindTextures(const GrPrimitiveProcessor& primProc,
const GrSurfaceProxy* const primProcTextures[],
const GrPipeline& pipeline);
void bindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
const GrBuffer* vertexBuffer, GrD3DDirectCommandList* commandList);
private:
/**
* We use the RT's size and origin to adjust from Skia device space to d3d normalized device
@ -101,6 +112,10 @@ private:
int fFragmentProcessorCnt;
GrD3DPipelineStateDataManager fDataManager;
int fNumSamplers;
size_t fVertexStride;
size_t fInstanceStride;
};
#endif

View File

@ -536,7 +536,8 @@ sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() {
return nullptr;
}
if (this->primitiveProcessor().willUseGeoShader()) {
const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
if (primProc.willUseGeoShader()) {
this->compileD3DProgram(SkSL::Program::kGeometry_Kind, fGS.fCompilerString, settings,
&geometryShader, &geomInputs);
if (!geometryShader.get()) {
@ -560,8 +561,11 @@ sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() {
fUniformHandles,
fUniformHandler.fUniforms,
fUniformHandler.fCurrentUBOOffset,
fUniformHandler.fSamplers.count(),
std::move(fGeometryProcessor),
std::move(fXferProcessor),
std::move(fFragmentProcessors),
fFragmentProcessorCnt));
fFragmentProcessorCnt,
primProc.vertexStride(),
primProc.instanceStride()));
}